From b0446380c6377f75cb45b5dac918433809d5e24e Mon Sep 17 00:00:00 2001 From: "Vladimir Golovnev (Glassez)" Date: Sat, 26 Jan 2019 21:49:58 +0300 Subject: [PATCH] Separate URL components before percent-decoding Allow special characters in query string parameters. Closes #9116. --- src/base/bittorrent/tracker.cpp | 7 +++++-- src/base/http/requestparser.cpp | 11 +++++++---- src/webui/webapplication.cpp | 9 +++++---- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/base/bittorrent/tracker.cpp b/src/base/bittorrent/tracker.cpp index 98cdda406..1e51a857e 100644 --- a/src/base/bittorrent/tracker.cpp +++ b/src/base/bittorrent/tracker.cpp @@ -140,8 +140,11 @@ void Tracker::respondToAnnounceRequest() const int sepPos = param.indexOf('='); if (sepPos <= 0) continue; // ignores params without name - const QString paramName {QString::fromUtf8(param.constData(), sepPos)}; - const QByteArray paramValue {param.mid(sepPos + 1)}; + const QByteArray nameComponent = midView(param, 0, sepPos); + const QByteArray valueComponent = midView(param, (sepPos + 1)); + + const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent)); + const QByteArray paramValue = QByteArray::fromPercentEncoding(valueComponent); queryParams[paramName] = paramValue; } diff --git a/src/base/http/requestparser.cpp b/src/base/http/requestparser.cpp index a6b038a32..6067cbaa0 100644 --- a/src/base/http/requestparser.cpp +++ b/src/base/http/requestparser.cpp @@ -180,11 +180,14 @@ bool RequestParser::parseRequestLine(const QString &line) m_request.method = match.captured(1); // Request Target - const QByteArray decodedUrl {QByteArray::fromPercentEncoding(match.captured(2).toLatin1())}; - const int sepPos = decodedUrl.indexOf('?'); - m_request.path = QString::fromUtf8(decodedUrl.constData(), (sepPos == -1 ? decodedUrl.size() : sepPos)); + // URL components should be separated before percent-decoding + // [rfc3986] 2.4 When to Encode or Decode + const QByteArray url {match.captured(2).toLatin1()}; + const int sepPos = url.indexOf('?'); + const QByteArray pathComponent = ((sepPos == -1) ? url : Utils::ByteArray::midView(url, 0, sepPos)); + m_request.path = QString::fromUtf8(QByteArray::fromPercentEncoding(pathComponent)); if (sepPos >= 0) - m_request.query = decodedUrl.mid(sepPos + 1); + m_request.query = url.mid(sepPos + 1); // HTTP-version m_request.version = match.captured(3); diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp index 90ee96996..fffc9a32f 100644 --- a/src/webui/webapplication.cpp +++ b/src/webui/webapplication.cpp @@ -423,10 +423,11 @@ Http::Response WebApplication::processRequest(const Http::Request &request, cons const int sepPos = param.indexOf('='); if (sepPos <= 0) continue; // ignores params without name - const QString paramName {QString::fromUtf8(param.constData(), sepPos)}; - const int valuePos = sepPos + 1; - const QString paramValue { - QString::fromUtf8(param.constData() + valuePos, param.size() - valuePos)}; + const QByteArray nameComponent = midView(param, 0, sepPos); + const QByteArray valueComponent = midView(param, (sepPos + 1)); + + const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent)); + const QString paramValue = QString::fromUtf8(QByteArray::fromPercentEncoding(valueComponent)); m_params[paramName] = paramValue; } }