From bd8d70bf604ce2db1a99cafeec6195b7396d4a0b Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Thu, 9 May 2019 11:52:58 +0800 Subject: [PATCH] Refactor HTTP query parsing --- src/base/bittorrent/tracker.cpp | 21 +-------------------- src/base/bittorrent/tracker.h | 1 - src/base/http/requestparser.cpp | 26 +++++++++++++++++++++----- src/base/http/types.h | 2 +- src/webui/webapplication.cpp | 15 ++------------- 5 files changed, 25 insertions(+), 40 deletions(-) diff --git a/src/base/bittorrent/tracker.cpp b/src/base/bittorrent/tracker.cpp index b04f005ad..db7ac6e47 100644 --- a/src/base/bittorrent/tracker.cpp +++ b/src/base/bittorrent/tracker.cpp @@ -29,16 +29,11 @@ #include "tracker.h" -#include - #include #include -#include "base/global.h" #include "base/http/server.h" #include "base/preferences.h" -#include "base/utils/bytearray.h" -#include "base/utils/string.h" // static limits static const int MAX_TORRENTS = 100; @@ -133,21 +128,7 @@ Http::Response Tracker::processRequest(const Http::Request &request, const Http: void Tracker::respondToAnnounceRequest() { - QMap queryParams; - // Parse GET parameters - using namespace Utils::ByteArray; - for (const QByteArray ¶m : asConst(splitToViews(m_request.query, "&"))) { - const int sepPos = param.indexOf('='); - if (sepPos <= 0) continue; // ignores params without name - - const QByteArray nameComponent = midView(param, 0, sepPos); - const QByteArray valueComponent = midView(param, (sepPos + 1)); - - const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent).replace('+', ' ')); - const QByteArray paramValue = QByteArray::fromPercentEncoding(valueComponent).replace('+', ' '); - queryParams[paramName] = paramValue; - } - + const QMap &queryParams = m_request.query; TrackerAnnounceRequest announceReq; // IP diff --git a/src/base/bittorrent/tracker.h b/src/base/bittorrent/tracker.h index 09075676d..02e799908 100644 --- a/src/base/bittorrent/tracker.h +++ b/src/base/bittorrent/tracker.h @@ -36,7 +36,6 @@ #include "base/http/irequesthandler.h" #include "base/http/responsebuilder.h" -#include "base/http/types.h" namespace libtorrent { diff --git a/src/base/http/requestparser.cpp b/src/base/http/requestparser.cpp index aab7edcfe..fa5ded1c8 100644 --- a/src/base/http/requestparser.cpp +++ b/src/base/http/requestparser.cpp @@ -38,6 +38,7 @@ #include #include +#include "base/global.h" #include "base/utils/bytearray.h" #include "base/utils/string.h" @@ -182,14 +183,29 @@ bool RequestParser::parseRequestLine(const QString &line) m_request.method = match.captured(1); // Request Target - // 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)); + const QByteArray pathComponent = ((sepPos == -1) ? url : midView(url, 0, sepPos)); + m_request.path = QString::fromUtf8(QByteArray::fromPercentEncoding(pathComponent)); - if (sepPos >= 0) - m_request.query = url.mid(sepPos + 1); + + if (sepPos >= 0) { + const QByteArray query = midView(url, (sepPos + 1)); + + // [rfc3986] 2.4 When to Encode or Decode + // URL components should be separated before percent-decoding + for (const QByteArray ¶m : asConst(splitToViews(query, "&"))) { + const int eqCharPos = param.indexOf('='); + if (eqCharPos <= 0) continue; // ignores params without name + + const QByteArray nameComponent = midView(param, 0, eqCharPos); + const QByteArray valueComponent = midView(param, (eqCharPos + 1)); + const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent).replace('+', ' ')); + const QByteArray paramValue = QByteArray::fromPercentEncoding(valueComponent).replace('+', ' '); + + m_request.query[paramName] = paramValue; + } + } // HTTP-version m_request.version = match.captured(3); diff --git a/src/base/http/types.h b/src/base/http/types.h index a38e3d328..6bb443d6a 100644 --- a/src/base/http/types.h +++ b/src/base/http/types.h @@ -97,8 +97,8 @@ namespace Http QString version; QString method; QString path; - QByteArray query; QStringMap headers; + QMap query; QStringMap posts; QVector files; }; diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp index e6d668a57..326ba424c 100644 --- a/src/webui/webapplication.cpp +++ b/src/webui/webapplication.cpp @@ -417,19 +417,8 @@ Http::Response WebApplication::processRequest(const Http::Request &request, cons m_params.clear(); if (m_request.method == Http::METHOD_GET) { - // Parse GET parameters - using namespace Utils::ByteArray; - for (const QByteArray ¶m : asConst(splitToViews(m_request.query, "&"))) { - const int sepPos = param.indexOf('='); - if (sepPos <= 0) continue; // ignores params without name - - const QByteArray nameComponent = midView(param, 0, sepPos); - const QByteArray valueComponent = midView(param, (sepPos + 1)); - - const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent).replace('+', ' ')); - const QString paramValue = QString::fromUtf8(QByteArray::fromPercentEncoding(valueComponent).replace('+', ' ')); - m_params[paramName] = paramValue; - } + for (auto iter = m_request.query.cbegin(); iter != m_request.query.cend(); ++iter) + m_params[iter.key()] = QString::fromUtf8(iter.value()); } else { m_params = m_request.posts;