mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-02-09 21:34:20 +00:00
parent
a0fa1709d5
commit
06581636a1
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <QByteArrayView>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@ -50,10 +51,10 @@ namespace
|
|||||||
{
|
{
|
||||||
const QByteArray EOH = QByteArray(CRLF).repeated(2);
|
const QByteArray EOH = QByteArray(CRLF).repeated(2);
|
||||||
|
|
||||||
const QByteArray viewWithoutEndingWith(const QByteArray &in, const QByteArray &str)
|
const QByteArrayView viewWithoutEndingWith(const QByteArrayView in, const QByteArrayView str)
|
||||||
{
|
{
|
||||||
if (in.endsWith(str))
|
if (in.endsWith(str))
|
||||||
return QByteArray::fromRawData(in.constData(), (in.size() - str.size()));
|
return in.chopped(str.size());
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +82,7 @@ RequestParser::ParseResult RequestParser::parse(const QByteArray &data)
|
|||||||
return RequestParser().doParse(data);
|
return RequestParser().doParse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestParser::ParseResult RequestParser::doParse(const QByteArray &data)
|
RequestParser::ParseResult RequestParser::doParse(const QByteArrayView data)
|
||||||
{
|
{
|
||||||
// we don't handle malformed requests which use double `LF` as delimiter
|
// we don't handle malformed requests which use double `LF` as delimiter
|
||||||
const int headerEnd = data.indexOf(EOH);
|
const int headerEnd = data.indexOf(EOH);
|
||||||
@ -130,7 +131,7 @@ RequestParser::ParseResult RequestParser::doParse(const QByteArray &data)
|
|||||||
|
|
||||||
if (contentLength > 0)
|
if (contentLength > 0)
|
||||||
{
|
{
|
||||||
const QByteArray httpBodyView = midView(data, headerLength, contentLength);
|
const QByteArrayView httpBodyView = data.mid(headerLength, contentLength);
|
||||||
if (httpBodyView.length() < contentLength)
|
if (httpBodyView.length() < contentLength)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << "incomplete request";
|
qDebug() << Q_FUNC_INFO << "incomplete request";
|
||||||
@ -204,27 +205,27 @@ bool RequestParser::parseRequestLine(const QString &line)
|
|||||||
// Request Target
|
// Request Target
|
||||||
const QByteArray url {match.captured(2).toLatin1()};
|
const QByteArray url {match.captured(2).toLatin1()};
|
||||||
const int sepPos = url.indexOf('?');
|
const int sepPos = url.indexOf('?');
|
||||||
const QByteArray pathComponent = ((sepPos == -1) ? url : midView(url, 0, sepPos));
|
const QByteArrayView pathComponent = ((sepPos == -1) ? url : QByteArrayView(url).mid(0, sepPos));
|
||||||
|
|
||||||
m_request.path = QString::fromUtf8(QByteArray::fromPercentEncoding(pathComponent));
|
m_request.path = QString::fromUtf8(QByteArray::fromPercentEncoding(pathComponent.toByteArray()));
|
||||||
|
|
||||||
if (sepPos >= 0)
|
if (sepPos >= 0)
|
||||||
{
|
{
|
||||||
const QByteArray query = midView(url, (sepPos + 1));
|
const QByteArrayView query = url.mid(sepPos + 1);
|
||||||
|
|
||||||
// [rfc3986] 2.4 When to Encode or Decode
|
// [rfc3986] 2.4 When to Encode or Decode
|
||||||
// URL components should be separated before percent-decoding
|
// URL components should be separated before percent-decoding
|
||||||
for (const QByteArray ¶m : asConst(splitToViews(query, "&")))
|
for (const QByteArrayView ¶m : asConst(splitToViews(query, "&")))
|
||||||
{
|
{
|
||||||
const int eqCharPos = param.indexOf('=');
|
const int eqCharPos = param.indexOf('=');
|
||||||
if (eqCharPos <= 0) continue; // ignores params without name
|
if (eqCharPos <= 0) continue; // ignores params without name
|
||||||
|
|
||||||
const QByteArray nameComponent = midView(param, 0, eqCharPos);
|
const QByteArrayView nameComponent = param.mid(0, eqCharPos);
|
||||||
const QByteArray valueComponent = midView(param, (eqCharPos + 1));
|
const QByteArrayView valueComponent = param.mid(eqCharPos + 1);
|
||||||
const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent).replace('+', ' '));
|
const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent.toByteArray()).replace('+', ' '));
|
||||||
const QByteArray paramValue = valueComponent.isNull()
|
const QByteArray paramValue = valueComponent.isNull()
|
||||||
? QByteArray("")
|
? QByteArray("")
|
||||||
: QByteArray::fromPercentEncoding(valueComponent).replace('+', ' ');
|
: QByteArray::fromPercentEncoding(valueComponent.toByteArray()).replace('+', ' ');
|
||||||
|
|
||||||
m_request.query[paramName] = paramValue;
|
m_request.query[paramName] = paramValue;
|
||||||
}
|
}
|
||||||
@ -236,7 +237,7 @@ bool RequestParser::parseRequestLine(const QString &line)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RequestParser::parsePostMessage(const QByteArray &data)
|
bool RequestParser::parsePostMessage(const QByteArrayView data)
|
||||||
{
|
{
|
||||||
// parse POST message-body
|
// parse POST message-body
|
||||||
const QString contentType = m_request.headers[HEADER_CONTENT_TYPE];
|
const QString contentType = m_request.headers[HEADER_CONTENT_TYPE];
|
||||||
@ -246,7 +247,7 @@ bool RequestParser::parsePostMessage(const QByteArray &data)
|
|||||||
if (contentTypeLower.startsWith(CONTENT_TYPE_FORM_ENCODED))
|
if (contentTypeLower.startsWith(CONTENT_TYPE_FORM_ENCODED))
|
||||||
{
|
{
|
||||||
// [URL Standard] 5.1 application/x-www-form-urlencoded parsing
|
// [URL Standard] 5.1 application/x-www-form-urlencoded parsing
|
||||||
const QByteArray processedData = QByteArray(data).replace('+', ' ');
|
const QByteArray processedData = data.toByteArray().replace('+', ' ');
|
||||||
|
|
||||||
QListIterator<QStringPair> i(QUrlQuery(QString::fromUtf8(processedData)).queryItems(QUrl::FullyDecoded));
|
QListIterator<QStringPair> i(QUrlQuery(QString::fromUtf8(processedData)).queryItems(QUrl::FullyDecoded));
|
||||||
while (i.hasNext())
|
while (i.hasNext())
|
||||||
@ -281,7 +282,7 @@ bool RequestParser::parsePostMessage(const QByteArray &data)
|
|||||||
|
|
||||||
// split data by "dash-boundary"
|
// split data by "dash-boundary"
|
||||||
const QByteArray dashDelimiter = QByteArray("--") + delimiter + CRLF;
|
const QByteArray dashDelimiter = QByteArray("--") + delimiter + CRLF;
|
||||||
QVector<QByteArray> multipart = splitToViews(data, dashDelimiter, Qt::SkipEmptyParts);
|
QList<QByteArrayView> multipart = splitToViews(data, dashDelimiter, Qt::SkipEmptyParts);
|
||||||
if (multipart.isEmpty())
|
if (multipart.isEmpty())
|
||||||
{
|
{
|
||||||
qWarning() << Q_FUNC_INFO << "multipart empty";
|
qWarning() << Q_FUNC_INFO << "multipart empty";
|
||||||
@ -292,7 +293,7 @@ bool RequestParser::parsePostMessage(const QByteArray &data)
|
|||||||
const QByteArray endDelimiter = QByteArray("--") + delimiter + QByteArray("--") + CRLF;
|
const QByteArray endDelimiter = QByteArray("--") + delimiter + QByteArray("--") + CRLF;
|
||||||
multipart.push_back(viewWithoutEndingWith(multipart.takeLast(), endDelimiter));
|
multipart.push_back(viewWithoutEndingWith(multipart.takeLast(), endDelimiter));
|
||||||
|
|
||||||
return std::all_of(multipart.cbegin(), multipart.cend(), [this](const QByteArray &part)
|
return std::all_of(multipart.cbegin(), multipart.cend(), [this](const QByteArrayView &part)
|
||||||
{
|
{
|
||||||
return this->parseFormData(part);
|
return this->parseFormData(part);
|
||||||
});
|
});
|
||||||
@ -302,7 +303,7 @@ bool RequestParser::parsePostMessage(const QByteArray &data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RequestParser::parseFormData(const QByteArray &data)
|
bool RequestParser::parseFormData(const QByteArrayView data)
|
||||||
{
|
{
|
||||||
const int eohPos = data.indexOf(EOH);
|
const int eohPos = data.indexOf(EOH);
|
||||||
|
|
||||||
@ -312,8 +313,8 @@ bool RequestParser::parseFormData(const QByteArray &data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString headers = QString::fromLatin1(Utils::ByteArray::midView(data, 0, eohPos));
|
const QString headers = QString::fromLatin1(data.mid(0, eohPos));
|
||||||
const QByteArray payload = viewWithoutEndingWith(Utils::ByteArray::midView(data, (eohPos + EOH.size()), data.size()), CRLF);
|
const QByteArrayView payload = viewWithoutEndingWith(data.mid((eohPos + EOH.size()), data.size()), CRLF);
|
||||||
|
|
||||||
HeaderMap headersMap;
|
HeaderMap headersMap;
|
||||||
const QList<QStringView> headerLines = QStringView(headers).split(QString::fromLatin1(CRLF), Qt::SkipEmptyParts);
|
const QList<QStringView> headerLines = QStringView(headers).split(QString::fromLatin1(CRLF), Qt::SkipEmptyParts);
|
||||||
@ -348,7 +349,7 @@ bool RequestParser::parseFormData(const QByteArray &data)
|
|||||||
|
|
||||||
if (headersMap.contains(filename))
|
if (headersMap.contains(filename))
|
||||||
{
|
{
|
||||||
m_request.files.append({headersMap[filename], headersMap[HEADER_CONTENT_TYPE], payload});
|
m_request.files.append({headersMap[filename], headersMap[HEADER_CONTENT_TYPE], payload.toByteArray()});
|
||||||
}
|
}
|
||||||
else if (headersMap.contains(name))
|
else if (headersMap.contains(name))
|
||||||
{
|
{
|
||||||
|
@ -60,12 +60,12 @@ namespace Http
|
|||||||
private:
|
private:
|
||||||
RequestParser() = default;
|
RequestParser() = default;
|
||||||
|
|
||||||
ParseResult doParse(const QByteArray &data);
|
ParseResult doParse(QByteArrayView data);
|
||||||
bool parseStartLines(QStringView data);
|
bool parseStartLines(QStringView data);
|
||||||
bool parseRequestLine(const QString &line);
|
bool parseRequestLine(const QString &line);
|
||||||
|
|
||||||
bool parsePostMessage(const QByteArray &data);
|
bool parsePostMessage(QByteArrayView data);
|
||||||
bool parseFormData(const QByteArray &data);
|
bool parseFormData(QByteArrayView data);
|
||||||
|
|
||||||
Request m_request;
|
Request m_request;
|
||||||
};
|
};
|
||||||
|
@ -580,14 +580,14 @@ void SearchPluginManager::parseVersionInfo(const QByteArray &info)
|
|||||||
QHash<QString, PluginVersion> updateInfo;
|
QHash<QString, PluginVersion> updateInfo;
|
||||||
int numCorrectData = 0;
|
int numCorrectData = 0;
|
||||||
|
|
||||||
const QVector<QByteArray> lines = Utils::ByteArray::splitToViews(info, "\n", Qt::SkipEmptyParts);
|
const QList<QByteArrayView> lines = Utils::ByteArray::splitToViews(info, "\n", Qt::SkipEmptyParts);
|
||||||
for (QByteArray line : lines)
|
for (QByteArrayView line : lines)
|
||||||
{
|
{
|
||||||
line = line.trimmed();
|
line = line.trimmed();
|
||||||
if (line.isEmpty()) continue;
|
if (line.isEmpty()) continue;
|
||||||
if (line.startsWith('#')) continue;
|
if (line.startsWith('#')) continue;
|
||||||
|
|
||||||
const QVector<QByteArray> list = Utils::ByteArray::splitToViews(line, ":", Qt::SkipEmptyParts);
|
const QList<QByteArrayView> list = Utils::ByteArray::splitToViews(line, ":", Qt::SkipEmptyParts);
|
||||||
if (list.size() != 2) continue;
|
if (list.size() != 2) continue;
|
||||||
|
|
||||||
const auto pluginName = QString::fromUtf8(list.first().trimmed());
|
const auto pluginName = QString::fromUtf8(list.first().trimmed());
|
||||||
|
@ -30,14 +30,15 @@
|
|||||||
#include "bytearray.h"
|
#include "bytearray.h"
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QVector>
|
#include <QByteArrayView>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
QVector<QByteArray> Utils::ByteArray::splitToViews(const QByteArray &in, const QByteArray &sep, const Qt::SplitBehavior behavior)
|
QList<QByteArrayView> Utils::ByteArray::splitToViews(const QByteArrayView in, const QByteArrayView sep, const Qt::SplitBehavior behavior)
|
||||||
{
|
{
|
||||||
if (sep.isEmpty())
|
if (sep.isEmpty())
|
||||||
return {in};
|
return {in};
|
||||||
|
|
||||||
QVector<QByteArray> ret;
|
QList<QByteArrayView> ret;
|
||||||
ret.reserve((behavior == Qt::KeepEmptyParts)
|
ret.reserve((behavior == Qt::KeepEmptyParts)
|
||||||
? (1 + (in.size() / sep.size()))
|
? (1 + (in.size() / sep.size()))
|
||||||
: (1 + (in.size() / (sep.size() + 1))));
|
: (1 + (in.size() / (sep.size() + 1))));
|
||||||
@ -49,7 +50,7 @@ QVector<QByteArray> Utils::ByteArray::splitToViews(const QByteArray &in, const Q
|
|||||||
end = in.size();
|
end = in.size();
|
||||||
|
|
||||||
// omit empty parts
|
// omit empty parts
|
||||||
const QByteArray part = QByteArray::fromRawData((in.constData() + head), (end - head));
|
const QByteArrayView part = in.mid(head, (end - head));
|
||||||
if (!part.isEmpty() || (behavior == Qt::KeepEmptyParts))
|
if (!part.isEmpty() || (behavior == Qt::KeepEmptyParts))
|
||||||
ret += part;
|
ret += part;
|
||||||
|
|
||||||
@ -59,17 +60,6 @@ QVector<QByteArray> Utils::ByteArray::splitToViews(const QByteArray &in, const Q
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray Utils::ByteArray::midView(const QByteArray &in, const int pos, const int len)
|
|
||||||
{
|
|
||||||
if ((pos < 0) || (pos >= in.size()) || (len == 0))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
const int validLen = ((len < 0) || (pos + len) >= in.size())
|
|
||||||
? in.size() - pos
|
|
||||||
: len;
|
|
||||||
return QByteArray::fromRawData(in.constData() + pos, validLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray Utils::ByteArray::toBase32(const QByteArray &in)
|
QByteArray Utils::ByteArray::toBase32(const QByteArray &in)
|
||||||
{
|
{
|
||||||
const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||||
|
@ -33,15 +33,12 @@
|
|||||||
#include <QtContainerFwd>
|
#include <QtContainerFwd>
|
||||||
|
|
||||||
class QByteArray;
|
class QByteArray;
|
||||||
|
class QByteArrayView;
|
||||||
|
|
||||||
namespace Utils::ByteArray
|
namespace Utils::ByteArray
|
||||||
{
|
{
|
||||||
// Mimic QStringView(in).split(sep, behavior)
|
// Mimic QStringView(in).split(sep, behavior)
|
||||||
QVector<QByteArray> splitToViews(const QByteArray &in, const QByteArray &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts);
|
QList<QByteArrayView> splitToViews(QByteArrayView in, QByteArrayView sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts);
|
||||||
|
|
||||||
// Mimic QByteArray::mid(pos, len) but instead of returning a full-copy,
|
|
||||||
// we only return a partial view
|
|
||||||
const QByteArray midView(const QByteArray &in, int pos, int len = -1);
|
|
||||||
|
|
||||||
QByteArray toBase32(const QByteArray &in);
|
QByteArray toBase32(const QByteArray &in);
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ namespace
|
|||||||
// Software 'Anaconda' installs its own python interpreter
|
// Software 'Anaconda' installs its own python interpreter
|
||||||
// and `python --version` returns a string like this:
|
// and `python --version` returns a string like this:
|
||||||
// "Python 3.4.3 :: Anaconda 2.3.0 (64-bit)"
|
// "Python 3.4.3 :: Anaconda 2.3.0 (64-bit)"
|
||||||
const QVector<QByteArray> outputSplit = Utils::ByteArray::splitToViews(procOutput, " ", Qt::SkipEmptyParts);
|
const QList<QByteArrayView> outputSplit = Utils::ByteArray::splitToViews(procOutput, " ", Qt::SkipEmptyParts);
|
||||||
if (outputSplit.size() <= 1)
|
if (outputSplit.size() <= 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -99,12 +99,12 @@ bool Utils::Password::PBKDF2::verify(const QByteArray &secret, const QString &pa
|
|||||||
|
|
||||||
bool Utils::Password::PBKDF2::verify(const QByteArray &secret, const QByteArray &password)
|
bool Utils::Password::PBKDF2::verify(const QByteArray &secret, const QByteArray &password)
|
||||||
{
|
{
|
||||||
const QVector<QByteArray> list = ByteArray::splitToViews(secret, ":", Qt::SkipEmptyParts);
|
const QList<QByteArrayView> list = ByteArray::splitToViews(secret, ":", Qt::SkipEmptyParts);
|
||||||
if (list.size() != 2)
|
if (list.size() != 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QByteArray salt = QByteArray::fromBase64(list[0]);
|
const QByteArray salt = QByteArray::fromBase64(list[0].toByteArray());
|
||||||
const QByteArray key = QByteArray::fromBase64(list[1]);
|
const QByteArray key = QByteArray::fromBase64(list[1].toByteArray());
|
||||||
|
|
||||||
std::array<unsigned char, 64> outBuf {};
|
std::array<unsigned char, 64> outBuf {};
|
||||||
const int hmacResult = PKCS5_PBKDF2_HMAC(password.constData(), password.size()
|
const int hmacResult = PKCS5_PBKDF2_HMAC(password.constData(), password.size()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user