access/qnetworkcookie.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 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 "qnetworkcookie.h" -
43#include "qnetworkcookie_p.h" -
44 -
45#include "qnetworkrequest.h" -
46#include "qnetworkreply.h" -
47#include "QtCore/qbytearray.h" -
48#include "QtCore/qdebug.h" -
49#include "QtCore/qlist.h" -
50#include "QtCore/qlocale.h" -
51#include "QtCore/qstring.h" -
52#include "QtCore/qstringlist.h" -
53#include "QtCore/qurl.h" -
54#include "private/qobject_p.h" -
55 -
56QT_BEGIN_NAMESPACE -
57 -
58/*! -
59 \class QNetworkCookie -
60 \since 4.4 -
61 \ingroup shared -
62 \inmodule QtNetwork -
63 -
64 \brief The QNetworkCookie class holds one network cookie. -
65 -
66 Cookies are small bits of information that stateless protocols -
67 like HTTP use to maintain some persistent information across -
68 requests. -
69 -
70 A cookie is set by a remote server when it replies to a request -
71 and it expects the same cookie to be sent back when further -
72 requests are sent. -
73 -
74 QNetworkCookie holds one such cookie as received from the -
75 network. A cookie has a name and a value, but those are opaque to -
76 the application (that is, the information stored in them has no -
77 meaning to the application). A cookie has an associated path name -
78 and domain, which indicate when the cookie should be sent again to -
79 the server. -
80 -
81 A cookie can also have an expiration date, indicating its -
82 validity. If the expiration date is not present, the cookie is -
83 considered a "session cookie" and should be discarded when the -
84 application exits (or when its concept of session is over). -
85 -
86 QNetworkCookie provides a way of parsing a cookie from the HTTP -
87 header format using the QNetworkCookie::parseCookies() -
88 function. However, when received in a QNetworkReply, the cookie is -
89 already parsed. -
90 -
91 This class implements cookies as described by the -
92 \l{Netscape Cookie Specification}{initial cookie specification by -
93 Netscape}, which is somewhat similar to the \l{http://www.rfc-editor.org/rfc/rfc2109.txt}{RFC 2109} specification, -
94 plus the \l{Mitigating Cross-site Scripting With HTTP-only Cookies} -
95 {"HttpOnly" extension}. The more recent \l{http://www.rfc-editor.org/rfc/rfc2965.txt}{RFC 2965} specification -
96 (which uses the Set-Cookie2 header) is not supported. -
97 -
98 \sa QNetworkCookieJar, QNetworkRequest, QNetworkReply -
99*/ -
100 -
101/*! -
102 Create a new QNetworkCookie object, initializing the cookie name -
103 to \a name and its value to \a value. -
104 -
105 A cookie is only valid if it has a name. However, the value is -
106 opaque to the application and being empty may have significance to -
107 the remote server. -
108*/ -
109QNetworkCookie::QNetworkCookie(const QByteArray &name, const QByteArray &value) -
110 : d(new QNetworkCookiePrivate) -
111{ -
112 qRegisterMetaType<QNetworkCookie>();
executed (the execution status of this line is deduced): qRegisterMetaType<QNetworkCookie>();
-
113 qRegisterMetaType<QList<QNetworkCookie> >();
executed (the execution status of this line is deduced): qRegisterMetaType<QList<QNetworkCookie> >();
-
114 -
115 d->name = name;
executed (the execution status of this line is deduced): d->name = name;
-
116 d->value = value;
executed (the execution status of this line is deduced): d->value = value;
-
117}
executed: }
Execution Count:917
917
118 -
119/*! -
120 Creates a new QNetworkCookie object by copying the contents of \a -
121 other. -
122*/ -
123QNetworkCookie::QNetworkCookie(const QNetworkCookie &other) -
124 : d(other.d) -
125{ -
126}
executed: }
Execution Count:2305
2305
127 -
128/*! -
129 Destroys this QNetworkCookie object. -
130*/ -
131QNetworkCookie::~QNetworkCookie() -
132{ -
133 // QSharedDataPointer auto deletes -
134 d = 0;
executed (the execution status of this line is deduced): d = 0;
-
135}
executed: }
Execution Count:3222
3222
136 -
137/*! -
138 Copies the contents of the QNetworkCookie object \a other to this -
139 object. -
140*/ -
141QNetworkCookie &QNetworkCookie::operator=(const QNetworkCookie &other) -
142{ -
143 d = other.d;
executed (the execution status of this line is deduced): d = other.d;
-
144 return *this;
executed: return *this;
Execution Count:16
16
145} -
146 -
147/*! -
148 \fn void QNetworkCookie::swap(QNetworkCookie &other) -
149 \since 5.0 -
150 -
151 Swaps this cookie with \a other. This function is very fast and -
152 never fails. -
153*/ -
154 -
155/*! -
156 \fn bool QNetworkCookie::operator!=(const QNetworkCookie &other) const -
157 -
158 Returns true if this cookie is not equal to \a other. -
159 -
160 \sa operator==() -
161*/ -
162 -
163/*! -
164 \since 5.0 -
165 Returns true if this cookie is equal to \a other. This function -
166 only returns true if all fields of the cookie are the same. -
167 -
168 However, in some contexts, two cookies of the same name could be -
169 considered equal. -
170 -
171 \sa operator!=(), hasSameIdentifier() -
172*/ -
173bool QNetworkCookie::operator==(const QNetworkCookie &other) const -
174{ -
175 if (d == other.d)
evaluated: d == other.d
TRUEFALSE
yes
Evaluation Count:32
yes
Evaluation Count:496
32-496
176 return true;
executed: return true;
Execution Count:32
32
177 return d->name == other.d->name &&
executed: return d->name == other.d->name && d->value == other.d->value && d->expirationDate.toUTC() == other.d->expirationDate.toUTC() && d->domain == other.d->domain && d->path == other.d->path && d->secure == other.d->secure && d->comment == other.d->comment;
Execution Count:496
496
178 d->value == other.d->value &&
executed: return d->name == other.d->name && d->value == other.d->value && d->expirationDate.toUTC() == other.d->expirationDate.toUTC() && d->domain == other.d->domain && d->path == other.d->path && d->secure == other.d->secure && d->comment == other.d->comment;
Execution Count:496
496
179 d->expirationDate.toUTC() == other.d->expirationDate.toUTC() &&
executed: return d->name == other.d->name && d->value == other.d->value && d->expirationDate.toUTC() == other.d->expirationDate.toUTC() && d->domain == other.d->domain && d->path == other.d->path && d->secure == other.d->secure && d->comment == other.d->comment;
Execution Count:496
496
180 d->domain == other.d->domain &&
executed: return d->name == other.d->name && d->value == other.d->value && d->expirationDate.toUTC() == other.d->expirationDate.toUTC() && d->domain == other.d->domain && d->path == other.d->path && d->secure == other.d->secure && d->comment == other.d->comment;
Execution Count:496
496
181 d->path == other.d->path &&
executed: return d->name == other.d->name && d->value == other.d->value && d->expirationDate.toUTC() == other.d->expirationDate.toUTC() && d->domain == other.d->domain && d->path == other.d->path && d->secure == other.d->secure && d->comment == other.d->comment;
Execution Count:496
496
182 d->secure == other.d->secure &&
executed: return d->name == other.d->name && d->value == other.d->value && d->expirationDate.toUTC() == other.d->expirationDate.toUTC() && d->domain == other.d->domain && d->path == other.d->path && d->secure == other.d->secure && d->comment == other.d->comment;
Execution Count:496
496
183 d->comment == other.d->comment;
executed: return d->name == other.d->name && d->value == other.d->value && d->expirationDate.toUTC() == other.d->expirationDate.toUTC() && d->domain == other.d->domain && d->path == other.d->path && d->secure == other.d->secure && d->comment == other.d->comment;
Execution Count:496
496
184} -
185 -
186/*! -
187 Returns true if this cookie has the same identifier tuple as \a other. -
188 The identifier tuple is composed of the name, domain and path. -
189 -
190 \sa operator==() -
191*/ -
192bool QNetworkCookie::hasSameIdentifier(const QNetworkCookie &other) const -
193{ -
194 return d->name == other.d->name && d->domain == other.d->domain && d->path == other.d->path;
executed: return d->name == other.d->name && d->domain == other.d->domain && d->path == other.d->path;
Execution Count:45
45
195} -
196 -
197/*! -
198 Returns true if the "secure" option was specified in the cookie -
199 string, false otherwise. -
200 -
201 Secure cookies may contain private information and should not be -
202 resent over unencrypted connections. -
203 -
204 \sa setSecure() -
205*/ -
206bool QNetworkCookie::isSecure() const -
207{ -
208 return d->secure;
executed: return d->secure;
Execution Count:1412
1412
209} -
210 -
211/*! -
212 Sets the secure flag of this cookie to \a enable. -
213 -
214 Secure cookies may contain private information and should not be -
215 resent over unencrypted connections. -
216 -
217 \sa isSecure() -
218*/ -
219void QNetworkCookie::setSecure(bool enable) -
220{ -
221 d->secure = enable;
executed (the execution status of this line is deduced): d->secure = enable;
-
222}
executed: }
Execution Count:44
44
223 -
224/*! -
225 \since 4.5 -
226 -
227 Returns true if the "HttpOnly" flag is enabled for this cookie. -
228 -
229 A cookie that is "HttpOnly" is only set and retrieved by the -
230 network requests and replies; i.e., the HTTP protocol. It is not -
231 accessible from scripts running on browsers. -
232 -
233 \sa isSecure() -
234*/ -
235bool QNetworkCookie::isHttpOnly() const -
236{ -
237 return d->httpOnly;
executed: return d->httpOnly;
Execution Count:1205
1205
238} -
239 -
240/*! -
241 \since 4.5 -
242 -
243 Sets this cookie's "HttpOnly" flag to \a enable. -
244*/ -
245void QNetworkCookie::setHttpOnly(bool enable) -
246{ -
247 d->httpOnly = enable;
executed (the execution status of this line is deduced): d->httpOnly = enable;
-
248}
executed: }
Execution Count:18
18
249 -
250/*! -
251 Returns true if this cookie is a session cookie. A session cookie -
252 is a cookie which has no expiration date, which means it should be -
253 discarded when the application's concept of session is over -
254 (usually, when the application exits). -
255 -
256 \sa expirationDate(), setExpirationDate() -
257*/ -
258bool QNetworkCookie::isSessionCookie() const -
259{ -
260 return !d->expirationDate.isValid();
executed: return !d->expirationDate.isValid();
Execution Count:1643
1643
261} -
262 -
263/*! -
264 Returns the expiration date for this cookie. If this cookie is a -
265 session cookie, the QDateTime returned will not be valid. If the -
266 date is in the past, this cookie has already expired and should -
267 not be sent again back to a remote server. -
268 -
269 The expiration date corresponds to the parameters of the "expires" -
270 entry in the cookie string. -
271 -
272 \sa isSessionCookie(), setExpirationDate() -
273*/ -
274QDateTime QNetworkCookie::expirationDate() const -
275{ -
276 return d->expirationDate;
executed: return d->expirationDate;
Execution Count:252
252
277} -
278 -
279/*! -
280 Sets the expiration date of this cookie to \a date. Setting an -
281 invalid expiration date to this cookie will mean it's a session -
282 cookie. -
283 -
284 \sa isSessionCookie(), expirationDate() -
285*/ -
286void QNetworkCookie::setExpirationDate(const QDateTime &date) -
287{ -
288 d->expirationDate = date;
executed (the execution status of this line is deduced): d->expirationDate = date;
-
289}
executed: }
Execution Count:506
506
290 -
291/*! -
292 Returns the domain this cookie is associated with. This -
293 corresponds to the "domain" field of the cookie string. -
294 -
295 Note that the domain here may start with a dot, which is not a -
296 valid hostname. However, it means this cookie matches all -
297 hostnames ending with that domain name. -
298 -
299 \sa setDomain() -
300*/ -
301QString QNetworkCookie::domain() const -
302{ -
303 return d->domain;
executed: return d->domain;
Execution Count:526
526
304} -
305 -
306/*! -
307 Sets the domain associated with this cookie to be \a domain. -
308 -
309 \sa domain() -
310*/ -
311void QNetworkCookie::setDomain(const QString &domain) -
312{ -
313 d->domain = domain;
executed (the execution status of this line is deduced): d->domain = domain;
-
314}
executed: }
Execution Count:154
154
315 -
316/*! -
317 Returns the path associated with this cookie. This corresponds to -
318 the "path" field of the cookie string. -
319 -
320 \sa setPath() -
321*/ -
322QString QNetworkCookie::path() const -
323{ -
324 return d->path;
executed: return d->path;
Execution Count:309
309
325} -
326 -
327/*! -
328 Sets the path associated with this cookie to be \a path. -
329 -
330 \sa path() -
331*/ -
332void QNetworkCookie::setPath(const QString &path) -
333{ -
334 d->path = path;
executed (the execution status of this line is deduced): d->path = path;
-
335}
executed: }
Execution Count:196
196
336 -
337/*! -
338 Returns the name of this cookie. The only mandatory field of a -
339 cookie is its name, without which it is not considered valid. -
340 -
341 \sa setName(), value() -
342*/ -
343QByteArray QNetworkCookie::name() const -
344{ -
345 return d->name;
executed: return d->name;
Execution Count:979
979
346} -
347 -
348/*! -
349 Sets the name of this cookie to be \a cookieName. Note that -
350 setting a cookie name to an empty QByteArray will make this cookie -
351 invalid. -
352 -
353 \sa name(), value() -
354*/ -
355void QNetworkCookie::setName(const QByteArray &cookieName) -
356{ -
357 d->name = cookieName;
executed (the execution status of this line is deduced): d->name = cookieName;
-
358}
executed: }
Execution Count:856
856
359 -
360/*! -
361 Returns this cookies value, as specified in the cookie -
362 string. Note that a cookie is still valid if its value is empty. -
363 -
364 Cookie name-value pairs are considered opaque to the application: -
365 that is, their values don't mean anything. -
366 -
367 \sa setValue(), name() -
368*/ -
369QByteArray QNetworkCookie::value() const -
370{ -
371 return d->value;
executed: return d->value;
Execution Count:307
307
372} -
373 -
374/*! -
375 Sets the value of this cookie to be \a value. -
376 -
377 \sa value(), name() -
378*/ -
379void QNetworkCookie::setValue(const QByteArray &value) -
380{ -
381 d->value = value;
executed (the execution status of this line is deduced): d->value = value;
-
382}
executed: }
Execution Count:864
864
383 -
384// ### move this to qnetworkcookie_p.h and share with qnetworkaccesshttpbackend -
385static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &position, bool isNameValue) -
386{ -
387 // format is one of: -
388 // (1) token -
389 // (2) token = token -
390 // (3) token = quoted-string -
391 const int length = text.length();
executed (the execution status of this line is deduced): const int length = text.length();
-
392 position = nextNonWhitespace(text, position);
executed (the execution status of this line is deduced): position = nextNonWhitespace(text, position);
-
393 -
394 int semiColonPosition = text.indexOf(';', position);
executed (the execution status of this line is deduced): int semiColonPosition = text.indexOf(';', position);
-
395 if (semiColonPosition < 0)
evaluated: semiColonPosition < 0
TRUEFALSE
yes
Evaluation Count:715
yes
Evaluation Count:690
690-715
396 semiColonPosition = length; //no ';' means take everything to end of string
executed: semiColonPosition = length;
Execution Count:715
715
397 -
398 int equalsPosition = text.indexOf('=', position);
executed (the execution status of this line is deduced): int equalsPosition = text.indexOf('=', position);
-
399 if (equalsPosition < 0 || equalsPosition > semiColonPosition) {
evaluated: equalsPosition < 0
TRUEFALSE
yes
Evaluation Count:124
yes
Evaluation Count:1281
evaluated: equalsPosition > semiColonPosition
TRUEFALSE
yes
Evaluation Count:20
yes
Evaluation Count:1261
20-1281
400 if (isNameValue)
evaluated: isNameValue
TRUEFALSE
yes
Evaluation Count:34
yes
Evaluation Count:110
34-110
401 return qMakePair(QByteArray(), QByteArray()); //'=' is required for name-value-pair (RFC6265 section 5.2, rule 2)
executed: return qMakePair(QByteArray(), QByteArray());
Execution Count:34
34
402 equalsPosition = semiColonPosition; //no '=' means there is an attribute-name but no attribute-value
executed (the execution status of this line is deduced): equalsPosition = semiColonPosition;
-
403 }
executed: }
Execution Count:110
110
404 -
405 QByteArray first = text.mid(position, equalsPosition - position).trimmed();
executed (the execution status of this line is deduced): QByteArray first = text.mid(position, equalsPosition - position).trimmed();
-
406 QByteArray second;
executed (the execution status of this line is deduced): QByteArray second;
-
407 int secondLength = semiColonPosition - equalsPosition - 1;
executed (the execution status of this line is deduced): int secondLength = semiColonPosition - equalsPosition - 1;
-
408 if (secondLength > 0)
evaluated: secondLength > 0
TRUEFALSE
yes
Evaluation Count:1232
yes
Evaluation Count:139
139-1232
409 second = text.mid(equalsPosition + 1, secondLength).trimmed();
executed: second = text.mid(equalsPosition + 1, secondLength).trimmed();
Execution Count:1232
1232
410 -
411 position = semiColonPosition;
executed (the execution status of this line is deduced): position = semiColonPosition;
-
412 return qMakePair(first, second);
executed: return qMakePair(first, second);
Execution Count:1371
1371
413} -
414 -
415/*! -
416 \enum QNetworkCookie::RawForm -
417 -
418 This enum is used with the toRawForm() function to declare which -
419 form of a cookie shall be returned. -
420 -
421 \value NameAndValueOnly makes toRawForm() return only the -
422 "NAME=VALUE" part of the cookie, as suitable for sending back -
423 to a server in a client request's "Cookie:" header. Multiple -
424 cookies are separated by a semi-colon in the "Cookie:" header -
425 field. -
426 -
427 \value Full makes toRawForm() return the full -
428 cookie contents, as suitable for sending to a client in a -
429 server's "Set-Cookie:" header. -
430 -
431 Note that only the Full form of the cookie can be parsed back into -
432 its original contents. -
433 -
434 \sa toRawForm(), parseCookies() -
435*/ -
436 -
437/*! -
438 Returns the raw form of this QNetworkCookie. The QByteArray -
439 returned by this function is suitable for an HTTP header, either -
440 in a server response (the Set-Cookie header) or the client request -
441 (the Cookie header). You can choose from one of two formats, using -
442 \a form. -
443 -
444 \sa parseCookies() -
445*/ -
446QByteArray QNetworkCookie::toRawForm(RawForm form) const -
447{ -
448 QByteArray result;
executed (the execution status of this line is deduced): QByteArray result;
-
449 if (d->name.isEmpty())
evaluated: d->name.isEmpty()
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:1219
2-1219
450 return result; // not a valid cookie
executed: return result;
Execution Count:2
2
451 -
452 result = d->name;
executed (the execution status of this line is deduced): result = d->name;
-
453 result += '=';
executed (the execution status of this line is deduced): result += '=';
-
454 result += d->value;
executed (the execution status of this line is deduced): result += d->value;
-
455 -
456 if (form == Full) {
evaluated: form == Full
TRUEFALSE
yes
Evaluation Count:1205
yes
Evaluation Count:14
14-1205
457 // same as above, but encoding everything back -
458 if (isSecure())
evaluated: isSecure()
TRUEFALSE
yes
Evaluation Count:64
yes
Evaluation Count:1141
64-1141
459 result += "; secure";
executed: result += "; secure";
Execution Count:64
64
460 if (isHttpOnly())
evaluated: isHttpOnly()
TRUEFALSE
yes
Evaluation Count:40
yes
Evaluation Count:1165
40-1165
461 result += "; HttpOnly";
executed: result += "; HttpOnly";
Execution Count:40
40
462 if (!isSessionCookie()) {
evaluated: !isSessionCookie()
TRUEFALSE
yes
Evaluation Count:625
yes
Evaluation Count:580
580-625
463 result += "; expires=";
executed (the execution status of this line is deduced): result += "; expires=";
-
464 result += QLocale::c().toString(d->expirationDate.toUTC(),
executed (the execution status of this line is deduced): result += QLocale::c().toString(d->expirationDate.toUTC(),
-
465 QLatin1String("ddd, dd-MMM-yyyy hh:mm:ss 'GMT")).toLatin1();
executed (the execution status of this line is deduced): QLatin1String("ddd, dd-MMM-yyyy hh:mm:ss 'GMT")).toLatin1();
-
466 }
executed: }
Execution Count:625
625
467 if (!d->domain.isEmpty()) {
evaluated: !d->domain.isEmpty()
TRUEFALSE
yes
Evaluation Count:226
yes
Evaluation Count:979
226-979
468 result += "; domain=";
executed (the execution status of this line is deduced): result += "; domain=";
-
469 QString domainNoDot = d->domain;
executed (the execution status of this line is deduced): QString domainNoDot = d->domain;
-
470 if (domainNoDot.startsWith(QLatin1Char('.'))) {
evaluated: domainNoDot.startsWith(QLatin1Char('.'))
TRUEFALSE
yes
Evaluation Count:178
yes
Evaluation Count:48
48-178
471 result += '.';
executed (the execution status of this line is deduced): result += '.';
-
472 domainNoDot = domainNoDot.mid(1);
executed (the execution status of this line is deduced): domainNoDot = domainNoDot.mid(1);
-
473 }
executed: }
Execution Count:178
178
474 result += QUrl::toAce(domainNoDot);
executed (the execution status of this line is deduced): result += QUrl::toAce(domainNoDot);
-
475 }
executed: }
Execution Count:226
226
476 if (!d->path.isEmpty()) {
evaluated: !d->path.isEmpty()
TRUEFALSE
yes
Evaluation Count:282
yes
Evaluation Count:923
282-923
477 result += "; path=";
executed (the execution status of this line is deduced): result += "; path=";
-
478 result += d->path.toUtf8();
executed (the execution status of this line is deduced): result += d->path.toUtf8();
-
479 }
executed: }
Execution Count:282
282
480 }
executed: }
Execution Count:1205
1205
481 return result;
executed: return result;
Execution Count:1219
1219
482} -
483 -
484static const char zones[] = -
485 "pst\0" // -8 -
486 "pdt\0" -
487 "mst\0" // -7 -
488 "mdt\0" -
489 "cst\0" // -6 -
490 "cdt\0" -
491 "est\0" // -5 -
492 "edt\0" -
493 "ast\0" // -4 -
494 "nst\0" // -3 -
495 "gmt\0" // 0 -
496 "utc\0" -
497 "bst\0" -
498 "met\0" // 1 -
499 "eet\0" // 2 -
500 "jst\0" // 9 -
501 "\0"; -
502static int zoneOffsets[] = {-8, -8, -7, -7, -6, -6, -5, -5, -4, -3, 0, 0, 0, 1, 2, 9 }; -
503 -
504static const char months[] = -
505 "jan\0" -
506 "feb\0" -
507 "mar\0" -
508 "apr\0" -
509 "may\0" -
510 "jun\0" -
511 "jul\0" -
512 "aug\0" -
513 "sep\0" -
514 "oct\0" -
515 "nov\0" -
516 "dec\0" -
517 "\0"; -
518 -
519static inline bool isNumber(char s) -
520{ return s >= '0' && s <= '9'; }
executed: return s >= '0' && s <= '9';
Execution Count:4711
4711
521 -
522static inline bool isTerminator(char c) -
523{ return c == '\n' || c == '\r'; }
executed: return c == '\n' || c == '\r';
Execution Count:6304
6304
524 -
525static inline bool isValueSeparator(char c) -
526{ return isTerminator(c) || c == ';'; }
executed: return isTerminator(c) || c == ';';
Execution Count:6304
6304
527 -
528static inline bool isWhitespace(char c) -
529{ return c == ' ' || c == '\t'; }
executed: return c == ' ' || c == '\t';
Execution Count:313
313
530 -
531static bool checkStaticArray(int &val, const QByteArray &dateString, int at, const char *array, int size) -
532{ -
533 if (dateString[at] < 'a' || dateString[at] > 'z')
evaluated: dateString[at] < 'a'
TRUEFALSE
yes
Evaluation Count:2625
yes
Evaluation Count:1791
partially evaluated: dateString[at] > 'z'
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1791
0-2625
534 return false;
executed: return false;
Execution Count:2625
2625
535 if (val == -1 && dateString.length() >= at + 3) {
evaluated: val == -1
TRUEFALSE
yes
Evaluation Count:1573
yes
Evaluation Count:218
evaluated: dateString.length() >= at + 3
TRUEFALSE
yes
Evaluation Count:1563
yes
Evaluation Count:10
10-1573
536 int j = 0;
executed (the execution status of this line is deduced): int j = 0;
-
537 int i = 0;
executed (the execution status of this line is deduced): int i = 0;
-
538 while (i <= size) {
evaluated: i <= size
TRUEFALSE
yes
Evaluation Count:21389
yes
Evaluation Count:1150
1150-21389
539 const char *str = array + i;
executed (the execution status of this line is deduced): const char *str = array + i;
-
540 if (str[0] == dateString[at]
evaluated: str[0] == dateString[at]
TRUEFALSE
yes
Evaluation Count:1142
yes
Evaluation Count:20247
1142-20247
541 && str[1] == dateString[at + 1]
evaluated: str[1] == dateString[at + 1]
TRUEFALSE
yes
Evaluation Count:457
yes
Evaluation Count:685
457-685
542 && str[2] == dateString[at + 2]) {
evaluated: str[2] == dateString[at + 2]
TRUEFALSE
yes
Evaluation Count:413
yes
Evaluation Count:44
44-413
543 val = j;
executed (the execution status of this line is deduced): val = j;
-
544 return true;
executed: return true;
Execution Count:413
413
545 } -
546 i += int(strlen(str)) + 1;
executed (the execution status of this line is deduced): i += int(strlen(str)) + 1;
-
547 ++j;
executed (the execution status of this line is deduced): ++j;
-
548 }
executed: }
Execution Count:20976
20976
549 }
executed: }
Execution Count:1150
1150
550 return false;
executed: return false;
Execution Count:1378
1378
551} -
552 -
553//#define PARSEDATESTRINGDEBUG -
554 -
555#define ADAY 1 -
556#define AMONTH 2 -
557#define AYEAR 4 -
558 -
559/* -
560 Parse all the date formats that Firefox can. -
561 -
562 The official format is: -
563 expires=ddd(d)?, dd-MMM-yyyy hh:mm:ss GMT -
564 -
565 But browsers have been supporting a very wide range of date -
566 strings. To work on many sites we need to support more then -
567 just the official date format. -
568 -
569 For reference see Firefox's PR_ParseTimeStringToExplodedTime in -
570 prtime.c. The Firefox date parser is coded in a very complex way -
571 and is slightly over ~700 lines long. While this implementation -
572 will be slightly slower for the non standard dates it is smaller, -
573 more readable, and maintainable. -
574 -
575 Or in their own words: -
576 "} // else what the hell is this." -
577*/ -
578static QDateTime parseDateString(const QByteArray &dateString) -
579{ -
580 QTime time;
executed (the execution status of this line is deduced): QTime time;
-
581 // placeholders for values when we are not sure it is a year, month or day -
582 int unknown[3] = {-1, -1, -1};
executed (the execution status of this line is deduced): int unknown[3] = {-1, -1, -1};
-
583 int month = -1;
executed (the execution status of this line is deduced): int month = -1;
-
584 int day = -1;
executed (the execution status of this line is deduced): int day = -1;
-
585 int year = -1;
executed (the execution status of this line is deduced): int year = -1;
-
586 int zoneOffset = -1;
executed (the execution status of this line is deduced): int zoneOffset = -1;
-
587 -
588 // hour:minute:second.ms pm -
589 QRegExp timeRx(QLatin1String("(\\d{1,2}):(\\d{1,2})(:(\\d{1,2})|)(\\.(\\d{1,3})|)((\\s{0,}(am|pm))|)"));
executed (the execution status of this line is deduced): QRegExp timeRx(QLatin1String("(\\d{1,2}):(\\d{1,2})(:(\\d{1,2})|)(\\.(\\d{1,3})|)((\\s{0,}(am|pm))|)"));
-
590 -
591 int at = 0;
executed (the execution status of this line is deduced): int at = 0;
-
592 while (at < dateString.length()) {
evaluated: at < dateString.length()
TRUEFALSE
yes
Evaluation Count:3162
yes
Evaluation Count:266
266-3162
593#ifdef PARSEDATESTRINGDEBUG -
594 qDebug() << dateString.mid(at); -
595#endif -
596 bool isNum = isNumber(dateString[at]);
executed (the execution status of this line is deduced): bool isNum = isNumber(dateString[at]);
-
597 -
598 // Month -
599 if (!isNum
evaluated: !isNum
TRUEFALSE
yes
Evaluation Count:2343
yes
Evaluation Count:819
819-2343
600 && checkStaticArray(month, dateString, at, months, sizeof(months)- 1)) {
evaluated: checkStaticArray(month, dateString, at, months, sizeof(months)- 1)
TRUEFALSE
yes
Evaluation Count:228
yes
Evaluation Count:2115
228-2115
601 ++month;
executed (the execution status of this line is deduced): ++month;
-
602#ifdef PARSEDATESTRINGDEBUG -
603 qDebug() << "Month:" << month; -
604#endif -
605 at += 3;
executed (the execution status of this line is deduced): at += 3;
-
606 continue;
executed: continue;
Execution Count:228
228
607 } -
608 // Zone -
609 if (!isNum
evaluated: !isNum
TRUEFALSE
yes
Evaluation Count:2115
yes
Evaluation Count:819
819-2115
610 && zoneOffset == -1
evaluated: zoneOffset == -1
TRUEFALSE
yes
Evaluation Count:2073
yes
Evaluation Count:42
42-2073
611 && checkStaticArray(zoneOffset, dateString, at, zones, sizeof(zones)- 1)) {
evaluated: checkStaticArray(zoneOffset, dateString, at, zones, sizeof(zones)- 1)
TRUEFALSE
yes
Evaluation Count:185
yes
Evaluation Count:1888
185-1888
612 int sign = (at >= 0 && dateString[at - 1] == '-') ? -1 : 1;
partially evaluated: at >= 0
TRUEFALSE
yes
Evaluation Count:185
no
Evaluation Count:0
evaluated: dateString[at - 1] == '-'
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:184
0-185
613 zoneOffset = sign * zoneOffsets[zoneOffset] * 60 * 60;
executed (the execution status of this line is deduced): zoneOffset = sign * zoneOffsets[zoneOffset] * 60 * 60;
-
614#ifdef PARSEDATESTRINGDEBUG -
615 qDebug() << "Zone:" << month; -
616#endif -
617 at += 3;
executed (the execution status of this line is deduced): at += 3;
-
618 continue;
executed: continue;
Execution Count:185
185
619 } -
620 // Zone offset -
621 if (!isNum
evaluated: !isNum
TRUEFALSE
yes
Evaluation Count:1930
yes
Evaluation Count:819
819-1930
622 && (zoneOffset == -1 || zoneOffset == 0) // Can only go after gmt
evaluated: zoneOffset == -1
TRUEFALSE
yes
Evaluation Count:1888
yes
Evaluation Count:42
evaluated: zoneOffset == 0
TRUEFALSE
yes
Evaluation Count:27
yes
Evaluation Count:15
15-1888
623 && (dateString[at] == '+' || dateString[at] == '-')
evaluated: dateString[at] == '+'
TRUEFALSE
yes
Evaluation Count:9
yes
Evaluation Count:1906
evaluated: dateString[at] == '-'
TRUEFALSE
yes
Evaluation Count:304
yes
Evaluation Count:1602
9-1906
624 && (at == 0
partially evaluated: at == 0
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:313
0-313
625 || isWhitespace(dateString[at - 1])
evaluated: isWhitespace(dateString[at - 1])
TRUEFALSE
yes
Evaluation Count:7
yes
Evaluation Count:306
7-306
626 || dateString[at - 1] == ','
partially evaluated: dateString[at - 1] == ','
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:306
0-306
627 || (at >= 3
evaluated: at >= 3
TRUEFALSE
yes
Evaluation Count:299
yes
Evaluation Count:7
7-299
628 && (dateString[at - 3] == 'g')
evaluated: (dateString[at - 3] == 'g')
TRUEFALSE
yes
Evaluation Count:5
yes
Evaluation Count:294
5-294
629 && (dateString[at - 2] == 'm')
partially evaluated: (dateString[at - 2] == 'm')
TRUEFALSE
yes
Evaluation Count:5
no
Evaluation Count:0
0-5
630 && (dateString[at - 1] == 't')))) {
partially evaluated: (dateString[at - 1] == 't')
TRUEFALSE
yes
Evaluation Count:5
no
Evaluation Count:0
0-5
631 -
632 int end = 1;
executed (the execution status of this line is deduced): int end = 1;
-
633 while (end < 5 && dateString.length() > at+end
evaluated: end < 5
TRUEFALSE
yes
Evaluation Count:38
yes
Evaluation Count:5
evaluated: dateString.length() > at+end
TRUEFALSE
yes
Evaluation Count:31
yes
Evaluation Count:7
5-38
634 && dateString[at + end] >= '0' && dateString[at + end] <= '9')
partially evaluated: dateString[at + end] >= '0'
TRUEFALSE
yes
Evaluation Count:31
no
Evaluation Count:0
partially evaluated: dateString[at + end] <= '9'
TRUEFALSE
yes
Evaluation Count:31
no
Evaluation Count:0
0-31
635 ++end;
executed: ++end;
Execution Count:31
31
636 int minutes = 0;
executed (the execution status of this line is deduced): int minutes = 0;
-
637 int hours = 0;
executed (the execution status of this line is deduced): int hours = 0;
-
638 switch (end - 1) { -
639 case 4: -
640 minutes = atoi(dateString.mid(at + 3, 2).constData());
executed (the execution status of this line is deduced): minutes = atoi(dateString.mid(at + 3, 2).constData());
-
641 // fall through -
642 case 2:
code before this statement executed: case 2:
Execution Count:5
5
643 hours = atoi(dateString.mid(at + 1, 2).constData());
executed (the execution status of this line is deduced): hours = atoi(dateString.mid(at + 1, 2).constData());
-
644 break;
executed: break;
Execution Count:7
7
645 case 1: -
646 hours = atoi(dateString.mid(at + 1, 1).constData());
executed (the execution status of this line is deduced): hours = atoi(dateString.mid(at + 1, 1).constData());
-
647 break;
executed: break;
Execution Count:4
4
648 default: -
649 at += end;
executed (the execution status of this line is deduced): at += end;
-
650 continue;
executed: continue;
Execution Count:1
1
651 } -
652 if (end != 1) {
partially evaluated: end != 1
TRUEFALSE
yes
Evaluation Count:11
no
Evaluation Count:0
0-11
653 int sign = dateString[at] == '-' ? -1 : 1;
evaluated: dateString[at] == '-'
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:8
3-8
654 zoneOffset = sign * ((minutes * 60) + (hours * 60 * 60));
executed (the execution status of this line is deduced): zoneOffset = sign * ((minutes * 60) + (hours * 60 * 60));
-
655#ifdef PARSEDATESTRINGDEBUG -
656 qDebug() << "Zone offset:" << zoneOffset << hours << minutes; -
657#endif -
658 at += end;
executed (the execution status of this line is deduced): at += end;
-
659 continue;
executed: continue;
Execution Count:11
11
660 } -
661 }
never executed: }
0
662 -
663 // Time -
664 if (isNum && time.isNull()
evaluated: isNum
TRUEFALSE
yes
Evaluation Count:819
yes
Evaluation Count:1918
evaluated: time.isNull()
TRUEFALSE
yes
Evaluation Count:802
yes
Evaluation Count:17
17-1918
665 && dateString.length() >= at + 3
evaluated: dateString.length() >= at + 3
TRUEFALSE
yes
Evaluation Count:801
yes
Evaluation Count:1
1-801
666 && (dateString[at + 2] == ':' || dateString[at + 1] == ':')) {
evaluated: dateString[at + 2] == ':'
TRUEFALSE
yes
Evaluation Count:183
yes
Evaluation Count:618
evaluated: dateString[at + 1] == ':'
TRUEFALSE
yes
Evaluation Count:78
yes
Evaluation Count:540
78-618
667 // While the date can be found all over the string the format -
668 // for the time is set and a nice regexp can be used. -
669 int pos = timeRx.indexIn(QLatin1String(dateString), at);
executed (the execution status of this line is deduced): int pos = timeRx.indexIn(QLatin1String(dateString), at);
-
670 if (pos != -1) {
partially evaluated: pos != -1
TRUEFALSE
yes
Evaluation Count:261
no
Evaluation Count:0
0-261
671 QStringList list = timeRx.capturedTexts();
executed (the execution status of this line is deduced): QStringList list = timeRx.capturedTexts();
-
672 int h = atoi(list.at(1).toLatin1().constData());
executed (the execution status of this line is deduced): int h = atoi(list.at(1).toLatin1().constData());
-
673 int m = atoi(list.at(2).toLatin1().constData());
executed (the execution status of this line is deduced): int m = atoi(list.at(2).toLatin1().constData());
-
674 int s = atoi(list.at(4).toLatin1().constData());
executed (the execution status of this line is deduced): int s = atoi(list.at(4).toLatin1().constData());
-
675 int ms = atoi(list.at(6).toLatin1().constData());
executed (the execution status of this line is deduced): int ms = atoi(list.at(6).toLatin1().constData());
-
676 if (h < 12 && !list.at(9).isEmpty())
evaluated: h < 12
TRUEFALSE
yes
Evaluation Count:198
yes
Evaluation Count:63
evaluated: !list.at(9).isEmpty()
TRUEFALSE
yes
Evaluation Count:8
yes
Evaluation Count:190
8-198
677 if (list.at(9) == QLatin1String("pm"))
evaluated: list.at(9) == QLatin1String("pm")
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:2
2-6
678 h += 12;
executed: h += 12;
Execution Count:6
6
679 time = QTime(h, m, s, ms);
executed (the execution status of this line is deduced): time = QTime(h, m, s, ms);
-
680#ifdef PARSEDATESTRINGDEBUG -
681 qDebug() << "Time:" << list << timeRx.matchedLength(); -
682#endif -
683 at += timeRx.matchedLength();
executed (the execution status of this line is deduced): at += timeRx.matchedLength();
-
684 continue;
executed: continue;
Execution Count:261
261
685 } -
686 }
never executed: }
0
687 -
688 // 4 digit Year -
689 if (isNum
evaluated: isNum
TRUEFALSE
yes
Evaluation Count:558
yes
Evaluation Count:1918
558-1918
690 && year == -1
evaluated: year == -1
TRUEFALSE
yes
Evaluation Count:536
yes
Evaluation Count:22
22-536
691 && dateString.length() > at + 3) {
evaluated: dateString.length() > at + 3
TRUEFALSE
yes
Evaluation Count:532
yes
Evaluation Count:4
4-532
692 if (isNumber(dateString[at + 1])
evaluated: isNumber(dateString[at + 1])
TRUEFALSE
yes
Evaluation Count:461
yes
Evaluation Count:71
71-461
693 && isNumber(dateString[at + 2])
evaluated: isNumber(dateString[at + 2])
TRUEFALSE
yes
Evaluation Count:166
yes
Evaluation Count:295
166-295
694 && isNumber(dateString[at + 3])) {
partially evaluated: isNumber(dateString[at + 3])
TRUEFALSE
yes
Evaluation Count:166
no
Evaluation Count:0
0-166
695 year = atoi(dateString.mid(at, 4).constData());
executed (the execution status of this line is deduced): year = atoi(dateString.mid(at, 4).constData());
-
696 at += 4;
executed (the execution status of this line is deduced): at += 4;
-
697#ifdef PARSEDATESTRINGDEBUG -
698 qDebug() << "Year:" << year; -
699#endif -
700 continue;
executed: continue;
Execution Count:166
166
701 } -
702 }
executed: }
Execution Count:366
366
703 -
704 // a one or two digit number -
705 // Could be month, day or year -
706 if (isNum) {
evaluated: isNum
TRUEFALSE
yes
Evaluation Count:392
yes
Evaluation Count:1918
392-1918
707 int length = 1;
executed (the execution status of this line is deduced): int length = 1;
-
708 if (dateString.length() > at + 1
evaluated: dateString.length() > at + 1
TRUEFALSE
yes
Evaluation Count:390
yes
Evaluation Count:2
2-390
709 && isNumber(dateString[at + 1]))
evaluated: isNumber(dateString[at + 1])
TRUEFALSE
yes
Evaluation Count:312
yes
Evaluation Count:78
78-312
710 ++length;
executed: ++length;
Execution Count:312
312
711 int x = atoi(dateString.mid(at, length).constData());
executed (the execution status of this line is deduced): int x = atoi(dateString.mid(at, length).constData());
-
712 if (year == -1 && (x > 31 || x == 0)) {
evaluated: year == -1
TRUEFALSE
yes
Evaluation Count:370
yes
Evaluation Count:22
evaluated: x > 31
TRUEFALSE
yes
Evaluation Count:70
yes
Evaluation Count:300
evaluated: x == 0
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:298
2-370
713 year = x;
executed (the execution status of this line is deduced): year = x;
-
714 } else {
executed: }
Execution Count:72
72
715 if (unknown[0] == -1) unknown[0] = x;
executed: unknown[0] = x;
Execution Count:262
evaluated: unknown[0] == -1
TRUEFALSE
yes
Evaluation Count:262
yes
Evaluation Count:58
58-262
716 else if (unknown[1] == -1) unknown[1] = x;
executed: unknown[1] = x;
Execution Count:40
evaluated: unknown[1] == -1
TRUEFALSE
yes
Evaluation Count:40
yes
Evaluation Count:18
18-40
717 else if (unknown[2] == -1) unknown[2] = x;
executed: unknown[2] = x;
Execution Count:18
partially evaluated: unknown[2] == -1
TRUEFALSE
yes
Evaluation Count:18
no
Evaluation Count:0
0-18
718 } -
719 at += length;
executed (the execution status of this line is deduced): at += length;
-
720#ifdef PARSEDATESTRINGDEBUG -
721 qDebug() << "Saving" << x; -
722#endif -
723 continue;
executed: continue;
Execution Count:392
392
724 } -
725 -
726 // Unknown character, typically a weekday such as 'Mon' -
727 ++at;
executed (the execution status of this line is deduced): ++at;
-
728 }
executed: }
Execution Count:1918
1918
729 -
730 // Once we are done parsing the string take the digits in unknown -
731 // and determine which is the unknown year/month/day -
732 -
733 int couldBe[3] = { 0, 0, 0 };
executed (the execution status of this line is deduced): int couldBe[3] = { 0, 0, 0 };
-
734 int unknownCount = 3;
executed (the execution status of this line is deduced): int unknownCount = 3;
-
735 for (int i = 0; i < unknownCount; ++i) {
evaluated: i < unknownCount
TRUEFALSE
yes
Evaluation Count:568
yes
Evaluation Count:266
266-568
736 if (unknown[i] == -1) {
evaluated: unknown[i] == -1
TRUEFALSE
yes
Evaluation Count:248
yes
Evaluation Count:320
248-320
737 couldBe[i] = ADAY | AYEAR | AMONTH;
executed (the execution status of this line is deduced): couldBe[i] = 1 | 4 | 2;
-
738 unknownCount = i;
executed (the execution status of this line is deduced): unknownCount = i;
-
739 continue;
executed: continue;
Execution Count:248
248
740 } -
741 -
742 if (unknown[i] >= 1)
partially evaluated: unknown[i] >= 1
TRUEFALSE
yes
Evaluation Count:320
no
Evaluation Count:0
0-320
743 couldBe[i] = ADAY;
executed: couldBe[i] = 1;
Execution Count:320
320
744 -
745 if (month == -1 && unknown[i] >= 1 && unknown[i] <= 12)
evaluated: month == -1
TRUEFALSE
yes
Evaluation Count:86
yes
Evaluation Count:234
partially evaluated: unknown[i] >= 1
TRUEFALSE
yes
Evaluation Count:86
no
Evaluation Count:0
evaluated: unknown[i] <= 12
TRUEFALSE
yes
Evaluation Count:52
yes
Evaluation Count:34
0-234
746 couldBe[i] |= AMONTH;
executed: couldBe[i] |= 2;
Execution Count:52
52
747 -
748 if (year == -1)
evaluated: year == -1
TRUEFALSE
yes
Evaluation Count:66
yes
Evaluation Count:254
66-254
749 couldBe[i] |= AYEAR;
executed: couldBe[i] |= 4;
Execution Count:66
66
750 }
executed: }
Execution Count:320
320
751 -
752 // For any possible day make sure one of the values that could be a month -
753 // can contain that day. -
754 // For any possible month make sure one of the values that can be a -
755 // day that month can have. -
756 // Example: 31 11 06 -
757 // 31 can't be a day because 11 and 6 don't have 31 days -
758 for (int i = 0; i < unknownCount; ++i) {
evaluated: i < unknownCount
TRUEFALSE
yes
Evaluation Count:320
yes
Evaluation Count:266
266-320
759 int currentValue = unknown[i];
executed (the execution status of this line is deduced): int currentValue = unknown[i];
-
760 bool findMatchingMonth = couldBe[i] & ADAY && currentValue >= 29;
partially evaluated: couldBe[i] & 1
TRUEFALSE
yes
Evaluation Count:320
no
Evaluation Count:0
evaluated: currentValue >= 29
TRUEFALSE
yes
Evaluation Count:26
yes
Evaluation Count:294
0-320
761 bool findMatchingDay = couldBe[i] & AMONTH;
executed (the execution status of this line is deduced): bool findMatchingDay = couldBe[i] & 2;
-
762 if (!findMatchingMonth || !findMatchingDay)
evaluated: !findMatchingMonth
TRUEFALSE
yes
Evaluation Count:294
yes
Evaluation Count:26
partially evaluated: !findMatchingDay
TRUEFALSE
yes
Evaluation Count:26
no
Evaluation Count:0
0-294
763 continue;
executed: continue;
Execution Count:320
320
764 for (int j = 0; j < 3; ++j) {
never evaluated: j < 3
0
765 if (j == i)
never evaluated: j == i
0
766 continue;
never executed: continue;
0
767 for (int k = 0; k < 2; ++k) {
never evaluated: k < 2
0
768 if (k == 0 && !(findMatchingMonth && (couldBe[j] & AMONTH)))
never evaluated: k == 0
never evaluated: findMatchingMonth
never evaluated: (couldBe[j] & 2)
0
769 continue;
never executed: continue;
0
770 else if (k == 1 && !(findMatchingDay && (couldBe[j] & ADAY)))
never evaluated: k == 1
never evaluated: findMatchingDay
never evaluated: (couldBe[j] & 1)
0
771 continue;
never executed: continue;
0
772 int m = currentValue;
never executed (the execution status of this line is deduced): int m = currentValue;
-
773 int d = unknown[j];
never executed (the execution status of this line is deduced): int d = unknown[j];
-
774 if (k == 0)
never evaluated: k == 0
0
775 qSwap(m, d);
never executed: qSwap(m, d);
0
776 if (m == -1) m = month;
never executed: m = month;
never evaluated: m == -1
0
777 bool found = true;
never executed (the execution status of this line is deduced): bool found = true;
-
778 switch(m) { -
779 case 2: -
780 // When we get 29 and the year ends up having only 28 -
781 // See date.isValid below -
782 // Example: 29 23 Feb -
783 if (d <= 29)
never evaluated: d <= 29
0
784 found = false;
never executed: found = false;
0
785 break;
never executed: break;
0
786 case 4: case 6: case 9: case 11: -
787 if (d <= 30)
never evaluated: d <= 30
0
788 found = false;
never executed: found = false;
0
789 break;
never executed: break;
0
790 default: -
791 if (d > 0 && d <= 31)
never evaluated: d > 0
never evaluated: d <= 31
0
792 found = false;
never executed: found = false;
0
793 }
never executed: }
0
794 if (k == 0) findMatchingMonth = found;
never executed: findMatchingMonth = found;
never evaluated: k == 0
0
795 else if (k == 1) findMatchingDay = found;
never executed: findMatchingDay = found;
never evaluated: k == 1
0
796 } -
797 }
never executed: }
0
798 if (findMatchingMonth)
never evaluated: findMatchingMonth
0
799 couldBe[i] &= ~ADAY;
never executed: couldBe[i] &= ~1;
0
800 if (findMatchingDay)
never evaluated: findMatchingDay
0
801 couldBe[i] &= ~AMONTH;
never executed: couldBe[i] &= ~2;
0
802 }
never executed: }
0
803 -
804 // First set the year/month/day that have been deduced -
805 // and reduce the set as we go along to deduce more -
806 for (int i = 0; i < unknownCount; ++i) {
evaluated: i < unknownCount
TRUEFALSE
yes
Evaluation Count:320
yes
Evaluation Count:266
266-320
807 int unset = 0;
executed (the execution status of this line is deduced): int unset = 0;
-
808 for (int j = 0; j < 3; ++j) {
partially evaluated: j < 3
TRUEFALSE
yes
Evaluation Count:550
no
Evaluation Count:0
0-550
809 if (couldBe[j] == ADAY && day == -1) {
evaluated: couldBe[j] == 1
TRUEFALSE
yes
Evaluation Count:232
yes
Evaluation Count:318
evaluated: day == -1
TRUEFALSE
yes
Evaluation Count:230
yes
Evaluation Count:2
2-318
810 day = unknown[j];
executed (the execution status of this line is deduced): day = unknown[j];
-
811 unset |= ADAY;
executed (the execution status of this line is deduced): unset |= 1;
-
812 } else if (couldBe[j] == AMONTH && month == -1) {
executed: }
Execution Count:230
partially evaluated: couldBe[j] == 2
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:320
never evaluated: month == -1
0-320
813 month = unknown[j];
never executed (the execution status of this line is deduced): month = unknown[j];
-
814 unset |= AMONTH;
never executed (the execution status of this line is deduced): unset |= 2;
-
815 } else if (couldBe[j] == AYEAR && year == -1) {
never executed: }
partially evaluated: couldBe[j] == 4
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:320
never evaluated: year == -1
0-320
816 year = unknown[j];
never executed (the execution status of this line is deduced): year = unknown[j];
-
817 unset |= AYEAR;
never executed (the execution status of this line is deduced): unset |= 4;
-
818 } else {
never executed: }
0
819 // common case -
820 break;
executed: break;
Execution Count:320
320
821 } -
822 couldBe[j] &= ~unset;
executed (the execution status of this line is deduced): couldBe[j] &= ~unset;
-
823 }
executed: }
Execution Count:230
230
824 }
executed: }
Execution Count:320
320
825 -
826 // Now fallback to a standardized order to fill in the rest with -
827 for (int i = 0; i < unknownCount; ++i) {
evaluated: i < unknownCount
TRUEFALSE
yes
Evaluation Count:320
yes
Evaluation Count:266
266-320
828 if (couldBe[i] & AMONTH && month == -1) month = unknown[i];
executed: month = unknown[i];
Execution Count:33
evaluated: couldBe[i] & 2
TRUEFALSE
yes
Evaluation Count:52
yes
Evaluation Count:268
evaluated: month == -1
TRUEFALSE
yes
Evaluation Count:33
yes
Evaluation Count:19
19-268
829 else if (couldBe[i] & ADAY && day == -1) day = unknown[i];
executed: day = unknown[i];
Execution Count:32
evaluated: couldBe[i] & 1
TRUEFALSE
yes
Evaluation Count:57
yes
Evaluation Count:230
evaluated: day == -1
TRUEFALSE
yes
Evaluation Count:32
yes
Evaluation Count:25
25-230
830 else if (couldBe[i] & AYEAR && year == -1) year = unknown[i];
executed: year = unknown[i];
Execution Count:23
evaluated: couldBe[i] & 4
TRUEFALSE
yes
Evaluation Count:23
yes
Evaluation Count:232
partially evaluated: year == -1
TRUEFALSE
yes
Evaluation Count:23
no
Evaluation Count:0
0-232
831 } -
832#ifdef PARSEDATESTRINGDEBUG -
833 qDebug() << "Final set" << year << month << day; -
834#endif -
835 -
836 if (year == -1 || month == -1 || day == -1) {
evaluated: year == -1
TRUEFALSE
yes
Evaluation Count:5
yes
Evaluation Count:261
evaluated: month == -1
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:260
partially evaluated: day == -1
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:260
0-261
837#ifdef PARSEDATESTRINGDEBUG -
838 qDebug() << "Parser failure" << year << month << day; -
839#endif -
840 return QDateTime();
executed: return QDateTime();
Execution Count:6
6
841 } -
842 -
843 // Y2k behavior -
844 int y2k = 0;
executed (the execution status of this line is deduced): int y2k = 0;
-
845 if (year < 70)
evaluated: year < 70
TRUEFALSE
yes
Evaluation Count:26
yes
Evaluation Count:234
26-234
846 y2k = 2000;
executed: y2k = 2000;
Execution Count:26
26
847 else if (year < 100)
evaluated: year < 100
TRUEFALSE
yes
Evaluation Count:68
yes
Evaluation Count:166
68-166
848 y2k = 1900;
executed: y2k = 1900;
Execution Count:68
68
849 -
850 QDate date(year + y2k, month, day);
executed (the execution status of this line is deduced): QDate date(year + y2k, month, day);
-
851 -
852 // When we were given a bad cookie that when parsed -
853 // set the day to 29 and the year to one that doesn't -
854 // have the 29th of Feb rather then adding the extra -
855 // complicated checking earlier just swap here. -
856 // Example: 29 23 Feb -
857 if (!date.isValid())
evaluated: !date.isValid()
TRUEFALSE
yes
Evaluation Count:9
yes
Evaluation Count:251
9-251
858 date = QDate(day + y2k, month, year);
executed: date = QDate(day + y2k, month, year);
Execution Count:9
9
859 -
860 QDateTime dateTime(date, time, Qt::UTC);
executed (the execution status of this line is deduced): QDateTime dateTime(date, time, Qt::UTC);
-
861 -
862 if (zoneOffset != -1) {
evaluated: zoneOffset != -1
TRUEFALSE
yes
Evaluation Count:190
yes
Evaluation Count:70
70-190
863 dateTime = dateTime.addSecs(zoneOffset);
executed (the execution status of this line is deduced): dateTime = dateTime.addSecs(zoneOffset);
-
864 }
executed: }
Execution Count:190
190
865 if (!dateTime.isValid())
partially evaluated: !dateTime.isValid()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:260
0-260
866 return QDateTime();
never executed: return QDateTime();
0
867 return dateTime;
executed: return dateTime;
Execution Count:260
260
868} -
869 -
870/*! -
871 Parses the cookie string \a cookieString as received from a server -
872 response in the "Set-Cookie:" header. If there's a parsing error, -
873 this function returns an empty list. -
874 -
875 Since the HTTP header can set more than one cookie at the same -
876 time, this function returns a QList<QNetworkCookie>, one for each -
877 cookie that is parsed. -
878 -
879 \sa toRawForm() -
880*/ -
881QList<QNetworkCookie> QNetworkCookie::parseCookies(const QByteArray &cookieString) -
882{ -
883 // cookieString can be a number of set-cookie header strings joined together -
884 // by \n, parse each line separately. -
885 QList<QNetworkCookie> cookies;
executed (the execution status of this line is deduced): QList<QNetworkCookie> cookies;
-
886 QList<QByteArray> list = cookieString.split('\n');
executed (the execution status of this line is deduced): QList<QByteArray> list = cookieString.split('\n');
-
887 for (int a = 0; a < list.size(); a++)
evaluated: a < list.size()
TRUEFALSE
yes
Evaluation Count:732
yes
Evaluation Count:724
724-732
888 cookies += QNetworkCookiePrivate::parseSetCookieHeaderLine(list.at(a));
executed: cookies += QNetworkCookiePrivate::parseSetCookieHeaderLine(list.at(a));
Execution Count:732
732
889 return cookies;
executed: return cookies;
Execution Count:724
724
890} -
891 -
892QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByteArray &cookieString) -
893{ -
894 // According to http://wp.netscape.com/newsref/std/cookie_spec.html,< -
895 // the Set-Cookie response header is of the format: -
896 // -
897 // Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure -
898 // -
899 // where only the NAME=VALUE part is mandatory -
900 // -
901 // We do not support RFC 2965 Set-Cookie2-style cookies -
902 -
903 QList<QNetworkCookie> result;
executed (the execution status of this line is deduced): QList<QNetworkCookie> result;
-
904 QDateTime now = QDateTime::currentDateTime().toUTC();
executed (the execution status of this line is deduced): QDateTime now = QDateTime::currentDateTime().toUTC();
-
905 -
906 int position = 0;
executed (the execution status of this line is deduced): int position = 0;
-
907 const int length = cookieString.length();
executed (the execution status of this line is deduced): const int length = cookieString.length();
-
908 while (position < length) {
evaluated: position < length
TRUEFALSE
yes
Evaluation Count:726
yes
Evaluation Count:678
678-726
909 QNetworkCookie cookie;
executed (the execution status of this line is deduced): QNetworkCookie cookie;
-
910 -
911 // The first part is always the "NAME=VALUE" part -
912 QPair<QByteArray,QByteArray> field = nextField(cookieString, position, true);
executed (the execution status of this line is deduced): QPair<QByteArray,QByteArray> field = nextField(cookieString, position, true);
-
913 if (field.first.isEmpty())
evaluated: field.first.isEmpty()
TRUEFALSE
yes
Evaluation Count:46
yes
Evaluation Count:680
46-680
914 // parsing error -
915 break;
executed: break;
Execution Count:46
46
916 cookie.setName(field.first);
executed (the execution status of this line is deduced): cookie.setName(field.first);
-
917 cookie.setValue(field.second);
executed (the execution status of this line is deduced): cookie.setValue(field.second);
-
918 -
919 position = nextNonWhitespace(cookieString, position);
executed (the execution status of this line is deduced): position = nextNonWhitespace(cookieString, position);
-
920 while (position < length) {
evaluated: position < length
TRUEFALSE
yes
Evaluation Count:679
yes
Evaluation Count:672
672-679
921 switch (cookieString.at(position++)) { -
922 case ';': -
923 // new field in the cookie -
924 field = nextField(cookieString, position, false);
executed (the execution status of this line is deduced): field = nextField(cookieString, position, false);
-
925 field.first = field.first.toLower(); // everything but the NAME=VALUE is case-insensitive
executed (the execution status of this line is deduced): field.first = field.first.toLower();
-
926 -
927 if (field.first == "expires") {
evaluated: field.first == "expires"
TRUEFALSE
yes
Evaluation Count:266
yes
Evaluation Count:413
266-413
928 position -= field.second.length();
executed (the execution status of this line is deduced): position -= field.second.length();
-
929 int end;
executed (the execution status of this line is deduced): int end;
-
930 for (end = position; end < length; ++end)
evaluated: end < length
TRUEFALSE
yes
Evaluation Count:6304
yes
Evaluation Count:245
245-6304
931 if (isValueSeparator(cookieString.at(end)))
evaluated: isValueSeparator(cookieString.at(end))
TRUEFALSE
yes
Evaluation Count:21
yes
Evaluation Count:6283
21-6283
932 break;
executed: break;
Execution Count:21
21
933 -
934 QByteArray dateString = cookieString.mid(position, end - position).trimmed();
executed (the execution status of this line is deduced): QByteArray dateString = cookieString.mid(position, end - position).trimmed();
-
935 position = end;
executed (the execution status of this line is deduced): position = end;
-
936 QDateTime dt = parseDateString(dateString.toLower());
executed (the execution status of this line is deduced): QDateTime dt = parseDateString(dateString.toLower());
-
937 if (dt.isValid())
evaluated: dt.isValid()
TRUEFALSE
yes
Evaluation Count:260
yes
Evaluation Count:6
6-260
938 cookie.setExpirationDate(dt);
executed: cookie.setExpirationDate(dt);
Execution Count:260
260
939 //if unparsed, ignore the attribute but not the whole cookie (RFC6265 section 5.2.1) -
940 } else if (field.first == "domain") {
executed: }
Execution Count:266
evaluated: field.first == "domain"
TRUEFALSE
yes
Evaluation Count:121
yes
Evaluation Count:292
121-292
941 QByteArray rawDomain = field.second;
executed (the execution status of this line is deduced): QByteArray rawDomain = field.second;
-
942 //empty domain should be ignored (RFC6265 section 5.2.3) -
943 if (!rawDomain.isEmpty()) {
evaluated: !rawDomain.isEmpty()
TRUEFALSE
yes
Evaluation Count:117
yes
Evaluation Count:4
4-117
944 QString maybeLeadingDot;
executed (the execution status of this line is deduced): QString maybeLeadingDot;
-
945 if (rawDomain.startsWith('.')) {
evaluated: rawDomain.startsWith('.')
TRUEFALSE
yes
Evaluation Count:66
yes
Evaluation Count:51
51-66
946 maybeLeadingDot = QLatin1Char('.');
executed (the execution status of this line is deduced): maybeLeadingDot = QLatin1Char('.');
-
947 rawDomain = rawDomain.mid(1);
executed (the execution status of this line is deduced): rawDomain = rawDomain.mid(1);
-
948 }
executed: }
Execution Count:66
66
949 -
950 //IDN domains are required by RFC6265, accepting utf8 as well doesn't break any test cases. -
951 QString normalizedDomain = QUrl::fromAce(QUrl::toAce(QString::fromUtf8(rawDomain)));
executed (the execution status of this line is deduced): QString normalizedDomain = QUrl::fromAce(QUrl::toAce(QString::fromUtf8(rawDomain)));
-
952 if (!normalizedDomain.isEmpty()) {
evaluated: !normalizedDomain.isEmpty()
TRUEFALSE
yes
Evaluation Count:109
yes
Evaluation Count:8
8-109
953 cookie.setDomain(maybeLeadingDot + normalizedDomain);
executed (the execution status of this line is deduced): cookie.setDomain(maybeLeadingDot + normalizedDomain);
-
954 } else {
executed: }
Execution Count:109
109
955 //Normalization fails for malformed domains, e.g. "..example.org", reject the cookie now -
956 //rather than accepting it but never sending it due to domain match failure, as the -
957 //strict reading of RFC6265 would indicate. -
958 return result;
executed: return result;
Execution Count:8
8
959 } -
960 } -
961 } else if (field.first == "max-age") {
executed: }
Execution Count:113
evaluated: field.first == "max-age"
TRUEFALSE
yes
Evaluation Count:21
yes
Evaluation Count:271
21-271
962 bool ok = false;
executed (the execution status of this line is deduced): bool ok = false;
-
963 int secs = field.second.toInt(&ok);
executed (the execution status of this line is deduced): int secs = field.second.toInt(&ok);
-
964 if (ok) {
evaluated: ok
TRUEFALSE
yes
Evaluation Count:19
yes
Evaluation Count:2
2-19
965 if (secs <= 0) {
evaluated: secs <= 0
TRUEFALSE
yes
Evaluation Count:8
yes
Evaluation Count:11
8-11
966 //earliest representable time (RFC6265 section 5.2.2) -
967 cookie.setExpirationDate(QDateTime::fromTime_t(0));
executed (the execution status of this line is deduced): cookie.setExpirationDate(QDateTime::fromTime_t(0));
-
968 } else {
executed: }
Execution Count:8
8
969 cookie.setExpirationDate(now.addSecs(secs));
executed (the execution status of this line is deduced): cookie.setExpirationDate(now.addSecs(secs));
-
970 }
executed: }
Execution Count:11
11
971 } -
972 //if unparsed, ignore the attribute but not the whole cookie (RFC6265 section 5.2.2) -
973 } else if (field.first == "path") {
executed: }
Execution Count:21
evaluated: field.first == "path"
TRUEFALSE
yes
Evaluation Count:144
yes
Evaluation Count:127
21-144
974 if (field.second.startsWith('/')) {
evaluated: field.second.startsWith('/')
TRUEFALSE
yes
Evaluation Count:134
yes
Evaluation Count:10
10-134
975 // ### we should treat cookie paths as an octet sequence internally -
976 // However RFC6265 says we should assume UTF-8 for presentation as a string -
977 cookie.setPath(QString::fromUtf8(field.second));
executed (the execution status of this line is deduced): cookie.setPath(QString::fromUtf8(field.second));
-
978 } else {
executed: }
Execution Count:134
134
979 // if the path doesn't start with '/' then set the default path (RFC6265 section 5.2.4) -
980 // and also IETF test case path0030 which has valid and empty path in the same cookie -
981 cookie.setPath(QString());
executed (the execution status of this line is deduced): cookie.setPath(QString());
-
982 }
executed: }
Execution Count:10
10
983 } else if (field.first == "secure") {
evaluated: field.first == "secure"
TRUEFALSE
yes
Evaluation Count:38
yes
Evaluation Count:89
38-89
984 cookie.setSecure(true);
executed (the execution status of this line is deduced): cookie.setSecure(true);
-
985 } else if (field.first == "httponly") {
executed: }
Execution Count:38
evaluated: field.first == "httponly"
TRUEFALSE
yes
Evaluation Count:16
yes
Evaluation Count:73
16-73
986 cookie.setHttpOnly(true);
executed (the execution status of this line is deduced): cookie.setHttpOnly(true);
-
987 } else {
executed: }
Execution Count:16
16
988 // ignore unknown fields in the cookie (RFC6265 section 5.2, rule 6) -
989 }
executed: }
Execution Count:73
73
990 -
991 position = nextNonWhitespace(cookieString, position);
executed (the execution status of this line is deduced): position = nextNonWhitespace(cookieString, position);
-
992 }
executed: }
Execution Count:671
671
993 }
executed: }
Execution Count:671
671
994 -
995 if (!cookie.name().isEmpty())
partially evaluated: !cookie.name().isEmpty()
TRUEFALSE
yes
Evaluation Count:672
no
Evaluation Count:0
0-672
996 result += cookie;
executed: result += cookie;
Execution Count:672
672
997 }
executed: }
Execution Count:672
672
998 -
999 return result;
executed: return result;
Execution Count:724
724
1000} -
1001 -
1002/*! -
1003 \since 5.0 -
1004 This functions normalizes the path and domain of the cookie if they were previously empty. -
1005 The \a url parameter is used to determine the correct domain and path. -
1006*/ -
1007void QNetworkCookie::normalize(const QUrl &url) -
1008{ -
1009 // don't do path checking. See http://bugreports.qt-project.org/browse/QTBUG-5815 -
1010 if (d->path.isEmpty()) {
evaluated: d->path.isEmpty()
TRUEFALSE
yes
Evaluation Count:183
yes
Evaluation Count:70
70-183
1011 QString pathAndFileName = url.path();
executed (the execution status of this line is deduced): QString pathAndFileName = url.path();
-
1012 QString defaultPath = pathAndFileName.left(pathAndFileName.lastIndexOf(QLatin1Char('/'))+1);
executed (the execution status of this line is deduced): QString defaultPath = pathAndFileName.left(pathAndFileName.lastIndexOf(QLatin1Char('/'))+1);
-
1013 if (defaultPath.isEmpty())
evaluated: defaultPath.isEmpty()
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:180
3-180
1014 defaultPath = QLatin1Char('/');
executed: defaultPath = QLatin1Char('/');
Execution Count:3
3
1015 d->path = defaultPath;
executed (the execution status of this line is deduced): d->path = defaultPath;
-
1016 }
executed: }
Execution Count:183
183
1017 -
1018 if (d->domain.isEmpty())
evaluated: d->domain.isEmpty()
TRUEFALSE
yes
Evaluation Count:191
yes
Evaluation Count:62
62-191
1019 d->domain = url.host();
executed: d->domain = url.host();
Execution Count:191
191
1020 else if (!d->domain.startsWith(QLatin1Char('.')))
evaluated: !d->domain.startsWith(QLatin1Char('.'))
TRUEFALSE
yes
Evaluation Count:27
yes
Evaluation Count:35
27-35
1021 // Ensure the domain starts with a dot if its field was not empty -
1022 // in the HTTP header. There are some servers that forget the -
1023 // leading dot and this is actually forbidden according to RFC 2109, -
1024 // but all browsers accept it anyway so we do that as well. -
1025 d->domain.prepend(QLatin1Char('.'));
executed: d->domain.prepend(QLatin1Char('.'));
Execution Count:27
27
1026} -
1027 -
1028#ifndef QT_NO_DEBUG_STREAM -
1029QDebug operator<<(QDebug s, const QNetworkCookie &cookie) -
1030{ -
1031 s.nospace() << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ')';
never executed (the execution status of this line is deduced): s.nospace() << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ')';
-
1032 return s.space();
never executed: return s.space();
0
1033} -
1034#endif -
1035 -
1036QT_END_NAMESPACE -
1037 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial