diff options
Diffstat (limited to 'src/network/access/qnetworkrequest.cpp')
-rw-r--r-- | src/network/access/qnetworkrequest.cpp | 134 |
1 files changed, 124 insertions, 10 deletions
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 4cb93805dc..689eecfbb9 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -98,6 +98,25 @@ QT_BEGIN_NAMESPACE header and contains a QDateTime representing the last modification date of the contents. + \value IfModifiedSinceHeader Corresponds to the HTTP If-Modified-Since + header and contains a QDateTime. It is usually added to a + QNetworkRequest. The server shall send a 304 (Not Modified) response + if the resource has not changed since this time. + + \value ETagHeader Corresponds to the HTTP ETag + header and contains a QString representing the last modification + state of the contents. + + \value IfMatchHeader Corresponds to the HTTP If-Match + header and contains a QStringList. It is usually added to a + QNetworkRequest. The server shall send a 412 (Precondition Failed) + response if the resource does not match. + + \value IfNoneMatchHeader Corresponds to the HTTP If-None-Match + header and contains a QStringList. It is usually added to a + QNetworkRequest. The server shall send a 304 (Not Modified) response + if the resource does match. + \value CookieHeader Corresponds to the HTTP Cookie header and contains a QList<QNetworkCookie> representing the cookies to be sent back to the server. @@ -785,6 +804,18 @@ static QByteArray headerName(QNetworkRequest::KnownHeaders header) case QNetworkRequest::LastModifiedHeader: return "Last-Modified"; + case QNetworkRequest::IfModifiedSinceHeader: + return "If-Modified-Since"; + + case QNetworkRequest::ETagHeader: + return "ETag"; + + case QNetworkRequest::IfMatchHeader: + return "If-Match"; + + case QNetworkRequest::IfNoneMatchHeader: + return "If-None-Match"; + case QNetworkRequest::CookieHeader: return "Cookie"; @@ -815,6 +846,9 @@ static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVaria case QNetworkRequest::ContentDispositionHeader: case QNetworkRequest::UserAgentHeader: case QNetworkRequest::ServerHeader: + case QNetworkRequest::ETagHeader: + case QNetworkRequest::IfMatchHeader: + case QNetworkRequest::IfNoneMatchHeader: return value.toByteArray(); case QNetworkRequest::LocationHeader: @@ -827,6 +861,7 @@ static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVaria } case QNetworkRequest::LastModifiedHeader: + case QNetworkRequest::IfModifiedSinceHeader: switch (value.userType()) { case QMetaType::QDate: case QMetaType::QDateTime: @@ -880,32 +915,46 @@ static int parseHeaderName(const QByteArray &headerName) switch (tolower(headerName.at(0))) { case 'c': - if (qstricmp(headerName.constData(), "content-type") == 0) + if (headerName.compare("content-type", Qt::CaseInsensitive) == 0) return QNetworkRequest::ContentTypeHeader; - else if (qstricmp(headerName.constData(), "content-length") == 0) + else if (headerName.compare("content-length", Qt::CaseInsensitive) == 0) return QNetworkRequest::ContentLengthHeader; - else if (qstricmp(headerName.constData(), "cookie") == 0) + else if (headerName.compare("cookie", Qt::CaseInsensitive) == 0) return QNetworkRequest::CookieHeader; else if (qstricmp(headerName.constData(), "content-disposition") == 0) return QNetworkRequest::ContentDispositionHeader; break; + case 'e': + if (qstricmp(headerName.constData(), "etag") == 0) + return QNetworkRequest::ETagHeader; + break; + + case 'i': + if (qstricmp(headerName.constData(), "if-modified-since") == 0) + return QNetworkRequest::IfModifiedSinceHeader; + if (qstricmp(headerName.constData(), "if-match") == 0) + return QNetworkRequest::IfMatchHeader; + if (qstricmp(headerName.constData(), "if-none-match") == 0) + return QNetworkRequest::IfNoneMatchHeader; + break; + case 'l': - if (qstricmp(headerName.constData(), "location") == 0) + if (headerName.compare("location", Qt::CaseInsensitive) == 0) return QNetworkRequest::LocationHeader; - else if (qstricmp(headerName.constData(), "last-modified") == 0) + else if (headerName.compare("last-modified", Qt::CaseInsensitive) == 0) return QNetworkRequest::LastModifiedHeader; break; case 's': - if (qstricmp(headerName.constData(), "set-cookie") == 0) + if (headerName.compare("set-cookie", Qt::CaseInsensitive) == 0) return QNetworkRequest::SetCookieHeader; - else if (qstricmp(headerName.constData(), "server") == 0) + else if (headerName.compare("server", Qt::CaseInsensitive) == 0) return QNetworkRequest::ServerHeader; break; case 'u': - if (qstricmp(headerName.constData(), "user-agent") == 0) + if (headerName.compare("user-agent", Qt::CaseInsensitive) == 0) return QNetworkRequest::UserAgentHeader; break; } @@ -936,6 +985,61 @@ static QVariant parseCookieHeader(const QByteArray &raw) return QVariant::fromValue(result); } +static QVariant parseETag(const QByteArray &raw) +{ + const QByteArray trimmed = raw.trimmed(); + if (!trimmed.startsWith('"') && !trimmed.startsWith(R"(W/")")) + return QVariant(); + + if (!trimmed.endsWith('"')) + return QVariant(); + + return QString::fromLatin1(trimmed); +} + +static QVariant parseIfMatch(const QByteArray &raw) +{ + const QByteArray trimmedRaw = raw.trimmed(); + if (trimmedRaw == "*") + return QStringList(QStringLiteral("*")); + + QStringList tags; + const QList<QByteArray> split = trimmedRaw.split(','); + for (const QByteArray &element : split) { + const QByteArray trimmed = element.trimmed(); + if (!trimmed.startsWith('"')) + continue; + + if (!trimmed.endsWith('"')) + continue; + + tags += QString::fromLatin1(trimmed); + } + return tags; +} + +static QVariant parseIfNoneMatch(const QByteArray &raw) +{ + const QByteArray trimmedRaw = raw.trimmed(); + if (trimmedRaw == "*") + return QStringList(QStringLiteral("*")); + + QStringList tags; + const QList<QByteArray> split = trimmedRaw.split(','); + for (const QByteArray &element : split) { + const QByteArray trimmed = element.trimmed(); + if (!trimmed.startsWith('"') && !trimmed.startsWith(R"(W/")")) + continue; + + if (!trimmed.endsWith('"')) + continue; + + tags += QString::fromLatin1(trimmed); + } + return tags; +} + + static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QByteArray &value) { // header is always a valid value @@ -963,8 +1067,18 @@ static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QBy } case QNetworkRequest::LastModifiedHeader: + case QNetworkRequest::IfModifiedSinceHeader: return parseHttpDate(value); + case QNetworkRequest::ETagHeader: + return parseETag(value); + + case QNetworkRequest::IfMatchHeader: + return parseIfMatch(value); + + case QNetworkRequest::IfNoneMatchHeader: + return parseIfNoneMatch(value); + case QNetworkRequest::CookieHeader: return parseCookieHeader(value); @@ -983,7 +1097,7 @@ QNetworkHeadersPrivate::findRawHeader(const QByteArray &key) const RawHeadersList::ConstIterator it = rawHeaders.constBegin(); RawHeadersList::ConstIterator end = rawHeaders.constEnd(); for ( ; it != end; ++it) - if (qstricmp(it->first.constData(), key.constData()) == 0) + if (it->first.compare(key, Qt::CaseInsensitive) == 0) return it; return end; // not found @@ -1064,7 +1178,7 @@ void QNetworkHeadersPrivate::setCookedHeader(QNetworkRequest::KnownHeaders heade void QNetworkHeadersPrivate::setRawHeaderInternal(const QByteArray &key, const QByteArray &value) { auto firstEqualsKey = [&key](const RawHeaderPair &header) { - return qstricmp(header.first.constData(), key.constData()) == 0; + return header.first.compare(key, Qt::CaseInsensitive) == 0; }; rawHeaders.erase(std::remove_if(rawHeaders.begin(), rawHeaders.end(), firstEqualsKey), |