aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtad/gtad.yaml4
-rw-r--r--gtad/operation.cpp.mustache2
-rw-r--r--lib/jobs/basejob.cpp51
-rw-r--r--lib/jobs/basejob.h21
-rw-r--r--lib/jobs/syncjob.cpp2
5 files changed, 56 insertions, 24 deletions
diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml
index ee8a43fe..943ac013 100644
--- a/gtad/gtad.yaml
+++ b/gtad/gtad.yaml
@@ -190,8 +190,8 @@ mustache:
joinedParamDef: "{{>maybeCrefType}} {{paramName}}{{>cjoin}}"
passPathAndMaybeQuery: >-
- QStringLiteral("{{basePathWithoutHost}}")
- {{#pathParts}} % {{_}}{{/pathParts}}{{#queryParams?}},
+ makePath("{{basePathWithoutHost}}"{{#pathParts}},
+ {{_}}{{/pathParts}}){{#queryParams?}},
queryTo{{camelCaseOperationId}}(
{{#queryParams}}{{paramName}}{{>cjoin}}{{/queryParams}}){{/queryParams?}}
diff --git a/gtad/operation.cpp.mustache b/gtad/operation.cpp.mustache
index 7f692e4a..3d26ec73 100644
--- a/gtad/operation.cpp.mustache
+++ b/gtad/operation.cpp.mustache
@@ -4,8 +4,6 @@ SPDX-License-Identifier: LGPL-2.1-or-later
}}{{>preamble}}
#include "{{filenameBase}}.h"
-#include <QtCore/QStringBuilder>
-
using namespace Quotient;
{{#operations}}{{#operation}}
{{#queryParams?}}
diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp
index 85066024..73762e4f 100644
--- a/lib/jobs/basejob.cpp
+++ b/lib/jobs/basejob.cpp
@@ -71,7 +71,7 @@ public:
// Using an idiom from clang-tidy:
// http://clang.llvm.org/extra/clang-tidy/checks/modernize-pass-by-value.html
- Private(HttpVerb v, QString endpoint, const QUrlQuery& q,
+ Private(HttpVerb v, QByteArray endpoint, const QUrlQuery& q,
RequestData&& data, bool nt)
: verb(v)
, apiEndpoint(std::move(endpoint))
@@ -106,7 +106,7 @@ public:
// Contents for the network request
HttpVerb verb;
- QString apiEndpoint;
+ QByteArray apiEndpoint;
QHash<QByteArray, QByteArray> requestHeaders;
QUrlQuery requestQuery;
RequestData requestData;
@@ -166,14 +166,36 @@ public:
}
};
-BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint,
+inline bool isHex(QChar c)
+{
+ return c.isDigit() || (c >= u'A' && c <= u'F') || (c >= u'a' && c <= u'f');
+}
+
+QByteArray BaseJob::encodeIfParam(const QString& paramPart)
+{
+ const auto percentIndex = paramPart.indexOf('%');
+ if (percentIndex != -1 && paramPart.size() > percentIndex + 2
+ && isHex(paramPart[percentIndex + 1])
+ && isHex(paramPart[percentIndex + 2])) {
+ qCWarning(JOBS)
+ << "Developers, upfront percent-encoding of job parameters is "
+ "deprecated since libQuotient 0.7; the string involved is"
+ << paramPart;
+ return QUrl(paramPart, QUrl::TolerantMode).toEncoded();
+ }
+ return QUrl::toPercentEncoding(paramPart);
+}
+
+BaseJob::BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint,
bool needsToken)
- : BaseJob(verb, name, endpoint, QUrlQuery {}, RequestData {}, needsToken)
+ : BaseJob(verb, name, std::move(endpoint), QUrlQuery {}, RequestData {},
+ needsToken)
{}
-BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint,
+BaseJob::BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint,
const QUrlQuery& query, RequestData&& data, bool needsToken)
- : d(new Private(verb, endpoint, query, std::move(data), needsToken))
+ : d(new Private(verb, std::move(endpoint), query, std::move(data),
+ needsToken))
{
setObjectName(name);
connect(&d->timer, &QTimer::timeout, this, &BaseJob::timeout);
@@ -194,13 +216,6 @@ QUrl BaseJob::requestUrl() const { return d->reply ? d->reply->url() : QUrl(); }
bool BaseJob::isBackground() const { return d->inBackground; }
-//const QString& BaseJob::apiEndpoint() const { return d->apiUrl.path(); }
-
-//void BaseJob::setApiEndpoint(const QString& apiEndpoint)
-//{
-// d->apiEndpoint = apiEndpoint;
-//}
-
const BaseJob::headers_t& BaseJob::requestHeaders() const
{
return d->requestHeaders;
@@ -259,13 +274,17 @@ const QNetworkReply* BaseJob::reply() const { return d->reply.data(); }
QNetworkReply* BaseJob::reply() { return d->reply.data(); }
-QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QString& path,
+QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QByteArray& encodedPath,
const QUrlQuery& query)
{
// Make sure the added path is relative even if it's not (the official
// API definitions have the leading slash though it's not really correct).
- baseUrl = baseUrl.resolved(
- QUrl(path.mid(path.startsWith('/')), QUrl::TolerantMode));
+ const auto pathUrl =
+ QUrl::fromEncoded(encodedPath.mid(encodedPath.startsWith('/')),
+ QUrl::StrictMode);
+ Q_ASSERT_X(pathUrl.isValid(), __FUNCTION__,
+ qPrintable(pathUrl.errorString()));
+ baseUrl = baseUrl.resolved(pathUrl);
baseUrl.setQuery(query);
return baseUrl;
}
diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h
index 663c121c..81455307 100644
--- a/lib/jobs/basejob.h
+++ b/lib/jobs/basejob.h
@@ -9,6 +9,7 @@
#include "../converters.h"
#include <QtCore/QObject>
+#include <QtCore/QStringBuilder>
class QNetworkReply;
class QSslError;
@@ -23,6 +24,14 @@ class BaseJob : public QObject {
Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT)
Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries)
Q_PROPERTY(int statusCode READ error NOTIFY statusChanged)
+
+ static QByteArray encodeIfParam(const QString& paramPart);
+ template <int N>
+ static inline auto encodeIfParam(const char (&constPart)[N])
+ {
+ return constPart;
+ }
+
public:
/*! The status code of a job
*
@@ -70,6 +79,12 @@ public:
};
Q_ENUM(StatusCode)
+ template <typename... StrTs>
+ static QByteArray makePath(StrTs&&... parts)
+ {
+ return (QByteArray() % ... % encodeIfParam(parts));
+ }
+
using Data
#ifndef Q_CC_MSVC
Q_DECL_DEPRECATED_X("Use Quotient::RequestData instead")
@@ -124,9 +139,9 @@ public:
};
public:
- BaseJob(HttpVerb verb, const QString& name, const QString& endpoint,
+ BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint,
bool needsToken = true);
- BaseJob(HttpVerb verb, const QString& name, const QString& endpoint,
+ BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint,
const QUrlQuery& query, RequestData&& data = {},
bool needsToken = true);
@@ -352,7 +367,7 @@ protected:
* The function ensures exactly one '/' between the path component of
* \p baseUrl and \p path. The query component of \p baseUrl is ignored.
*/
- static QUrl makeRequestUrl(QUrl baseUrl, const QString& path,
+ static QUrl makeRequestUrl(QUrl baseUrl, const QByteArray &encodedPath,
const QUrlQuery& query = {});
/*! Prepares the job for execution
diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp
index 59a34ef3..9b1b46f0 100644
--- a/lib/jobs/syncjob.cpp
+++ b/lib/jobs/syncjob.cpp
@@ -10,7 +10,7 @@ static size_t jobId = 0;
SyncJob::SyncJob(const QString& since, const QString& filter, int timeout,
const QString& presence)
: BaseJob(HttpVerb::Get, QStringLiteral("SyncJob-%1").arg(++jobId),
- QStringLiteral("_matrix/client/r0/sync"))
+ "_matrix/client/r0/sync")
{
setLoggingCategory(SYNCJOB);
QUrlQuery query;