Qt 4.8
qnetworkcookiejar.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qnetworkcookiejar.h"
43 #include "qnetworkcookiejar_p.h"
44 
45 #include "QtNetwork/qnetworkcookie.h"
46 #include "QtCore/qurl.h"
47 #include "QtCore/qdatetime.h"
48 #include "private/qtldurl_p.h"
49 
51 
99  : QObject(*new QNetworkCookieJarPrivate, parent)
100 {
101 }
102 
112 {
113 }
114 
123 {
124  return d_func()->allCookies;
125 }
126 
137 {
139  d->allCookies = cookieList;
140 }
141 
142 static inline bool isParentPath(QString path, QString reference)
143 {
144  if (!path.endsWith(QLatin1Char('/')))
145  path += QLatin1Char('/');
146  if (!reference.endsWith(QLatin1Char('/')))
147  reference += QLatin1Char('/');
148  return path.startsWith(reference);
149 }
150 
151 static inline bool isParentDomain(QString domain, QString reference)
152 {
153  if (!reference.startsWith(QLatin1Char('.')))
154  return domain == reference;
155 
156  return domain.endsWith(reference) || domain == reference.mid(1);
157 }
158 
182  const QUrl &url)
183 {
185  QString defaultDomain = url.host();
186  QString pathAndFileName = url.path();
187  QString defaultPath = pathAndFileName.left(pathAndFileName.lastIndexOf(QLatin1Char('/'))+1);
188  if (defaultPath.isEmpty())
189  defaultPath = QLatin1Char('/');
190 
191  int added = 0;
193  foreach (QNetworkCookie cookie, cookieList) {
194  bool isDeletion = !cookie.isSessionCookie() &&
195  cookie.expirationDate() < now;
196 
197  // validate the cookie & set the defaults if unset
198  if (cookie.path().isEmpty())
199  cookie.setPath(defaultPath);
200  // don't do path checking. See http://bugreports.qt-project.org/browse/QTBUG-5815
201 // else if (!isParentPath(pathAndFileName, cookie.path())) {
202 // continue; // not accepted
203 // }
204  if (cookie.domain().isEmpty()) {
205  cookie.setDomain(defaultDomain);
206  } else {
207  // Ensure the domain starts with a dot if its field was not empty
208  // in the HTTP header. There are some servers that forget the
209  // leading dot and this is actually forbidden according to RFC 2109,
210  // but all browsers accept it anyway so we do that as well.
211  if (!cookie.domain().startsWith(QLatin1Char('.')))
212  cookie.setDomain(QLatin1Char('.') + cookie.domain());
213 
214  QString domain = cookie.domain();
215  if (!(isParentDomain(domain, defaultDomain)
216  || isParentDomain(defaultDomain, domain)))
217  continue; // not accepted
218 
219  // the check for effective TLDs makes the "embedded dot" rule from RFC 2109 section 4.3.2
220  // redundant; the "leading dot" rule has been relaxed anyway, see above
221  // we remove the leading dot for this check
222  if (qIsEffectiveTLD(domain.remove(0, 1)))
223  continue; // not accepted
224  }
225 
226  for (int i = 0; i < d->allCookies.size(); ++i) {
227  // does this cookie already exist?
228  const QNetworkCookie &current = d->allCookies.at(i);
229  if (cookie.name() == current.name() &&
230  cookie.domain() == current.domain() &&
231  cookie.path() == current.path()) {
232  // found a match
233  d->allCookies.removeAt(i);
234  break;
235  }
236  }
237 
238  // did not find a match
239  if (!isDeletion) {
240  int countForDomain = 0;
241  for (int i = d->allCookies.size() - 1; i >= 0; --i) {
242  // Start from the end and delete the oldest cookies to keep a maximum count of 50.
243  const QNetworkCookie &current = d->allCookies.at(i);
244  if (isParentDomain(cookie.domain(), current.domain())
245  || isParentDomain(current.domain(), cookie.domain())) {
246  if (countForDomain >= 49)
247  d->allCookies.removeAt(i);
248  else
249  ++countForDomain;
250  }
251  }
252 
253  d->allCookies += cookie;
254  ++added;
255  }
256  }
257  return (added > 0);
258 }
259 
279 {
280 // \b Warning! This is only a dumb implementation!
281 // It does NOT follow all of the recommendations from
282 // http://wp.netscape.com/newsref/std/cookie_spec.html
283 // It does not implement a very good cross-domain verification yet.
284 
285  Q_D(const QNetworkCookieJar);
287  QList<QNetworkCookie> result;
288  bool isEncrypted = url.scheme().toLower() == QLatin1String("https");
289 
290  // scan our cookies for something that matches
291  QList<QNetworkCookie>::ConstIterator it = d->allCookies.constBegin(),
292  end = d->allCookies.constEnd();
293  for ( ; it != end; ++it) {
294  if (!isParentDomain(url.host(), it->domain()))
295  continue;
296  if (!isParentPath(url.path(), it->path()))
297  continue;
298  if (!(*it).isSessionCookie() && (*it).expirationDate() < now)
299  continue;
300  if ((*it).isSecure() && !isEncrypted)
301  continue;
302 
303  // insert this cookie into result, sorted by path
304  QList<QNetworkCookie>::Iterator insertIt = result.begin();
305  while (insertIt != result.end()) {
306  if (insertIt->path().length() < it->path().length()) {
307  // insert here
308  insertIt = result.insert(insertIt, *it);
309  break;
310  } else {
311  ++insertIt;
312  }
313  }
314 
315  // this is the shortest path yet, just append
316  if (insertIt == result.end())
317  result += *it;
318  }
319 
320  return result;
321 }
322 
double d
Definition: qnumeric_p.h:62
QString domain() const
Returns the domain this cookie is associated with.
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool isSessionCookie() const
Returns true if this cookie is a session cookie.
#define it(className, varName)
virtual QList< QNetworkCookie > cookiesForUrl(const QUrl &url) const
Returns the cookies to be added to when a request is sent to url.
virtual ~QNetworkCookieJar()
Destroys this cookie jar object and discards all cookies stored in it.
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
Definition: qlist.h:267
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
void insert(int i, const T &t)
Inserts value at index position i in the list.
Definition: qlist.h:575
void setDomain(const QString &domain)
Sets the domain associated with this cookie to be domain.
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
void setPath(const QString &path)
Sets the path associated with this cookie to be path.
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
QString host() const
Returns the host of the URL if it is defined; otherwise an empty string is returned.
Definition: qurl.cpp:4837
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define Q_D(Class)
Definition: qglobal.h:2482
QString path() const
Returns the path of the URL.
Definition: qurl.cpp:4977
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
QString path() const
Returns the path associated with this cookie.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:270
QDateTime expirationDate() const
Returns the expiration date for this cookie.
virtual bool setCookiesFromUrl(const QList< QNetworkCookie > &cookieList, const QUrl &url)
Adds the cookies in the list cookieList to this cookie jar.
QList< QNetworkCookie > allCookies() const
Returns all cookies stored in this cookie jar.
The QNetworkCookieJar class implements a simple jar of QNetworkCookie objects.
The QNetworkCookie class holds one network cookie.
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
QString scheme() const
Returns the scheme of the URL.
Definition: qurl.cpp:4550
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
QNetworkCookieJar(QObject *parent=0)
Creates a QNetworkCookieJar object and sets the parent object to be parent.
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
static bool isParentPath(QString path, QString reference)
int length() const
This function is identical to count().
Definition: qlist.h:281
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
QByteArray name() const
Returns the name of this cookie.
void setAllCookies(const QList< QNetworkCookie > &cookieList)
Sets the internal list of cookies held by this cookie jar to be cookieList.
static QDateTime currentDateTime()
Returns the current datetime, as reported by the system clock, in the local time zone.
Definition: qdatetime.cpp:3138
Q_CORE_EXPORT bool qIsEffectiveTLD(const QString &domain)
Return true if domain is a top-level-domain per Qt&#39;s copy of the Mozilla public suffix list...
Definition: qtldurl.cpp:97
static bool isParentDomain(QString domain, QString reference)
QString & remove(int i, int len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition: qstring.cpp:1867
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
static const KeyPair *const end
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55