Qt 6.x
The Qt SDK
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
94 : d(other.d)
95{
96}
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
203{
204 return d->sameSite;
205}
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
269{
270 return d->expirationDate;
271}
272
281{
282 d->expirationDate = date;
283}
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(const QByteArray &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();
400 QByteArray second;
401 int secondLength = semiColonPosition - equalsPosition - 1;
402 if (secondLength > 0)
403 second = text.mid(equalsPosition + 1, secondLength).trimmed();
404
405 position = semiColonPosition;
406 return qMakePair(first, second);
407}
408
445namespace {
446QByteArray sameSiteToRawString(QNetworkCookie::SameSite samesite)
447{
448 switch (samesite) {
450 return QByteArrayLiteral("None");
452 return QByteArrayLiteral("Lax");
454 return QByteArrayLiteral("Strict");
456 break;
457 }
458 return QByteArray();
459}
460
461QNetworkCookie::SameSite sameSiteFromRawString(QByteArray str)
462{
463 str = str.toLower();
464 if (str == QByteArrayLiteral("none"))
466 if (str == QByteArrayLiteral("lax"))
468 if (str == QByteArrayLiteral("strict"))
471}
472} // namespace
473
484{
486 if (d->name.isEmpty())
487 return result; // not a valid cookie
488
489 result = d->name;
490 result += '=';
491 result += d->value;
492
493 if (form == Full) {
494 // same as above, but encoding everything back
495 if (isSecure())
496 result += "; secure";
497 if (isHttpOnly())
498 result += "; HttpOnly";
499 if (d->sameSite != SameSite::Default) {
500 result += "; SameSite=";
501 result += sameSiteToRawString(d->sameSite);
502 }
503 if (!isSessionCookie()) {
504 result += "; expires=";
506 "ddd, dd-MMM-yyyy hh:mm:ss 'GMT"_L1).toLatin1();
507 }
508 if (!d->domain.isEmpty()) {
509 result += "; domain=";
510 if (d->domain.startsWith(u'.')) {
511 result += '.';
512 result += QUrl::toAce(d->domain.mid(1));
513 } else {
514 QHostAddress hostAddr(d->domain);
515 if (hostAddr.protocol() == QAbstractSocket::IPv6Protocol) {
516 result += '[';
517 result += d->domain.toUtf8();
518 result += ']';
519 } else {
521 }
522 }
523 }
524 if (!d->path.isEmpty()) {
525 result += "; path=";
526 result += d->path.toUtf8();
527 }
528 }
529 return result;
530}
531
532static const char zones[] =
533 "pst\0" // -8
534 "pdt\0"
535 "mst\0" // -7
536 "mdt\0"
537 "cst\0" // -6
538 "cdt\0"
539 "est\0" // -5
540 "edt\0"
541 "ast\0" // -4
542 "nst\0" // -3
543 "gmt\0" // 0
544 "utc\0"
545 "bst\0"
546 "met\0" // 1
547 "eet\0" // 2
548 "jst\0" // 9
549 "\0";
550static const int zoneOffsets[] = {-8, -8, -7, -7, -6, -6, -5, -5, -4, -3, 0, 0, 0, 1, 2, 9 };
551
552static const char months[] =
553 "jan\0"
554 "feb\0"
555 "mar\0"
556 "apr\0"
557 "may\0"
558 "jun\0"
559 "jul\0"
560 "aug\0"
561 "sep\0"
562 "oct\0"
563 "nov\0"
564 "dec\0"
565 "\0";
566
567static inline bool isNumber(char s)
568{ return s >= '0' && s <= '9'; }
569
570static inline bool isTerminator(char c)
571{ return c == '\n' || c == '\r'; }
572
573static inline bool isValueSeparator(char c)
574{ return isTerminator(c) || c == ';'; }
575
576static inline bool isWhitespace(char c)
577{ return c == ' ' || c == '\t'; }
578
579static bool checkStaticArray(int &val, const QByteArray &dateString, int at, const char *array, int size)
580{
581 if (dateString[at] < 'a' || dateString[at] > 'z')
582 return false;
583 if (val == -1 && dateString.size() >= at + 3) {
584 int j = 0;
585 int i = 0;
586 while (i <= size) {
587 const char *str = array + i;
588 if (str[0] == dateString[at]
589 && str[1] == dateString[at + 1]
590 && str[2] == dateString[at + 2]) {
591 val = j;
592 return true;
593 }
594 i += int(strlen(str)) + 1;
595 ++j;
596 }
597 }
598 return false;
599}
600
601//#define PARSEDATESTRINGDEBUG
602
603#define ADAY 1
604#define AMONTH 2
605#define AYEAR 4
606
607/*
608 Parse all the date formats that Firefox can.
609
610 The official format is:
611 expires=ddd(d)?, dd-MMM-yyyy hh:mm:ss GMT
612
613 But browsers have been supporting a very wide range of date
614 strings. To work on many sites we need to support more then
615 just the official date format.
616
617 For reference see Firefox's PR_ParseTimeStringToExplodedTime in
618 prtime.c. The Firefox date parser is coded in a very complex way
619 and is slightly over ~700 lines long. While this implementation
620 will be slightly slower for the non standard dates it is smaller,
621 more readable, and maintainable.
622
623 Or in their own words:
624 "} // else what the hell is this."
625*/
626static QDateTime parseDateString(const QByteArray &dateString)
627{
628 QTime time;
629 // placeholders for values when we are not sure it is a year, month or day
630 int unknown[3] = {-1, -1, -1};
631 int month = -1;
632 int day = -1;
633 int year = -1;
634 int zoneOffset = -1;
635
636 // hour:minute:second.ms pm
637 static const QRegularExpression timeRx(
638 u"(\\d\\d?):(\\d\\d?)(?::(\\d\\d?)(?:\\.(\\d{1,3}))?)?(?:\\s*(am|pm))?"_s);
639
640 int at = 0;
641 while (at < dateString.size()) {
642#ifdef PARSEDATESTRINGDEBUG
643 qDebug() << dateString.mid(at);
644#endif
645 bool isNum = isNumber(dateString[at]);
646
647 // Month
648 if (!isNum
649 && checkStaticArray(month, dateString, at, months, sizeof(months)- 1)) {
650 ++month;
651#ifdef PARSEDATESTRINGDEBUG
652 qDebug() << "Month:" << month;
653#endif
654 at += 3;
655 continue;
656 }
657 // Zone
658 if (!isNum
659 && zoneOffset == -1
660 && checkStaticArray(zoneOffset, dateString, at, zones, sizeof(zones)- 1)) {
661 int sign = (at >= 0 && dateString[at - 1] == '-') ? -1 : 1;
662 zoneOffset = sign * zoneOffsets[zoneOffset] * 60 * 60;
663#ifdef PARSEDATESTRINGDEBUG
664 qDebug() << "Zone:" << month;
665#endif
666 at += 3;
667 continue;
668 }
669 // Zone offset
670 if (!isNum
671 && (zoneOffset == -1 || zoneOffset == 0) // Can only go after gmt
672 && (dateString[at] == '+' || dateString[at] == '-')
673 && (at == 0
674 || isWhitespace(dateString[at - 1])
675 || dateString[at - 1] == ','
676 || (at >= 3
677 && (dateString[at - 3] == 'g')
678 && (dateString[at - 2] == 'm')
679 && (dateString[at - 1] == 't')))) {
680
681 int end = 1;
682 while (end < 5 && dateString.size() > at+end
683 && dateString[at + end] >= '0' && dateString[at + end] <= '9')
684 ++end;
685 int minutes = 0;
686 int hours = 0;
687 switch (end - 1) {
688 case 4:
689 minutes = atoi(dateString.mid(at + 3, 2).constData());
691 case 2:
692 hours = atoi(dateString.mid(at + 1, 2).constData());
693 break;
694 case 1:
695 hours = atoi(dateString.mid(at + 1, 1).constData());
696 break;
697 default:
698 at += end;
699 continue;
700 }
701 if (end != 1) {
702 int sign = dateString[at] == '-' ? -1 : 1;
703 zoneOffset = sign * ((minutes * 60) + (hours * 60 * 60));
704#ifdef PARSEDATESTRINGDEBUG
705 qDebug() << "Zone offset:" << zoneOffset << hours << minutes;
706#endif
707 at += end;
708 continue;
709 }
710 }
711
712 // Time
713 if (isNum && time.isNull()
714 && dateString.size() >= at + 3
715 && (dateString[at + 2] == ':' || dateString[at + 1] == ':')) {
716 // While the date can be found all over the string the format
717 // for the time is set and a nice regexp can be used.
718 // This string needs to stay for as long as the QRegularExpressionMatch is used,
719 // or else we get use-after-free issues:
720 QString dateToString = QString::fromLatin1(dateString);
721 if (auto match = timeRx.match(dateToString, at); match.hasMatch()) {
722 int h = match.capturedView(1).toInt();
723 int m = match.capturedView(2).toInt();
724 int s = match.capturedView(3).toInt();
725 int ms = match.capturedView(4).toInt();
726 QStringView ampm = match.capturedView(5);
727 if (h < 12 && !ampm.isEmpty())
728 if (ampm == "pm"_L1)
729 h += 12;
730 time = QTime(h, m, s, ms);
731#ifdef PARSEDATESTRINGDEBUG
732 qDebug() << "Time:" << match.capturedTexts() << match.capturedLength();
733#endif
734 at += match.capturedLength();
735 continue;
736 }
737 }
738
739 // 4 digit Year
740 if (isNum
741 && year == -1
742 && dateString.size() > at + 3) {
743 if (isNumber(dateString[at + 1])
744 && isNumber(dateString[at + 2])
745 && isNumber(dateString[at + 3])) {
746 year = atoi(dateString.mid(at, 4).constData());
747 at += 4;
748#ifdef PARSEDATESTRINGDEBUG
749 qDebug() << "Year:" << year;
750#endif
751 continue;
752 }
753 }
754
755 // a one or two digit number
756 // Could be month, day or year
757 if (isNum) {
758 int length = 1;
759 if (dateString.size() > at + 1
760 && isNumber(dateString[at + 1]))
761 ++length;
762 int x = atoi(dateString.mid(at, length).constData());
763 if (year == -1 && (x > 31 || x == 0)) {
764 year = x;
765 } else {
766 if (unknown[0] == -1) unknown[0] = x;
767 else if (unknown[1] == -1) unknown[1] = x;
768 else if (unknown[2] == -1) unknown[2] = x;
769 }
770 at += length;
771#ifdef PARSEDATESTRINGDEBUG
772 qDebug() << "Saving" << x;
773#endif
774 continue;
775 }
776
777 // Unknown character, typically a weekday such as 'Mon'
778 ++at;
779 }
780
781 // Once we are done parsing the string take the digits in unknown
782 // and determine which is the unknown year/month/day
783
784 int couldBe[3] = { 0, 0, 0 };
785 int unknownCount = 3;
786 for (int i = 0; i < unknownCount; ++i) {
787 if (unknown[i] == -1) {
788 couldBe[i] = ADAY | AYEAR | AMONTH;
789 unknownCount = i;
790 continue;
791 }
792
793 if (unknown[i] >= 1)
794 couldBe[i] = ADAY;
795
796 if (month == -1 && unknown[i] >= 1 && unknown[i] <= 12)
797 couldBe[i] |= AMONTH;
798
799 if (year == -1)
800 couldBe[i] |= AYEAR;
801 }
802
803 // For any possible day make sure one of the values that could be a month
804 // can contain that day.
805 // For any possible month make sure one of the values that can be a
806 // day that month can have.
807 // Example: 31 11 06
808 // 31 can't be a day because 11 and 6 don't have 31 days
809 for (int i = 0; i < unknownCount; ++i) {
810 int currentValue = unknown[i];
811 bool findMatchingMonth = couldBe[i] & ADAY && currentValue >= 29;
812 bool findMatchingDay = couldBe[i] & AMONTH;
813 if (!findMatchingMonth || !findMatchingDay)
814 continue;
815 for (int j = 0; j < 3; ++j) {
816 if (j == i)
817 continue;
818 for (int k = 0; k < 2; ++k) {
819 if (k == 0 && !(findMatchingMonth && (couldBe[j] & AMONTH)))
820 continue;
821 else if (k == 1 && !(findMatchingDay && (couldBe[j] & ADAY)))
822 continue;
823 int m = currentValue;
824 int d = unknown[j];
825 if (k == 0)
826 qSwap(m, d);
827 if (m == -1) m = month;
828 bool found = true;
829 switch(m) {
830 case 2:
831 // When we get 29 and the year ends up having only 28
832 // See date.isValid below
833 // Example: 29 23 Feb
834 if (d <= 29)
835 found = false;
836 break;
837 case 4: case 6: case 9: case 11:
838 if (d <= 30)
839 found = false;
840 break;
841 default:
842 if (d > 0 && d <= 31)
843 found = false;
844 }
845 if (k == 0) findMatchingMonth = found;
846 else if (k == 1) findMatchingDay = found;
847 }
848 }
849 if (findMatchingMonth)
850 couldBe[i] &= ~ADAY;
851 if (findMatchingDay)
852 couldBe[i] &= ~AMONTH;
853 }
854
855 // First set the year/month/day that have been deduced
856 // and reduce the set as we go along to deduce more
857 for (int i = 0; i < unknownCount; ++i) {
858 int unset = 0;
859 for (int j = 0; j < 3; ++j) {
860 if (couldBe[j] == ADAY && day == -1) {
861 day = unknown[j];
862 unset |= ADAY;
863 } else if (couldBe[j] == AMONTH && month == -1) {
864 month = unknown[j];
865 unset |= AMONTH;
866 } else if (couldBe[j] == AYEAR && year == -1) {
867 year = unknown[j];
868 unset |= AYEAR;
869 } else {
870 // common case
871 break;
872 }
873 couldBe[j] &= ~unset;
874 }
875 }
876
877 // Now fallback to a standardized order to fill in the rest with
878 for (int i = 0; i < unknownCount; ++i) {
879 if (couldBe[i] & AMONTH && month == -1) month = unknown[i];
880 else if (couldBe[i] & ADAY && day == -1) day = unknown[i];
881 else if (couldBe[i] & AYEAR && year == -1) year = unknown[i];
882 }
883#ifdef PARSEDATESTRINGDEBUG
884 qDebug() << "Final set" << year << month << day;
885#endif
886
887 if (year == -1 || month == -1 || day == -1) {
888#ifdef PARSEDATESTRINGDEBUG
889 qDebug() << "Parser failure" << year << month << day;
890#endif
891 return QDateTime();
892 }
893
894 // Y2k behavior
895 int y2k = 0;
896 if (year < 70)
897 y2k = 2000;
898 else if (year < 100)
899 y2k = 1900;
900
901 QDate date(year + y2k, month, day);
902
903 // When we were given a bad cookie that when parsed
904 // set the day to 29 and the year to one that doesn't
905 // have the 29th of Feb rather then adding the extra
906 // complicated checking earlier just swap here.
907 // Example: 29 23 Feb
908 if (!date.isValid())
909 date = QDate(day + y2k, month, year);
910
912
913 if (zoneOffset != -1)
914 dateTime = dateTime.addSecs(zoneOffset);
915
916 if (!dateTime.isValid())
917 return QDateTime();
918 return dateTime;
919}
920
933{
934 // cookieString can be a number of set-cookie header strings joined together
935 // by \n, parse each line separately.
936 QList<QNetworkCookie> cookies;
937 QList<QByteArray> list = cookieString.split('\n');
938 for (int a = 0; a < list.size(); a++)
940 return cookies;
941}
942
944{
945 // According to http://wp.netscape.com/newsref/std/cookie_spec.html,<
946 // the Set-Cookie response header is of the format:
947 //
948 // Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
949 //
950 // where only the NAME=VALUE part is mandatory
951 //
952 // We do not support RFC 2965 Set-Cookie2-style cookies
953
956
957 int position = 0;
958 const int length = cookieString.size();
959 while (position < length) {
960 QNetworkCookie cookie;
961
962 // The first part is always the "NAME=VALUE" part
963 QPair<QByteArray,QByteArray> field = nextField(cookieString, position, true);
964 if (field.first.isEmpty())
965 // parsing error
966 break;
967 cookie.setName(field.first);
968 cookie.setValue(field.second);
969
970 position = nextNonWhitespace(cookieString, position);
971 while (position < length) {
972 switch (cookieString.at(position++)) {
973 case ';':
974 // new field in the cookie
975 field = nextField(cookieString, position, false);
976 field.first = field.first.toLower(); // everything but the NAME=VALUE is case-insensitive
977
978 if (field.first == "expires") {
979 position -= field.second.size();
980 int end;
981 for (end = position; end < length; ++end)
982 if (isValueSeparator(cookieString.at(end)))
983 break;
984
985 QByteArray dateString = cookieString.mid(position, end - position).trimmed();
986 position = end;
987 QDateTime dt = parseDateString(dateString.toLower());
988 if (dt.isValid())
989 cookie.setExpirationDate(dt);
990 //if unparsed, ignore the attribute but not the whole cookie (RFC6265 section 5.2.1)
991 } else if (field.first == "domain") {
992 QByteArray rawDomain = field.second;
993 //empty domain should be ignored (RFC6265 section 5.2.3)
994 if (!rawDomain.isEmpty()) {
995 QString maybeLeadingDot;
996 if (rawDomain.startsWith('.')) {
997 maybeLeadingDot = u'.';
998 rawDomain = rawDomain.mid(1);
999 }
1000
1001 //IDN domains are required by RFC6265, accepting utf8 as well doesn't break any test cases.
1002 QString normalizedDomain = QUrl::fromAce(QUrl::toAce(QString::fromUtf8(rawDomain)));
1003 if (!normalizedDomain.isEmpty()) {
1004 cookie.setDomain(maybeLeadingDot + normalizedDomain);
1005 } else {
1006 //Normalization fails for malformed domains, e.g. "..example.org", reject the cookie now
1007 //rather than accepting it but never sending it due to domain match failure, as the
1008 //strict reading of RFC6265 would indicate.
1009 return result;
1010 }
1011 }
1012 } else if (field.first == "max-age") {
1013 bool ok = false;
1014 int secs = field.second.toInt(&ok);
1015 if (ok) {
1016 if (secs <= 0) {
1017 //earliest representable time (RFC6265 section 5.2.2)
1019 } else {
1020 cookie.setExpirationDate(now.addSecs(secs));
1021 }
1022 }
1023 //if unparsed, ignore the attribute but not the whole cookie (RFC6265 section 5.2.2)
1024 } else if (field.first == "path") {
1025 if (field.second.startsWith('/')) {
1026 // ### we should treat cookie paths as an octet sequence internally
1027 // However RFC6265 says we should assume UTF-8 for presentation as a string
1028 cookie.setPath(QString::fromUtf8(field.second));
1029 } else {
1030 // if the path doesn't start with '/' then set the default path (RFC6265 section 5.2.4)
1031 // and also IETF test case path0030 which has valid and empty path in the same cookie
1032 cookie.setPath(QString());
1033 }
1034 } else if (field.first == "secure") {
1035 cookie.setSecure(true);
1036 } else if (field.first == "httponly") {
1037 cookie.setHttpOnly(true);
1038 } else if (field.first == "samesite") {
1039 cookie.setSameSitePolicy(sameSiteFromRawString(field.second));
1040 } else {
1041 // ignore unknown fields in the cookie (RFC6265 section 5.2, rule 6)
1042 }
1043
1044 position = nextNonWhitespace(cookieString, position);
1045 }
1046 }
1047
1048 if (!cookie.name().isEmpty())
1049 result += cookie;
1050 }
1051
1052 return result;
1053}
1054
1061{
1062 // don't do path checking. See QTBUG-5815
1063 if (d->path.isEmpty()) {
1064 QString pathAndFileName = url.path();
1065 QString defaultPath = pathAndFileName.left(pathAndFileName.lastIndexOf(u'/') + 1);
1066 if (defaultPath.isEmpty())
1067 defaultPath = u'/';
1068 d->path = defaultPath;
1069 }
1070
1071 if (d->domain.isEmpty()) {
1072 d->domain = url.host();
1073 } else {
1074 QHostAddress hostAddress(d->domain);
1075 if (hostAddress.protocol() != QAbstractSocket::IPv4Protocol
1076 && hostAddress.protocol() != QAbstractSocket::IPv6Protocol
1077 && !d->domain.startsWith(u'.')) {
1078 // Ensure the domain starts with a dot if its field was not empty
1079 // in the HTTP header. There are some servers that forget the
1080 // leading dot and this is actually forbidden according to RFC 2109,
1081 // but all browsers accept it anyway so we do that as well.
1082 d->domain.prepend(u'.');
1083 }
1084 }
1085}
1086
1087#ifndef QT_NO_DEBUG_STREAM
1089{
1090 QDebugStateSaver saver(s);
1091 s.resetFormat().nospace();
1092 s << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ')';
1093 return s;
1094}
1095#endif
1096
1098
1099#include "moc_qnetworkcookie.cpp"
static constexpr auto IPv4Protocol
static constexpr auto IPv6Protocol
\inmodule QtCore
Definition qbytearray.h:57
QByteArray trimmed() const &
Definition qbytearray.h:198
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays.
bool startsWith(QByteArrayView bv) const
Definition qbytearray.h:170
char at(qsizetype i) const
Returns the byte at index position i in the byte array.
Definition qbytearray.h:523
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
QByteArray toLower() const &
Definition qbytearray.h:190
QByteArray mid(qsizetype index, qsizetype len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos.
\inmodule QtCore\reentrant
Definition qdatetime.h:257
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:27
constexpr bool isValid() const
Returns true if this date is valid; otherwise returns false.
Definition qdatetime.h:86
\inmodule QtCore
\inmodule QtCore
The QHostAddress class provides an IP address.
NetworkLayerProtocol protocol() const
Returns the network layer protocol of the host address.
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
static QLocale c()
Returns a QLocale object initialized to the "C" locale.
Definition qlocale.h:1103
QString toString(qlonglong i) const
Returns a localized string representation of i.
Definition qlocale.cpp:1962
static QList< QNetworkCookie > parseSetCookieHeaderLine(const QByteArray &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.
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.
static QList< QNetworkCookie > parseCookies(const QByteArray &cookieString)
Parses the cookie string cookieString as received from a server response in the "Set-Cookie:" header.
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
QRegularExpressionMatch match(const QString &subject, qsizetype offset=0, MatchType matchType=NormalMatch, MatchOptions matchOptions=NoMatchOption) const
Attempts to match the regular expression against the given subject string, starting at the position o...
\inmodule QtCore
Definition qstringview.h:76
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QByteArray toLatin1() const &
Definition qstring.h:559
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
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:5299
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString toLower() const &
Definition qstring.h:368
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
QString trimmed() const &
Definition qstring.h:380
QByteArray toUtf8() const &
Definition qstring.h:563
QString & prepend(QChar c)
Definition qstring.h:411
\inmodule QtCore \reentrant
Definition qdatetime.h:189
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:197
\inmodule QtCore
Definition qurl.h:94
static QByteArray toAce(const QString &domain, AceProcessingOptions options={})
Definition qurl.cpp:3061
QString host(ComponentFormattingOptions=FullyDecoded) const
Returns the host of the URL if it is defined; otherwise an empty string is returned.
Definition qurl.cpp:2337
static QString fromAce(const QByteArray &domain, AceProcessingOptions options={})
Definition qurl.cpp:3038
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2465
QString str
[2]
QString text
QDate date
[1]
qSwap(pi, e)
Combined button and popup list for selecting options.
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
#define Q_FALLTHROUGH()
std::pair< T1, T2 > QPair
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qDebug
[1]
Definition qlogging.h:160
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1369
static QPair< QByteArray, QByteArray > nextField(const QByteArray &text, int &position, bool isNameValue)
#define ADAY
static const char months[]
QDebug operator<<(QDebug s, const QNetworkCookie &cookie)
#define AMONTH
static bool isValueSeparator(char c)
static bool isWhitespace(char c)
#define AYEAR
static QDateTime parseDateString(const QByteArray &dateString)
static bool checkStaticArray(int &val, const QByteArray &dateString, int at, const char *array, int size)
static const int zoneOffsets[]
static bool isNumber(char s)
static bool isTerminator(char c)
static const char zones[]
static int nextNonWhitespace(const QByteArray &text, int from)
GLint GLint GLint GLint GLint x
[0]
const GLfloat * m
GLboolean GLboolean GLboolean GLboolean a
[7]
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
const GLubyte * c
GLuint GLfloat * val
GLenum array
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
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[]
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
static int sign(int x)
QList< int > list
[14]
QUrl url("example.com")
[constructor-url-reference]
QDateTime dateTime
[12]
QSharedPointer< T > other(t)
[5]
QAction * at