Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qnetworkcookie.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qnetworkcookie.h"
5#include "qnetworkcookie_p.h"
6
7#include "qnetworkrequest.h"
8#include "qnetworkreply.h"
9#include "QtCore/qbytearray.h"
10#include "QtCore/qdatetime.h"
11#include "QtCore/qdebug.h"
12#include "QtCore/qlist.h"
13#include "QtCore/qlocale.h"
14#include <QtCore/qregularexpression.h>
15#include "QtCore/qstring.h"
16#include "QtCore/qstringlist.h"
17#include "QtCore/qtimezone.h"
18#include "QtCore/qurl.h"
19#include "QtNetwork/qhostaddress.h"
20#include "private/qobject_p.h"
21
23
24using namespace Qt::StringLiterals;
25
27
28
81{
82 qRegisterMetaType<QNetworkCookie>();
83 qRegisterMetaType<QList<QNetworkCookie> >();
84
85 d->name = name;
86 d->value = value;
87}
88
97
102{
103 // QSharedDataPointer auto deletes
104 d = nullptr;
105}
106
112{
113 d = other.d;
114 return *this;
115}
116
144{
145 if (d == other.d)
146 return true;
147 return d->name == other.d->name &&
148 d->value == other.d->value &&
149 d->expirationDate.toUTC() == other.d->expirationDate.toUTC() &&
150 d->domain == other.d->domain &&
151 d->path == other.d->path &&
152 d->secure == other.d->secure &&
153 d->comment == other.d->comment &&
154 d->sameSite == other.d->sameSite;
155}
156
164{
165 return d->name == other.d->name && d->domain == other.d->domain && d->path == other.d->path;
166}
167
178{
179 return d->secure;
180}
181
191{
192 d->secure = enable;
193}
194
206
214{
215 d->sameSite = sameSite;
216}
217
230{
231 return d->httpOnly;
232}
233
240{
241 d->httpOnly = enable;
242}
243
253{
254 return !d->expirationDate.isValid();
255}
256
272
284
296{
297 return d->domain;
298}
299
306{
307 d->domain = domain;
308}
309
317{
318 return d->path;
319}
320
327{
328 d->path = path;
329}
330
338{
339 return d->name;
340}
341
349void QNetworkCookie::setName(const QByteArray &cookieName)
350{
351 d->name = cookieName;
352}
353
364{
365 return d->value;
366}
367
374{
375 d->value = value;
376}
377
378// ### move this to qnetworkcookie_p.h and share with qnetworkaccesshttpbackend
379static QPair<QByteArray, QByteArray> nextField(QByteArrayView text, int &position, bool isNameValue)
380{
381 // format is one of:
382 // (1) token
383 // (2) token = token
384 // (3) token = quoted-string
385 const int length = text.size();
387
388 int semiColonPosition = text.indexOf(';', position);
389 if (semiColonPosition < 0)
390 semiColonPosition = length; //no ';' means take everything to end of string
391
392 int equalsPosition = text.indexOf('=', position);
393 if (equalsPosition < 0 || equalsPosition > semiColonPosition) {
394 if (isNameValue)
395 return qMakePair(QByteArray(), QByteArray()); //'=' is required for name-value-pair (RFC6265 section 5.2, rule 2)
396 equalsPosition = semiColonPosition; //no '=' means there is an attribute-name but no attribute-value
397 }
398
399 QByteArray first = text.mid(position, equalsPosition - position).trimmed().toByteArray();
400 QByteArray second;
401 int secondLength = semiColonPosition - equalsPosition - 1;
402 if (secondLength > 0)
403 second = text.mid(equalsPosition + 1, secondLength).trimmed().toByteArray();
404
405 position = semiColonPosition;
406 return qMakePair(first, second);
407}
408
445namespace {
446
447constexpr QByteArrayView sameSiteNone() noexcept { return "None"; }
448constexpr QByteArrayView sameSiteLax() noexcept { return "Lax"; }
449constexpr QByteArrayView sameSiteStrict() noexcept { return "Strict"; }
450
451QByteArrayView sameSiteToRawString(QNetworkCookie::SameSite samesite) noexcept
452{
453 switch (samesite) {
455 return sameSiteNone();
457 return sameSiteLax();
459 return sameSiteStrict();
461 break;
462 }
463 return QByteArrayView();
464}
465
466QNetworkCookie::SameSite sameSiteFromRawString(QByteArrayView str) noexcept
467{
468 if (str.compare(sameSiteNone(), Qt::CaseInsensitive) == 0)
470 if (str.compare(sameSiteLax(), Qt::CaseInsensitive) == 0)
472 if (str.compare(sameSiteStrict(), Qt::CaseInsensitive) == 0)
475}
476} // namespace
477
488{
490 if (d->name.isEmpty())
491 return result; // not a valid cookie
492
493 result = d->name;
494 result += '=';
495 result += d->value;
496
497 if (form == Full) {
498 // same as above, but encoding everything back
499 if (isSecure())
500 result += "; secure";
501 if (isHttpOnly())
502 result += "; HttpOnly";
503 if (d->sameSite != SameSite::Default) {
504 result += "; SameSite=";
505 result += sameSiteToRawString(d->sameSite);
506 }
507 if (!isSessionCookie()) {
508 result += "; expires=";
509 result += QLocale::c().toString(d->expirationDate.toUTC(),
510 "ddd, dd-MMM-yyyy hh:mm:ss 'GMT"_L1).toLatin1();
511 }
512 if (!d->domain.isEmpty()) {
513 result += "; domain=";
514 if (d->domain.startsWith(u'.')) {
515 result += '.';
516 result += QUrl::toAce(d->domain.mid(1));
517 } else {
518 QHostAddress hostAddr(d->domain);
519 if (hostAddr.protocol() == QAbstractSocket::IPv6Protocol) {
520 result += '[';
521 result += d->domain.toUtf8();
522 result += ']';
523 } else {
525 }
526 }
527 }
528 if (!d->path.isEmpty()) {
529 result += "; path=";
530 result += d->path.toUtf8();
531 }
532 }
533 return result;
534}
535
536static const char zones[] =
537 "pst\0" // -8
538 "pdt\0"
539 "mst\0" // -7
540 "mdt\0"
541 "cst\0" // -6
542 "cdt\0"
543 "est\0" // -5
544 "edt\0"
545 "ast\0" // -4
546 "nst\0" // -3
547 "gmt\0" // 0
548 "utc\0"
549 "bst\0"
550 "met\0" // 1
551 "eet\0" // 2
552 "jst\0" // 9
553 "\0";
554static const int zoneOffsets[] = {-8, -8, -7, -7, -6, -6, -5, -5, -4, -3, 0, 0, 0, 1, 2, 9 };
555
556static const char months[] =
557 "jan\0"
558 "feb\0"
559 "mar\0"
560 "apr\0"
561 "may\0"
562 "jun\0"
563 "jul\0"
564 "aug\0"
565 "sep\0"
566 "oct\0"
567 "nov\0"
568 "dec\0"
569 "\0";
570
571static inline bool isNumber(char s)
572{ return s >= '0' && s <= '9'; }
573
574static inline bool isTerminator(char c)
575{ return c == '\n' || c == '\r'; }
576
577static inline bool isValueSeparator(char c)
578{ return isTerminator(c) || c == ';'; }
579
580static inline bool isWhitespace(char c)
581{ return c == ' ' || c == '\t'; }
582
583static bool checkStaticArray(int &val, QByteArrayView dateString, int at, const char *array, int size)
584{
585 if (dateString[at] < 'a' || dateString[at] > 'z')
586 return false;
587 if (val == -1 && dateString.size() >= at + 3) {
588 int j = 0;
589 int i = 0;
590 while (i <= size) {
591 const char *str = array + i;
592 if (str[0] == dateString[at]
593 && str[1] == dateString[at + 1]
594 && str[2] == dateString[at + 2]) {
595 val = j;
596 return true;
597 }
598 i += int(strlen(str)) + 1;
599 ++j;
600 }
601 }
602 return false;
603}
604
605//#define PARSEDATESTRINGDEBUG
606
607#define ADAY 1
608#define AMONTH 2
609#define AYEAR 4
610
611/*
612 Parse all the date formats that Firefox can.
613
614 The official format is:
615 expires=ddd(d)?, dd-MMM-yyyy hh:mm:ss GMT
616
617 But browsers have been supporting a very wide range of date
618 strings. To work on many sites we need to support more then
619 just the official date format.
620
621 For reference see Firefox's PR_ParseTimeStringToExplodedTime in
622 prtime.c. The Firefox date parser is coded in a very complex way
623 and is slightly over ~700 lines long. While this implementation
624 will be slightly slower for the non standard dates it is smaller,
625 more readable, and maintainable.
626
627 Or in their own words:
628 "} // else what the hell is this."
629*/
631{
632 QTime time;
633 // placeholders for values when we are not sure it is a year, month or day
634 int unknown[3] = {-1, -1, -1};
635 int month = -1;
636 int day = -1;
637 int year = -1;
638 int zoneOffset = -1;
639
640 // hour:minute:second.ms pm
641 static const QRegularExpression timeRx(
642 u"(\\d\\d?):(\\d\\d?)(?::(\\d\\d?)(?:\\.(\\d{1,3}))?)?(?:\\s*(am|pm))?"_s);
643
644 int at = 0;
645 while (at < dateString.size()) {
646#ifdef PARSEDATESTRINGDEBUG
647 qDebug() << dateString.mid(at);
648#endif
649 bool isNum = isNumber(dateString[at]);
650
651 // Month
652 if (!isNum
653 && checkStaticArray(month, dateString, at, months, sizeof(months)- 1)) {
654 ++month;
655#ifdef PARSEDATESTRINGDEBUG
656 qDebug() << "Month:" << month;
657#endif
658 at += 3;
659 continue;
660 }
661 // Zone
662 if (!isNum
663 && zoneOffset == -1
664 && checkStaticArray(zoneOffset, dateString, at, zones, sizeof(zones)- 1)) {
665 int sign = (at >= 0 && dateString[at - 1] == '-') ? -1 : 1;
666 zoneOffset = sign * zoneOffsets[zoneOffset] * 60 * 60;
667#ifdef PARSEDATESTRINGDEBUG
668 qDebug() << "Zone:" << month;
669#endif
670 at += 3;
671 continue;
672 }
673 // Zone offset
674 if (!isNum
675 && (zoneOffset == -1 || zoneOffset == 0) // Can only go after gmt
676 && (dateString[at] == '+' || dateString[at] == '-')
677 && (at == 0
678 || isWhitespace(dateString[at - 1])
679 || dateString[at - 1] == ','
680 || (at >= 3
681 && (dateString[at - 3] == 'g')
682 && (dateString[at - 2] == 'm')
683 && (dateString[at - 1] == 't')))) {
684
685 int end = 1;
686 while (end < 5 && dateString.size() > at+end
687 && dateString[at + end] >= '0' && dateString[at + end] <= '9')
688 ++end;
689 int minutes = 0;
690 int hours = 0;
691 switch (end - 1) {
692 case 4:
693 minutes = dateString.mid(at + 3, 2).toInt();
695 case 2:
696 hours = dateString.mid(at + 1, 2).toInt();
697 break;
698 case 1:
699 hours = dateString.mid(at + 1, 1).toInt();
700 break;
701 default:
702 at += end;
703 continue;
704 }
705 if (end != 1) {
706 int sign = dateString[at] == '-' ? -1 : 1;
707 zoneOffset = sign * ((minutes * 60) + (hours * 60 * 60));
708#ifdef PARSEDATESTRINGDEBUG
709 qDebug() << "Zone offset:" << zoneOffset << hours << minutes;
710#endif
711 at += end;
712 continue;
713 }
714 }
715
716 // Time
717 if (isNum && time.isNull()
718 && dateString.size() >= at + 3
719 && (dateString[at + 2] == ':' || dateString[at + 1] == ':')) {
720 // While the date can be found all over the string the format
721 // for the time is set and a nice regexp can be used.
722 // This string needs to stay for as long as the QRegularExpressionMatch is used,
723 // or else we get use-after-free issues:
724 QString dateToString = QString::fromLatin1(dateString);
725 if (auto match = timeRx.match(dateToString, at); match.hasMatch()) {
726 int h = match.capturedView(1).toInt();
727 int m = match.capturedView(2).toInt();
728 int s = match.capturedView(3).toInt();
729 int ms = match.capturedView(4).toInt();
730 QStringView ampm = match.capturedView(5);
731 if (h < 12 && !ampm.isEmpty())
732 if (ampm == "pm"_L1)
733 h += 12;
734 time = QTime(h, m, s, ms);
735#ifdef PARSEDATESTRINGDEBUG
736 qDebug() << "Time:" << match.capturedTexts() << match.capturedLength();
737#endif
738 at += match.capturedLength();
739 continue;
740 }
741 }
742
743 // 4 digit Year
744 if (isNum
745 && year == -1
746 && dateString.size() > at + 3) {
747 if (isNumber(dateString[at + 1])
748 && isNumber(dateString[at + 2])
749 && isNumber(dateString[at + 3])) {
750 year = dateString.mid(at, 4).toInt();
751 at += 4;
752#ifdef PARSEDATESTRINGDEBUG
753 qDebug() << "Year:" << year;
754#endif
755 continue;
756 }
757 }
758
759 // a one or two digit number
760 // Could be month, day or year
761 if (isNum) {
762 int length = 1;
763 if (dateString.size() > at + 1
764 && isNumber(dateString[at + 1]))
765 ++length;
766 int x = dateString.mid(at, length).toInt();
767 if (year == -1 && (x > 31 || x == 0)) {
768 year = x;
769 } else {
770 if (unknown[0] == -1) unknown[0] = x;
771 else if (unknown[1] == -1) unknown[1] = x;
772 else if (unknown[2] == -1) unknown[2] = x;
773 }
774 at += length;
775#ifdef PARSEDATESTRINGDEBUG
776 qDebug() << "Saving" << x;
777#endif
778 continue;
779 }
780
781 // Unknown character, typically a weekday such as 'Mon'
782 ++at;
783 }
784
785 // Once we are done parsing the string take the digits in unknown
786 // and determine which is the unknown year/month/day
787
788 int couldBe[3] = { 0, 0, 0 };
789 int unknownCount = 3;
790 for (int i = 0; i < unknownCount; ++i) {
791 if (unknown[i] == -1) {
792 couldBe[i] = ADAY | AYEAR | AMONTH;
793 unknownCount = i;
794 continue;
795 }
796
797 if (unknown[i] >= 1)
798 couldBe[i] = ADAY;
799
800 if (month == -1 && unknown[i] >= 1 && unknown[i] <= 12)
801 couldBe[i] |= AMONTH;
802
803 if (year == -1)
804 couldBe[i] |= AYEAR;
805 }
806
807 // For any possible day make sure one of the values that could be a month
808 // can contain that day.
809 // For any possible month make sure one of the values that can be a
810 // day that month can have.
811 // Example: 31 11 06
812 // 31 can't be a day because 11 and 6 don't have 31 days
813 for (int i = 0; i < unknownCount; ++i) {
814 int currentValue = unknown[i];
815 bool findMatchingMonth = couldBe[i] & ADAY && currentValue >= 29;
816 bool findMatchingDay = couldBe[i] & AMONTH;
817 if (!findMatchingMonth || !findMatchingDay)
818 continue;
819 for (int j = 0; j < 3; ++j) {
820 if (j == i)
821 continue;
822 for (int k = 0; k < 2; ++k) {
823 if (k == 0 && !(findMatchingMonth && (couldBe[j] & AMONTH)))
824 continue;
825 else if (k == 1 && !(findMatchingDay && (couldBe[j] & ADAY)))
826 continue;
827 int m = currentValue;
828 int d = unknown[j];
829 if (k == 0)
830 qSwap(m, d);
831 if (m == -1) m = month;
832 bool found = true;
833 switch(m) {
834 case 2:
835 // When we get 29 and the year ends up having only 28
836 // See date.isValid below
837 // Example: 29 23 Feb
838 if (d <= 29)
839 found = false;
840 break;
841 case 4: case 6: case 9: case 11:
842 if (d <= 30)
843 found = false;
844 break;
845 default:
846 if (d > 0 && d <= 31)
847 found = false;
848 }
849 if (k == 0) findMatchingMonth = found;
850 else if (k == 1) findMatchingDay = found;
851 }
852 }
853 if (findMatchingMonth)
854 couldBe[i] &= ~ADAY;
855 if (findMatchingDay)
856 couldBe[i] &= ~AMONTH;
857 }
858
859 // First set the year/month/day that have been deduced
860 // and reduce the set as we go along to deduce more
861 for (int i = 0; i < unknownCount; ++i) {
862 int unset = 0;
863 for (int j = 0; j < 3; ++j) {
864 if (couldBe[j] == ADAY && day == -1) {
865 day = unknown[j];
866 unset |= ADAY;
867 } else if (couldBe[j] == AMONTH && month == -1) {
868 month = unknown[j];
869 unset |= AMONTH;
870 } else if (couldBe[j] == AYEAR && year == -1) {
871 year = unknown[j];
872 unset |= AYEAR;
873 } else {
874 // common case
875 break;
876 }
877 couldBe[j] &= ~unset;
878 }
879 }
880
881 // Now fallback to a standardized order to fill in the rest with
882 for (int i = 0; i < unknownCount; ++i) {
883 if (couldBe[i] & AMONTH && month == -1) month = unknown[i];
884 else if (couldBe[i] & ADAY && day == -1) day = unknown[i];
885 else if (couldBe[i] & AYEAR && year == -1) year = unknown[i];
886 }
887#ifdef PARSEDATESTRINGDEBUG
888 qDebug() << "Final set" << year << month << day;
889#endif
890
891 if (year == -1 || month == -1 || day == -1) {
892#ifdef PARSEDATESTRINGDEBUG
893 qDebug() << "Parser failure" << year << month << day;
894#endif
895 return QDateTime();
896 }
897
898 // Y2k behavior
899 int y2k = 0;
900 if (year < 70)
901 y2k = 2000;
902 else if (year < 100)
903 y2k = 1900;
904
905 QDate date(year + y2k, month, day);
906
907 // When we were given a bad cookie that when parsed
908 // set the day to 29 and the year to one that doesn't
909 // have the 29th of Feb rather then adding the extra
910 // complicated checking earlier just swap here.
911 // Example: 29 23 Feb
912 if (!date.isValid())
913 date = QDate(day + y2k, month, year);
914
916
917 if (zoneOffset != -1)
918 dateTime = dateTime.addSecs(zoneOffset);
919
920 if (!dateTime.isValid())
921 return QDateTime();
922 return dateTime;
923}
924
937QList<QNetworkCookie> QNetworkCookie::parseCookies(QByteArrayView cookieString)
938{
939 // cookieString can be a number of set-cookie header strings joined together
940 // by \n, parse each line separately.
941 QList<QNetworkCookie> cookies;
942 for (auto s : QLatin1StringView(cookieString).tokenize('\n'_L1))
944 return cookies;
945}
946
948{
949 // According to http://wp.netscape.com/newsref/std/cookie_spec.html,<
950 // the Set-Cookie response header is of the format:
951 //
952 // Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
953 //
954 // where only the NAME=VALUE part is mandatory
955 //
956 // We do not support RFC 2965 Set-Cookie2-style cookies
957
958 QList<QNetworkCookie> result;
960
961 int position = 0;
962 const int length = cookieString.size();
963 while (position < length) {
964 QNetworkCookie cookie;
965
966 // The first part is always the "NAME=VALUE" part
967 QPair<QByteArray,QByteArray> field = nextField(cookieString, position, true);
968 if (field.first.isEmpty())
969 // parsing error
970 break;
971 cookie.setName(field.first);
972 cookie.setValue(field.second);
973
974 position = nextNonWhitespace(cookieString, position);
975 while (position < length) {
976 switch (cookieString.at(position++)) {
977 case ';':
978 // new field in the cookie
979 field = nextField(cookieString, position, false);
980
981 if (field.first.compare("expires", Qt::CaseInsensitive) == 0) {
982 position -= field.second.size();
983 int end;
984 for (end = position; end < length; ++end)
985 if (isValueSeparator(cookieString.at(end)))
986 break;
987
988 QByteArray dateString = cookieString.mid(position, end - position).trimmed().toByteArray().toLower();
989 position = end;
990 QDateTime dt = parseDateString(dateString);
991 if (dt.isValid())
992 cookie.setExpirationDate(dt);
993 //if unparsed, ignore the attribute but not the whole cookie (RFC6265 section 5.2.1)
994 } else if (field.first.compare("domain", Qt::CaseInsensitive) == 0) {
995 QByteArrayView rawDomain = field.second;
996 //empty domain should be ignored (RFC6265 section 5.2.3)
997 if (!rawDomain.isEmpty()) {
998 QLatin1StringView maybeLeadingDot;
999 if (rawDomain.startsWith('.')) {
1000 maybeLeadingDot = "."_L1;
1001 rawDomain = rawDomain.mid(1);
1002 }
1003
1004 //IDN domains are required by RFC6265, accepting utf8 as well doesn't break any test cases.
1005 QString normalizedDomain = QUrl::fromAce(QUrl::toAce(QString::fromUtf8(rawDomain)));
1006 if (!normalizedDomain.isEmpty()) {
1007 cookie.setDomain(maybeLeadingDot + normalizedDomain);
1008 } else {
1009 //Normalization fails for malformed domains, e.g. "..example.org", reject the cookie now
1010 //rather than accepting it but never sending it due to domain match failure, as the
1011 //strict reading of RFC6265 would indicate.
1012 return result;
1013 }
1014 }
1015 } else if (field.first.compare("max-age", Qt::CaseInsensitive) == 0) {
1016 bool ok = false;
1017 int secs = field.second.toInt(&ok);
1018 if (ok) {
1019 if (secs <= 0) {
1020 //earliest representable time (RFC6265 section 5.2.2)
1022 } else {
1023 cookie.setExpirationDate(now.addSecs(secs));
1024 }
1025 }
1026 //if unparsed, ignore the attribute but not the whole cookie (RFC6265 section 5.2.2)
1027 } else if (field.first.compare("path", Qt::CaseInsensitive) == 0) {
1028 if (field.second.startsWith('/')) {
1029 // ### we should treat cookie paths as an octet sequence internally
1030 // However RFC6265 says we should assume UTF-8 for presentation as a string
1031 cookie.setPath(QString::fromUtf8(field.second));
1032 } else {
1033 // if the path doesn't start with '/' then set the default path (RFC6265 section 5.2.4)
1034 // and also IETF test case path0030 which has valid and empty path in the same cookie
1035 cookie.setPath(QString());
1036 }
1037 } else if (field.first.compare("secure", Qt::CaseInsensitive) == 0) {
1038 cookie.setSecure(true);
1039 } else if (field.first.compare("httponly", Qt::CaseInsensitive) == 0) {
1040 cookie.setHttpOnly(true);
1041 } else if (field.first.compare("samesite", Qt::CaseInsensitive) == 0) {
1042 cookie.setSameSitePolicy(sameSiteFromRawString(field.second));
1043 } else {
1044 // ignore unknown fields in the cookie (RFC6265 section 5.2, rule 6)
1045 }
1046
1047 position = nextNonWhitespace(cookieString, position);
1048 }
1049 }
1050
1051 if (!cookie.name().isEmpty())
1052 result += cookie;
1053 }
1054
1055 return result;
1056}
1057
1064{
1065 // don't do path checking. See QTBUG-5815
1066 if (d->path.isEmpty()) {
1067 QString pathAndFileName = url.path();
1068 QString defaultPath = pathAndFileName.left(pathAndFileName.lastIndexOf(u'/') + 1);
1069 if (defaultPath.isEmpty())
1070 defaultPath = u'/';
1071 d->path = defaultPath;
1072 }
1073
1074 if (d->domain.isEmpty()) {
1075 d->domain = url.host();
1076 } else {
1077 QHostAddress hostAddress(d->domain);
1078 if (hostAddress.protocol() != QAbstractSocket::IPv4Protocol
1079 && hostAddress.protocol() != QAbstractSocket::IPv6Protocol
1080 && !d->domain.startsWith(u'.')) {
1081 // Ensure the domain starts with a dot if its field was not empty
1082 // in the HTTP header. There are some servers that forget the
1083 // leading dot and this is actually forbidden according to RFC 2109,
1084 // but all browsers accept it anyway so we do that as well.
1085 d->domain.prepend(u'.');
1086 }
1087 }
1088}
1089
1090#ifndef QT_NO_DEBUG_STREAM
1092{
1093 QDebugStateSaver saver(s);
1094 s.resetFormat().nospace();
1095 s << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ')';
1096 return s;
1097}
1098#endif
1099
1101
1102#include "moc_qnetworkcookie.cpp"
static constexpr auto IPv4Protocol
static constexpr auto IPv6Protocol
\inmodule QtCore
Definition qbytearray.h:57
QByteArray trimmed() const &
Definition qbytearray.h:262
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
QByteArray toLower() const &
Definition qbytearray.h:254
QByteArray mid(qsizetype index, qsizetype len=-1) const &
\inmodule QtCore\reentrant
Definition qdatetime.h:283
static QDateTime fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone)
QDateTime toUTC() const
Returns a copy of this datetime converted to UTC.
QDateTime addSecs(qint64 secs) const
Returns a QDateTime object containing a datetime s seconds later than the datetime of this object (or...
bool isValid() const
Returns true if this datetime represents a definite moment, otherwise false.
static QDateTime currentDateTimeUtc()
\inmodule QtCore \reentrant
Definition qdatetime.h:29
constexpr bool isValid() const
Returns true if this date is valid; otherwise returns false.
Definition qdatetime.h:71
\inmodule QtCore
\inmodule QtCore
The QHostAddress class provides an IP address.
constexpr auto tokenize(Needle &&needle, Flags...flags) const noexcept(noexcept(qTokenize(std::declval< const QLatin1StringView & >(), std::forward< Needle >(needle), flags...))) -> decltype(qTokenize(*this, std::forward< Needle >(needle), flags...))
constexpr QLatin1StringView mid(qsizetype pos, qsizetype n=-1) const
static QLocale c()
Returns a QLocale object initialized to the "C" locale.
Definition qlocale.h:1146
static QList< QNetworkCookie > parseSetCookieHeaderLine(QByteArrayView cookieString)
QNetworkCookie::SameSite sameSite
The QNetworkCookie class holds one network cookie.
bool isSessionCookie() const
Returns true if this cookie is a session cookie.
SameSite sameSitePolicy() const
Returns the "SameSite" option if specified in the cookie string, SameSite::Default if not present.
bool hasSameIdentifier(const QNetworkCookie &other) const
Returns true if this cookie has the same identifier tuple as other.
QString domain() const
Returns the domain this cookie is associated with.
QByteArray name() const
Returns the name of this cookie.
static QList< QNetworkCookie > parseCookies(QByteArrayView cookieString)
Parses the cookie string cookieString as received from a server response in the "Set-Cookie:" header.
QByteArray value() const
Returns this cookies value, as specified in the cookie string.
void setPath(const QString &path)
Sets the path associated with this cookie to be path.
bool isSecure() const
Returns true if the "secure" option was specified in the cookie string, false otherwise.
void normalize(const QUrl &url)
QDateTime expirationDate() const
Returns the expiration date for this cookie.
void setSecure(bool enable)
Sets the secure flag of this cookie to enable.
bool operator==(const QNetworkCookie &other) const
QByteArray toRawForm(RawForm form=Full) const
Returns the raw form of this QNetworkCookie.
void setDomain(const QString &domain)
Sets the domain associated with this cookie to be domain.
void setValue(const QByteArray &value)
Sets the value of this cookie to be value.
void setSameSitePolicy(SameSite sameSite)
Sets the "SameSite" option of this cookie to sameSite.
void setHttpOnly(bool enable)
QString path() const
Returns the path associated with this cookie.
RawForm
This enum is used with the toRawForm() function to declare which form of a cookie shall be returned.
bool isHttpOnly() const
QNetworkCookie & operator=(QNetworkCookie &&other) noexcept
void setName(const QByteArray &cookieName)
Sets the name of this cookie to be cookieName.
void setExpirationDate(const QDateTime &date)
Sets the expiration date of this cookie to date.
~QNetworkCookie()
Destroys this QNetworkCookie object.
QNetworkCookie(const QByteArray &name=QByteArray(), const QByteArray &value=QByteArray())
Create a new QNetworkCookie object, initializing the cookie name to name and its value to value.
\inmodule QtCore \reentrant
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString left(qsizetype n) const &
Definition qstring.h:363
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
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:5455
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6664
QString trimmed() const &
Definition qstring.h:447
QByteArray toUtf8() const &
Definition qstring.h:634
QString & prepend(QChar c)
Definition qstring.h:478
\inmodule QtCore \reentrant
Definition qdatetime.h:215
constexpr bool isNull() const
Returns true if the time is null (i.e., the QTime object was constructed using the default constructo...
Definition qdatetime.h:223
\inmodule QtCore
Definition qurl.h:94
static QByteArray toAce(const QString &domain, AceProcessingOptions options={})
Definition qurl.cpp:3064
QString host(ComponentFormattingOptions=FullyDecoded) const
Returns the host of the URL if it is defined; otherwise an empty string is returned.
Definition qurl.cpp:2340
static QString fromAce(const QByteArray &domain, AceProcessingOptions options={})
Definition qurl.cpp:3041
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2468
QString str
[2]
QString text
QDate date
[1]
Combined button and popup list for selecting options.
@ CaseInsensitive
#define Q_FALLTHROUGH()
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qDebug
[1]
Definition qlogging.h:164
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1390
static QPair< QByteArray, QByteArray > nextField(QByteArrayView text, int &position, bool isNameValue)
#define ADAY
static const char months[]
QDebug operator<<(QDebug s, const QNetworkCookie &cookie)
static bool checkStaticArray(int &val, QByteArrayView dateString, int at, const char *array, int size)
#define AMONTH
static bool isValueSeparator(char c)
static bool isWhitespace(char c)
static QDateTime parseDateString(QByteArrayView dateString)
#define AYEAR
static const int zoneOffsets[]
static bool isNumber(char s)
static bool isTerminator(char c)
static const char zones[]
static int nextNonWhitespace(QByteArrayView text, int from)
GLint GLint GLint GLint GLint x
[0]
const GLfloat * m
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLenum GLuint GLenum GLsizei length
GLboolean enable
GLuint name
GLint first
GLfloat GLfloat GLfloat GLfloat h
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLuint GLfloat * val
GLenum array
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static const struct ImageFormatTab unknown[]
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
static int sign(int x)
QUrl url("example.com")
[constructor-url-reference]
QDateTime dateTime
[12]
QSharedPointer< T > other(t)
[5]
QAction * at