Browse Source

Utilize QByteArrayView

PR #19417.
adaptive-webui-19844
Vladimir Golovnev 1 year ago committed by GitHub
parent
commit
06581636a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 41
      src/base/http/requestparser.cpp
  2. 6
      src/base/http/requestparser.h
  3. 6
      src/base/search/searchpluginmanager.cpp
  4. 20
      src/base/utils/bytearray.cpp
  5. 7
      src/base/utils/bytearray.h
  6. 2
      src/base/utils/foreignapps.cpp
  7. 6
      src/base/utils/password.cpp

41
src/base/http/requestparser.cpp

@ -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 &param : asConst(splitToViews(query, "&"))) for (const QByteArrayView &param : 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))
{ {

6
src/base/http/requestparser.h

@ -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;
}; };

6
src/base/search/searchpluginmanager.cpp

@ -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());

20
src/base/utils/bytearray.cpp

@ -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";

7
src/base/utils/bytearray.h

@ -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);
} }

2
src/base/utils/foreignapps.cpp

@ -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;

6
src/base/utils/password.cpp

@ -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…
Cancel
Save