diff options
Diffstat (limited to 'src/network/access')
-rw-r--r-- | src/network/access/http2/http2protocol.cpp | 15 | ||||
-rw-r--r-- | src/network/access/qhsts.cpp | 42 | ||||
-rw-r--r-- | src/network/access/qhsts_p.h | 6 | ||||
-rw-r--r-- | src/network/access/qhttp2protocolhandler.cpp | 2 | ||||
-rw-r--r-- | src/network/access/qhttpheaderparser.cpp | 35 | ||||
-rw-r--r-- | src/network/access/qhttpheaderparser_p.h | 5 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnection.cpp | 13 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkheader.cpp | 2 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkheader_p.h | 5 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkreply.cpp | 2 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkreply_p.h | 3 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkrequest.cpp | 4 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkrequest_p.h | 2 | ||||
-rw-r--r-- | src/network/access/qhttpthreaddelegate_p.h | 5 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyhttpimpl.cpp | 4 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyhttpimpl_p.h | 2 |
16 files changed, 67 insertions, 80 deletions
diff --git a/src/network/access/http2/http2protocol.cpp b/src/network/access/http2/http2protocol.cpp index 1e7291e48e..7d582497ab 100644 --- a/src/network/access/http2/http2protocol.cpp +++ b/src/network/access/http2/http2protocol.cpp @@ -184,14 +184,13 @@ QNetworkReply::NetworkError qt_error(quint32 errorCode) bool is_protocol_upgraded(const QHttpNetworkReply &reply) { - if (reply.statusCode() == 101) { - // Do some minimal checks here - we expect 'Upgrade: h2c' to be found. - const auto &header = reply.header(); - for (const QPair<QByteArray, QByteArray> &field : header) { - if (field.first.compare("upgrade", Qt::CaseInsensitive) == 0 && - field.second.compare("h2c", Qt::CaseInsensitive) == 0) - return true; - } + if (reply.statusCode() != 101) + return false; + + // Do some minimal checks here - we expect 'Upgrade: h2c' to be found. + for (const auto &v : reply.header().values(QHttpHeaders::WellKnownHeader::Upgrade)) { + if (v.compare("h2c", Qt::CaseInsensitive) == 0) + return true; } return false; diff --git a/src/network/access/qhsts.cpp b/src/network/access/qhsts.cpp index 13755d0003..21ed08ce4a 100644 --- a/src/network/access/qhsts.cpp +++ b/src/network/access/qhsts.cpp @@ -3,6 +3,8 @@ #include "qhsts_p.h" +#include "qhttpheaders.h" + #include "QtCore/private/qipaddress_p.h" #include "QtCore/qlist.h" @@ -40,7 +42,7 @@ static bool is_valid_domain_name(const QString &host) return true; } -void QHstsCache::updateFromHeaders(const QList<QPair<QByteArray, QByteArray>> &headers, +void QHstsCache::updateFromHeaders(const QHttpHeaders &headers, const QUrl &url) { if (!url.isValid()) @@ -324,27 +326,25 @@ quoted-pair = "\" CHAR */ -bool QHstsHeaderParser::parse(const QList<QPair<QByteArray, QByteArray>> &headers) +bool QHstsHeaderParser::parse(const QHttpHeaders &headers) { - for (const auto &h : headers) { - // We compare directly because header name was already 'trimmed' for us: - if (h.first.compare("Strict-Transport-Security", Qt::CaseInsensitive) == 0) { - header = h.second; - // RFC6797, 8.1: - // - // The UA MUST ignore any STS header fields not conforming to the - // grammar specified in Section 6.1 ("Strict-Transport-Security HTTP - // Response Header Field"). - // - // If a UA receives more than one STS header field in an HTTP - // response message over secure transport, then the UA MUST process - // only the first such header field. - // - // We read this as: ignore all invalid headers and take the first valid: - if (parseSTSHeader() && maxAgeFound) { - expiry = QDateTime::currentDateTimeUtc().addSecs(maxAge); - return true; - } + for (const auto &value : headers.values( + QHttpHeaders::WellKnownHeader::StrictTransportSecurity)) { + header = value; + // RFC6797, 8.1: + // + // The UA MUST ignore any STS header fields not conforming to the + // grammar specified in Section 6.1 ("Strict-Transport-Security HTTP + // Response Header Field"). + // + // If a UA receives more than one STS header field in an HTTP + // response message over secure transport, then the UA MUST process + // only the first such header field. + // + // We read this as: ignore all invalid headers and take the first valid: + if (parseSTSHeader() && maxAgeFound) { + expiry = QDateTime::currentDateTimeUtc().addSecs(maxAge); + return true; } } diff --git a/src/network/access/qhsts_p.h b/src/network/access/qhsts_p.h index 96d4ee8dc5..ff9378197b 100644 --- a/src/network/access/qhsts_p.h +++ b/src/network/access/qhsts_p.h @@ -31,11 +31,13 @@ QT_BEGIN_NAMESPACE +class QHttpHeaders; + class Q_AUTOTEST_EXPORT QHstsCache { public: - void updateFromHeaders(const QList<QPair<QByteArray, QByteArray>> &headers, + void updateFromHeaders(const QHttpHeaders &headers, const QUrl &url); void updateFromPolicies(const QList<QHstsPolicy> &hosts); void updateKnownHost(const QUrl &url, const QDateTime &expires, @@ -90,7 +92,7 @@ class Q_AUTOTEST_EXPORT QHstsHeaderParser { public: - bool parse(const QList<QPair<QByteArray, QByteArray>> &headers); + bool parse(const QHttpHeaders &headers); QDateTime expirationDate() const { return expiry; } bool includeSubDomains() const { return subDomainsFound; } diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 60f7ea12a6..4bb057b209 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -60,7 +60,7 @@ HPack::HttpHeader build_headers(const QHttpNetworkRequest &request, quint32 maxH if (size.second > maxHeaderListSize) return HttpHeader(); // Bad, we cannot send this request ... - const auto requestHeader = request.header(); + const auto requestHeader = request.header().toListOfPairs(); for (const auto &field : requestHeader) { const HeaderSize delta = entry_size(field.first, field.second); if (!delta.first) // Overflow??? diff --git a/src/network/access/qhttpheaderparser.cpp b/src/network/access/qhttpheaderparser.cpp index cb6b479543..0b7882c18a 100644 --- a/src/network/access/qhttpheaderparser.cpp +++ b/src/network/access/qhttpheaderparser.cpp @@ -52,11 +52,11 @@ bool QHttpHeaderParser::parseHeaders(QByteArrayView header) if (header.size() - (header.endsWith("\r\n") ? 2 : 1) > maxTotalSize) return false; - QList<QPair<QByteArray, QByteArray>> result; + QHttpHeaders result; while (!header.empty()) { const qsizetype colon = header.indexOf(':'); if (colon == -1) // if no colon check if empty headers - return result.empty() && (header == "\n" || header == "\r\n"); + return result.isEmpty() && (header == "\n" || header == "\r\n"); if (result.size() >= maxFieldCount) return false; QByteArrayView name = header.first(colon); @@ -82,7 +82,7 @@ bool QHttpHeaderParser::parseHeaders(QByteArrayView header) header = header.sliced(endLine + 1); } while (hSpaceStart(header)); Q_ASSERT(name.size() + 1 + value.size() <= maxFieldSize); - result.append(qMakePair(name.toByteArray(), value)); + result.append(name, value); } fields = result; @@ -128,25 +128,15 @@ bool QHttpHeaderParser::parseStatus(QByteArrayView status) return ok && uint(majorVersion) <= 9 && uint(minorVersion) <= 9; } -const QList<QPair<QByteArray, QByteArray> >& QHttpHeaderParser::headers() const +const QHttpHeaders& QHttpHeaderParser::headers() const { return fields; } -static auto firstEqualsName(QByteArrayView name) -{ - return [name](const QPair<QByteArray, QByteArray> &header) { - return name.compare(header.first, Qt::CaseInsensitive) == 0; - }; -} - QByteArray QHttpHeaderParser::firstHeaderField(QByteArrayView name, const QByteArray &defaultValue) const { - const auto it = std::find_if(fields.begin(), fields.end(), firstEqualsName(name)); - if (it != fields.end()) - return it->second; - return defaultValue; + return fields.value(name, defaultValue).toByteArray(); } QByteArray QHttpHeaderParser::combinedHeaderValue(QByteArrayView name, const QByteArray &defaultValue) const @@ -159,33 +149,28 @@ QByteArray QHttpHeaderParser::combinedHeaderValue(QByteArrayView name, const QBy QList<QByteArray> QHttpHeaderParser::headerFieldValues(QByteArrayView name) const { - QList<QByteArray> result; - for (auto it = fields.constBegin(); it != fields.constEnd(); ++it) - if (name.compare(it->first, Qt::CaseInsensitive) == 0) - result += it->second; - - return result; + return fields.values(name); } void QHttpHeaderParser::removeHeaderField(QByteArrayView name) { - fields.removeIf(firstEqualsName(name)); + fields.removeAll(name); } void QHttpHeaderParser::setHeaderField(const QByteArray &name, const QByteArray &data) { removeHeaderField(name); - fields.append(qMakePair(name, data)); + fields.append(name, data); } void QHttpHeaderParser::prependHeaderField(const QByteArray &name, const QByteArray &data) { - fields.prepend(qMakePair(name, data)); + fields.insert(0, name, data); } void QHttpHeaderParser::appendHeaderField(const QByteArray &name, const QByteArray &data) { - fields.append(qMakePair(name, data)); + fields.append(name, data); } void QHttpHeaderParser::clearHeaders() diff --git a/src/network/access/qhttpheaderparser_p.h b/src/network/access/qhttpheaderparser_p.h index 50ca83693a..5e8f3c8130 100644 --- a/src/network/access/qhttpheaderparser_p.h +++ b/src/network/access/qhttpheaderparser_p.h @@ -16,6 +16,7 @@ // #include <QtNetwork/private/qtnetworkglobal_p.h> +#include <QtNetwork/qhttpheaders.h> #include <QByteArray> #include <QList> @@ -52,7 +53,7 @@ public: bool parseHeaders(QByteArrayView headers); bool parseStatus(QByteArrayView status); - const QList<QPair<QByteArray, QByteArray> >& headers() const; + const QHttpHeaders& headers() const; void setStatusCode(int code); int getStatusCode() const; int getMajorVersion() const; @@ -83,7 +84,7 @@ public: qsizetype maxHeaderFields() const { return maxFieldCount; } private: - QList<QPair<QByteArray, QByteArray> > fields; + QHttpHeaders fields; QString reasonPhrase; int statusCode; int majorVersion; diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 1f2fb6d03c..b8a49a926d 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -411,7 +411,7 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket resend = false; //create the response header to be used with QAuthenticatorPrivate. - QList<QPair<QByteArray, QByteArray> > fields = reply->header(); + const auto headers = reply->header(); // Check that any of the proposed authenticate methods are supported const QByteArray header = isProxy ? "proxy-authenticate" : "www-authenticate"; @@ -427,7 +427,7 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket if (auth->isNull()) auth->detach(); QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(*auth); - priv->parseHttpResponse(fields, isProxy, reply->url().host()); + priv->parseHttpResponse(headers, isProxy, reply->url().host()); // Update method in case it changed if (priv->method == QAuthenticatorPrivate::None) return false; @@ -523,12 +523,9 @@ QHttpNetworkConnectionPrivate::parseRedirectResponse(QHttpNetworkReply *reply) return {{}, QNetworkReply::NoError}; QUrl redirectUrl; - const QList<QPair<QByteArray, QByteArray> > fields = reply->header(); - for (const QNetworkReply::RawHeaderPair &header : fields) { - if (header.first.compare("location", Qt::CaseInsensitive) == 0) { - redirectUrl = QUrl::fromEncoded(header.second); - break; - } + const QHttpHeaders fields = reply->header(); + if (const auto h = fields.values(QHttpHeaders::WellKnownHeader::Location); !h.empty()) { + redirectUrl = QUrl::fromEncoded(h.first()); } // If the location url is invalid/empty, we return ProtocolUnknownError diff --git a/src/network/access/qhttpnetworkheader.cpp b/src/network/access/qhttpnetworkheader.cpp index 8ef664c012..7f9c94dc9c 100644 --- a/src/network/access/qhttpnetworkheader.cpp +++ b/src/network/access/qhttpnetworkheader.cpp @@ -53,7 +53,7 @@ void QHttpNetworkHeaderPrivate::prependHeaderField(const QByteArray &name, const parser.prependHeaderField(name, data); } -QList<QPair<QByteArray, QByteArray> > QHttpNetworkHeaderPrivate::headers() const +QHttpHeaders QHttpNetworkHeaderPrivate::headers() const { return parser.headers(); } diff --git a/src/network/access/qhttpnetworkheader_p.h b/src/network/access/qhttpnetworkheader_p.h index 57c06eb95c..afbc6cb6fe 100644 --- a/src/network/access/qhttpnetworkheader_p.h +++ b/src/network/access/qhttpnetworkheader_p.h @@ -17,6 +17,7 @@ #include <QtNetwork/private/qtnetworkglobal_p.h> #include <QtNetwork/private/qhttpheaderparser_p.h> +#include <QtNetwork/qhttpheaders.h> #include <qshareddata.h> #include <qurl.h> @@ -40,7 +41,7 @@ public: virtual qint64 contentLength() const = 0; virtual void setContentLength(qint64 length) = 0; - virtual QList<QPair<QByteArray, QByteArray> > header() const = 0; + virtual QHttpHeaders header() const = 0; virtual QByteArray headerField(QByteArrayView name, const QByteArray &defaultValue = QByteArray()) const = 0; virtual void setHeaderField(const QByteArray &name, const QByteArray &data) = 0; }; @@ -61,7 +62,7 @@ public: void setHeaderField(const QByteArray &name, const QByteArray &data); void prependHeaderField(const QByteArray &name, const QByteArray &data); void clearHeaders(); - QList<QPair<QByteArray, QByteArray> > headers() const; + QHttpHeaders headers() const; bool operator==(const QHttpNetworkHeaderPrivate &other) const; }; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index aad41e9a14..6d82e81322 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -67,7 +67,7 @@ void QHttpNetworkReply::setContentLength(qint64 length) d->setContentLength(length); } -QList<QPair<QByteArray, QByteArray> > QHttpNetworkReply::header() const +QHttpHeaders QHttpNetworkReply::header() const { return d_func()->parser.headers(); } diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 54ff53452b..c1b155caa7 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -41,6 +41,7 @@ Q_MOC_INCLUDE(<QtNetwork/QNetworkProxy>) Q_MOC_INCLUDE(<QtNetwork/QAuthenticator>) #include <private/qdecompresshelper_p.h> +#include <QtNetwork/qhttpheaders.h> #include <QtCore/qpointer.h> @@ -72,7 +73,7 @@ public: qint64 contentLength() const override; void setContentLength(qint64 length) override; - QList<QPair<QByteArray, QByteArray> > header() const override; + QHttpHeaders header() const override; QByteArray headerField(QByteArrayView name, const QByteArray &defaultValue = QByteArray()) const override; void setHeaderField(const QByteArray &name, const QByteArray &data) override; void appendHeaderField(const QByteArray &name, const QByteArray &data); diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index c32a75eccb..bc3eb67adc 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -112,7 +112,7 @@ QByteArray QHttpNetworkRequest::uri(bool throughProxy) const QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request, bool throughProxy) { - const QList<QPair<QByteArray, QByteArray> > fields = request.header(); + const QList<QPair<QByteArray, QByteArray> > fields = request.header().toListOfPairs(); QByteArray ba; ba.reserve(40 + fields.size()*25); // very rough lower bound estimation @@ -235,7 +235,7 @@ void QHttpNetworkRequest::setContentLength(qint64 length) d->setContentLength(length); } -QList<QPair<QByteArray, QByteArray> > QHttpNetworkRequest::header() const +QHttpHeaders QHttpNetworkRequest::header() const { return d->parser.headers(); } diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index 6cf8ca2401..131885f6d2 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -65,7 +65,7 @@ public: qint64 contentLength() const override; void setContentLength(qint64 length) override; - QList<QPair<QByteArray, QByteArray> > header() const override; + QHttpHeaders header() const override; QByteArray headerField(QByteArrayView name, const QByteArray &defaultValue = QByteArray()) const override; void setHeaderField(const QByteArray &name, const QByteArray &data) override; void prependHeaderField(const QByteArray &name, const QByteArray &data); diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h index 0d052e2450..38e9fb4d78 100644 --- a/src/network/access/qhttpthreaddelegate_p.h +++ b/src/network/access/qhttpthreaddelegate_p.h @@ -33,6 +33,7 @@ #include "private/qnoncontiguousbytedevice_p.h" #include "qnetworkaccessauthenticationmanager_p.h" #include <QtNetwork/private/http2protocol_p.h> +#include <QtNetwork/qhttpheaders.h> QT_REQUIRE_CONFIG(http); @@ -74,7 +75,7 @@ public: // outgoing, Retrieved in the synchronous HTTP case QByteArray synchronousDownloadData; - QList<QPair<QByteArray,QByteArray> > incomingHeaders; + QHttpHeaders incomingHeaders; int incomingStatusCode; QString incomingReasonPhrase; bool isPipeliningUsed; @@ -112,7 +113,7 @@ signals: #endif void socketStartedConnecting(); void requestSent(); - void downloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &, bool, + void downloadMetaData(const QHttpHeaders &, int, const QString &, bool, QSharedPointer<char>, qint64, qint64, bool, bool); void downloadProgress(qint64, qint64); void downloadData(const QByteArray &); diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 53bc0f5283..84d9e08b91 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1325,7 +1325,7 @@ void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode) } } -void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &hm, +void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QHttpHeaders &hm, int sc, const QString &rp, bool pu, QSharedPointer<char> db, qint64 contentLength, @@ -1364,7 +1364,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByte const bool autoDecompress = request.rawHeader("accept-encoding").isEmpty(); const bool shouldDecompress = isCompressed && autoDecompress; // reconstruct the HTTP header - for (const auto &[key, originValue] : hm) { + for (const auto &[key, originValue] : hm.toListOfPairs()) { QByteArray value = q->rawHeader(key); // Reset any previous "location" header set in the reply. In case of diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index 11897d1420..e00c43bdb3 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -244,7 +244,7 @@ public: // From HTTP thread: void replyDownloadData(QByteArray); void replyFinished(); - void replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &, + void replyDownloadMetaData(const QHttpHeaders &, int, const QString &, bool, QSharedPointer<char>, qint64, qint64, bool, bool); void replyDownloadProgressSlot(qint64,qint64); void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); |