diff options
Diffstat (limited to 'src/network/access/qnetworkcookie.cpp')
-rw-r--r-- | src/network/access/qnetworkcookie.cpp | 105 |
1 files changed, 55 insertions, 50 deletions
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index 7ddce06360..8ea5fdbe57 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -7,12 +7,14 @@ #include "qnetworkrequest.h" #include "qnetworkreply.h" #include "QtCore/qbytearray.h" +#include "QtCore/qdatetime.h" #include "QtCore/qdebug.h" #include "QtCore/qlist.h" #include "QtCore/qlocale.h" #include <QtCore/qregularexpression.h> #include "QtCore/qstring.h" #include "QtCore/qstringlist.h" +#include "QtCore/qtimezone.h" #include "QtCore/qurl.h" #include "QtNetwork/qhostaddress.h" #include "private/qobject_p.h" @@ -374,13 +376,13 @@ void QNetworkCookie::setValue(const QByteArray &value) } // ### move this to qnetworkcookie_p.h and share with qnetworkaccesshttpbackend -static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &position, bool isNameValue) +static QPair<QByteArray, QByteArray> nextField(QByteArrayView text, int &position, bool isNameValue) { // format is one of: // (1) token // (2) token = token // (3) token = quoted-string - const int length = text.length(); + const int length = text.size(); position = nextNonWhitespace(text, position); int semiColonPosition = text.indexOf(';', position); @@ -394,11 +396,11 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi equalsPosition = semiColonPosition; //no '=' means there is an attribute-name but no attribute-value } - QByteArray first = text.mid(position, equalsPosition - position).trimmed(); + QByteArray first = text.mid(position, equalsPosition - position).trimmed().toByteArray(); QByteArray second; int secondLength = semiColonPosition - equalsPosition - 1; if (secondLength > 0) - second = text.mid(equalsPosition + 1, secondLength).trimmed(); + second = text.mid(equalsPosition + 1, secondLength).trimmed().toByteArray(); position = semiColonPosition; return qMakePair(first, second); @@ -441,29 +443,33 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi */ namespace { -QByteArray sameSiteToRawString(QNetworkCookie::SameSite samesite) + +constexpr QByteArrayView sameSiteNone() noexcept { return "None"; } +constexpr QByteArrayView sameSiteLax() noexcept { return "Lax"; } +constexpr QByteArrayView sameSiteStrict() noexcept { return "Strict"; } + +QByteArrayView sameSiteToRawString(QNetworkCookie::SameSite samesite) noexcept { switch (samesite) { case QNetworkCookie::SameSite::None: - return QByteArrayLiteral("None"); + return sameSiteNone(); case QNetworkCookie::SameSite::Lax: - return QByteArrayLiteral("Lax"); + return sameSiteLax(); case QNetworkCookie::SameSite::Strict: - return QByteArrayLiteral("Strict"); + return sameSiteStrict(); case QNetworkCookie::SameSite::Default: break; } - return QByteArray(); + return QByteArrayView(); } -QNetworkCookie::SameSite sameSiteFromRawString(QByteArray str) +QNetworkCookie::SameSite sameSiteFromRawString(QByteArrayView str) noexcept { - str = str.toLower(); - if (str == QByteArrayLiteral("none")) + if (str.compare(sameSiteNone(), Qt::CaseInsensitive) == 0) return QNetworkCookie::SameSite::None; - if (str == QByteArrayLiteral("lax")) + if (str.compare(sameSiteLax(), Qt::CaseInsensitive) == 0) return QNetworkCookie::SameSite::Lax; - if (str == QByteArrayLiteral("strict")) + if (str.compare(sameSiteStrict(), Qt::CaseInsensitive) == 0) return QNetworkCookie::SameSite::Strict; return QNetworkCookie::SameSite::Default; } @@ -574,11 +580,11 @@ static inline bool isValueSeparator(char c) static inline bool isWhitespace(char c) { return c == ' ' || c == '\t'; } -static bool checkStaticArray(int &val, const QByteArray &dateString, int at, const char *array, int size) +static bool checkStaticArray(int &val, QByteArrayView dateString, int at, const char *array, int size) { if (dateString[at] < 'a' || dateString[at] > 'z') return false; - if (val == -1 && dateString.length() >= at + 3) { + if (val == -1 && dateString.size() >= at + 3) { int j = 0; int i = 0; while (i <= size) { @@ -621,7 +627,7 @@ static bool checkStaticArray(int &val, const QByteArray &dateString, int at, con Or in their own words: "} // else what the hell is this." */ -static QDateTime parseDateString(const QByteArray &dateString) +static QDateTime parseDateString(QByteArrayView dateString) { QTime time; // placeholders for values when we are not sure it is a year, month or day @@ -636,7 +642,7 @@ static QDateTime parseDateString(const QByteArray &dateString) u"(\\d\\d?):(\\d\\d?)(?::(\\d\\d?)(?:\\.(\\d{1,3}))?)?(?:\\s*(am|pm))?"_s); int at = 0; - while (at < dateString.length()) { + while (at < dateString.size()) { #ifdef PARSEDATESTRINGDEBUG qDebug() << dateString.mid(at); #endif @@ -677,20 +683,20 @@ static QDateTime parseDateString(const QByteArray &dateString) && (dateString[at - 1] == 't')))) { int end = 1; - while (end < 5 && dateString.length() > at+end + while (end < 5 && dateString.size() > at+end && dateString[at + end] >= '0' && dateString[at + end] <= '9') ++end; int minutes = 0; int hours = 0; switch (end - 1) { case 4: - minutes = atoi(dateString.mid(at + 3, 2).constData()); + minutes = dateString.mid(at + 3, 2).toInt(); Q_FALLTHROUGH(); case 2: - hours = atoi(dateString.mid(at + 1, 2).constData()); + hours = dateString.mid(at + 1, 2).toInt(); break; case 1: - hours = atoi(dateString.mid(at + 1, 1).constData()); + hours = dateString.mid(at + 1, 1).toInt(); break; default: at += end; @@ -709,7 +715,7 @@ static QDateTime parseDateString(const QByteArray &dateString) // Time if (isNum && time.isNull() - && dateString.length() >= at + 3 + && dateString.size() >= at + 3 && (dateString[at + 2] == ':' || dateString[at + 1] == ':')) { // While the date can be found all over the string the format // for the time is set and a nice regexp can be used. @@ -737,11 +743,11 @@ static QDateTime parseDateString(const QByteArray &dateString) // 4 digit Year if (isNum && year == -1 - && dateString.length() > at + 3) { + && dateString.size() > at + 3) { if (isNumber(dateString[at + 1]) && isNumber(dateString[at + 2]) && isNumber(dateString[at + 3])) { - year = atoi(dateString.mid(at, 4).constData()); + year = dateString.mid(at, 4).toInt(); at += 4; #ifdef PARSEDATESTRINGDEBUG qDebug() << "Year:" << year; @@ -754,10 +760,10 @@ static QDateTime parseDateString(const QByteArray &dateString) // Could be month, day or year if (isNum) { int length = 1; - if (dateString.length() > at + 1 + if (dateString.size() > at + 1 && isNumber(dateString[at + 1])) ++length; - int x = atoi(dateString.mid(at, length).constData()); + int x = dateString.mid(at, length).toInt(); if (year == -1 && (x > 31 || x == 0)) { year = x; } else { @@ -906,11 +912,11 @@ static QDateTime parseDateString(const QByteArray &dateString) if (!date.isValid()) date = QDate(day + y2k, month, year); - QDateTime dateTime(date, time, Qt::UTC); + QDateTime dateTime(date, time, QTimeZone::UTC); - if (zoneOffset != -1) { + if (zoneOffset != -1) dateTime = dateTime.addSecs(zoneOffset); - } + if (!dateTime.isValid()) return QDateTime(); return dateTime; @@ -926,19 +932,19 @@ static QDateTime parseDateString(const QByteArray &dateString) cookie that is parsed. \sa toRawForm() + \note In Qt versions prior to 6.7, this function took QByteArray only. */ -QList<QNetworkCookie> QNetworkCookie::parseCookies(const QByteArray &cookieString) +QList<QNetworkCookie> QNetworkCookie::parseCookies(QByteArrayView cookieString) { // cookieString can be a number of set-cookie header strings joined together // by \n, parse each line separately. QList<QNetworkCookie> cookies; - QList<QByteArray> list = cookieString.split('\n'); - for (int a = 0; a < list.size(); a++) - cookies += QNetworkCookiePrivate::parseSetCookieHeaderLine(list.at(a)); + for (auto s : QLatin1StringView(cookieString).tokenize('\n'_L1)) + cookies += QNetworkCookiePrivate::parseSetCookieHeaderLine(s); return cookies; } -QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByteArray &cookieString) +QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(QByteArrayView cookieString) { // According to http://wp.netscape.com/newsref/std/cookie_spec.html,< // the Set-Cookie response header is of the format: @@ -953,7 +959,7 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt const QDateTime now = QDateTime::currentDateTimeUtc(); int position = 0; - const int length = cookieString.length(); + const int length = cookieString.size(); while (position < length) { QNetworkCookie cookie; @@ -971,28 +977,27 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt case ';': // new field in the cookie field = nextField(cookieString, position, false); - field.first = field.first.toLower(); // everything but the NAME=VALUE is case-insensitive - if (field.first == "expires") { - position -= field.second.length(); + if (field.first.compare("expires", Qt::CaseInsensitive) == 0) { + position -= field.second.size(); int end; for (end = position; end < length; ++end) if (isValueSeparator(cookieString.at(end))) break; - QByteArray dateString = cookieString.mid(position, end - position).trimmed(); + QByteArray dateString = cookieString.mid(position, end - position).trimmed().toByteArray().toLower(); position = end; - QDateTime dt = parseDateString(dateString.toLower()); + QDateTime dt = parseDateString(dateString); if (dt.isValid()) cookie.setExpirationDate(dt); //if unparsed, ignore the attribute but not the whole cookie (RFC6265 section 5.2.1) - } else if (field.first == "domain") { - QByteArray rawDomain = field.second; + } else if (field.first.compare("domain", Qt::CaseInsensitive) == 0) { + QByteArrayView rawDomain = field.second; //empty domain should be ignored (RFC6265 section 5.2.3) if (!rawDomain.isEmpty()) { - QString maybeLeadingDot; + QLatin1StringView maybeLeadingDot; if (rawDomain.startsWith('.')) { - maybeLeadingDot = u'.'; + maybeLeadingDot = "."_L1; rawDomain = rawDomain.mid(1); } @@ -1007,7 +1012,7 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt return result; } } - } else if (field.first == "max-age") { + } else if (field.first.compare("max-age", Qt::CaseInsensitive) == 0) { bool ok = false; int secs = field.second.toInt(&ok); if (ok) { @@ -1019,7 +1024,7 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt } } //if unparsed, ignore the attribute but not the whole cookie (RFC6265 section 5.2.2) - } else if (field.first == "path") { + } else if (field.first.compare("path", Qt::CaseInsensitive) == 0) { if (field.second.startsWith('/')) { // ### we should treat cookie paths as an octet sequence internally // However RFC6265 says we should assume UTF-8 for presentation as a string @@ -1029,11 +1034,11 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt // and also IETF test case path0030 which has valid and empty path in the same cookie cookie.setPath(QString()); } - } else if (field.first == "secure") { + } else if (field.first.compare("secure", Qt::CaseInsensitive) == 0) { cookie.setSecure(true); - } else if (field.first == "httponly") { + } else if (field.first.compare("httponly", Qt::CaseInsensitive) == 0) { cookie.setHttpOnly(true); - } else if (field.first == "samesite") { + } else if (field.first.compare("samesite", Qt::CaseInsensitive) == 0) { cookie.setSameSitePolicy(sameSiteFromRawString(field.second)); } else { // ignore unknown fields in the cookie (RFC6265 section 5.2, rule 6) |