From aacc4bcb4a487871daae6717f77605aaba444341 Mon Sep 17 00:00:00 2001 From: Marc Deop Date: Sat, 2 Mar 2019 12:26:57 +0100 Subject: style: apply .clang-format to all .cpp and .h files --- lib/jobs/basejob.cpp | 436 ++++++++++++++---------------- lib/jobs/basejob.h | 584 +++++++++++++++++++++-------------------- lib/jobs/downloadfilejob.cpp | 61 ++--- lib/jobs/downloadfilejob.h | 28 +- lib/jobs/mediathumbnailjob.cpp | 37 +-- lib/jobs/mediathumbnailjob.h | 29 +- lib/jobs/postreadmarkersjob.h | 20 +- lib/jobs/requestdata.cpp | 19 +- lib/jobs/requestdata.h | 37 ++- lib/jobs/syncjob.cpp | 18 +- lib/jobs/syncjob.h | 26 +- 11 files changed, 624 insertions(+), 671 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 8c3381ae..a023d4f7 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "basejob.h" @@ -21,19 +21,18 @@ #include "connectiondata.h" #include "util.h" +#include +#include +#include #include -#include #include -#include -#include -#include +#include #include using namespace QMatrixClient; -struct NetworkReplyDeleter : public QScopedPointerDeleteLater -{ +struct NetworkReplyDeleter : public QScopedPointerDeleteLater { static inline void cleanup(QNetworkReply* reply) { if (reply && reply->isRunning()) @@ -45,51 +44,58 @@ struct NetworkReplyDeleter : public QScopedPointerDeleteLater class BaseJob::Private { 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, - Data&& data, bool nt) - : verb(v), apiEndpoint(std::move(endpoint)), requestQuery(q) - , requestData(std::move(data)), needsToken(nt) - { } - - void sendRequest(bool inBackground); - const JobTimeoutConfig& getCurrentTimeoutConfig() const; - - const ConnectionData* connection = nullptr; - - // Contents for the network request - HttpVerb verb; - QString apiEndpoint; - QHash requestHeaders; - QUrlQuery requestQuery; - Data requestData; - bool needsToken; - - // There's no use of QMimeType here because we don't want to match - // content types against the known MIME type hierarchy; and at the same - // type QMimeType is of little help with MIME type globs (`text/*` etc.) - QByteArrayList expectedContentTypes; - - QScopedPointer reply; - Status status = Pending; - QByteArray rawResponse; - QUrl errorUrl; //< May contain a URL to help with some errors - - QTimer timer; - QTimer retryTimer; - - QVector errorStrategy = - { { 90, 5 }, { 90, 10 }, { 120, 30 } }; - int maxRetries = errorStrategy.size(); - int retriesTaken = 0; - - LoggingCategory logCat = JOBS; + // 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, Data&& data, + bool nt) + : verb(v), + apiEndpoint(std::move(endpoint)), + requestQuery(q), + requestData(std::move(data)), + needsToken(nt) + { + } + + void sendRequest(bool inBackground); + const JobTimeoutConfig& getCurrentTimeoutConfig() const; + + const ConnectionData* connection = nullptr; + + // Contents for the network request + HttpVerb verb; + QString apiEndpoint; + QHash requestHeaders; + QUrlQuery requestQuery; + Data requestData; + bool needsToken; + + // There's no use of QMimeType here because we don't want to match + // content types against the known MIME type hierarchy; and at the same + // type QMimeType is of little help with MIME type globs (`text/*` etc.) + QByteArrayList expectedContentTypes; + + QScopedPointer reply; + Status status = Pending; + QByteArray rawResponse; + QUrl errorUrl; //< May contain a URL to help with some errors + + QTimer timer; + QTimer retryTimer; + + QVector errorStrategy = { { 90, 5 }, + { 90, 10 }, + { 120, 30 } }; + int maxRetries = errorStrategy.size(); + int retriesTaken = 0; + + LoggingCategory logCat = JOBS; }; -BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, bool needsToken) - : BaseJob(verb, name, endpoint, Query { }, Data { }, needsToken) -{ } +BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, + bool needsToken) + : BaseJob(verb, name, endpoint, Query {}, Data {}, needsToken) +{ +} BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, const Query& query, Data&& data, bool needsToken) @@ -98,7 +104,7 @@ BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, setObjectName(name); setExpectedContentTypes({ "application/json" }); d->timer.setSingleShot(true); - connect (&d->timer, &QTimer::timeout, this, &BaseJob::timeout); + connect(&d->timer, &QTimer::timeout, this, &BaseJob::timeout); } BaseJob::~BaseJob() @@ -114,21 +120,20 @@ QUrl BaseJob::requestUrl() const bool BaseJob::isBackground() const { - return d->reply && d->reply->request().attribute( - QNetworkRequest::BackgroundRequestAttribute).toBool(); + return d->reply + && d->reply->request() + .attribute(QNetworkRequest::BackgroundRequestAttribute) + .toBool(); } -const QString& BaseJob::apiEndpoint() const -{ - return d->apiEndpoint; -} +const QString& BaseJob::apiEndpoint() const { return d->apiEndpoint; } void BaseJob::setApiEndpoint(const QString& apiEndpoint) { d->apiEndpoint = apiEndpoint; } -const BaseJob::headers_t&BaseJob::requestHeaders() const +const BaseJob::headers_t& BaseJob::requestHeaders() const { return d->requestHeaders; } @@ -144,25 +149,16 @@ void BaseJob::setRequestHeaders(const BaseJob::headers_t& headers) d->requestHeaders = headers; } -const QUrlQuery& BaseJob::query() const -{ - return d->requestQuery; -} +const QUrlQuery& BaseJob::query() const { return d->requestQuery; } void BaseJob::setRequestQuery(const QUrlQuery& query) { d->requestQuery = query; } -const BaseJob::Data& BaseJob::requestData() const -{ - return d->requestData; -} +const BaseJob::Data& BaseJob::requestData() const { return d->requestData; } -void BaseJob::setRequestData(Data&& data) -{ - std::swap(d->requestData, data); -} +void BaseJob::setRequestData(Data&& data) { std::swap(d->requestData, data); } const QByteArrayList& BaseJob::expectedContentTypes() const { @@ -179,22 +175,22 @@ void BaseJob::setExpectedContentTypes(const QByteArrayList& contentTypes) d->expectedContentTypes = contentTypes; } -QUrl BaseJob::makeRequestUrl(QUrl baseUrl, - const QString& path, const QUrlQuery& query) +QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QString& path, + const QUrlQuery& query) { auto pathBase = baseUrl.path(); if (!pathBase.endsWith('/') && !path.startsWith('/')) pathBase.push_back('/'); - baseUrl.setPath( pathBase + path ); + baseUrl.setPath(pathBase + path); baseUrl.setQuery(query); return baseUrl; } void BaseJob::Private::sendRequest(bool inBackground) { - QNetworkRequest req - { makeRequestUrl(connection->baseUrl(), apiEndpoint, requestQuery) }; + QNetworkRequest req { makeRequestUrl(connection->baseUrl(), apiEndpoint, + requestQuery) }; if (!requestHeaders.contains("Content-Type")) req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); req.setRawHeader("Authorization", @@ -211,38 +207,34 @@ void BaseJob::Private::sendRequest(bool inBackground) #endif for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) req.setRawHeader(it.key(), it.value()); - switch( verb ) - { - case HttpVerb::Get: - reply.reset( connection->nam()->get(req) ); - break; - case HttpVerb::Post: - reply.reset( connection->nam()->post(req, requestData.source()) ); - break; - case HttpVerb::Put: - reply.reset( connection->nam()->put(req, requestData.source()) ); - break; - case HttpVerb::Delete: - reply.reset( connection->nam()->deleteResource(req) ); - break; + switch (verb) { + case HttpVerb::Get: + reply.reset(connection->nam()->get(req)); + break; + case HttpVerb::Post: + reply.reset(connection->nam()->post(req, requestData.source())); + break; + case HttpVerb::Put: + reply.reset(connection->nam()->put(req, requestData.source())); + break; + case HttpVerb::Delete: + reply.reset(connection->nam()->deleteResource(req)); + break; } } -void BaseJob::beforeStart(const ConnectionData*) -{ } +void BaseJob::beforeStart(const ConnectionData*) {} -void BaseJob::afterStart(const ConnectionData*, QNetworkReply*) -{ } +void BaseJob::afterStart(const ConnectionData*, QNetworkReply*) {} -void BaseJob::beforeAbandon(QNetworkReply*) -{ } +void BaseJob::beforeAbandon(QNetworkReply*) {} void BaseJob::start(const ConnectionData* connData, bool inBackground) { d->connection = connData; d->retryTimer.setSingleShot(true); - connect (&d->retryTimer, &QTimer::timeout, - this, [this,inBackground] { sendRequest(inBackground); }); + connect(&d->retryTimer, &QTimer::timeout, this, + [this, inBackground] { sendRequest(inBackground); }); beforeStart(connData); if (status().good()) @@ -261,27 +253,23 @@ void BaseJob::sendRequest(bool inBackground) if (!d->requestQuery.isEmpty()) qCDebug(d->logCat) << " query:" << d->requestQuery.toString(); d->sendRequest(inBackground); - connect( d->reply.data(), &QNetworkReply::finished, this, &BaseJob::gotReply ); - if (d->reply->isRunning()) - { - connect( d->reply.data(), &QNetworkReply::metaDataChanged, - this, &BaseJob::checkReply); - connect( d->reply.data(), &QNetworkReply::uploadProgress, - this, &BaseJob::uploadProgress); - connect( d->reply.data(), &QNetworkReply::downloadProgress, - this, &BaseJob::downloadProgress); + connect(d->reply.data(), &QNetworkReply::finished, this, + &BaseJob::gotReply); + if (d->reply->isRunning()) { + connect(d->reply.data(), &QNetworkReply::metaDataChanged, this, + &BaseJob::checkReply); + connect(d->reply.data(), &QNetworkReply::uploadProgress, this, + &BaseJob::uploadProgress); + connect(d->reply.data(), &QNetworkReply::downloadProgress, this, + &BaseJob::downloadProgress); d->timer.start(getCurrentTimeout()); qCDebug(d->logCat) << this << "request has been sent"; emit started(); - } - else + } else qCWarning(d->logCat) << this << "request could not start"; } -void BaseJob::checkReply() -{ - setStatus(doCheckReply(d->reply.data())); -} +void BaseJob::checkReply() { setStatus(doCheckReply(d->reply.data())); } void BaseJob::gotReply() { @@ -293,20 +281,18 @@ void BaseJob::gotReply() d->rawResponse = d->reply->readAll(); const auto jsonBody = d->reply->rawHeader("Content-Type") == "application/json"; - qCDebug(d->logCat).noquote() - << "Error body (truncated if long):" << d->rawResponse.left(500); - if (jsonBody) - { + qCDebug(d->logCat).noquote() << "Error body (truncated if long):" + << d->rawResponse.left(500); + if (jsonBody) { auto json = QJsonDocument::fromJson(d->rawResponse).object(); const auto errCode = json.value("errcode"_ls).toString(); - if (error() == TooManyRequestsError || - errCode == "M_LIMIT_EXCEEDED") - { + if (error() == TooManyRequestsError + || errCode == "M_LIMIT_EXCEEDED") { QString msg = tr("Too many requests"); auto retryInterval = json.value("retry_after_ms"_ls).toInt(-1); if (retryInterval != -1) msg += tr(", next retry advised after %1 ms") - .arg(retryInterval); + .arg(retryInterval); else // We still have to figure some reasonable interval retryInterval = getNextRetryInterval(); @@ -320,19 +306,16 @@ void BaseJob::gotReply() emit retryScheduled(d->retriesTaken, retryInterval); return; } - if (errCode == "M_CONSENT_NOT_GIVEN") - { + if (errCode == "M_CONSENT_NOT_GIVEN") { d->status.code = UserConsentRequiredError; d->errorUrl = json.value("consent_uri"_ls).toString(); - } - else if (errCode == "M_UNSUPPORTED_ROOM_VERSION" || - errCode == "M_INCOMPATIBLE_ROOM_VERSION") - { + } else if (errCode == "M_UNSUPPORTED_ROOM_VERSION" + || errCode == "M_INCOMPATIBLE_ROOM_VERSION") { d->status.code = UnsupportedRoomVersionError; if (json.contains("room_version")) d->status.message = - tr("Requested room version: %1") - .arg(json.value("room_version").toString()); + tr("Requested room version: %1") + .arg(json.value("room_version").toString()); } else if (!json.isEmpty()) // Not localisable on the client side setStatus(IncorrectRequestError, json.value("error"_ls).toString()); @@ -350,18 +333,18 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) // ignore possible appendixes of the content type const auto ctype = type.split(';').front(); - for (const auto& pattern: patterns) - { + for (const auto& pattern : patterns) { if (pattern.startsWith('*') || ctype == pattern) // Fast lane return true; auto patternParts = pattern.split('/'); Q_ASSERT_X(patternParts.size() <= 2, __FUNCTION__, - "BaseJob: Expected content type should have up to two" - " /-separated parts; violating pattern: " + pattern); + "BaseJob: Expected content type should have up to two" + " /-separated parts; violating pattern: " + + pattern); - if (ctype.split('/').front() == patternParts.front() && - patternParts.back() == "*") + if (ctype.split('/').front() == patternParts.front() + && patternParts.back() == "*") return true; // Exact match already went on fast lane } @@ -376,24 +359,26 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes const auto httpCodeHeader = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); - if (!httpCodeHeader.isValid()) - { + if (!httpCodeHeader.isValid()) { qCWarning(d->logCat) << this << "didn't get valid HTTP headers"; return { NetworkError, reply->errorString() }; } - const QString replyState = reply->isRunning() ? - QStringLiteral("(tentative)") : QStringLiteral("(final)"); + const QString replyState = reply->isRunning() + ? QStringLiteral("(tentative)") + : QStringLiteral("(final)"); const auto urlString = '|' + d->reply->url().toDisplayString(); const auto httpCode = httpCodeHeader.toInt(); const auto reason = - reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); + reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute) + .toString(); if (httpCode / 100 == 2) // 2xx { qCDebug(d->logCat).noquote().nospace() << this << urlString; - qCDebug(d->logCat).noquote() << " " << httpCode << reason << replyState; + qCDebug(d->logCat).noquote() + << " " << httpCode << reason << replyState; if (!checkContentType(reply->rawHeader("Content-Type"), - d->expectedContentTypes)) + d->expectedContentTypes)) return { UnexpectedResponseTypeWarning, "Unexpected content type of the response" }; return NoError; @@ -402,29 +387,37 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const qCWarning(d->logCat).noquote().nospace() << this << urlString; qCWarning(d->logCat).noquote() << " " << httpCode << reason << replyState; return { [httpCode]() -> StatusCode { - if (httpCode / 10 == 41) - return httpCode == 410 ? IncorrectRequestError : NotFoundError; - switch (httpCode) - { - case 401: case 403: case 407: + if (httpCode / 10 == 41) + return httpCode == 410 ? IncorrectRequestError + : NotFoundError; + switch (httpCode) { + case 401: + case 403: + case 407: return ContentAccessError; case 404: return NotFoundError; - case 400: case 405: case 406: case 426: case 428: + case 400: + case 405: + case 406: + case 426: + case 428: case 505: case 494: // Unofficial nginx "Request header too large" case 497: // Unofficial nginx "HTTP request sent to HTTPS port" return IncorrectRequestError; case 429: return TooManyRequestsError; - case 501: case 510: + case 501: + case 510: return RequestNotImplementedError; case 511: return NetworkAuthRequiredError; default: return NetworkError; - } - }(), reply->errorString() }; + } + }(), + reply->errorString() }; } BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) @@ -432,30 +425,25 @@ BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) d->rawResponse = reply->readAll(); QJsonParseError error; const auto& json = QJsonDocument::fromJson(d->rawResponse, &error); - if( error.error == QJsonParseError::NoError ) + if (error.error == QJsonParseError::NoError) return parseJson(json); return { IncorrectResponseError, error.errorString() }; } -BaseJob::Status BaseJob::parseJson(const QJsonDocument&) -{ - return Success; -} +BaseJob::Status BaseJob::parseJson(const QJsonDocument&) { return Success; } void BaseJob::stop() { d->timer.stop(); - if (d->reply) - { + if (d->reply) { d->reply->disconnect(this); // Ignore whatever comes from the reply - if (d->reply->isRunning()) - { - qCWarning(d->logCat) << this << "stopped without ready network reply"; + if (d->reply->isRunning()) { + qCWarning(d->logCat) + << this << "stopped without ready network reply"; d->reply->abort(); } - } - else + } else qCWarning(d->logCat) << this << "stopped with empty network reply"; } @@ -463,16 +451,16 @@ void BaseJob::finishJob() { stop(); if ((error() == NetworkError || error() == TimeoutError) - && d->retriesTaken < d->maxRetries) - { + && d->retriesTaken < d->maxRetries) { // TODO: The whole retrying thing should be put to ConnectionManager // otherwise independently retrying jobs make a bit of notification // storm towards the UI. const auto retryInterval = error() == TimeoutError ? 0 : getNextRetryInterval(); ++d->retriesTaken; - qCWarning(d->logCat).nospace() << this << ": retry #" << d->retriesTaken - << " in " << retryInterval/1000 << " s"; + qCWarning(d->logCat).nospace() + << this << ": retry #" << d->retriesTaken << " in " + << retryInterval / 1000 << " s"; d->retryTimer.start(retryInterval); emit retryScheduled(d->retriesTaken, retryInterval); return; @@ -510,93 +498,78 @@ BaseJob::duration_t BaseJob::millisToRetry() const return d->retryTimer.isActive() ? d->retryTimer.remainingTime() : 0; } -int BaseJob::maxRetries() const -{ - return d->maxRetries; -} +int BaseJob::maxRetries() const { return d->maxRetries; } void BaseJob::setMaxRetries(int newMaxRetries) { d->maxRetries = newMaxRetries; } -BaseJob::Status BaseJob::status() const -{ - return d->status; -} +BaseJob::Status BaseJob::status() const { return d->status; } QByteArray BaseJob::rawData(int bytesAtMost) const { return bytesAtMost > 0 && d->rawResponse.size() > bytesAtMost - ? d->rawResponse.left(bytesAtMost) : d->rawResponse; + ? d->rawResponse.left(bytesAtMost) + : d->rawResponse; } QString BaseJob::rawDataSample(int bytesAtMost) const { auto data = rawData(bytesAtMost); Q_ASSERT(data.size() <= d->rawResponse.size()); - return data.size() == d->rawResponse.size() - ? data : data + tr("...(truncated, %Ln bytes in total)", - "Comes after trimmed raw network response", - d->rawResponse.size()); - + return data.size() == d->rawResponse.size() ? data + : data + + tr("...(truncated, %Ln bytes in total)", + "Comes after trimmed raw network response", + d->rawResponse.size()); } QString BaseJob::statusCaption() const { - switch (d->status.code) - { - case Success: - return tr("Success"); - case Pending: - return tr("Request still pending response"); - case UnexpectedResponseTypeWarning: - return tr("Warning: Unexpected response type"); - case Abandoned: - return tr("Request was abandoned"); - case NetworkError: - return tr("Network problems"); - case JsonParseError: - return tr("Response could not be parsed"); - case TimeoutError: - return tr("Request timed out"); - case ContentAccessError: - return tr("Access error"); - case NotFoundError: - return tr("Not found"); - case IncorrectRequestError: - return tr("Invalid request"); - case IncorrectResponseError: - return tr("Response could not be parsed"); - case TooManyRequestsError: - return tr("Too many requests"); - case RequestNotImplementedError: - return tr("Function not implemented by the server"); - case NetworkAuthRequiredError: - return tr("Network authentication required"); - case UserConsentRequiredError: - return tr("User consent required"); - case UnsupportedRoomVersionError: - return tr("The server does not support the needed room version"); - default: - return tr("Request failed"); + switch (d->status.code) { + case Success: + return tr("Success"); + case Pending: + return tr("Request still pending response"); + case UnexpectedResponseTypeWarning: + return tr("Warning: Unexpected response type"); + case Abandoned: + return tr("Request was abandoned"); + case NetworkError: + return tr("Network problems"); + case JsonParseError: + return tr("Response could not be parsed"); + case TimeoutError: + return tr("Request timed out"); + case ContentAccessError: + return tr("Access error"); + case NotFoundError: + return tr("Not found"); + case IncorrectRequestError: + return tr("Invalid request"); + case IncorrectResponseError: + return tr("Response could not be parsed"); + case TooManyRequestsError: + return tr("Too many requests"); + case RequestNotImplementedError: + return tr("Function not implemented by the server"); + case NetworkAuthRequiredError: + return tr("Network authentication required"); + case UserConsentRequiredError: + return tr("User consent required"); + case UnsupportedRoomVersionError: + return tr("The server does not support the needed room version"); + default: + return tr("Request failed"); } } -int BaseJob::error() const -{ - return d->status.code; -} +int BaseJob::error() const { return d->status.code; } -QString BaseJob::errorString() const -{ - return d->status.message; -} +QString BaseJob::errorString() const { return d->status.message; } -QUrl BaseJob::errorUrl() const -{ - return d->errorUrl; -} +QUrl BaseJob::errorUrl() const { return d->errorUrl; } void BaseJob::setStatus(Status s) { @@ -629,11 +602,8 @@ void BaseJob::abandon() void BaseJob::timeout() { - setStatus( TimeoutError, "The job has timed out" ); + setStatus(TimeoutError, "The job has timed out"); finishJob(); } -void BaseJob::setLoggingCategory(LoggingCategory lcf) -{ - d->logCat = lcf; -} +void BaseJob::setLoggingCategory(LoggingCategory lcf) { d->logCat = lcf; } diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 4c1c7706..8ff25d42 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once @@ -21,332 +21,336 @@ #include "../logging.h" #include "requestdata.h" +#include #include #include -#include class QNetworkReply; class QSslError; -namespace QMatrixClient -{ +namespace QMatrixClient { class ConnectionData; enum class HttpVerb { Get, Put, Post, Delete }; - struct JobTimeoutConfig - { + struct JobTimeoutConfig { int jobTimeout; int nextRetryInterval; }; - class BaseJob: public QObject + class BaseJob : public QObject { - Q_OBJECT - Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) - Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries) + Q_OBJECT + Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) + Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries) public: - /* Just in case, the values are compatible with KJob - * (which BaseJob used to inherit from). */ - enum StatusCode { NoError = 0 // To be compatible with Qt conventions - , Success = 0 - , Pending = 1 - , WarningLevel = 20 - , UnexpectedResponseTypeWarning = 21 - , Abandoned = 50 //< A very brief period between abandoning and object deletion - , ErrorLevel = 100 //< Errors have codes starting from this - , NetworkError = 100 - , JsonParseError // TODO: Merge into IncorrectResponseError - , TimeoutError - , ContentAccessError - , NotFoundError - , IncorrectRequestError - , IncorrectResponseError - , TooManyRequestsError - , RequestNotImplementedError - , UnsupportedRoomVersionError - , NetworkAuthRequiredError - , UserConsentRequiredError - , UserDefinedError = 200 - }; - - /** - * A simple wrapper around QUrlQuery that allows its creation from - * a list of string pairs - */ - class Query : public QUrlQuery + /* Just in case, the values are compatible with KJob + * (which BaseJob used to inherit from). */ + enum StatusCode { + NoError = 0 // To be compatible with Qt conventions + , + Success = 0, + Pending = 1, + WarningLevel = 20, + UnexpectedResponseTypeWarning = 21, + Abandoned = 50 //< A very brief period between abandoning and object + //deletion + , + ErrorLevel = 100 //< Errors have codes starting from this + , + NetworkError = 100, + JsonParseError // TODO: Merge into IncorrectResponseError + , + TimeoutError, + ContentAccessError, + NotFoundError, + IncorrectRequestError, + IncorrectResponseError, + TooManyRequestsError, + RequestNotImplementedError, + UnsupportedRoomVersionError, + NetworkAuthRequiredError, + UserConsentRequiredError, + UserDefinedError = 200 + }; + + /** + * A simple wrapper around QUrlQuery that allows its creation from + * a list of string pairs + */ + class Query : public QUrlQuery + { + public: + using QUrlQuery::QUrlQuery; + Query() = default; + Query(const std::initializer_list>& l) { - public: - using QUrlQuery::QUrlQuery; - Query() = default; - Query(const std::initializer_list< QPair >& l) - { - setQueryItems(l); - } - }; - - using Data = RequestData; - - /** - * This structure stores the status of a server call job. The status consists - * of a code, that is described (but not delimited) by the respective enum, - * and a freeform message. - * - * To extend the list of error codes, define an (anonymous) enum - * along the lines of StatusCode, with additional values - * starting at UserDefinedError - */ - class Status + setQueryItems(l); + } + }; + + using Data = RequestData; + + /** + * This structure stores the status of a server call job. The status + * consists of a code, that is described (but not delimited) by the + * respective enum, and a freeform message. + * + * To extend the list of error codes, define an (anonymous) enum + * along the lines of StatusCode, with additional values + * starting at UserDefinedError + */ + class Status + { + public: + Status(StatusCode c) : code(c) {} + Status(int c, QString m) : code(c), message(std::move(m)) {} + + bool good() const { return code < ErrorLevel; } + friend QDebug operator<<(QDebug dbg, const Status& s) { - public: - Status(StatusCode c) : code(c) { } - Status(int c, QString m) : code(c), message(std::move(m)) { } - - bool good() const { return code < ErrorLevel; } - friend QDebug operator<<(QDebug dbg, const Status& s) - { - QDebugStateSaver _s(dbg); - return dbg.noquote().nospace() - << s.code << ": " << s.message; - } - - bool operator==(const Status& other) const - { - return code == other.code && message == other.message; - } - bool operator!=(const Status& other) const - { - return !operator==(other); - } - - int code; - QString message; - }; - - using duration_t = int; // milliseconds + QDebugStateSaver _s(dbg); + return dbg.noquote().nospace() << s.code << ": " << s.message; + } - public: - BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, - bool needsToken = true); - BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, - const Query& query, Data&& data = {}, - bool needsToken = true); - - QUrl requestUrl() const; - bool isBackground() const; - - /** Current status of the job */ - Status status() const; - /** Short human-friendly message on the job status */ - QString statusCaption() const; - /** Get raw response body as received from the server - * \param bytesAtMost return this number of leftmost bytes, or -1 - * to return the entire response - */ - QByteArray rawData(int bytesAtMost = -1) const; - /** Get UI-friendly sample of raw data - * - * This is almost the same as rawData but appends the "truncated" - * suffix if not all data fit in bytesAtMost. This call is - * recommended to present a sample of raw data as "details" next to - * error messages. Note that the default \p bytesAtMost value is - * also tailored to UI cases. - */ - QString rawDataSample(int bytesAtMost = 65535) const; - - /** Error (more generally, status) code - * Equivalent to status().code - * \sa status - */ - int error() const; - /** Error-specific message, as returned by the server */ - virtual QString errorString() const; - /** A URL to help/clarify the error, if provided by the server */ - QUrl errorUrl() const; - - int maxRetries() const; - void setMaxRetries(int newMaxRetries); - - Q_INVOKABLE duration_t getCurrentTimeout() const; - Q_INVOKABLE duration_t getNextRetryInterval() const; - Q_INVOKABLE duration_t millisToRetry() const; - - friend QDebug operator<<(QDebug dbg, const BaseJob* j) + bool operator==(const Status& other) const { - return dbg << j->objectName(); + return code == other.code && message == other.message; } + bool operator!=(const Status& other) const + { + return !operator==(other); + } + + int code; + QString message; + }; + + using duration_t = int; // milliseconds + + public: + BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, + bool needsToken = true); + BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, + const Query& query, Data&& data = {}, bool needsToken = true); + + QUrl requestUrl() const; + bool isBackground() const; + + /** Current status of the job */ + Status status() const; + /** Short human-friendly message on the job status */ + QString statusCaption() const; + /** Get raw response body as received from the server + * \param bytesAtMost return this number of leftmost bytes, or -1 + * to return the entire response + */ + QByteArray rawData(int bytesAtMost = -1) const; + /** Get UI-friendly sample of raw data + * + * This is almost the same as rawData but appends the "truncated" + * suffix if not all data fit in bytesAtMost. This call is + * recommended to present a sample of raw data as "details" next to + * error messages. Note that the default \p bytesAtMost value is + * also tailored to UI cases. + */ + QString rawDataSample(int bytesAtMost = 65535) const; + + /** Error (more generally, status) code + * Equivalent to status().code + * \sa status + */ + int error() const; + /** Error-specific message, as returned by the server */ + virtual QString errorString() const; + /** A URL to help/clarify the error, if provided by the server */ + QUrl errorUrl() const; + + int maxRetries() const; + void setMaxRetries(int newMaxRetries); + + Q_INVOKABLE duration_t getCurrentTimeout() const; + Q_INVOKABLE duration_t getNextRetryInterval() const; + Q_INVOKABLE duration_t millisToRetry() const; + + friend QDebug operator<<(QDebug dbg, const BaseJob* j) + { + return dbg << j->objectName(); + } public slots: - void start(const ConnectionData* connData, - bool inBackground = false); - - /** - * Abandons the result of this job, arrived or unarrived. - * - * This aborts waiting for a reply from the server (if there was - * any pending) and deletes the job object. No result signals - * (result, success, failure) are emitted. - */ - void abandon(); + void start(const ConnectionData* connData, bool inBackground = false); + + /** + * Abandons the result of this job, arrived or unarrived. + * + * This aborts waiting for a reply from the server (if there was + * any pending) and deletes the job object. No result signals + * (result, success, failure) are emitted. + */ + void abandon(); signals: - /** The job is about to send a network request */ - void aboutToStart(); - - /** The job has sent a network request */ - void started(); - - /** The job has changed its status */ - void statusChanged(Status newStatus); - - /** - * The previous network request has failed; the next attempt will - * be done in the specified time - * @param nextAttempt the 1-based number of attempt (will always be more than 1) - * @param inMilliseconds the interval after which the next attempt will be taken - */ - void retryScheduled(int nextAttempt, int inMilliseconds); - - /** - * Emitted when the job is finished, in any case. It is used to notify - * observers that the job is terminated and that progress can be hidden. - * - * This should not be emitted directly by subclasses; - * use finishJob() instead. - * - * In general, to be notified of a job's completion, client code - * should connect to result(), success(), or failure() - * rather than finished(). However if you need to track the job's - * lifecycle you should connect to this instead of result(); - * in particular, only this signal will be emitted on abandoning. - * - * @param job the job that emitted this signal - * - * @see result, success, failure - */ - void finished(BaseJob* job); - - /** - * Emitted when the job is finished (except when abandoned). - * - * Use error() to know if the job was finished with error. - * - * @param job the job that emitted this signal - * - * @see success, failure - */ - void result(BaseJob* job); - - /** - * Emitted together with result() in case there's no error. - * - * @see result, failure - */ - void success(BaseJob*); - - /** - * Emitted together with result() if there's an error. - * Similar to result(), this won't be emitted in case of abandon(). - * - * @see result, success - */ - void failure(BaseJob*); - - void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); - void uploadProgress(qint64 bytesSent, qint64 bytesTotal); + /** The job is about to send a network request */ + void aboutToStart(); + + /** The job has sent a network request */ + void started(); + + /** The job has changed its status */ + void statusChanged(Status newStatus); + + /** + * The previous network request has failed; the next attempt will + * be done in the specified time + * @param nextAttempt the 1-based number of attempt (will always be more + * than 1) + * @param inMilliseconds the interval after which the next attempt will + * be taken + */ + void retryScheduled(int nextAttempt, int inMilliseconds); + + /** + * Emitted when the job is finished, in any case. It is used to notify + * observers that the job is terminated and that progress can be hidden. + * + * This should not be emitted directly by subclasses; + * use finishJob() instead. + * + * In general, to be notified of a job's completion, client code + * should connect to result(), success(), or failure() + * rather than finished(). However if you need to track the job's + * lifecycle you should connect to this instead of result(); + * in particular, only this signal will be emitted on abandoning. + * + * @param job the job that emitted this signal + * + * @see result, success, failure + */ + void finished(BaseJob* job); + + /** + * Emitted when the job is finished (except when abandoned). + * + * Use error() to know if the job was finished with error. + * + * @param job the job that emitted this signal + * + * @see success, failure + */ + void result(BaseJob* job); + + /** + * Emitted together with result() in case there's no error. + * + * @see result, failure + */ + void success(BaseJob*); + + /** + * Emitted together with result() if there's an error. + * Similar to result(), this won't be emitted in case of abandon(). + * + * @see result, success + */ + void failure(BaseJob*); + + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + void uploadProgress(qint64 bytesSent, qint64 bytesTotal); protected: - using headers_t = QHash; - - const QString& apiEndpoint() const; - void setApiEndpoint(const QString& apiEndpoint); - const headers_t& requestHeaders() const; - void setRequestHeader(const headers_t::key_type& headerName, - const headers_t::mapped_type& headerValue); - void setRequestHeaders(const headers_t& headers); - const QUrlQuery& query() const; - void setRequestQuery(const QUrlQuery& query); - const Data& requestData() const; - void setRequestData(Data&& data); - const QByteArrayList& expectedContentTypes() const; - void addExpectedContentType(const QByteArray& contentType); - void setExpectedContentTypes(const QByteArrayList& contentTypes); - - /** Construct a URL out of baseUrl, path and query - * The function automatically adds '/' between baseUrl's path and - * \p path if necessary. The query component of \p baseUrl - * is ignored. - */ - static QUrl makeRequestUrl(QUrl baseUrl, const QString& path, - const QUrlQuery& query = {}); - - virtual void beforeStart(const ConnectionData* connData); - virtual void afterStart(const ConnectionData* connData, - QNetworkReply* reply); - virtual void beforeAbandon(QNetworkReply*); - - /** - * Used by gotReply() to check the received reply for general - * issues such as network errors or access denial. - * Returning anything except NoError/Success prevents - * further parseReply()/parseJson() invocation. - * - * @param reply the reply received from the server - * @return the result of checking the reply - * - * @see gotReply - */ - virtual Status doCheckReply(QNetworkReply* reply) const; - - /** - * Processes the reply. By default, parses the reply into - * a QJsonDocument and calls parseJson() if it's a valid JSON. - * - * @param reply raw contents of a HTTP reply from the server (without headers) - * - * @see gotReply, parseJson - */ - virtual Status parseReply(QNetworkReply* reply); - - /** - * Processes the JSON document received from the Matrix server. - * By default returns succesful status without analysing the JSON. - * - * @param json valid JSON document received from the server - * - * @see parseReply - */ - virtual Status parseJson(const QJsonDocument&); - - void setStatus(Status s); - void setStatus(int code, QString message); - - // Q_DECLARE_LOGGING_CATEGORY return different function types - // in different versions - using LoggingCategory = decltype(JOBS)*; - void setLoggingCategory(LoggingCategory lcf); - - // Job objects should only be deleted via QObject::deleteLater - ~BaseJob() override; + using headers_t = QHash; + + const QString& apiEndpoint() const; + void setApiEndpoint(const QString& apiEndpoint); + const headers_t& requestHeaders() const; + void setRequestHeader(const headers_t::key_type& headerName, + const headers_t::mapped_type& headerValue); + void setRequestHeaders(const headers_t& headers); + const QUrlQuery& query() const; + void setRequestQuery(const QUrlQuery& query); + const Data& requestData() const; + void setRequestData(Data&& data); + const QByteArrayList& expectedContentTypes() const; + void addExpectedContentType(const QByteArray& contentType); + void setExpectedContentTypes(const QByteArrayList& contentTypes); + + /** Construct a URL out of baseUrl, path and query + * The function automatically adds '/' between baseUrl's path and + * \p path if necessary. The query component of \p baseUrl + * is ignored. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& path, + const QUrlQuery& query = {}); + + virtual void beforeStart(const ConnectionData* connData); + virtual void afterStart(const ConnectionData* connData, + QNetworkReply* reply); + virtual void beforeAbandon(QNetworkReply*); + + /** + * Used by gotReply() to check the received reply for general + * issues such as network errors or access denial. + * Returning anything except NoError/Success prevents + * further parseReply()/parseJson() invocation. + * + * @param reply the reply received from the server + * @return the result of checking the reply + * + * @see gotReply + */ + virtual Status doCheckReply(QNetworkReply* reply) const; + + /** + * Processes the reply. By default, parses the reply into + * a QJsonDocument and calls parseJson() if it's a valid JSON. + * + * @param reply raw contents of a HTTP reply from the server (without + * headers) + * + * @see gotReply, parseJson + */ + virtual Status parseReply(QNetworkReply* reply); + + /** + * Processes the JSON document received from the Matrix server. + * By default returns succesful status without analysing the JSON. + * + * @param json valid JSON document received from the server + * + * @see parseReply + */ + virtual Status parseJson(const QJsonDocument&); + + void setStatus(Status s); + void setStatus(int code, QString message); + + // Q_DECLARE_LOGGING_CATEGORY return different function types + // in different versions + using LoggingCategory = decltype(JOBS)*; + void setLoggingCategory(LoggingCategory lcf); + + // Job objects should only be deleted via QObject::deleteLater + ~BaseJob() override; protected slots: - void timeout(); + void timeout(); private slots: - void sendRequest(bool inBackground); - void checkReply(); - void gotReply(); + void sendRequest(bool inBackground); + void checkReply(); + void gotReply(); private: - void stop(); - void finishJob(); + void stop(); + void finishJob(); - class Private; - QScopedPointer d; + class Private; + QScopedPointer d; }; inline bool isJobRunning(BaseJob* job) { return job && job->error() == BaseJob::Pending; } -} // namespace QMatrixClient +} // namespace QMatrixClient diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 2bf9dd8f..12aacb8b 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -1,23 +1,24 @@ #include "downloadfilejob.h" -#include #include #include +#include using namespace QMatrixClient; class DownloadFileJob::Private { public: - Private() : tempFile(new QTemporaryFile()) { } + Private() : tempFile(new QTemporaryFile()) {} - explicit Private(const QString& localFilename) - : targetFile(new QFile(localFilename)) - , tempFile(new QFile(targetFile->fileName() + ".qmcdownload")) - { } + explicit Private(const QString& localFilename) + : targetFile(new QFile(localFilename)), + tempFile(new QFile(targetFile->fileName() + ".qmcdownload")) + { + } - QScopedPointer targetFile; - QScopedPointer tempFile; + QScopedPointer targetFile; + QScopedPointer tempFile; }; QUrl DownloadFileJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri) @@ -28,8 +29,8 @@ QUrl DownloadFileJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri) DownloadFileJob::DownloadFileJob(const QString& serverName, const QString& mediaId, const QString& localFilename) - : GetContentJob(serverName, mediaId) - , d(localFilename.isEmpty() ? new Private : new Private(localFilename)) + : GetContentJob(serverName, mediaId), + d(localFilename.isEmpty() ? new Private : new Private(localFilename)) { setObjectName("DownloadFileJob"); } @@ -41,16 +42,15 @@ QString DownloadFileJob::targetFileName() const void DownloadFileJob::beforeStart(const ConnectionData*) { - if (d->targetFile && !d->targetFile->isReadable() && - !d->targetFile->open(QIODevice::WriteOnly)) - { - qCWarning(JOBS) << "Couldn't open the file" - << d->targetFile->fileName() << "for writing"; + if (d->targetFile && !d->targetFile->isReadable() + && !d->targetFile->open(QIODevice::WriteOnly)) { + qCWarning(JOBS) << "Couldn't open the file" << d->targetFile->fileName() + << "for writing"; setStatus(FileError, "Could not open the target file for writing"); return; } - if (!d->tempFile->isReadable() && !d->tempFile->open(QIODevice::WriteOnly)) - { + if (!d->tempFile->isReadable() + && !d->tempFile->open(QIODevice::WriteOnly)) { qCWarning(JOBS) << "Couldn't open the temporary file" << d->tempFile->fileName() << "for writing"; setStatus(FileError, "Could not open the temporary download file"); @@ -61,16 +61,14 @@ void DownloadFileJob::beforeStart(const ConnectionData*) void DownloadFileJob::afterStart(const ConnectionData*, QNetworkReply* reply) { - connect(reply, &QNetworkReply::metaDataChanged, this, [this,reply] { + connect(reply, &QNetworkReply::metaDataChanged, this, [this, reply] { if (!status().good()) return; auto sizeHeader = reply->header(QNetworkRequest::ContentLengthHeader); - if (sizeHeader.isValid()) - { + if (sizeHeader.isValid()) { auto targetSize = sizeHeader.value(); if (targetSize != -1) - if (!d->tempFile->resize(targetSize)) - { + if (!d->tempFile->resize(targetSize)) { qCWarning(JOBS) << "Failed to allocate" << targetSize << "bytes for" << d->tempFile->fileName(); setStatus(FileError, @@ -78,16 +76,15 @@ void DownloadFileJob::afterStart(const ConnectionData*, QNetworkReply* reply) } } }); - connect(reply, &QIODevice::readyRead, this, [this,reply] { + connect(reply, &QIODevice::readyRead, this, [this, reply] { if (!status().good()) return; auto bytes = reply->read(reply->bytesAvailable()); if (!bytes.isEmpty()) d->tempFile->write(bytes); else - qCWarning(JOBS) - << "Unexpected empty chunk when downloading from" - << reply->url() << "to" << d->tempFile->fileName(); + qCWarning(JOBS) << "Unexpected empty chunk when downloading from" + << reply->url() << "to" << d->tempFile->fileName(); }); } @@ -100,22 +97,18 @@ void DownloadFileJob::beforeAbandon(QNetworkReply*) BaseJob::Status DownloadFileJob::parseReply(QNetworkReply*) { - if (d->targetFile) - { + if (d->targetFile) { d->targetFile->close(); - if (!d->targetFile->remove()) - { + if (!d->targetFile->remove()) { qCWarning(JOBS) << "Failed to remove the target file placeholder"; return { FileError, "Couldn't finalise the download" }; } - if (!d->tempFile->rename(d->targetFile->fileName())) - { + if (!d->tempFile->rename(d->targetFile->fileName())) { qCWarning(JOBS) << "Failed to rename" << d->tempFile->fileName() << "to" << d->targetFile->fileName(); return { FileError, "Couldn't finalise the download" }; } - } - else + } else d->tempFile->close(); qCDebug(JOBS) << "Saved a file as" << targetFileName(); return Success; diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index ce47ab1c..fd34ba5a 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -2,29 +2,27 @@ #include "csapi/content-repo.h" -namespace QMatrixClient -{ +namespace QMatrixClient { class DownloadFileJob : public GetContentJob { public: - enum { FileError = BaseJob::UserDefinedError + 1 }; + enum { FileError = BaseJob::UserDefinedError + 1 }; - using GetContentJob::makeRequestUrl; - static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri); + using GetContentJob::makeRequestUrl; + static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri); - DownloadFileJob(const QString& serverName, const QString& mediaId, - const QString& localFilename = {}); + DownloadFileJob(const QString& serverName, const QString& mediaId, + const QString& localFilename = {}); - QString targetFileName() const; + QString targetFileName() const; private: - class Private; - QScopedPointer d; + class Private; + QScopedPointer d; - void beforeStart(const ConnectionData*) override; - void afterStart(const ConnectionData*, - QNetworkReply* reply) override; - void beforeAbandon(QNetworkReply*) override; - Status parseReply(QNetworkReply*) override; + void beforeStart(const ConnectionData*) override; + void afterStart(const ConnectionData*, QNetworkReply* reply) override; + void beforeAbandon(QNetworkReply*) override; + Status parseReply(QNetworkReply*) override; }; } diff --git a/lib/jobs/mediathumbnailjob.cpp b/lib/jobs/mediathumbnailjob.cpp index aeb49839..d3370f1f 100644 --- a/lib/jobs/mediathumbnailjob.cpp +++ b/lib/jobs/mediathumbnailjob.cpp @@ -13,41 +13,42 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "mediathumbnailjob.h" using namespace QMatrixClient; -QUrl MediaThumbnailJob::makeRequestUrl(QUrl baseUrl, - const QUrl& mxcUri, QSize requestedSize) +QUrl MediaThumbnailJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri, + QSize requestedSize) { - return makeRequestUrl(std::move(baseUrl), - mxcUri.authority(), mxcUri.path().mid(1), - requestedSize.width(), requestedSize.height()); + return makeRequestUrl(std::move(baseUrl), mxcUri.authority(), + mxcUri.path().mid(1), requestedSize.width(), + requestedSize.height()); } MediaThumbnailJob::MediaThumbnailJob(const QString& serverName, - const QString& mediaId, QSize requestedSize) - : GetContentThumbnailJob(serverName, mediaId, - requestedSize.width(), requestedSize.height()) -{ } + const QString& mediaId, + QSize requestedSize) + : GetContentThumbnailJob(serverName, mediaId, requestedSize.width(), + requestedSize.height()) +{ +} MediaThumbnailJob::MediaThumbnailJob(const QUrl& mxcUri, QSize requestedSize) - : MediaThumbnailJob(mxcUri.authority(), mxcUri.path().mid(1), // sans leading '/' + : MediaThumbnailJob(mxcUri.authority(), + mxcUri.path().mid(1), // sans leading '/' requestedSize) -{ } - -QImage MediaThumbnailJob::thumbnail() const { - return _thumbnail; } +QImage MediaThumbnailJob::thumbnail() const { return _thumbnail; } + QImage MediaThumbnailJob::scaledThumbnail(QSize toSize) const { - return _thumbnail.scaled(toSize, - Qt::KeepAspectRatio, Qt::SmoothTransformation); + return _thumbnail.scaled(toSize, Qt::KeepAspectRatio, + Qt::SmoothTransformation); } BaseJob::Status MediaThumbnailJob::parseReply(QNetworkReply* reply) @@ -56,7 +57,7 @@ BaseJob::Status MediaThumbnailJob::parseReply(QNetworkReply* reply) if (!result.good()) return result; - if( _thumbnail.loadFromData(data()->readAll()) ) + if (_thumbnail.loadFromData(data()->readAll())) return Success; return { IncorrectResponseError, "Could not read image data" }; diff --git a/lib/jobs/mediathumbnailjob.h b/lib/jobs/mediathumbnailjob.h index 7963796e..1dcf8ccb 100644 --- a/lib/jobs/mediathumbnailjob.h +++ b/lib/jobs/mediathumbnailjob.h @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once @@ -22,26 +22,25 @@ #include -namespace QMatrixClient -{ - class MediaThumbnailJob: public GetContentThumbnailJob +namespace QMatrixClient { + class MediaThumbnailJob : public GetContentThumbnailJob { public: - using GetContentThumbnailJob::makeRequestUrl; - static QUrl makeRequestUrl(QUrl baseUrl, - const QUrl& mxcUri, QSize requestedSize); + using GetContentThumbnailJob::makeRequestUrl; + static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri, + QSize requestedSize); - MediaThumbnailJob(const QString& serverName, const QString& mediaId, - QSize requestedSize); - MediaThumbnailJob(const QUrl& mxcUri, QSize requestedSize); + MediaThumbnailJob(const QString& serverName, const QString& mediaId, + QSize requestedSize); + MediaThumbnailJob(const QUrl& mxcUri, QSize requestedSize); - QImage thumbnail() const; - QImage scaledThumbnail(QSize toSize) const; + QImage thumbnail() const; + QImage scaledThumbnail(QSize toSize) const; protected: - Status parseReply(QNetworkReply* reply) override; + Status parseReply(QNetworkReply* reply) override; private: - QImage _thumbnail; + QImage _thumbnail; }; -} // namespace QMatrixClient +} // namespace QMatrixClient diff --git a/lib/jobs/postreadmarkersjob.h b/lib/jobs/postreadmarkersjob.h index 63a8e1d0..3c5cac89 100644 --- a/lib/jobs/postreadmarkersjob.h +++ b/lib/jobs/postreadmarkersjob.h @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once @@ -27,13 +27,13 @@ using namespace QMatrixClient; class PostReadMarkersJob : public BaseJob { public: - explicit PostReadMarkersJob(const QString& roomId, - const QString& readUpToEventId) - : BaseJob(HttpVerb::Post, "PostReadMarkersJob", - QStringLiteral("_matrix/client/r0/rooms/%1/read_markers") - .arg(roomId)) - { - setRequestData(QJsonObject {{ - QStringLiteral("m.fully_read"), readUpToEventId }}); - } + explicit PostReadMarkersJob(const QString& roomId, + const QString& readUpToEventId) + : BaseJob(HttpVerb::Post, "PostReadMarkersJob", + QStringLiteral("_matrix/client/r0/rooms/%1/read_markers") + .arg(roomId)) + { + setRequestData(QJsonObject { + { QStringLiteral("m.fully_read"), readUpToEventId } }); + } }; diff --git a/lib/jobs/requestdata.cpp b/lib/jobs/requestdata.cpp index 5cb62221..477f49e7 100644 --- a/lib/jobs/requestdata.cpp +++ b/lib/jobs/requestdata.cpp @@ -1,10 +1,10 @@ #include "requestdata.h" +#include #include -#include #include #include -#include +#include using namespace QMatrixClient; @@ -17,22 +17,15 @@ auto fromData(const QByteArray& data) return source; } -template -inline auto fromJson(const JsonDataT& jdata) +template inline auto fromJson(const JsonDataT& jdata) { return fromData(QJsonDocument(jdata).toJson(QJsonDocument::Compact)); } -RequestData::RequestData(const QByteArray& a) - : _source(fromData(a)) -{ } +RequestData::RequestData(const QByteArray& a) : _source(fromData(a)) {} -RequestData::RequestData(const QJsonObject& jo) - : _source(fromJson(jo)) -{ } +RequestData::RequestData(const QJsonObject& jo) : _source(fromJson(jo)) {} -RequestData::RequestData(const QJsonArray& ja) - : _source(fromJson(ja)) -{ } +RequestData::RequestData(const QJsonArray& ja) : _source(fromJson(ja)) {} RequestData::~RequestData() = default; diff --git a/lib/jobs/requestdata.h b/lib/jobs/requestdata.h index db011b61..207ff731 100644 --- a/lib/jobs/requestdata.h +++ b/lib/jobs/requestdata.h @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once @@ -26,8 +26,7 @@ class QJsonArray; class QJsonDocument; class QIODevice; -namespace QMatrixClient -{ +namespace QMatrixClient { /** * A simple wrapper that represents the request body. * Provides a unified interface to dump an unstructured byte stream @@ -37,25 +36,23 @@ namespace QMatrixClient class RequestData { public: - RequestData() = default; - RequestData(const QByteArray& a); - RequestData(const QJsonObject& jo); - RequestData(const QJsonArray& ja); - RequestData(QIODevice* source) - : _source(std::unique_ptr(source)) - { } - RequestData(const RequestData&) = delete; - RequestData& operator=(const RequestData&) = delete; - RequestData(RequestData&&) = default; - RequestData& operator=(RequestData&&) = default; - ~RequestData(); + RequestData() = default; + RequestData(const QByteArray& a); + RequestData(const QJsonObject& jo); + RequestData(const QJsonArray& ja); + RequestData(QIODevice* source) + : _source(std::unique_ptr(source)) + { + } + RequestData(const RequestData&) = delete; + RequestData& operator=(const RequestData&) = delete; + RequestData(RequestData&&) = default; + RequestData& operator=(RequestData&&) = default; + ~RequestData(); - QIODevice* source() const - { - return _source.get(); - } + QIODevice* source() const { return _source.get(); } private: - std::unique_ptr _source; + std::unique_ptr _source; }; } // namespace QMatrixClient diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index 84385b55..db11005a 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "syncjob.h" @@ -29,25 +29,26 @@ SyncJob::SyncJob(const QString& since, const QString& filter, int timeout, { setLoggingCategory(SYNCJOB); QUrlQuery query; - if( !filter.isEmpty() ) + if (!filter.isEmpty()) query.addQueryItem(QStringLiteral("filter"), filter); - if( !presence.isEmpty() ) + if (!presence.isEmpty()) query.addQueryItem(QStringLiteral("set_presence"), presence); - if( timeout >= 0 ) + if (timeout >= 0) query.addQueryItem(QStringLiteral("timeout"), QString::number(timeout)); - if( !since.isEmpty() ) + if (!since.isEmpty()) query.addQueryItem(QStringLiteral("since"), since); setRequestQuery(query); setMaxRetries(std::numeric_limits::max()); } -SyncJob::SyncJob(const QString& since, const Filter& filter, - int timeout, const QString& presence) +SyncJob::SyncJob(const QString& since, const Filter& filter, int timeout, + const QString& presence) : SyncJob(since, QJsonDocument(toJson(filter)).toJson(QJsonDocument::Compact), timeout, presence) -{ } +{ +} BaseJob::Status SyncJob::parseJson(const QJsonDocument& data) { @@ -59,4 +60,3 @@ BaseJob::Status SyncJob::parseJson(const QJsonDocument& data) << d.unresolvedRooms().join(','); return BaseJob::IncorrectResponseError; } - diff --git a/lib/jobs/syncjob.h b/lib/jobs/syncjob.h index 036b25d0..2afaf0f7 100644 --- a/lib/jobs/syncjob.h +++ b/lib/jobs/syncjob.h @@ -13,33 +13,31 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include "basejob.h" -#include "../syncdata.h" #include "../csapi/definitions/sync_filter.h" +#include "../syncdata.h" -namespace QMatrixClient -{ - class SyncJob: public BaseJob +namespace QMatrixClient { + class SyncJob : public BaseJob { public: - explicit SyncJob(const QString& since = {}, - const QString& filter = {}, - int timeout = -1, const QString& presence = {}); - explicit SyncJob(const QString& since, const Filter& filter, - int timeout = -1, const QString& presence = {}); + explicit SyncJob(const QString& since = {}, const QString& filter = {}, + int timeout = -1, const QString& presence = {}); + explicit SyncJob(const QString& since, const Filter& filter, + int timeout = -1, const QString& presence = {}); - SyncData &&takeData() { return std::move(d); } + SyncData&& takeData() { return std::move(d); } protected: - Status parseJson(const QJsonDocument& data) override; + Status parseJson(const QJsonDocument& data) override; private: - SyncData d; + SyncData d; }; -} // namespace QMatrixClient +} // namespace QMatrixClient -- cgit v1.2.3 From d6cddf3e016a4fe3e906e2ab815a1e8b775c284c Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 14 Mar 2019 07:42:24 +0900 Subject: Fix read receipts and redactions on v3 rooms Previously slashes in eventIds (that come plenty in v3 due to base64 encoding) were not properly encoded - they are now. --- lib/jobs/basejob.cpp | 2 +- lib/room.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 8c3381ae..f738ce7a 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -186,7 +186,7 @@ QUrl BaseJob::makeRequestUrl(QUrl baseUrl, if (!pathBase.endsWith('/') && !path.startsWith('/')) pathBase.push_back('/'); - baseUrl.setPath( pathBase + path ); + baseUrl.setPath(pathBase + path, QUrl::TolerantMode); baseUrl.setQuery(query); return baseUrl; } diff --git a/lib/room.cpp b/lib/room.cpp index a4946b65..7494917d 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -579,8 +579,8 @@ Room::Changes Room::Private::markMessagesAsRead(rev_iter_t upToMarker) { if ((*upToMarker)->senderId() != q->localUser()->id()) { - connection->callApi(id, "m.read", - (*upToMarker)->id()); + connection->callApi(id, QStringLiteral("m.read"), + QUrl::toPercentEncoding((*upToMarker)->id())); break; } } @@ -1734,8 +1734,8 @@ void Room::unban(const QString& userId) void Room::redactEvent(const QString& eventId, const QString& reason) { - connection()->callApi( - id(), eventId, connection()->generateTxnId(), reason); + connection()->callApi(id(), + QUrl::toPercentEncoding(eventId), connection()->generateTxnId(), reason); } void Room::uploadFile(const QString& id, const QUrl& localFilename, -- cgit v1.2.3 From 432e7fd7107d8260e0016a1adcd8d94263dc1044 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 4 Apr 2019 21:27:38 +0900 Subject: Clean up on clang-tidy/clazy analysis --- lib/avatar.cpp | 2 +- lib/connection.cpp | 25 +++++++++++++++---------- lib/connectiondata.cpp | 6 +++--- lib/events/event.cpp | 3 ++- lib/events/stateevent.cpp | 2 +- lib/jobs/basejob.cpp | 2 +- lib/jobs/downloadfilejob.cpp | 5 +++-- lib/jobs/mediathumbnailjob.cpp | 2 +- lib/networkaccessmanager.cpp | 3 ++- lib/networksettings.cpp | 2 +- lib/room.cpp | 32 ++++++++++++++++---------------- lib/settings.cpp | 21 ++++++++++++--------- lib/settings.h | 2 +- lib/syncdata.cpp | 8 ++++---- lib/user.cpp | 14 ++++++++------ lib/util.cpp | 2 +- 16 files changed, 72 insertions(+), 59 deletions(-) (limited to 'lib/jobs') diff --git a/lib/avatar.cpp b/lib/avatar.cpp index c0ef3cba..9279ef9d 100644 --- a/lib/avatar.cpp +++ b/lib/avatar.cpp @@ -191,7 +191,7 @@ bool Avatar::Private::checkUrl(const QUrl& url) const } QString Avatar::Private::localFile() const { - static const auto cachePath = cacheLocation("avatars"); + static const auto cachePath = cacheLocation(QStringLiteral("avatars")); return cachePath % _url.authority() % '_' % _url.fileName() % ".png"; } diff --git a/lib/connection.cpp b/lib/connection.cpp index c09de979..5ed72616 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -717,8 +717,8 @@ void Connection::doInDirectChat(User* u, CreateRoomJob* Connection::createDirectChat(const QString& userId, const QString& topic, const QString& name) { - return createRoom(UnpublishRoom, "", name, topic, {userId}, - "trusted_private_chat", {}, true); + return createRoom(UnpublishRoom, {}, name, topic, {userId}, + QStringLiteral("trusted_private_chat"), {}, true); } ForgetRoomJob* Connection::forgetRoom(const QString& id) @@ -964,7 +964,8 @@ QHash> Connection::tagsToRooms() const QHash> result; for (auto* r: qAsConst(d->roomMap)) { - for (const auto& tagName: r->tagNames()) + const auto& tagNames = r->tagNames(); + for (const auto& tagName: tagNames) result[tagName].push_back(r); } for (auto it = result.begin(); it != result.end(); ++it) @@ -979,9 +980,12 @@ QStringList Connection::tagNames() const { QStringList tags ({FavouriteTag}); for (auto* r: qAsConst(d->roomMap)) - for (const auto& tag: r->tagNames()) + { + const auto& tagNames = r->tagNames(); + for (const auto& tag: tagNames) if (tag != LowPriorityTag && !tags.contains(tag)) tags.push_back(tag); + } tags.push_back(LowPriorityTag); return tags; } @@ -1264,18 +1268,19 @@ void Connection::saveState() const { QJsonObject rooms; QJsonObject inviteRooms; - for (const auto* i : roomMap()) // Pass on rooms in Leave state + const auto& rs = roomMap(); // Pass on rooms in Leave state + for (const auto* i : rs) (i->joinState() == JoinState::Invite ? inviteRooms : rooms) .insert(i->id(), QJsonValue::Null); QJsonObject roomObj; if (!rooms.isEmpty()) - roomObj.insert("join", rooms); + roomObj.insert(QStringLiteral("join"), rooms); if (!inviteRooms.isEmpty()) - roomObj.insert("invite", inviteRooms); + roomObj.insert(QStringLiteral("invite"), inviteRooms); - rootObj.insert("next_batch", d->data->lastEvent()); - rootObj.insert("rooms", roomObj); + rootObj.insert(QStringLiteral("next_batch"), d->data->lastEvent()); + rootObj.insert(QStringLiteral("rooms"), roomObj); } { QJsonArray accountDataEvents { @@ -1285,7 +1290,7 @@ void Connection::saveState() const accountDataEvents.append( basicEventJson(e.first, e.second->contentJson())); - rootObj.insert("account_data", + rootObj.insert(QStringLiteral("account_data"), QJsonObject {{ QStringLiteral("events"), accountDataEvents }}); } diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index eb516ef7..91cda09f 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -25,7 +25,7 @@ using namespace QMatrixClient; struct ConnectionData::Private { - explicit Private(const QUrl& url) : baseUrl(url) { } + explicit Private(QUrl url) : baseUrl(std::move(url)) { } QUrl baseUrl; QByteArray accessToken; @@ -37,7 +37,7 @@ struct ConnectionData::Private }; ConnectionData::ConnectionData(QUrl baseUrl) - : d(std::make_unique(baseUrl)) + : d(std::make_unique(std::move(baseUrl))) { } ConnectionData::~ConnectionData() = default; @@ -98,7 +98,7 @@ QString ConnectionData::lastEvent() const void ConnectionData::setLastEvent(QString identifier) { - d->lastEvent = identifier; + d->lastEvent = std::move(identifier); } QByteArray ConnectionData::generateTxnId() const diff --git a/lib/events/event.cpp b/lib/events/event.cpp index c98dfbb6..6505d89a 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -38,7 +38,8 @@ event_type_t EventTypeRegistry::initializeTypeId(event_mtype_t matrixTypeId) QString EventTypeRegistry::getMatrixType(event_type_t typeId) { - return typeId < get().eventTypes.size() ? get().eventTypes[typeId] : ""; + return typeId < get().eventTypes.size() + ? get().eventTypes[typeId] : QString(); } Event::Event(Type type, const QJsonObject& json) diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index e96614d2..a84f302b 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -27,7 +27,7 @@ using namespace QMatrixClient; RoomEvent::factory_t::addMethod( [] (const QJsonObject& json, const QString& matrixType) -> StateEventPtr { - if (!json.contains("state_key")) + if (!json.contains("state_key"_ls)) return nullptr; if (auto e = StateEventBase::factory_t::make(json, matrixType)) diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index f738ce7a..f521cc4b 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -430,7 +430,7 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) { d->rawResponse = reply->readAll(); - QJsonParseError error; + QJsonParseError error { 0, QJsonParseError::MissingObject }; const auto& json = QJsonDocument::fromJson(d->rawResponse, &error); if( error.error == QJsonParseError::NoError ) return parseJson(json); diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 2bf9dd8f..672a7b2d 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -22,7 +22,8 @@ class DownloadFileJob::Private QUrl DownloadFileJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri) { - return makeRequestUrl(baseUrl, mxcUri.authority(), mxcUri.path().mid(1)); + return makeRequestUrl( + std::move(baseUrl), mxcUri.authority(), mxcUri.path().mid(1)); } DownloadFileJob::DownloadFileJob(const QString& serverName, @@ -31,7 +32,7 @@ DownloadFileJob::DownloadFileJob(const QString& serverName, : GetContentJob(serverName, mediaId) , d(localFilename.isEmpty() ? new Private : new Private(localFilename)) { - setObjectName("DownloadFileJob"); + setObjectName(QStringLiteral("DownloadFileJob")); } QString DownloadFileJob::targetFileName() const diff --git a/lib/jobs/mediathumbnailjob.cpp b/lib/jobs/mediathumbnailjob.cpp index aeb49839..edb9b156 100644 --- a/lib/jobs/mediathumbnailjob.cpp +++ b/lib/jobs/mediathumbnailjob.cpp @@ -59,5 +59,5 @@ BaseJob::Status MediaThumbnailJob::parseReply(QNetworkReply* reply) if( _thumbnail.loadFromData(data()->readAll()) ) return Success; - return { IncorrectResponseError, "Could not read image data" }; + return { IncorrectResponseError, QStringLiteral("Could not read image data") }; } diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 89967a8a..7d9cb360 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -29,7 +29,8 @@ class NetworkAccessManager::Private QList ignoredSslErrors; }; -NetworkAccessManager::NetworkAccessManager(QObject* parent) : d(std::make_unique()) +NetworkAccessManager::NetworkAccessManager(QObject* parent) + : QNetworkAccessManager(parent), d(std::make_unique()) { } QList NetworkAccessManager::ignoredSslErrors() const diff --git a/lib/networksettings.cpp b/lib/networksettings.cpp index 48bd09f3..6ff2bc1f 100644 --- a/lib/networksettings.cpp +++ b/lib/networksettings.cpp @@ -27,5 +27,5 @@ void NetworkSettings::setupApplicationProxy() const } QMC_DEFINE_SETTING(NetworkSettings, QNetworkProxy::ProxyType, proxyType, "proxy_type", QNetworkProxy::DefaultProxy, setProxyType) -QMC_DEFINE_SETTING(NetworkSettings, QString, proxyHostName, "proxy_hostname", "", setProxyHostName) +QMC_DEFINE_SETTING(NetworkSettings, QString, proxyHostName, "proxy_hostname", {}, setProxyHostName) QMC_DEFINE_SETTING(NetworkSettings, quint16, proxyPort, "proxy_port", -1, setProxyPort) diff --git a/lib/room.cpp b/lib/room.cpp index 587b598d..f031273a 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -168,7 +168,7 @@ class Room::Private //void inviteUser(User* u); // We might get it at some point in time. void insertMemberIntoMap(User* u); - void renameMember(User* u, QString oldName); + void renameMember(User* u, const QString& oldName); void removeMemberFromMap(const QString& username, User* u); // This updates the room displayname field (which is the way a room @@ -185,7 +185,7 @@ class Room::Private void getPreviousContent(int limit = 10); template - const EventT* getCurrentState(QString stateKey = {}) const + const EventT* getCurrentState(const QString& stateKey = {}) const { static const EventT empty; const auto* evt = @@ -236,8 +236,8 @@ class Room::Private * @param placement - position and direction of insertion: Older for * historical messages, Newer for new ones */ - Timeline::difference_type moveEventsToTimeline(RoomEventsRange events, - EventsPlacement placement); + Timeline::size_type moveEventsToTimeline(RoomEventsRange events, + EventsPlacement placement); /** * Remove events from the passed container that are already in the timeline @@ -341,7 +341,7 @@ const QString& Room::id() const QString Room::version() const { const auto v = d->getCurrentState()->version(); - return v.isEmpty() ? "1" : v; + return v.isEmpty() ? QStringLiteral("1") : v; } bool Room::isUnstable() const @@ -546,8 +546,8 @@ Room::Changes Room::Private::promoteReadMarker(User* u, rev_iter_t newMarker, { const auto oldUnreadCount = unreadMessages; QElapsedTimer et; et.start(); - unreadMessages = count_if(eagerMarker, timeline.cend(), - std::bind(&Room::Private::isEventNotable, this, _1)); + unreadMessages = int(count_if(eagerMarker, timeline.cend(), + std::bind(&Room::Private::isEventNotable, this, _1))); if (et.nsecsElapsed() > profilerMinNsecs() / 10) qCDebug(PROFILER) << "Recounting unread messages took" << et; @@ -611,7 +611,7 @@ bool Room::canSwitchVersions() const // TODO, #276: m.room.power_levels const auto* plEvt = - d->currentState.value({"m.room.power_levels", ""}); + d->currentState.value({QStringLiteral("m.room.power_levels"), {}}); if (!plEvt) return true; @@ -621,7 +621,7 @@ bool Room::canSwitchVersions() const .value(localUser()->id()).toInt( plJson.value("users_default"_ls).toInt()); const auto tombstonePowerLevel = - plJson.value("events").toObject() + plJson.value("events"_ls).toObject() .value("m.room.tombstone"_ls).toInt( plJson.value("state_default"_ls).toInt()); return currentUserLevel >= tombstonePowerLevel; @@ -954,7 +954,7 @@ void Room::Private::setTags(TagsMap newTags) } tags = move(newTags); qCDebug(MAIN) << "Room" << q->objectName() << "is tagged with" - << q->tagNames().join(", "); + << q->tagNames().join(QStringLiteral(", ")); emit q->tagsChanged(); } @@ -1203,7 +1203,7 @@ void Room::Private::insertMemberIntoMap(User *u) emit q->memberRenamed(namesakes.front()); } -void Room::Private::renameMember(User* u, QString oldName) +void Room::Private::renameMember(User* u, const QString& oldName) { if (u->name(q) == oldName) { @@ -1241,7 +1241,7 @@ inline auto makeErrorStr(const Event& e, QByteArray msg) return msg.append("; event dump follows:\n").append(e.originalJson()); } -Room::Timeline::difference_type Room::Private::moveEventsToTimeline( +Room::Timeline::size_type Room::Private::moveEventsToTimeline( RoomEventsRange events, EventsPlacement placement) { Q_ASSERT(!events.empty()); @@ -1414,7 +1414,7 @@ QString Room::Private::doSendEvent(const RoomEvent* pEvent) return; } it->setDeparted(); - emit q->pendingEventChanged(it - unsyncedEvents.begin()); + emit q->pendingEventChanged(int(it - unsyncedEvents.begin())); }); Room::connect(call, &BaseJob::failure, q, std::bind(&Room::Private::onEventSendingFailure, this, txnId, call)); @@ -1430,7 +1430,7 @@ QString Room::Private::doSendEvent(const RoomEvent* pEvent) } it->setReachedServer(call->eventId()); - emit q->pendingEventChanged(it - unsyncedEvents.begin()); + emit q->pendingEventChanged(int(it - unsyncedEvents.begin())); }); } else onEventSendingFailure(txnId); @@ -1449,7 +1449,7 @@ void Room::Private::onEventSendingFailure(const QString& txnId, BaseJob* call) it->setSendingFailed(call ? call->statusCaption() % ": " % call->errorString() : tr("The call could not be started")); - emit q->pendingEventChanged(it - unsyncedEvents.begin()); + emit q->pendingEventChanged(int(it - unsyncedEvents.begin())); } QString Room::retryMessage(const QString& txnId) @@ -2052,7 +2052,7 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events) roomChanges |= q->processStateEvent(*eptr); auto timelineSize = timeline.size(); - auto totalInserted = 0; + size_t totalInserted = 0; for (auto it = events.begin(); it != events.end();) { auto nextPendingPair = findFirstOf(it, events.end(), diff --git a/lib/settings.cpp b/lib/settings.cpp index 852e19cb..124d7042 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -84,18 +84,21 @@ void SettingsGroup::remove(const QString& key) Settings::remove(fullKey); } -QMC_DEFINE_SETTING(AccountSettings, QString, deviceId, "device_id", "", setDeviceId) -QMC_DEFINE_SETTING(AccountSettings, QString, deviceName, "device_name", "", setDeviceName) +QMC_DEFINE_SETTING(AccountSettings, QString, deviceId, "device_id", {}, setDeviceId) +QMC_DEFINE_SETTING(AccountSettings, QString, deviceName, "device_name", {}, setDeviceName) QMC_DEFINE_SETTING(AccountSettings, bool, keepLoggedIn, "keep_logged_in", false, setKeepLoggedIn) +static const auto HomeserverKey = QStringLiteral("homeserver"); +static const auto AccessTokenKey = QStringLiteral("access_token"); + QUrl AccountSettings::homeserver() const { - return QUrl::fromUserInput(value("homeserver").toString()); + return QUrl::fromUserInput(value(HomeserverKey).toString()); } void AccountSettings::setHomeserver(const QUrl& url) { - setValue("homeserver", url.toString()); + setValue(HomeserverKey, url.toString()); } QString AccountSettings::userId() const @@ -105,19 +108,19 @@ QString AccountSettings::userId() const QString AccountSettings::accessToken() const { - return value("access_token").toString(); + return value(AccessTokenKey).toString(); } void AccountSettings::setAccessToken(const QString& accessToken) { qCWarning(MAIN) << "Saving access_token to QSettings is insecure." " Developers, please save access_token separately."; - setValue("access_token", accessToken); + setValue(AccessTokenKey, accessToken); } void AccountSettings::clearAccessToken() { - legacySettings.remove("access_token"); - legacySettings.remove("device_id"); // Force the server to re-issue it - remove("access_token"); + legacySettings.remove(AccessTokenKey); + legacySettings.remove(QStringLiteral("device_id")); // Force the server to re-issue it + remove(AccessTokenKey); } diff --git a/lib/settings.h b/lib/settings.h index 0b3ecaff..759bda35 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -119,7 +119,7 @@ type classname::propname() const \ \ void classname::setter(type newValue) \ { \ - setValue(QStringLiteral(qsettingname), newValue); \ + setValue(QStringLiteral(qsettingname), std::move(newValue)); \ } \ class AccountSettings: public SettingsGroup diff --git a/lib/syncdata.cpp b/lib/syncdata.cpp index f55d4396..21517884 100644 --- a/lib/syncdata.cpp +++ b/lib/syncdata.cpp @@ -72,7 +72,7 @@ void JsonObjectConverter::fillFrom(const QJsonObject& jo, { fromJson(jo["m.joined_member_count"_ls], rs.joinedMemberCount); fromJson(jo["m.invited_member_count"_ls], rs.invitedMemberCount); - fromJson(jo["m.heroes"], rs.heroes); + fromJson(jo["m.heroes"_ls], rs.heroes); } template @@ -85,7 +85,7 @@ SyncRoomData::SyncRoomData(const QString& roomId_, JoinState joinState_, const QJsonObject& room_) : roomId(roomId_) , joinState(joinState_) - , summary(fromJson(room_["summary"])) + , summary(fromJson(room_["summary"_ls])) , state(load(room_, joinState == JoinState::Invite ? "invite_state"_ls : "state"_ls)) { @@ -121,8 +121,8 @@ SyncData::SyncData(const QString& cacheFileName) QFileInfo cacheFileInfo { cacheFileName }; auto json = loadJson(cacheFileName); auto requiredVersion = std::get<0>(cacheVersion()); - auto actualVersion = json.value("cache_version").toObject() - .value("major").toInt(); + auto actualVersion = json.value("cache_version"_ls).toObject() + .value("major"_ls).toInt(); if (actualVersion == requiredVersion) parseJson(json, cacheFileInfo.absolutePath() + '/'); else diff --git a/lib/user.cpp b/lib/user.cpp index 951ad87d..17db5760 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -59,7 +59,7 @@ class User::Private QMultiHash otherNames; Avatar mostUsedAvatar { makeAvatar({}) }; std::vector otherAvatars; - auto otherAvatar(QUrl url) + auto otherAvatar(const QUrl& url) { return std::find_if(otherAvatars.begin(), otherAvatars.end(), [&url] (const auto& av) { return av.url() == url; }); @@ -69,7 +69,7 @@ class User::Private mutable int totalRooms = 0; QString nameForRoom(const Room* r, const QString& hint = {}) const; - void setNameForRoom(const Room* r, QString newName, QString oldName); + void setNameForRoom(const Room* r, QString newName, const QString& oldName); QUrl avatarUrlForRoom(const Room* r, const QUrl& hint = {}) const; void setAvatarForRoom(const Room* r, const QUrl& newUrl, const QUrl& oldUrl); @@ -91,7 +91,7 @@ QString User::Private::nameForRoom(const Room* r, const QString& hint) const static constexpr int MIN_JOINED_ROOMS_TO_LOG = 20; void User::Private::setNameForRoom(const Room* r, QString newName, - QString oldName) + const QString& oldName) { Q_ASSERT(oldName != newName); Q_ASSERT(oldName == mostUsedName || otherNames.contains(oldName, r)); @@ -118,7 +118,8 @@ void User::Private::setNameForRoom(const Room* r, QString newName, et.start(); } - for (auto* r1: connection->roomMap()) + const auto& roomMap = connection->roomMap(); + for (auto* r1: roomMap) if (nameForRoom(r1) == mostUsedName) otherNames.insert(mostUsedName, r1); @@ -178,7 +179,8 @@ void User::Private::setAvatarForRoom(const Room* r, const QUrl& newUrl, auto nextMostUsedIt = otherAvatar(newUrl); Q_ASSERT(nextMostUsedIt != otherAvatars.end()); std::swap(mostUsedAvatar, *nextMostUsedIt); - for (const auto* r1: connection->roomMap()) + const auto& roomMap = connection->roomMap(); + for (const auto* r1: roomMap) if (avatarUrlForRoom(r1) == nextMostUsedIt->url()) avatarsToRooms.insert(nextMostUsedIt->url(), r1); @@ -399,7 +401,7 @@ void User::processEvent(const RoomMemberEvent& event, const Room* room, // exceptionally rare (the only reasonable case being that the bridge // changes the naming convention). For the same reason room-specific // bridge tags are not supported at all. - QRegularExpression reSuffix(" \\((IRC|Gitter|Telegram)\\)$"); + QRegularExpression reSuffix(QStringLiteral(" \\((IRC|Gitter|Telegram)\\)$")); auto match = reSuffix.match(newName); if (match.hasMatch()) { diff --git a/lib/util.cpp b/lib/util.cpp index fe6286f3..c3e21c8e 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -157,7 +157,7 @@ static_assert(!is_callable_v>, "Test non-function object"); // "Test returns<> with static member function"); template -QString ft(T&&); +QString ft(T&&) { return {}; } static_assert(std::is_same)>, QString&&>(), "Test function templates"); -- cgit v1.2.3 From a6df4183d6da324f2c2329f21d732071b3337cb8 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 15 Apr 2019 20:29:00 +0900 Subject: BaseJob: fix a possible crash upon logout See https://github.com/QMatrixClient/Quaternion/issues/566 for details. --- lib/jobs/basejob.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index f521cc4b..a79d0e03 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -600,10 +600,25 @@ QUrl BaseJob::errorUrl() const void BaseJob::setStatus(Status s) { + // The crash that led to this code has been reported in + // https://github.com/QMatrixClient/Quaternion/issues/566 - basically, + // when cleaning up childrent of a deleted Connection, there's a chance + // of pending jobs being abandoned, calling setStatus(Abandoned). + // There's nothing wrong with this; however, the safety check for + // cleartext access tokens below uses d->connection - which is a dangling + // pointer. + // To alleviate that, a stricter condition is applied, that for Abandoned + // and to-be-Abandoned jobs the status message will be disregarded entirely. + // For 0.6 we might rectify the situation by making d->connection + // a QPointer<> (and derive ConnectionData from QObject, respectively). + if (d->status.code == Abandoned || s.code == Abandoned) + s.message.clear(); + if (d->status == s) return; - if (d->connection && !d->connection->accessToken().isEmpty()) + if (!s.message.isEmpty() + && d->connection && !d->connection->accessToken().isEmpty()) s.message.replace(d->connection->accessToken(), "(REDACTED)"); if (!s.good()) qCWarning(d->logCat) << this << "status" << s; -- cgit v1.2.3 From 8a3bb2d5b27824890482fa7185bbc1fcda9dd49c Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 16 Apr 2019 16:21:53 +0900 Subject: BaseJob: preserve the calculated error code if JSON error code is unknown Resetting the code to IncorrectRequestError has been a part of the cause for the incorrect Quaternion behaviour on expired tokens. --- lib/jobs/basejob.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index a79d0e03..0d9b9f10 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -334,8 +334,7 @@ void BaseJob::gotReply() tr("Requested room version: %1") .arg(json.value("room_version").toString()); } else if (!json.isEmpty()) // Not localisable on the client side - setStatus(IncorrectRequestError, - json.value("error"_ls).toString()); + setStatus(d->status.code, json.value("error"_ls).toString()); } } -- cgit v1.2.3 From 26c51455901a6c0112531d86d61d65d31a70dfaa Mon Sep 17 00:00:00 2001 From: Ville Ranki Date: Thu, 4 Apr 2019 11:45:41 +0300 Subject: Ignore some errors on leaving rooms, add new error enum. Fixes #307 --- lib/connection.cpp | 56 ++++++++++++++++++++++++++++++++++++---------------- lib/jobs/basejob.cpp | 3 +++ lib/jobs/basejob.h | 1 + 3 files changed, 43 insertions(+), 17 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index a7eae30f..5bf89815 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -110,6 +110,7 @@ class Connection::Private void connectWithToken(const QString& user, const QString& accessToken, const QString& deviceId); + void removeRoom(const QString& roomId); template EventT* unpackAccountData() const @@ -790,29 +791,36 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) if (room && room->joinState() != JoinState::Leave) { auto leaveJob = room->leaveRoom(); - connect(leaveJob, &BaseJob::success, this, [this, forgetJob, room] { - forgetJob->start(connectionData()); - // If the matching /sync response hasn't arrived yet, mark the room - // for explicit deletion - if (room->joinState() != JoinState::Leave) - d->roomIdsToForget.push_back(room->id()); + connect(leaveJob, &BaseJob::result, this, [this, leaveJob, forgetJob, room] { + // After leave, continue if there is no error or the room id is not found (IncorrectRequestError) + if(!leaveJob->error() || leaveJob->error() == BaseJob::StatusCode::UnknownObjectError) { + forgetJob->start(connectionData()); + // If the matching /sync response hasn't arrived yet, mark the room + // for explicit deletion + if (room->joinState() != JoinState::Leave) + d->roomIdsToForget.push_back(room->id()); + } else { + qCWarning(MAIN) << "Error leaving room " + << room->name() << ":" + << leaveJob->errorString(); + forgetJob->abandon(); + } }); connect(leaveJob, &BaseJob::failure, forgetJob, &BaseJob::abandon); } else forgetJob->start(connectionData()); - connect(forgetJob, &BaseJob::success, this, [this, id] + connect(forgetJob, &BaseJob::result, this, [this, id, forgetJob] { - // Delete whatever instances of the room are still in the map. - for (auto f: {false, true}) - if (auto r = d->roomMap.take({ id, f })) - { - qCDebug(MAIN) << "Room" << r->objectName() - << "in state" << toCString(r->joinState()) - << "will be deleted"; - emit r->beforeDestruction(r); - r->deleteLater(); - } + // Leave room in case of success, or room not known by server + if(!forgetJob->error() || forgetJob->error() == BaseJob::StatusCode::IncorrectRequestError || forgetJob->error() == BaseJob::StatusCode::UnknownObjectError) { + // Delete the room from roomMap + d->removeRoom(id); + } else { + qCWarning(MAIN) << "Error forgetting room " + << id << ":" + << forgetJob->errorString(); + } }); return forgetJob; } @@ -1056,6 +1064,20 @@ Connection::DirectChatsMap Connection::directChats() const return d->directChats; } +// Removes room with given id from roomMap +void Connection::Private::removeRoom(const QString& roomId) +{ + for (auto f: {false, true}) + if (auto r = roomMap.take({ roomId, f })) + { + qCDebug(MAIN) << "Room" << r->objectName() + << "in state" << toCString(r->joinState()) + << "will be deleted"; + emit r->beforeDestruction(r); + r->deleteLater(); + } +} + void Connection::addToDirectChats(const Room* room, User* user) { Q_ASSERT(room != nullptr && user != nullptr); diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 0d9b9f10..97b5a904 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -325,6 +325,9 @@ void BaseJob::gotReply() d->status.code = UserConsentRequiredError; d->errorUrl = json.value("consent_uri"_ls).toString(); } + else if (errCode == "M_UNKNOWN") { + d->status.code = UnknownObjectError; + } else if (errCode == "M_UNSUPPORTED_ROOM_VERSION" || errCode == "M_INCOMPATIBLE_ROOM_VERSION") { diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 4c1c7706..c1747cca 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -67,6 +67,7 @@ namespace QMatrixClient , UnsupportedRoomVersionError , NetworkAuthRequiredError , UserConsentRequiredError + , UnknownObjectError // Unknown room or other item (M_UNKNOWN) , UserDefinedError = 200 }; -- cgit v1.2.3 From e8718d8b1d61d6f70e61da0436f793a461e83bd7 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 7 Jun 2019 19:23:55 +0900 Subject: BaseJob::StatusCode: add Error-less synonyms; officially deprecate JsonParseError --- lib/jobs/basejob.cpp | 2 -- lib/jobs/basejob.h | 34 +++++++++++++++++++++------------- 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 0d9b9f10..34fc0f57 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -555,8 +555,6 @@ QString BaseJob::statusCaption() const return tr("Request was abandoned"); case NetworkError: return tr("Network problems"); - case JsonParseError: - return tr("Response could not be parsed"); case TimeoutError: return tr("Request timed out"); case ContentAccessError: diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 4c1c7706..4ee63adb 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -46,28 +46,36 @@ namespace QMatrixClient Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries) public: - /* Just in case, the values are compatible with KJob - * (which BaseJob used to inherit from). */ enum StatusCode { NoError = 0 // To be compatible with Qt conventions , Success = 0 , Pending = 1 , WarningLevel = 20 - , UnexpectedResponseTypeWarning = 21 + , UnexpectedResponseType = 21 + , UnexpectedResponseTypeWarning = UnexpectedResponseType , Abandoned = 50 //< A very brief period between abandoning and object deletion , ErrorLevel = 100 //< Errors have codes starting from this , NetworkError = 100 - , JsonParseError // TODO: Merge into IncorrectResponseError - , TimeoutError + , Timeout + , TimeoutError = Timeout , ContentAccessError , NotFoundError - , IncorrectRequestError - , IncorrectResponseError - , TooManyRequestsError - , RequestNotImplementedError - , UnsupportedRoomVersionError - , NetworkAuthRequiredError - , UserConsentRequiredError - , UserDefinedError = 200 + , IncorrectRequest + , IncorrectRequestError = IncorrectRequest + , IncorrectResponse + , IncorrectResponseError = IncorrectResponse + , JsonParseError //< deprecated; Use IncorrectResponse instead + = IncorrectResponse + , TooManyRequests + , TooManyRequestsError = TooManyRequests + , RequestNotImplemented + , RequestNotImplementedError = RequestNotImplemented + , UnsupportedRoomVersion + , UnsupportedRoomVersionError = UnsupportedRoomVersion + , NetworkAuthRequired + , NetworkAuthRequiredError = NetworkAuthRequired + , UserConsentRequired + , UserConsentRequiredError = UserConsentRequired + , UserDefinedError = 256 }; /** -- cgit v1.2.3 From 5722ceaf4bd10c29f1091e3dc5a87f5650ea8c71 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 26 Jun 2019 07:51:08 +0900 Subject: BaseJob::Status: fromHttpCode --- lib/jobs/basejob.cpp | 61 +++++++++++++++++++++++++--------------------------- lib/jobs/basejob.h | 4 ++-- 2 files changed, 31 insertions(+), 34 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index a0a3dc29..9c0b431c 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -348,6 +348,34 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) return false; } +BaseJob::Status BaseJob::Status::fromHttpCode(int httpCode, QString msg) +{ + // clang-format off + return { [httpCode]() -> StatusCode { + if (httpCode / 10 == 41) // 41x errors + return httpCode == 410 ? IncorrectRequestError : NotFoundError; + switch (httpCode) { + case 401: case 403: case 407: + return ContentAccessError; + case 404: + return NotFoundError; + case 400: case 405: case 406: case 426: case 428: case 505: + case 494: // Unofficial nginx "Request header too large" + case 497: // Unofficial nginx "HTTP request sent to HTTPS port" + return IncorrectRequestError; + case 429: + return TooManyRequestsError; + case 501: case 510: + return RequestNotImplementedError; + case 511: + return NetworkAuthRequiredError; + default: + return NetworkError; + } + }(), msg }; + // clang-format on +} + BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const { // QNetworkReply error codes seem to be flawed when it comes to HTTP; @@ -381,38 +409,7 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const qCWarning(d->logCat).noquote().nospace() << this << urlString; qCWarning(d->logCat).noquote() << " " << httpCode << reason << replyState; - return { [httpCode]() -> StatusCode { - if (httpCode / 10 == 41) - return httpCode == 410 ? IncorrectRequestError - : NotFoundError; - switch (httpCode) { - case 401: - case 403: - case 407: - return ContentAccessError; - case 404: - return NotFoundError; - case 400: - case 405: - case 406: - case 426: - case 428: - case 505: - case 494: // Unofficial nginx "Request header too large" - case 497: // Unofficial nginx "HTTP request sent to HTTPS port" - return IncorrectRequestError; - case 429: - return TooManyRequestsError; - case 501: - case 510: - return RequestNotImplementedError; - case 511: - return NetworkAuthRequiredError; - default: - return NetworkError; - } - }(), - reply->errorString() }; + return Status::fromHttpCode(httpCode, reply->errorString()); } BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 04d79c66..4d379f26 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -116,9 +116,8 @@ public: * along the lines of StatusCode, with additional values * starting at UserDefinedError */ - class Status + struct Status { - public: Status(StatusCode c) : code(c) {} @@ -126,6 +125,7 @@ public: : code(c) , message(std::move(m)) {} + static Status fromHttpCode(int httpCode, QString msg = {}); bool good() const { return code < ErrorLevel; } friend QDebug operator<<(QDebug dbg, const Status& s) -- cgit v1.2.3 From 12478cf7330727083103d22f76de92c4aa476f5b Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 1 Jul 2019 16:10:35 +0900 Subject: Handle M_UNKNOWN as The Spec says; factor out BaseJob::parseError() --- lib/connection.cpp | 46 ++++++++++++------------- lib/jobs/basejob.cpp | 96 +++++++++++++++++++++++++++------------------------- lib/jobs/basejob.h | 14 ++++++-- 3 files changed, 83 insertions(+), 73 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index af2aa2ab..4c068b8f 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -791,21 +791,23 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) if (room && room->joinState() != JoinState::Leave) { auto leaveJob = room->leaveRoom(); - connect(leaveJob, &BaseJob::result, this, [this, leaveJob, forgetJob, room] { - // After leave, continue if there is no error or the room id is not found - if(!leaveJob->error() || leaveJob->error() == BaseJob::StatusCode::UnknownObjectError) { - forgetJob->start(connectionData()); - // If the matching /sync response hasn't arrived yet, mark the room - // for explicit deletion - if (room->joinState() != JoinState::Leave) - d->roomIdsToForget.push_back(room->id()); - } else { - qCWarning(MAIN) << "Error leaving room " - << room->name() << ":" - << leaveJob->errorString(); - forgetJob->abandon(); - } - }); + connect(leaveJob, &BaseJob::result, this, + [this, leaveJob, forgetJob, room] { + if (leaveJob->error() == BaseJob::Success + || leaveJob->error() == BaseJob::NotFoundError) + { + forgetJob->start(connectionData()); + // If the matching /sync response hasn't arrived yet, + // mark the room for explicit deletion + if (room->joinState() != JoinState::Leave) + d->roomIdsToForget.push_back(room->id()); + } else { + qCWarning(MAIN).nospace() + << "Error leaving room " << room->objectName() + << ": " << leaveJob->errorString(); + forgetJob->abandon(); + } + }); connect(leaveJob, &BaseJob::failure, forgetJob, &BaseJob::abandon); } else @@ -813,14 +815,12 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) connect(forgetJob, &BaseJob::result, this, [this, id, forgetJob] { // Leave room in case of success, or room not known by server - if(!forgetJob->error() || forgetJob->error() == BaseJob::UnknownObjectError) { - // Delete the room from roomMap - d->removeRoom(id); - } else { - qCWarning(MAIN) << "Error forgetting room " - << id << ":" - << forgetJob->errorString(); - } + if(forgetJob->error() == BaseJob::Success + || forgetJob->error() == BaseJob::NotFoundError) + d->removeRoom(id); // Delete the room from roomMap + else + qCWarning(MAIN).nospace() << "Error forgetting room " << id << ": " + << forgetJob->errorString(); }); return forgetJob; } diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 97b5a904..dbf197ec 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -289,59 +289,23 @@ void BaseJob::gotReply() if (status().good()) setStatus(parseReply(d->reply.data())); else { - // FIXME: Factor out to smth like BaseJob::handleError() d->rawResponse = d->reply->readAll(); const auto jsonBody = - d->reply->rawHeader("Content-Type") == "application/json"; + d->reply->rawHeader("Content-Type") == "application/json"; qCDebug(d->logCat).noquote() - << "Error body (truncated if long):" << d->rawResponse.left(500); + << "Error body (truncated if long):" << d->rawResponse.left(500); if (jsonBody) - { - auto json = QJsonDocument::fromJson(d->rawResponse).object(); - const auto errCode = json.value("errcode"_ls).toString(); - if (error() == TooManyRequestsError || - errCode == "M_LIMIT_EXCEEDED") - { - QString msg = tr("Too many requests"); - auto retryInterval = json.value("retry_after_ms"_ls).toInt(-1); - if (retryInterval != -1) - msg += tr(", next retry advised after %1 ms") - .arg(retryInterval); - else // We still have to figure some reasonable interval - retryInterval = getNextRetryInterval(); - - setStatus(TooManyRequestsError, msg); - - // Shortcut to retry instead of executing finishJob() - stop(); - qCWarning(d->logCat) - << this << "will retry in" << retryInterval << "ms"; - d->retryTimer.start(retryInterval); - emit retryScheduled(d->retriesTaken, retryInterval); - return; - } - if (errCode == "M_CONSENT_NOT_GIVEN") - { - d->status.code = UserConsentRequiredError; - d->errorUrl = json.value("consent_uri"_ls).toString(); - } - else if (errCode == "M_UNKNOWN") { - d->status.code = UnknownObjectError; - } - else if (errCode == "M_UNSUPPORTED_ROOM_VERSION" || - errCode == "M_INCOMPATIBLE_ROOM_VERSION") - { - d->status.code = UnsupportedRoomVersionError; - if (json.contains("room_version")) - d->status.message = - tr("Requested room version: %1") - .arg(json.value("room_version").toString()); - } else if (!json.isEmpty()) // Not localisable on the client side - setStatus(d->status.code, json.value("error"_ls).toString()); - } + setStatus( + parseError(d->reply.data(), + QJsonDocument::fromJson(d->rawResponse).object())); } - finishJob(); + if (error() != TooManyRequestsError) + finishJob(); + else { + stop(); + emit retryScheduled(d->retriesTaken, d->retryTimer.interval()); + } } bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) @@ -445,8 +409,46 @@ BaseJob::Status BaseJob::parseJson(const QJsonDocument&) return Success; } +BaseJob::Status BaseJob::parseError(QNetworkReply* reply, + const QJsonObject& errorJson) +{ + const auto errCode = errorJson.value("errcode"_ls).toString(); + if (error() == TooManyRequestsError || errCode == "M_LIMIT_EXCEEDED") { + QString msg = tr("Too many requests"); + auto retryInterval = errorJson.value("retry_after_ms"_ls).toInt(-1); + if (retryInterval != -1) + msg += tr(", next retry advised after %1 ms").arg(retryInterval); + else // We still have to figure some reasonable interval + retryInterval = getNextRetryInterval(); + + qCWarning(d->logCat) << this << "will retry in" << retryInterval << "ms"; + d->retryTimer.start(retryInterval); + + return { TooManyRequestsError, msg }; + } + if (errCode == "M_CONSENT_NOT_GIVEN") { + d->errorUrl = errorJson.value("consent_uri"_ls).toString(); + return { UserConsentRequiredError }; + } + if (errCode == "M_UNSUPPORTED_ROOM_VERSION" + || errCode == "M_INCOMPATIBLE_ROOM_VERSION") + return { UnsupportedRoomVersionError, + errorJson.contains("room_version"_ls) + ? tr("Requested room version: %1") + .arg(errorJson.value("room_version"_ls).toString()) + : errorJson.value("error"_ls).toString() }; + + // Not localisable on the client side + if (errorJson.contains("error"_ls)) + d->status.message = errorJson.value("error"_ls).toString(); + + return d->status; +} + void BaseJob::stop() { + // This method is used to semi-finalise the job before retrying; so + // stop the timeout timer but keep the retry timer running. d->timer.stop(); if (d->reply) { diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index c1747cca..30ecceb3 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -67,7 +67,6 @@ namespace QMatrixClient , UnsupportedRoomVersionError , NetworkAuthRequiredError , UserConsentRequiredError - , UnknownObjectError // Unknown room or other item (M_UNKNOWN) , UserDefinedError = 200 }; @@ -303,7 +302,7 @@ namespace QMatrixClient * Processes the reply. By default, parses the reply into * a QJsonDocument and calls parseJson() if it's a valid JSON. * - * @param reply raw contents of a HTTP reply from the server (without headers) + * @param reply raw contents of a HTTP reply from the server * * @see gotReply, parseJson */ @@ -311,7 +310,7 @@ namespace QMatrixClient /** * Processes the JSON document received from the Matrix server. - * By default returns succesful status without analysing the JSON. + * By default returns successful status without analysing the JSON. * * @param json valid JSON document received from the server * @@ -319,6 +318,15 @@ namespace QMatrixClient */ virtual Status parseJson(const QJsonDocument&); + /** + * Processes the reply in case of unsuccessful HTTP code. + * The body is already loaded from the reply object to errorJson. + * @param reply the HTTP reply from the server + * @param errorJson the JSON payload describing the error + */ + virtual Status parseError(QNetworkReply* reply, + const QJsonObject& errorJson); + void setStatus(Status s); void setStatus(int code, QString message); -- cgit v1.2.3 From 74caea2669b8f76ca76507bc40321fdcd23dc522 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 12 Jul 2019 18:02:27 +0900 Subject: Minor polish --- lib/connection.cpp | 2 +- lib/jobs/basejob.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index 79411dce..1bd2e32e 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -200,7 +200,7 @@ void Connection::resolveServer(const QString& mxid) } else { QUrl baseUrl(getWellKnownJob->data().homeserver.baseUrl); - qCDebug(MAIN) << ".well-known for" << maybeBaseUrl.host() << "is" << baseUrl.authority(); + qCDebug(MAIN) << ".well-known for" << maybeBaseUrl.host() << "is" << baseUrl.toString(); setHomeserver(baseUrl); } diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 6ad8d971..b3cfc527 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -300,7 +300,7 @@ void BaseJob::gotReply() QJsonDocument::fromJson(d->rawResponse).object())); } - if (error() != TooManyRequestsError) + if (status().code != TooManyRequestsError) finishJob(); else { stop(); -- cgit v1.2.3 From c05ade838f0fce81f2bbe80a3295618a8a26ff52 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 2 Aug 2019 19:59:40 +0900 Subject: Apply the new brace wrapping to source files --- examples/qmc-example.cpp | 7 +-- lib/avatar.cpp | 15 ++----- lib/avatar.h | 6 +-- lib/connection.cpp | 79 ++++++++++++++++---------------- lib/connection.h | 21 +++------ lib/connectiondata.cpp | 7 +-- lib/connectiondata.h | 6 +-- lib/converters.h | 97 ++++++++++++++-------------------------- lib/e2ee.h | 3 +- lib/encryptionmanager.cpp | 3 +- lib/encryptionmanager.h | 9 ++-- lib/eventitem.h | 24 ++++------ lib/events/accountdataevents.h | 50 +++++++++------------ lib/events/callanswerevent.h | 6 +-- lib/events/callcandidatesevent.h | 6 +-- lib/events/callhangupevent.h | 6 +-- lib/events/callinviteevent.h | 6 +-- lib/events/directchatevent.h | 10 ++--- lib/events/encryptedevent.h | 6 +-- lib/events/encryptionevent.cpp | 6 +-- lib/events/encryptionevent.h | 15 ++----- lib/events/event.cpp | 4 +- lib/events/event.h | 24 ++++------ lib/events/eventcontent.cpp | 3 +- lib/events/eventcontent.h | 46 ++++++------------- lib/events/eventloader.h | 9 ++-- lib/events/reactionevent.h | 16 +++---- lib/events/receiptevent.cpp | 3 +- lib/events/receiptevent.h | 12 ++--- lib/events/redactionevent.h | 9 ++-- lib/events/roomavatarevent.h | 9 ++-- lib/events/roomcreateevent.h | 13 ++---- lib/events/roomevent.cpp | 3 +- lib/events/roomevent.h | 9 ++-- lib/events/roommemberevent.cpp | 6 +-- lib/events/roommemberevent.h | 22 +++------ lib/events/roommessageevent.cpp | 12 ++--- lib/events/roommessageevent.h | 24 ++++------ lib/events/roomtombstoneevent.h | 10 ++--- lib/events/simplestateevents.h | 25 ++++------- lib/events/stateevent.h | 21 +++------ lib/events/typingevent.cpp | 3 +- lib/events/typingevent.h | 6 +-- lib/jobs/basejob.cpp | 6 +-- lib/jobs/basejob.h | 35 ++++----------- lib/jobs/downloadfilejob.cpp | 7 +-- lib/jobs/downloadfilejob.h | 11 ++--- lib/jobs/mediathumbnailjob.h | 6 +-- lib/jobs/postreadmarkersjob.h | 3 +- lib/jobs/requestdata.cpp | 12 ++--- lib/jobs/requestdata.h | 9 ++-- lib/jobs/syncjob.h | 6 +-- lib/joinstate.h | 6 +-- lib/logging.h | 3 +- lib/networkaccessmanager.cpp | 6 +-- lib/networkaccessmanager.h | 6 +-- lib/networksettings.h | 6 +-- lib/qt_connection_util.h | 12 ++--- lib/room.cpp | 35 ++++++--------- lib/room.h | 28 +++--------- lib/settings.h | 16 +++---- lib/syncdata.h | 15 +++---- lib/user.cpp | 6 +-- lib/user.h | 6 +-- lib/util.cpp | 18 +++----- lib/util.h | 64 ++++++++------------------ 66 files changed, 335 insertions(+), 664 deletions(-) (limited to 'lib/jobs') diff --git a/examples/qmc-example.cpp b/examples/qmc-example.cpp index d6cba76a..f4067009 100644 --- a/examples/qmc-example.cpp +++ b/examples/qmc-example.cpp @@ -24,8 +24,7 @@ using std::cout; using std::endl; using namespace std::placeholders; -class QMCTest : public QObject -{ +class QMCTest : public QObject { public: QMCTest(Connection* conn, QString testRoomName, QString source); @@ -92,9 +91,7 @@ bool QMCTest::validatePendingEvent(const QString& txnId) } QMCTest::QMCTest(Connection* conn, QString testRoomName, QString source) - : c(conn) - , origin(std::move(source)) - , targetRoomName(std::move(testRoomName)) + : c(conn), origin(std::move(source)), targetRoomName(std::move(testRoomName)) { if (!origin.isEmpty()) cout << "Origin for the test message: " << origin.toStdString() << endl; diff --git a/lib/avatar.cpp b/lib/avatar.cpp index 0e58a1ce..614f008d 100644 --- a/lib/avatar.cpp +++ b/lib/avatar.cpp @@ -32,12 +32,9 @@ using namespace QMatrixClient; using std::move; -class Avatar::Private -{ +class Avatar::Private { public: - explicit Private(QUrl url = {}) - : _url(move(url)) - {} + explicit Private(QUrl url = {}) : _url(move(url)) {} ~Private() { if (isJobRunning(_thumbnailRequest)) @@ -65,13 +62,9 @@ public: mutable std::vector callbacks; }; -Avatar::Avatar() - : d(std::make_unique()) -{} +Avatar::Avatar() : d(std::make_unique()) {} -Avatar::Avatar(QUrl url) - : d(std::make_unique(std::move(url))) -{} +Avatar::Avatar(QUrl url) : d(std::make_unique(std::move(url))) {} Avatar::Avatar(Avatar&&) = default; diff --git a/lib/avatar.h b/lib/avatar.h index 37991192..c33e1982 100644 --- a/lib/avatar.h +++ b/lib/avatar.h @@ -24,12 +24,10 @@ #include #include -namespace QMatrixClient -{ +namespace QMatrixClient { class Connection; -class Avatar -{ +class Avatar { public: explicit Avatar(); explicit Avatar(QUrl url); diff --git a/lib/connection.cpp b/lib/connection.cpp index 6ebe05dc..6cd6ad0b 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -70,8 +70,7 @@ HashT erase_if(HashT& hashMap, Pred pred) return removals; } -class Connection::Private -{ +class Connection::Private { public: explicit Private(std::unique_ptr&& connection) : data(move(connection)) @@ -151,15 +150,12 @@ public: }; Connection::Connection(const QUrl& server, QObject* parent) - : QObject(parent) - , d(new Private(std::make_unique(server))) + : QObject(parent), d(new Private(std::make_unique(server))) { d->q = this; // All d initialization should occur before this line } -Connection::Connection(QObject* parent) - : Connection({}, parent) -{} +Connection::Connection(QObject* parent) : Connection({}, parent) {} Connection::~Connection() { @@ -183,45 +179,47 @@ void Connection::resolveServer(const QString& mxid) qCDebug(MAIN) << "Finding the server" << domain; auto getWellKnownJob = callApi(); - connect(getWellKnownJob, &BaseJob::finished, - [this, getWellKnownJob, maybeBaseUrl] { - if (getWellKnownJob->status() == BaseJob::NotFoundError) { - qCDebug(MAIN) << "No .well-known file, IGNORE"; - } else if (getWellKnownJob->status() != BaseJob::Success) { + connect( + getWellKnownJob, &BaseJob::finished, + [this, getWellKnownJob, maybeBaseUrl] { + if (getWellKnownJob->status() == BaseJob::NotFoundError) + qCDebug(MAIN) << "No .well-known file, IGNORE"; + else { + if (getWellKnownJob->status() != BaseJob::Success) { qCDebug(MAIN) << "Fetching .well-known file failed, FAIL_PROMPT"; emit resolveError(tr("Fetching .well-known file failed")); return; - } else if (getWellKnownJob->data().homeserver.baseUrl.isEmpty()) { + } + QUrl baseUrl(getWellKnownJob->data().homeserver.baseUrl); + if (baseUrl.isEmpty()) { qCDebug(MAIN) << "base_url not provided, FAIL_PROMPT"; emit resolveError(tr("base_url not provided")); return; - } else if (!QUrl(getWellKnownJob->data().homeserver.baseUrl) - .isValid()) { + } + if (!baseUrl.isValid()) { qCDebug(MAIN) << "base_url invalid, FAIL_ERROR"; emit resolveError(tr("base_url invalid")); return; - } else { - QUrl baseUrl(getWellKnownJob->data().homeserver.baseUrl); - - qCDebug(MAIN) << ".well-known for" << maybeBaseUrl.host() - << "is" << baseUrl.toString(); - setHomeserver(baseUrl); } - auto getVersionsJob = callApi(); - - connect(getVersionsJob, &BaseJob::finished, - [this, getVersionsJob] { - if (getVersionsJob->status() == BaseJob::Success) { - qCDebug(MAIN) << "homeserver url is valid"; - emit resolved(); - } else { - qCDebug(MAIN) << "homeserver url invalid"; - emit resolveError(tr("homeserver url invalid")); - } - }); + qCDebug(MAIN) << ".well-known for" << maybeBaseUrl.host() + << "is" << baseUrl.toString(); + setHomeserver(baseUrl); + } + + auto getVersionsJob = callApi(); + + connect(getVersionsJob, &BaseJob::finished, [this, getVersionsJob] { + if (getVersionsJob->status() == BaseJob::Success) { + qCDebug(MAIN) << "homeserver url is valid"; + emit resolved(); + } else { + qCDebug(MAIN) << "homeserver url invalid"; + emit resolveError(tr("homeserver url invalid")); + } }); + }); } void Connection::connectToServer(const QString& user, const QString& password, @@ -372,8 +370,8 @@ void Connection::sync(int timeout) connect(job, &SyncJob::failure, this, [this, job] { d->syncJob = nullptr; if (job->error() == BaseJob::ContentAccessError) { - qCWarning(SYNCJOB) - << "Sync job failed with ContentAccessError - login expired?"; + qCWarning(SYNCJOB) << "Sync job failed with ContentAccessError - " + "login expired?"; emit loginError(job->errorString(), job->rawDataSample()); } else emit syncError(job->errorString(), job->rawDataSample()); @@ -437,7 +435,6 @@ void Connection::onSyncSuccess(SyncData&& data, bool fromCache) visit( *eventPtr, [this](const DirectChatEvent& dce) { - // See // https://github.com/QMatrixClient/libqmatrixclient/wiki/Handling-direct-chat-events const auto& usersToDCs = dce.usersToDirectChats(); DirectChatsMap remoteRemovals = @@ -492,8 +489,8 @@ void Connection::onSyncSuccess(SyncData&& data, bool fromCache) << QStringList::fromSet(ignoredUsers()).join(','); auto& currentData = d->accountData[accountEvent.matrixType()]; - // A polymorphic event-specific comparison might be a bit more - // efficient; maaybe do it another day + // A polymorphic event-specific comparison might be a bit + // more efficient; maaybe do it another day if (!currentData || currentData->contentJson() != accountEvent.contentJson()) { currentData = std::move(eventPtr); @@ -678,9 +675,9 @@ void Connection::requestDirectChat(const QString& userId) if (auto* u = user(userId)) requestDirectChat(u); else - qCCritical(MAIN) - << "Connection::requestDirectChat: Couldn't get a user object for" - << userId; + qCCritical(MAIN) << "Connection::requestDirectChat: Couldn't get a " + "user object for" + << userId; } void Connection::requestDirectChat(User* u) diff --git a/lib/connection.h b/lib/connection.h index 8d65f0e7..b89c0c65 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -32,13 +32,11 @@ #include -namespace QtOlm -{ +namespace QtOlm { class Account; } -namespace QMatrixClient -{ +namespace QMatrixClient { class Room; class User; class ConnectionData; @@ -93,14 +91,9 @@ static inline user_factory_t defaultUserFactory() * * \sa Connection::callApi */ -enum RunningPolicy -{ - ForegroundRequest = 0x0, - BackgroundRequest = 0x1 -}; +enum RunningPolicy { ForegroundRequest = 0x0, BackgroundRequest = 0x1 }; -class Connection : public QObject -{ +class Connection : public QObject { Q_OBJECT Q_PROPERTY(User* localUser READ user NOTIFY stateChanged) @@ -129,8 +122,7 @@ public: using UsersToDevicesToEvents = std::unordered_map>; - enum RoomVisibility - { + enum RoomVisibility { PublishRoom, UnpublishRoom }; // FIXME: Should go inside CreateRoomJob @@ -285,8 +277,7 @@ public: Q_INVOKABLE void getTurnServers(); - struct SupportedRoomVersion - { + struct SupportedRoomVersion { QString id; QString status; diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index c157565f..df4cece2 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -23,11 +23,8 @@ using namespace QMatrixClient; -struct ConnectionData::Private -{ - explicit Private(QUrl url) - : baseUrl(std::move(url)) - {} +struct ConnectionData::Private { + explicit Private(QUrl url) : baseUrl(std::move(url)) {} QUrl baseUrl; QByteArray accessToken; diff --git a/lib/connectiondata.h b/lib/connectiondata.h index 6f9f090c..9b579b1c 100644 --- a/lib/connectiondata.h +++ b/lib/connectiondata.h @@ -24,10 +24,8 @@ class QNetworkAccessManager; -namespace QMatrixClient -{ -class ConnectionData -{ +namespace QMatrixClient { +class ConnectionData { public: explicit ConnectionData(QUrl baseUrl); virtual ~ConnectionData(); diff --git a/lib/converters.h b/lib/converters.h index aa07261d..0085fa4b 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -38,11 +38,9 @@ using optional = std::experimental::optional; #endif // Enable std::unordered_map -namespace std -{ +namespace std { template <> -struct hash -{ +struct hash { size_t operator()(const QString& s) const Q_DECL_NOEXCEPT { return qHash(s @@ -57,18 +55,15 @@ struct hash class QVariant; -namespace QMatrixClient -{ +namespace QMatrixClient { template -struct JsonObjectConverter -{ +struct JsonObjectConverter { static void dumpTo(QJsonObject& jo, const T& pod) { jo = pod.toJson(); } static void fillFrom(const QJsonObject& jo, T& pod) { pod = T(jo); } }; template -struct JsonConverter -{ +struct JsonConverter { static QJsonObject dump(const T& pod) { QJsonObject jo; @@ -139,52 +134,44 @@ inline void fillFromJson(const QJsonValue& jv, T& pod) // JsonConverter<> specialisations template -struct TrivialJsonDumper -{ +struct TrivialJsonDumper { // Works for: QJsonValue (and all things it can consume), // QJsonObject, QJsonArray static auto dump(const T& val) { return val; } }; template <> -struct JsonConverter : public TrivialJsonDumper -{ +struct JsonConverter : public TrivialJsonDumper { static auto load(const QJsonValue& jv) { return jv.toBool(); } }; template <> -struct JsonConverter : public TrivialJsonDumper -{ +struct JsonConverter : public TrivialJsonDumper { static auto load(const QJsonValue& jv) { return jv.toInt(); } }; template <> -struct JsonConverter : public TrivialJsonDumper -{ +struct JsonConverter : public TrivialJsonDumper { static auto load(const QJsonValue& jv) { return jv.toDouble(); } }; template <> -struct JsonConverter : public TrivialJsonDumper -{ +struct JsonConverter : public TrivialJsonDumper { static auto load(const QJsonValue& jv) { return float(jv.toDouble()); } }; template <> -struct JsonConverter : public TrivialJsonDumper -{ +struct JsonConverter : public TrivialJsonDumper { static auto load(const QJsonValue& jv) { return qint64(jv.toDouble()); } }; template <> -struct JsonConverter : public TrivialJsonDumper -{ +struct JsonConverter : public TrivialJsonDumper { static auto load(const QJsonValue& jv) { return jv.toString(); } }; template <> -struct JsonConverter -{ +struct JsonConverter { static auto dump(const QDateTime& val) = delete; // not provided yet static auto load(const QJsonValue& jv) { @@ -193,8 +180,7 @@ struct JsonConverter }; template <> -struct JsonConverter -{ +struct JsonConverter { static auto dump(const QDate& val) = delete; // not provided yet static auto load(const QJsonValue& jv) { @@ -203,14 +189,12 @@ struct JsonConverter }; template <> -struct JsonConverter : public TrivialJsonDumper -{ +struct JsonConverter : public TrivialJsonDumper { static auto load(const QJsonValue& jv) { return jv.toArray(); } }; template <> -struct JsonConverter -{ +struct JsonConverter { static QString dump(const QByteArray& ba) { return ba.constData(); } static auto load(const QJsonValue& jv) { @@ -219,15 +203,13 @@ struct JsonConverter }; template <> -struct JsonConverter -{ +struct JsonConverter { static QJsonValue dump(const QVariant& v); static QVariant load(const QJsonValue& jv); }; template -struct JsonConverter> -{ +struct JsonConverter> { static QJsonValue dump(const Omittable& from) { return from.omitted() ? QJsonValue() : toJson(from.value()); @@ -241,8 +223,7 @@ struct JsonConverter> }; template -struct JsonArrayConverter -{ +struct JsonArrayConverter { static void dumpTo(QJsonArray& ar, const VectorT& vals) { for (const auto& v : vals) @@ -267,20 +248,17 @@ struct JsonArrayConverter }; template -struct JsonConverter> : public JsonArrayConverter> -{}; +struct JsonConverter> + : public JsonArrayConverter> {}; template -struct JsonConverter> : public JsonArrayConverter> -{}; +struct JsonConverter> : public JsonArrayConverter> {}; template -struct JsonConverter> : public JsonArrayConverter> -{}; +struct JsonConverter> : public JsonArrayConverter> {}; template <> -struct JsonConverter : public JsonConverter> -{ +struct JsonConverter : public JsonConverter> { static auto dump(const QStringList& sl) { return QJsonArray::fromStringList(sl); @@ -288,8 +266,7 @@ struct JsonConverter : public JsonConverter> }; template <> -struct JsonObjectConverter> -{ +struct JsonObjectConverter> { static void dumpTo(QJsonObject& json, const QSet& s) { for (const auto& e : s) @@ -305,8 +282,7 @@ struct JsonObjectConverter> }; template -struct HashMapFromJson -{ +struct HashMapFromJson { static void dumpTo(QJsonObject& json, const HashMapT& hashMap) { for (auto it = hashMap.begin(); it != hashMap.end(); ++it) @@ -322,13 +298,11 @@ struct HashMapFromJson template struct JsonObjectConverter> - : public HashMapFromJson> -{}; + : public HashMapFromJson> {}; template struct JsonObjectConverter> - : public HashMapFromJson> -{}; + : public HashMapFromJson> {}; // We could use std::conditional<> below but QT_VERSION* macros in C++ code // cause (kinda valid but useless and noisy) compiler warnings about @@ -340,16 +314,14 @@ using variant_map_t = QVariantMap; #endif template <> -struct JsonConverter -{ +struct JsonConverter { static QJsonObject dump(const variant_map_t& vh); static QVariantHash load(const QJsonValue& jv); }; // Conditional insertion into a QJsonObject -namespace _impl -{ +namespace _impl { template inline void addTo(QJsonObject& o, const QString& k, ValT&& v) { @@ -384,8 +356,7 @@ namespace _impl // This one is for types that don't have isEmpty() and for all types // when Force is true template - struct AddNode - { + struct AddNode { template static void impl(ContT& container, const QString& key, ForwardedT&& value) @@ -396,8 +367,7 @@ namespace _impl // This one is for types that have isEmpty() when Force is false template - struct AddNode().isEmpty())> - { + struct AddNode().isEmpty())> { template static void impl(ContT& container, const QString& key, ForwardedT&& value) @@ -409,8 +379,7 @@ namespace _impl // This one unfolds Omittable<> (also only when Force is false) template - struct AddNode, false> - { + struct AddNode, false> { template static void impl(ContT& container, const QString& key, const OmittableT& value) diff --git a/lib/e2ee.h b/lib/e2ee.h index d3329def..c85211be 100644 --- a/lib/e2ee.h +++ b/lib/e2ee.h @@ -4,8 +4,7 @@ #include -namespace QMatrixClient -{ +namespace QMatrixClient { static const auto CiphertextKeyL = "ciphertext"_ls; static const auto SenderKeyKeyL = "sender_key"_ls; static const auto DeviceIdKeyL = "device_id"_ls; diff --git a/lib/encryptionmanager.cpp b/lib/encryptionmanager.cpp index 46d937b8..15723688 100644 --- a/lib/encryptionmanager.cpp +++ b/lib/encryptionmanager.cpp @@ -16,8 +16,7 @@ using namespace QMatrixClient; using namespace QtOlm; using std::move; -class EncryptionManager::Private -{ +class EncryptionManager::Private { public: explicit Private(const QByteArray& encryptionAccountPickle, float signedKeysProportion, float oneTimeKeyThreshold) diff --git a/lib/encryptionmanager.h b/lib/encryptionmanager.h index 02bb882f..79c25a00 100644 --- a/lib/encryptionmanager.h +++ b/lib/encryptionmanager.h @@ -5,17 +5,14 @@ #include #include -namespace QtOlm -{ +namespace QtOlm { class Account; } -namespace QMatrixClient -{ +namespace QMatrixClient { class Connection; -class EncryptionManager : public QObject -{ +class EncryptionManager : public QObject { Q_OBJECT public: diff --git a/lib/eventitem.h b/lib/eventitem.h index 58f5479c..68d1ae06 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -22,12 +22,10 @@ #include -namespace QMatrixClient -{ +namespace QMatrixClient { class StateEventBase; -class EventStatus -{ +class EventStatus { Q_GADGET public: /** Special marks an event can assume @@ -35,8 +33,7 @@ public: * This is used to hint at a special status of some events in UI. * All values except Redacted and Hidden are mutually exclusive. */ - enum Code - { + enum Code { Normal = 0x0, //< No special designation Submitted = 0x01, //< The event has just been submitted for sending FileUploaded = 0x02, //< The file attached to the event has been @@ -51,11 +48,9 @@ public: Q_FLAG(Status) }; -class EventItemBase -{ +class EventItemBase { public: - explicit EventItemBase(RoomEventPtr&& e) - : evt(std::move(e)) + explicit EventItemBase(RoomEventPtr&& e) : evt(std::move(e)) { Q_ASSERT(evt); } @@ -87,16 +82,14 @@ private: RoomEventPtr evt; }; -class TimelineItem : public EventItemBase -{ +class TimelineItem : public EventItemBase { public: // For compatibility with Qt containers, even though we use // a std:: container now for the room timeline using index_t = int; TimelineItem(RoomEventPtr&& e, index_t number) - : EventItemBase(std::move(e)) - , idx(number) + : EventItemBase(std::move(e)), idx(number) {} index_t index() const { return idx; } @@ -118,8 +111,7 @@ inline const CallEventBase* EventItemBase::viewAs() const return evt->isCallEvent() ? weakPtrCast(evt) : nullptr; } -class PendingEventItem : public EventItemBase -{ +class PendingEventItem : public EventItemBase { Q_GADGET public: using EventItemBase::EventItemBase; diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h index abab9867..3f519668 100644 --- a/lib/events/accountdataevents.h +++ b/lib/events/accountdataevents.h @@ -24,20 +24,16 @@ #include "event.h" #include "eventcontent.h" -namespace QMatrixClient -{ +namespace QMatrixClient { constexpr const char* FavouriteTag = "m.favourite"; constexpr const char* LowPriorityTag = "m.lowpriority"; -struct TagRecord -{ +struct TagRecord { using order_type = Omittable; order_type order; - TagRecord(order_type order = none) - : order(order) - {} + TagRecord(order_type order = none) : order(order) {} bool operator<(const TagRecord& other) const { @@ -48,8 +44,7 @@ struct TagRecord }; template <> -struct JsonObjectConverter -{ +struct JsonObjectConverter { static void fillFrom(const QJsonObject& jo, TagRecord& rec) { // Parse a float both from JSON double and JSON string because @@ -72,26 +67,23 @@ struct JsonObjectConverter using TagsMap = QHash; -#define DEFINE_SIMPLE_EVENT(_Name, _TypeId, _ContentType, _ContentKey) \ - class _Name : public Event \ - { \ - public: \ - using content_type = _ContentType; \ - DEFINE_EVENT_TYPEID(_TypeId, _Name) \ - explicit _Name(QJsonObject obj) \ - : Event(typeId(), std::move(obj)) \ - {} \ - explicit _Name(_ContentType content) \ - : Event(typeId(), matrixTypeId(), \ - QJsonObject { { QStringLiteral(#_ContentKey), \ - toJson(std::move(content)) } }) \ - {} \ - auto _ContentKey() const \ - { \ - return content(#_ContentKey##_ls); \ - } \ - }; \ - REGISTER_EVENT_TYPE(_Name) \ +#define DEFINE_SIMPLE_EVENT(_Name, _TypeId, _ContentType, _ContentKey) \ + class _Name : public Event { \ + public: \ + using content_type = _ContentType; \ + DEFINE_EVENT_TYPEID(_TypeId, _Name) \ + explicit _Name(QJsonObject obj) : Event(typeId(), std::move(obj)) {} \ + explicit _Name(_ContentType content) \ + : Event(typeId(), matrixTypeId(), \ + QJsonObject { { QStringLiteral(#_ContentKey), \ + toJson(std::move(content)) } }) \ + {} \ + auto _ContentKey() const \ + { \ + return content(#_ContentKey##_ls); \ + } \ + }; \ + REGISTER_EVENT_TYPE(_Name) \ // End of macro DEFINE_SIMPLE_EVENT(TagEvent, "m.tag", TagsMap, tags) diff --git a/lib/events/callanswerevent.h b/lib/events/callanswerevent.h index 69662eb9..052f732d 100644 --- a/lib/events/callanswerevent.h +++ b/lib/events/callanswerevent.h @@ -20,10 +20,8 @@ #include "roomevent.h" -namespace QMatrixClient -{ -class CallAnswerEvent : public CallEventBase -{ +namespace QMatrixClient { +class CallAnswerEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.answer", CallAnswerEvent) diff --git a/lib/events/callcandidatesevent.h b/lib/events/callcandidatesevent.h index 1c12b800..2a915a43 100644 --- a/lib/events/callcandidatesevent.h +++ b/lib/events/callcandidatesevent.h @@ -20,10 +20,8 @@ #include "roomevent.h" -namespace QMatrixClient -{ -class CallCandidatesEvent : public CallEventBase -{ +namespace QMatrixClient { +class CallCandidatesEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.candidates", CallCandidatesEvent) diff --git a/lib/events/callhangupevent.h b/lib/events/callhangupevent.h index 0a5a3283..97fa2f52 100644 --- a/lib/events/callhangupevent.h +++ b/lib/events/callhangupevent.h @@ -20,10 +20,8 @@ #include "roomevent.h" -namespace QMatrixClient -{ -class CallHangupEvent : public CallEventBase -{ +namespace QMatrixClient { +class CallHangupEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.hangup", CallHangupEvent) diff --git a/lib/events/callinviteevent.h b/lib/events/callinviteevent.h index 4334ca5b..9b9d0ae5 100644 --- a/lib/events/callinviteevent.h +++ b/lib/events/callinviteevent.h @@ -20,10 +20,8 @@ #include "roomevent.h" -namespace QMatrixClient -{ -class CallInviteEvent : public CallEventBase -{ +namespace QMatrixClient { +class CallInviteEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.invite", CallInviteEvent) diff --git a/lib/events/directchatevent.h b/lib/events/directchatevent.h index 6b4a08ee..94857a93 100644 --- a/lib/events/directchatevent.h +++ b/lib/events/directchatevent.h @@ -20,16 +20,12 @@ #include "event.h" -namespace QMatrixClient -{ -class DirectChatEvent : public Event -{ +namespace QMatrixClient { +class DirectChatEvent : public Event { public: DEFINE_EVENT_TYPEID("m.direct", DirectChatEvent) - explicit DirectChatEvent(const QJsonObject& obj) - : Event(typeId(), obj) - {} + explicit DirectChatEvent(const QJsonObject& obj) : Event(typeId(), obj) {} QMultiHash usersToDirectChats() const; }; diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h index 0dbce25c..67298a27 100644 --- a/lib/events/encryptedevent.h +++ b/lib/events/encryptedevent.h @@ -3,8 +3,7 @@ #include "e2ee.h" #include "roomevent.h" -namespace QMatrixClient -{ +namespace QMatrixClient { class Room; /* * While the specification states: @@ -24,8 +23,7 @@ class Room; * in general. It's possible, because RoomEvent interface is similar to Event's * one and doesn't add new restrictions, just provides additional features. */ -class EncryptedEvent : public RoomEvent -{ +class EncryptedEvent : public RoomEvent { Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.encrypted", EncryptedEvent) diff --git a/lib/events/encryptionevent.cpp b/lib/events/encryptionevent.cpp index 995c8dad..0c732a51 100644 --- a/lib/events/encryptionevent.cpp +++ b/lib/events/encryptionevent.cpp @@ -15,11 +15,9 @@ static const std::array encryptionStrings = { { QMatrixClient::MegolmV1AesSha2AlgoKey } }; -namespace QMatrixClient -{ +namespace QMatrixClient { template <> -struct JsonConverter -{ +struct JsonConverter { static EncryptionType load(const QJsonValue& jv) { const auto& encryptionString = jv.toString(); diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h index 97119c8d..debabcae 100644 --- a/lib/events/encryptionevent.h +++ b/lib/events/encryptionevent.h @@ -21,16 +21,10 @@ #include "eventcontent.h" #include "stateevent.h" -namespace QMatrixClient -{ -class EncryptionEventContent : public EventContent::Base -{ +namespace QMatrixClient { +class EncryptionEventContent : public EventContent::Base { public: - enum EncryptionType : size_t - { - MegolmV1AesSha2 = 0, - Undefined - }; + enum EncryptionType : size_t { MegolmV1AesSha2 = 0, Undefined }; explicit EncryptionEventContent(EncryptionType et = Undefined) : encryption(et) @@ -48,8 +42,7 @@ protected: using EncryptionType = EncryptionEventContent::EncryptionType; -class EncryptionEvent : public StateEvent -{ +class EncryptionEvent : public StateEvent { Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.encryption", EncryptionEvent) diff --git a/lib/events/event.cpp b/lib/events/event.cpp index 718a6602..694254fe 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -42,9 +42,7 @@ QString EventTypeRegistry::getMatrixType(event_type_t typeId) : QString(); } -Event::Event(Type type, const QJsonObject& json) - : _type(type) - , _json(json) +Event::Event(Type type, const QJsonObject& json) : _type(type), _json(json) { if (!json.contains(ContentKeyL) && !json.value(UnsignedKeyL).toObject().contains(RedactedCauseKeyL)) { diff --git a/lib/events/event.h b/lib/events/event.h index d6525281..686bd8e0 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -25,8 +25,7 @@ # define USE_EVENTTYPE_ALIAS 1 #endif -namespace QMatrixClient -{ +namespace QMatrixClient { // === event_ptr_tt<> and type casting facilities === template @@ -85,8 +84,7 @@ inline QJsonObject basicEventJson(StrT matrixType, const QJsonObject& content) using event_type_t = size_t; using event_mtype_t = const char*; -class EventTypeRegistry -{ +class EventTypeRegistry { public: ~EventTypeRegistry() = default; @@ -121,8 +119,7 @@ inline event_type_t EventTypeRegistry::initializeTypeId() } template -struct EventTypeTraits -{ +struct EventTypeTraits { static event_type_t id() { static const auto id = EventTypeRegistry::initializeTypeId(); @@ -148,8 +145,7 @@ inline event_ptr_tt makeEvent(ArgTs&&... args) } template -class EventFactory -{ +class EventFactory { public: template static auto addMethod(FnT&& method) @@ -223,8 +219,7 @@ inline auto registerEventType() // === Event === -class Event -{ +class Event { Q_GADGET Q_PROPERTY(Type type READ type CONSTANT) Q_PROPERTY(QJsonObject contentJson READ contentJson CONSTANT) @@ -304,16 +299,14 @@ using Events = EventsArray; // to enable its deserialisation from a /sync and other // polymorphic event arrays #define REGISTER_EVENT_TYPE(_Type) \ - namespace \ - { \ + namespace { \ [[gnu::unused]] static const auto _factoryAdded##_Type = \ registerEventType<_Type>(); \ } \ // End of macro #ifdef USE_EVENTTYPE_ALIAS -namespace EventType -{ +namespace EventType { inline event_type_t logEventType(event_type_t id, const char* idName) { qDebug(EVENTS) << "Using id" << id << "for" << idName; @@ -324,8 +317,7 @@ namespace EventType // This macro provides constants in EventType:: namespace for // back-compatibility with libQMatrixClient 0.3 event type system. # define DEFINE_EVENTTYPE_ALIAS(_Id, _Type) \ - namespace EventType \ - { \ + namespace EventType { \ [[deprecated("Use is<>(), eventCast<>() or " \ "visit<>()")]] static const auto _Id = \ logEventType(typeId<_Type>(), #_Id); \ diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index 2b84c2b7..814f2787 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -70,8 +70,7 @@ void FileInfo::fillInfoJson(QJsonObject* infoJson) const ImageInfo::ImageInfo(const QUrl& u, qint64 fileSize, QMimeType mimeType, const QSize& imageSize, const QString& originalFilename) - : FileInfo(u, fileSize, mimeType, originalFilename) - , imageSize(imageSize) + : FileInfo(u, fileSize, mimeType, originalFilename), imageSize(imageSize) {} ImageInfo::ImageInfo(const QUrl& u, const QJsonObject& infoJson, diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 7a3db1fc..5c0f92d1 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -26,10 +26,8 @@ #include #include -namespace QMatrixClient -{ -namespace EventContent -{ +namespace QMatrixClient { +namespace EventContent { /** * A base class for all content types that can be stored * in a RoomMessageEvent @@ -40,12 +38,9 @@ namespace EventContent * assumed but not required that a content object can also be created * from plain data. */ - class Base - { + class Base { public: - explicit Base(QJsonObject o = {}) - : originalJson(std::move(o)) - {} + explicit Base(QJsonObject o = {}) : originalJson(std::move(o)) {} virtual ~Base() = default; // FIXME: make toJson() from converters.* work on base classes @@ -90,8 +85,7 @@ namespace EventContent * * This class is not polymorphic. */ - class FileInfo - { + class FileInfo { public: explicit FileInfo(const QUrl& u, qint64 payloadSize = -1, const QMimeType& mimeType = {}, @@ -131,8 +125,7 @@ namespace EventContent /** * A content info class for image content types: image, thumbnail, video */ - class ImageInfo : public FileInfo - { + class ImageInfo : public FileInfo { public: explicit ImageInfo(const QUrl& u, qint64 fileSize = -1, QMimeType mimeType = {}, const QSize& imageSize = {}, @@ -153,16 +146,11 @@ namespace EventContent * the JSON representation of event content; namely, * "info/thumbnail_url" and "info/thumbnail_info" fields are used. */ - class Thumbnail : public ImageInfo - { + class Thumbnail : public ImageInfo { public: - Thumbnail() - : ImageInfo(QUrl()) - {} // To allow empty thumbnails + Thumbnail() : ImageInfo(QUrl()) {} // To allow empty thumbnails Thumbnail(const QJsonObject& infoJson); - Thumbnail(const ImageInfo& info) - : ImageInfo(info) - {} + Thumbnail(const ImageInfo& info) : ImageInfo(info) {} using ImageInfo::ImageInfo; /** @@ -172,12 +160,9 @@ namespace EventContent void fillInfoJson(QJsonObject* infoJson) const; }; - class TypedBase : public Base - { + class TypedBase : public Base { public: - explicit TypedBase(QJsonObject o = {}) - : Base(std::move(o)) - {} + explicit TypedBase(QJsonObject o = {}) : Base(std::move(o)) {} virtual QMimeType type() const = 0; virtual const FileInfo* fileInfo() const { return nullptr; } virtual FileInfo* fileInfo() { return nullptr; } @@ -198,8 +183,7 @@ namespace EventContent * \tparam InfoT base info class */ template - class UrlBasedContent : public TypedBase, public InfoT - { + class UrlBasedContent : public TypedBase, public InfoT { public: using InfoT::InfoT; explicit UrlBasedContent(const QJsonObject& json) @@ -227,13 +211,11 @@ namespace EventContent }; template - class UrlWithThumbnailContent : public UrlBasedContent - { + class UrlWithThumbnailContent : public UrlBasedContent { public: using UrlBasedContent::UrlBasedContent; explicit UrlWithThumbnailContent(const QJsonObject& json) - : UrlBasedContent(json) - , thumbnail(InfoT::originalInfoJson) + : UrlBasedContent(json), thumbnail(InfoT::originalInfoJson) { // Another small hack, to simplify making a thumbnail link UrlBasedContent::originalJson.insert("thumbnailMediaId", diff --git a/lib/events/eventloader.h b/lib/events/eventloader.h index a203eaa3..9e8bb410 100644 --- a/lib/events/eventloader.h +++ b/lib/events/eventloader.h @@ -20,10 +20,8 @@ #include "stateevent.h" -namespace QMatrixClient -{ -namespace _impl -{ +namespace QMatrixClient { +namespace _impl { template static inline auto loadEvent(const QJsonObject& json, const QString& matrixType) @@ -75,8 +73,7 @@ inline StateEventPtr loadStateEvent(const QString& matrixType, } template -struct JsonConverter> -{ +struct JsonConverter> { static auto load(const QJsonValue& jv) { return loadEvent(jv.toObject()); diff --git a/lib/events/reactionevent.h b/lib/events/reactionevent.h index d524b549..b1e04561 100644 --- a/lib/events/reactionevent.h +++ b/lib/events/reactionevent.h @@ -20,11 +20,9 @@ #include "roomevent.h" -namespace QMatrixClient -{ +namespace QMatrixClient { -struct EventRelation -{ +struct EventRelation { using reltypeid_t = const char*; static constexpr reltypeid_t Reply() { return "m.in_reply_to"; } static constexpr reltypeid_t Annotation() { return "m.annotation"; } @@ -48,14 +46,12 @@ struct EventRelation } }; template <> -struct JsonObjectConverter -{ +struct JsonObjectConverter { static void dumpTo(QJsonObject& jo, const EventRelation& pod); static void fillFrom(const QJsonObject& jo, EventRelation& pod); }; -class ReactionEvent : public RoomEvent -{ +class ReactionEvent : public RoomEvent { public: DEFINE_EVENT_TYPEID("m.reaction", ReactionEvent) @@ -63,9 +59,7 @@ public: : RoomEvent(typeId(), matrixTypeId(), { { QStringLiteral("m.relates_to"), toJson(value) } }) {} - explicit ReactionEvent(const QJsonObject& obj) - : RoomEvent(typeId(), obj) - {} + explicit ReactionEvent(const QJsonObject& obj) : RoomEvent(typeId(), obj) {} EventRelation relation() const { return content(QStringLiteral("m.relates_to")); diff --git a/lib/events/receiptevent.cpp b/lib/events/receiptevent.cpp index fcb8431b..4a54b744 100644 --- a/lib/events/receiptevent.cpp +++ b/lib/events/receiptevent.cpp @@ -40,8 +40,7 @@ Example of a Receipt Event: using namespace QMatrixClient; -ReceiptEvent::ReceiptEvent(const QJsonObject& obj) - : Event(typeId(), obj) +ReceiptEvent::ReceiptEvent(const QJsonObject& obj) : Event(typeId(), obj) { const auto& contents = contentJson(); _eventsWithReceipts.reserve(contents.size()); diff --git a/lib/events/receiptevent.h b/lib/events/receiptevent.h index e8396670..c32e0543 100644 --- a/lib/events/receiptevent.h +++ b/lib/events/receiptevent.h @@ -23,22 +23,18 @@ #include #include -namespace QMatrixClient -{ -struct Receipt -{ +namespace QMatrixClient { +struct Receipt { QString userId; QDateTime timestamp; }; -struct ReceiptsForEvent -{ +struct ReceiptsForEvent { QString evtId; QVector receipts; }; using EventsWithReceipts = QVector; -class ReceiptEvent : public Event -{ +class ReceiptEvent : public Event { public: DEFINE_EVENT_TYPEID("m.receipt", ReceiptEvent) explicit ReceiptEvent(const QJsonObject& obj); diff --git a/lib/events/redactionevent.h b/lib/events/redactionevent.h index a7dd9705..3628fb33 100644 --- a/lib/events/redactionevent.h +++ b/lib/events/redactionevent.h @@ -20,15 +20,12 @@ #include "roomevent.h" -namespace QMatrixClient -{ -class RedactionEvent : public RoomEvent -{ +namespace QMatrixClient { +class RedactionEvent : public RoomEvent { public: DEFINE_EVENT_TYPEID("m.room.redaction", RedactionEvent) - explicit RedactionEvent(const QJsonObject& obj) - : RoomEvent(typeId(), obj) + explicit RedactionEvent(const QJsonObject& obj) : RoomEvent(typeId(), obj) {} QString redactedEvent() const diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h index ee460339..16aeb070 100644 --- a/lib/events/roomavatarevent.h +++ b/lib/events/roomavatarevent.h @@ -21,18 +21,15 @@ #include "eventcontent.h" #include "stateevent.h" -namespace QMatrixClient -{ -class RoomAvatarEvent : public StateEvent -{ +namespace QMatrixClient { +class RoomAvatarEvent : public StateEvent { // It's a bit of an overkill to use a full-fledged ImageContent // because in reality m.room.avatar usually only has a single URL, // without a thumbnail. But The Spec says there be thumbnails, and // we follow The Spec. public: DEFINE_EVENT_TYPEID("m.room.avatar", RoomAvatarEvent) - explicit RoomAvatarEvent(const QJsonObject& obj) - : StateEvent(typeId(), obj) + explicit RoomAvatarEvent(const QJsonObject& obj) : StateEvent(typeId(), obj) {} QUrl url() const { return content().url; } }; diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h index 17b86388..c8ba8c40 100644 --- a/lib/events/roomcreateevent.h +++ b/lib/events/roomcreateevent.h @@ -20,22 +20,17 @@ #include "stateevent.h" -namespace QMatrixClient -{ -class RoomCreateEvent : public StateEventBase -{ +namespace QMatrixClient { +class RoomCreateEvent : public StateEventBase { public: DEFINE_EVENT_TYPEID("m.room.create", RoomCreateEvent) - explicit RoomCreateEvent() - : StateEventBase(typeId(), matrixTypeId()) - {} + explicit RoomCreateEvent() : StateEventBase(typeId(), matrixTypeId()) {} explicit RoomCreateEvent(const QJsonObject& obj) : StateEventBase(typeId(), obj) {} - struct Predecessor - { + struct Predecessor { QString roomId; QString eventId; }; diff --git a/lib/events/roomevent.cpp b/lib/events/roomevent.cpp index fb715473..543640ca 100644 --- a/lib/events/roomevent.cpp +++ b/lib/events/roomevent.cpp @@ -32,8 +32,7 @@ RoomEvent::RoomEvent(Type type, event_mtype_t matrixType, : Event(type, matrixType, contentJson) {} -RoomEvent::RoomEvent(Type type, const QJsonObject& json) - : Event(type, json) +RoomEvent::RoomEvent(Type type, const QJsonObject& json) : Event(type, json) { const auto unsignedData = json[UnsignedKeyL].toObject(); const auto redaction = unsignedData[RedactedCauseKeyL]; diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h index 8edb397c..155d4600 100644 --- a/lib/events/roomevent.h +++ b/lib/events/roomevent.h @@ -22,13 +22,11 @@ #include -namespace QMatrixClient -{ +namespace QMatrixClient { class RedactionEvent; /** This class corresponds to m.room.* events */ -class RoomEvent : public Event -{ +class RoomEvent : public Event { Q_GADGET Q_PROPERTY(QString id READ id) Q_PROPERTY(QDateTime timestamp READ timestamp CONSTANT) @@ -93,8 +91,7 @@ using RoomEventPtr = event_ptr_tt; using RoomEvents = EventsArray; using RoomEventsRange = Range; -class CallEventBase : public RoomEvent -{ +class CallEventBase : public RoomEvent { public: CallEventBase(Type type, event_mtype_t matrixType, const QString& callId, int version, const QJsonObject& contentJson = {}); diff --git a/lib/events/roommemberevent.cpp b/lib/events/roommemberevent.cpp index e6292b73..3cbf6685 100644 --- a/lib/events/roommemberevent.cpp +++ b/lib/events/roommemberevent.cpp @@ -28,11 +28,9 @@ static const std::array membershipStrings = { QStringLiteral("leave"), QStringLiteral("ban") } }; -namespace QMatrixClient -{ +namespace QMatrixClient { template <> -struct JsonConverter -{ +struct JsonConverter { static MembershipType load(const QJsonValue& jv) { const auto& membershipString = jv.toString(); diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index c1015df2..59d59e3a 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -21,13 +21,10 @@ #include "eventcontent.h" #include "stateevent.h" -namespace QMatrixClient -{ -class MemberEventContent : public EventContent::Base -{ +namespace QMatrixClient { +class MemberEventContent : public EventContent::Base { public: - enum MembershipType : size_t - { + enum MembershipType : size_t { Invite = 0, Join, Knock, @@ -36,9 +33,7 @@ public: Undefined }; - explicit MemberEventContent(MembershipType mt = Join) - : membership(mt) - {} + explicit MemberEventContent(MembershipType mt = Join) : membership(mt) {} explicit MemberEventContent(const QJsonObject& json); MembershipType membership; @@ -52,16 +47,14 @@ protected: using MembershipType = MemberEventContent::MembershipType; -class RoomMemberEvent : public StateEvent -{ +class RoomMemberEvent : public StateEvent { Q_GADGET public: DEFINE_EVENT_TYPEID("m.room.member", RoomMemberEvent) using MembershipType = MemberEventContent::MembershipType; - explicit RoomMemberEvent(const QJsonObject& obj) - : StateEvent(typeId(), obj) + explicit RoomMemberEvent(const QJsonObject& obj) : StateEvent(typeId(), obj) {} [[deprecated("Use RoomMemberEvent(userId, contentArgs) " "instead")]] RoomMemberEvent(MemberEventContent&& c) @@ -103,8 +96,7 @@ private: }; template <> -class EventFactory -{ +class EventFactory { public: static event_ptr_tt make(const QJsonObject& json, const QString&) diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index da8d59ca..991931de 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -54,8 +54,7 @@ TypedBase* make(const QJsonObject& json) : nullptr; } -struct MsgTypeDesc -{ +struct MsgTypeDesc { QString matrixType; MsgType enumType; TypedBase* (*maker)(const QJsonObject&); @@ -174,8 +173,7 @@ RoomMessageEvent::RoomMessageEvent(const QString& plainBody, {} RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) - : RoomEvent(typeId(), obj) - , _content(nullptr) + : RoomEvent(typeId(), obj), _content(nullptr) { if (isRedacted()) return; @@ -281,8 +279,7 @@ TextContent::TextContent(const QString& text, const QString& contentType, mimeType = QMimeDatabase().mimeTypeForName("text/html"); } -namespace QMatrixClient -{ +namespace QMatrixClient { // Overload the default fromJson<> logic that defined in converters.h // as we want template <> @@ -350,8 +347,7 @@ void TextContent::fillJson(QJsonObject* json) const LocationContent::LocationContent(const QString& geoUri, const Thumbnail& thumbnail) - : geoUri(geoUri) - , thumbnail(thumbnail) + : geoUri(geoUri), thumbnail(thumbnail) {} LocationContent::LocationContent(const QJsonObject& json) diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index 1f1fde41..c7a5cb47 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -23,15 +23,13 @@ class QFileInfo; -namespace QMatrixClient -{ +namespace QMatrixClient { namespace MessageEventContent = EventContent; // Back-compatibility /** * The event class corresponding to m.room.message events */ -class RoomMessageEvent : public RoomEvent -{ +class RoomMessageEvent : public RoomEvent { Q_GADGET Q_PROPERTY(QString msgType READ rawMsgtype CONSTANT) Q_PROPERTY(QString plainBody READ plainBody CONSTANT) @@ -40,8 +38,7 @@ class RoomMessageEvent : public RoomEvent public: DEFINE_EVENT_TYPEID("m.room.message", RoomMessageEvent) - enum class MsgType - { + enum class MsgType { Text, Emote, Notice, @@ -96,12 +93,10 @@ REGISTER_EVENT_TYPE(RoomMessageEvent) DEFINE_EVENTTYPE_ALIAS(RoomMessage, RoomMessageEvent) using MessageEventType = RoomMessageEvent::MsgType; -namespace EventContent -{ +namespace EventContent { // Additional event content types - struct RelatesTo - { + struct RelatesTo { static constexpr const char* ReplyTypeId() { return "m.in_reply_to"; } static constexpr const char* ReplacementTypeId() { return "m.replace"; } QString type; // The only supported relation so far @@ -118,8 +113,7 @@ namespace EventContent * Available fields: mimeType, body. The body can be either rich text * or plain text, depending on what mimeType specifies. */ - class TextContent : public TypedBase - { + class TextContent : public TypedBase { public: TextContent(const QString& text, const QString& contentType, Omittable relatesTo = none); @@ -148,8 +142,7 @@ namespace EventContent * - thumbnail.mimeType * - thumbnail.imageSize */ - class LocationContent : public TypedBase - { + class LocationContent : public TypedBase { public: LocationContent(const QString& geoUri, const Thumbnail& thumbnail = {}); explicit LocationContent(const QJsonObject& json); @@ -168,8 +161,7 @@ namespace EventContent * A base class for info types that include duration: audio and video */ template - class PlayableContent : public ContentT - { + class PlayableContent : public ContentT { public: using ContentT::ContentT; PlayableContent(const QJsonObject& json) diff --git a/lib/events/roomtombstoneevent.h b/lib/events/roomtombstoneevent.h index aa9cb766..95fed998 100644 --- a/lib/events/roomtombstoneevent.h +++ b/lib/events/roomtombstoneevent.h @@ -20,16 +20,12 @@ #include "stateevent.h" -namespace QMatrixClient -{ -class RoomTombstoneEvent : public StateEventBase -{ +namespace QMatrixClient { +class RoomTombstoneEvent : public StateEventBase { public: DEFINE_EVENT_TYPEID("m.room.tombstone", RoomTombstoneEvent) - explicit RoomTombstoneEvent() - : StateEventBase(typeId(), matrixTypeId()) - {} + explicit RoomTombstoneEvent() : StateEventBase(typeId(), matrixTypeId()) {} explicit RoomTombstoneEvent(const QJsonObject& obj) : StateEventBase(typeId(), obj) {} diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 0078c44d..6dad8020 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -20,25 +20,20 @@ #include "stateevent.h" -namespace QMatrixClient -{ -namespace EventContent -{ +namespace QMatrixClient { +namespace EventContent { template - class SimpleContent - { + class SimpleContent { public: using value_type = T; // The constructor is templated to enable perfect forwarding template SimpleContent(QString keyName, TT&& value) - : value(std::forward(value)) - , key(std::move(keyName)) + : value(std::forward(value)), key(std::move(keyName)) {} SimpleContent(const QJsonObject& json, QString keyName) - : value(fromJson(json[keyName])) - , key(std::move(keyName)) + : value(fromJson(json[keyName])), key(std::move(keyName)) {} QJsonObject toJson() const { @@ -54,14 +49,11 @@ namespace EventContent } // namespace EventContent #define DEFINE_SIMPLE_STATE_EVENT(_Name, _TypeId, _ValueType, _ContentKey) \ - class _Name : public StateEvent> \ - { \ + class _Name : public StateEvent> { \ public: \ using value_type = content_type::value_type; \ DEFINE_EVENT_TYPEID(_TypeId, _Name) \ - explicit _Name() \ - : _Name(value_type()) \ - {} \ + explicit _Name() : _Name(value_type()) {} \ template \ explicit _Name(T&& value) \ : StateEvent(typeId(), matrixTypeId(), QString(), \ @@ -86,8 +78,7 @@ DEFINE_EVENTTYPE_ALIAS(RoomTopic, RoomTopicEvent) DEFINE_EVENTTYPE_ALIAS(RoomEncryption, EncryptionEvent) class RoomAliasesEvent - : public StateEvent> -{ + : public StateEvent> { public: DEFINE_EVENT_TYPEID("m.room.aliases", RoomAliasesEvent) explicit RoomAliasesEvent(const QJsonObject& obj) diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index d1b742ba..757c94ee 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -20,8 +20,7 @@ #include "roomevent.h" -namespace QMatrixClient -{ +namespace QMatrixClient { /// Make a minimal correct Matrix state event JSON template @@ -34,13 +33,11 @@ inline QJsonObject basicStateEventJson(StrT matrixType, { ContentKey, content } }; } -class StateEventBase : public RoomEvent -{ +class StateEventBase : public RoomEvent { public: using factory_t = EventFactory; - StateEventBase(Type type, const QJsonObject& json) - : RoomEvent(type, json) + StateEventBase(Type type, const QJsonObject& json) : RoomEvent(type, json) {} StateEventBase(Type type, event_mtype_t matrixType, const QString& stateKey = {}, @@ -71,8 +68,7 @@ inline bool is(const Event& e) using StateEventKey = QPair; template -struct Prev -{ +struct Prev { template explicit Prev(const QJsonObject& unsignedJson, ContentParamTs&&... contentParams) @@ -86,8 +82,7 @@ struct Prev }; template -class StateEvent : public StateEventBase -{ +class StateEvent : public StateEventBase { public: using content_type = ContentT; @@ -135,11 +130,9 @@ private: }; } // namespace QMatrixClient -namespace std -{ +namespace std { template <> -struct hash -{ +struct hash { size_t operator()(const QMatrixClient::StateEventKey& k) const Q_DECL_NOEXCEPT { return qHash(k); diff --git a/lib/events/typingevent.cpp b/lib/events/typingevent.cpp index 128a206a..ee3d6b67 100644 --- a/lib/events/typingevent.cpp +++ b/lib/events/typingevent.cpp @@ -22,8 +22,7 @@ using namespace QMatrixClient; -TypingEvent::TypingEvent(const QJsonObject& obj) - : Event(typeId(), obj) +TypingEvent::TypingEvent(const QJsonObject& obj) : Event(typeId(), obj) { const auto& array = contentJson()["user_ids"_ls].toArray(); for (const auto& user : array) diff --git a/lib/events/typingevent.h b/lib/events/typingevent.h index 241359b4..c8170865 100644 --- a/lib/events/typingevent.h +++ b/lib/events/typingevent.h @@ -20,10 +20,8 @@ #include "event.h" -namespace QMatrixClient -{ -class TypingEvent : public Event -{ +namespace QMatrixClient { +class TypingEvent : public Event { public: DEFINE_EVENT_TYPEID("m.typing", TypingEvent) diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index e4a74954..a6471ece 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -32,8 +32,7 @@ using namespace QMatrixClient; -struct NetworkReplyDeleter : public QScopedPointerDeleteLater -{ +struct NetworkReplyDeleter : public QScopedPointerDeleteLater { static inline void cleanup(QNetworkReply* reply) { if (reply && reply->isRunning()) @@ -42,8 +41,7 @@ struct NetworkReplyDeleter : public QScopedPointerDeleteLater } }; -class BaseJob::Private -{ +class BaseJob::Private { public: // Using an idiom from clang-tidy: // http://clang.llvm.org/extra/clang-tidy/checks/modernize-pass-by-value.html diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index f445d087..c85d2d90 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -28,32 +28,22 @@ class QNetworkReply; class QSslError; -namespace QMatrixClient -{ +namespace QMatrixClient { class ConnectionData; -enum class HttpVerb -{ - Get, - Put, - Post, - Delete -}; +enum class HttpVerb { Get, Put, Post, Delete }; -struct JobTimeoutConfig -{ +struct JobTimeoutConfig { int jobTimeout; int nextRetryInterval; }; -class BaseJob : public QObject -{ +class BaseJob : public QObject { Q_OBJECT Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries) public: - enum StatusCode - { + enum StatusCode { NoError = 0 // To be compatible with Qt conventions , Success = 0, @@ -93,8 +83,7 @@ public: * A simple wrapper around QUrlQuery that allows its creation from * a list of string pairs */ - class Query : public QUrlQuery - { + class Query : public QUrlQuery { public: using QUrlQuery::QUrlQuery; Query() = default; @@ -115,16 +104,10 @@ public: * along the lines of StatusCode, with additional values * starting at UserDefinedError */ - class Status - { + class Status { public: - Status(StatusCode c) - : code(c) - {} - Status(int c, QString m) - : code(c) - , message(std::move(m)) - {} + Status(StatusCode c) : code(c) {} + Status(int c, QString m) : code(c), message(std::move(m)) {} bool good() const { return code < ErrorLevel; } friend QDebug operator<<(QDebug dbg, const Status& s) diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 3dff5a68..9722186c 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -6,12 +6,9 @@ using namespace QMatrixClient; -class DownloadFileJob::Private -{ +class DownloadFileJob::Private { public: - Private() - : tempFile(new QTemporaryFile()) - {} + Private() : tempFile(new QTemporaryFile()) {} explicit Private(const QString& localFilename) : targetFile(new QFile(localFilename)) diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index 58858448..ebfe5a0d 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -2,15 +2,10 @@ #include "csapi/content-repo.h" -namespace QMatrixClient -{ -class DownloadFileJob : public GetContentJob -{ +namespace QMatrixClient { +class DownloadFileJob : public GetContentJob { public: - enum - { - FileError = BaseJob::UserDefinedError + 1 - }; + enum { FileError = BaseJob::UserDefinedError + 1 }; using GetContentJob::makeRequestUrl; static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri); diff --git a/lib/jobs/mediathumbnailjob.h b/lib/jobs/mediathumbnailjob.h index eeabe7a9..df0a7f31 100644 --- a/lib/jobs/mediathumbnailjob.h +++ b/lib/jobs/mediathumbnailjob.h @@ -22,10 +22,8 @@ #include -namespace QMatrixClient -{ -class MediaThumbnailJob : public GetContentThumbnailJob -{ +namespace QMatrixClient { +class MediaThumbnailJob : public GetContentThumbnailJob { public: using GetContentThumbnailJob::makeRequestUrl; static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri, diff --git a/lib/jobs/postreadmarkersjob.h b/lib/jobs/postreadmarkersjob.h index d53ae66c..cf482a9a 100644 --- a/lib/jobs/postreadmarkersjob.h +++ b/lib/jobs/postreadmarkersjob.h @@ -24,8 +24,7 @@ using namespace QMatrixClient; -class PostReadMarkersJob : public BaseJob -{ +class PostReadMarkersJob : public BaseJob { public: explicit PostReadMarkersJob(const QString& roomId, const QString& readUpToEventId) diff --git a/lib/jobs/requestdata.cpp b/lib/jobs/requestdata.cpp index 8248d6b1..6ad7c007 100644 --- a/lib/jobs/requestdata.cpp +++ b/lib/jobs/requestdata.cpp @@ -23,16 +23,10 @@ inline auto fromJson(const JsonDataT& jdata) return fromData(QJsonDocument(jdata).toJson(QJsonDocument::Compact)); } -RequestData::RequestData(const QByteArray& a) - : _source(fromData(a)) -{} +RequestData::RequestData(const QByteArray& a) : _source(fromData(a)) {} -RequestData::RequestData(const QJsonObject& jo) - : _source(fromJson(jo)) -{} +RequestData::RequestData(const QJsonObject& jo) : _source(fromJson(jo)) {} -RequestData::RequestData(const QJsonArray& ja) - : _source(fromJson(ja)) -{} +RequestData::RequestData(const QJsonArray& ja) : _source(fromJson(ja)) {} RequestData::~RequestData() = default; diff --git a/lib/jobs/requestdata.h b/lib/jobs/requestdata.h index 974a9ddf..55987a3b 100644 --- a/lib/jobs/requestdata.h +++ b/lib/jobs/requestdata.h @@ -26,23 +26,20 @@ class QJsonArray; class QJsonDocument; class QIODevice; -namespace QMatrixClient -{ +namespace QMatrixClient { /** * A simple wrapper that represents the request body. * Provides a unified interface to dump an unstructured byte stream * as well as JSON (and possibly other structures in the future) to * a QByteArray consumed by QNetworkAccessManager request methods. */ -class RequestData -{ +class RequestData { public: RequestData() = default; RequestData(const QByteArray& a); RequestData(const QJsonObject& jo); RequestData(const QJsonArray& ja); - RequestData(QIODevice* source) - : _source(std::unique_ptr(source)) + RequestData(QIODevice* source) : _source(std::unique_ptr(source)) {} RequestData(const RequestData&) = delete; RequestData& operator=(const RequestData&) = delete; diff --git a/lib/jobs/syncjob.h b/lib/jobs/syncjob.h index e2cec8f7..8f925414 100644 --- a/lib/jobs/syncjob.h +++ b/lib/jobs/syncjob.h @@ -22,10 +22,8 @@ #include "../syncdata.h" #include "basejob.h" -namespace QMatrixClient -{ -class SyncJob : public BaseJob -{ +namespace QMatrixClient { +class SyncJob : public BaseJob { public: explicit SyncJob(const QString& since = {}, const QString& filter = {}, int timeout = -1, const QString& presence = {}); diff --git a/lib/joinstate.h b/lib/joinstate.h index e4dc679a..fcf840ae 100644 --- a/lib/joinstate.h +++ b/lib/joinstate.h @@ -22,10 +22,8 @@ #include -namespace QMatrixClient -{ -enum class JoinState : unsigned int -{ +namespace QMatrixClient { +enum class JoinState : unsigned int { Join = 0x1, Invite = 0x2, Leave = 0x4, diff --git a/lib/logging.h b/lib/logging.h index a50c1795..24799752 100644 --- a/lib/logging.h +++ b/lib/logging.h @@ -28,8 +28,7 @@ Q_DECLARE_LOGGING_CATEGORY(EPHEMERAL) Q_DECLARE_LOGGING_CATEGORY(JOBS) Q_DECLARE_LOGGING_CATEGORY(SYNCJOB) -namespace QMatrixClient -{ +namespace QMatrixClient { // QDebug manipulators using QDebugManip = QDebug (*)(QDebug); diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 9ac589b8..7bff654c 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -23,15 +23,13 @@ using namespace QMatrixClient; -class NetworkAccessManager::Private -{ +class NetworkAccessManager::Private { public: QList ignoredSslErrors; }; NetworkAccessManager::NetworkAccessManager(QObject* parent) - : QNetworkAccessManager(parent) - , d(std::make_unique()) + : QNetworkAccessManager(parent), d(std::make_unique()) {} QList NetworkAccessManager::ignoredSslErrors() const diff --git a/lib/networkaccessmanager.h b/lib/networkaccessmanager.h index bf8f0cbc..dfa388f0 100644 --- a/lib/networkaccessmanager.h +++ b/lib/networkaccessmanager.h @@ -22,10 +22,8 @@ #include -namespace QMatrixClient -{ -class NetworkAccessManager : public QNetworkAccessManager -{ +namespace QMatrixClient { +class NetworkAccessManager : public QNetworkAccessManager { Q_OBJECT public: NetworkAccessManager(QObject* parent = nullptr); diff --git a/lib/networksettings.h b/lib/networksettings.h index 0c21a9fe..75bf726d 100644 --- a/lib/networksettings.h +++ b/lib/networksettings.h @@ -24,10 +24,8 @@ Q_DECLARE_METATYPE(QNetworkProxy::ProxyType) -namespace QMatrixClient -{ -class NetworkSettings : public SettingsGroup -{ +namespace QMatrixClient { +class NetworkSettings : public SettingsGroup { Q_OBJECT QMC_DECLARE_SETTING(QNetworkProxy::ProxyType, proxyType, setProxyType) QMC_DECLARE_SETTING(QString, proxyHostName, setProxyHostName) diff --git a/lib/qt_connection_util.h b/lib/qt_connection_util.h index 1b3229d4..94c1ec60 100644 --- a/lib/qt_connection_util.h +++ b/lib/qt_connection_util.h @@ -22,10 +22,8 @@ #include -namespace QMatrixClient -{ -namespace _impl -{ +namespace QMatrixClient { +namespace _impl { template inline QMetaObject::Connection connectUntil(SenderT* sender, SignalT signal, ContextT* context, @@ -86,12 +84,10 @@ inline auto connectSingleShot(SenderT* sender, SignalT signal, * destruction. */ template -class ConnectionsGuard : public QPointer -{ +class ConnectionsGuard : public QPointer { public: ConnectionsGuard(T* publisher, QObject* subscriber) - : QPointer(publisher) - , subscriber(subscriber) + : QPointer(publisher), subscriber(subscriber) {} ~ConnectionsGuard() { diff --git a/lib/room.cpp b/lib/room.cpp index cf58f3c0..b32d3492 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -78,24 +78,16 @@ using std::move; using std::llround; #endif -enum EventsPlacement : int -{ - Older = -1, - Newer = 1 -}; +enum EventsPlacement : int { Older = -1, Newer = 1 }; -class Room::Private -{ +class Room::Private { public: /// Map of user names to users /** User names potentially duplicate, hence QMultiHash. */ using members_map_t = QMultiHash; Private(Connection* c, QString id_, JoinState initialJoinState) - : q(nullptr) - , connection(c) - , id(move(id_)) - , joinState(initialJoinState) + : q(nullptr), connection(c), id(move(id_)), joinState(initialJoinState) {} Room* q; @@ -144,8 +136,7 @@ public: QPointer eventsHistoryJob; QPointer allMembersJob; - struct FileTransferPrivateInfo - { + struct FileTransferPrivateInfo { FileTransferPrivateInfo() = default; FileTransferPrivateInfo(BaseJob* j, const QString& fileName, bool isUploading = false) @@ -354,8 +345,7 @@ private: decltype(Room::Private::baseState) Room::Private::stubbedState {}; Room::Room(Connection* connection, QString id, JoinState initialJoinState) - : QObject(connection) - , d(new Private(connection, id, initialJoinState)) + : QObject(connection), d(new Private(connection, id, initialJoinState)) { setObjectName(id); // See "Accessing the Public Class" section in @@ -1617,9 +1607,9 @@ QString Room::postFile(const QString& plainText, const QUrl& localPath, // Normally in this situation we should instruct // the media server to delete the file; alas, there's no // API specced for that. - qCWarning(MAIN) - << "File uploaded to" << mxcUri - << "but the event referring to it was cancelled"; + qCWarning(MAIN) << "File uploaded to" << mxcUri + << "but the event referring to it was " + "cancelled"; } context->deleteLater(); } @@ -2382,9 +2372,9 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) break; case MembershipType::Join: if (evt.membership() == MembershipType::Invite) - qCWarning(MAIN) - << "Invalid membership change from Join to Invite:" - << evt; + qCWarning(MAIN) << "Invalid membership change from " + "Join to Invite:" + << evt; if (evt.membership() != prevMembership) { disconnect(u, &User::nameAboutToChange, this, nullptr); disconnect(u, &User::nameChanged, this, nullptr); @@ -2564,7 +2554,8 @@ Room::Private::buildShortlist(const ContT& users) const std::partial_sort_copy( users.begin(), users.end(), shortlist.begin(), shortlist.end(), [this](const User* u1, const User* u2) { - // localUser(), if it's in the list, is sorted below all others + // localUser(), if it's in the list, is sorted + // below all others return isLocalUser(u2) || (!isLocalUser(u1) && u1->id() < u2->id()); }); return shortlist; diff --git a/lib/room.h b/lib/room.h index f5433fb6..d6fb8a61 100644 --- a/lib/room.h +++ b/lib/room.h @@ -35,8 +35,7 @@ #include #include -namespace QMatrixClient -{ +namespace QMatrixClient { class Event; class Avatar; class SyncRoomData; @@ -52,8 +51,7 @@ class RedactEventJob; * This is specifically tuned to work with QML exposing all traits as * Q_PROPERTY values. */ -class FileTransferInfo -{ +class FileTransferInfo { Q_GADGET Q_PROPERTY(bool isUpload MEMBER isUpload CONSTANT) Q_PROPERTY(bool active READ active CONSTANT) @@ -65,14 +63,7 @@ class FileTransferInfo Q_PROPERTY(QUrl localDir MEMBER localDir CONSTANT) Q_PROPERTY(QUrl localPath MEMBER localPath CONSTANT) public: - enum Status - { - None, - Started, - Completed, - Failed, - Cancelled - }; + enum Status { None, Started, Completed, Failed, Cancelled }; Status status = None; bool isUpload = false; int progress = 0; @@ -86,8 +77,7 @@ public: bool failed() const { return status == Failed; } }; -class Room : public QObject -{ +class Room : public QObject { Q_OBJECT Q_PROPERTY(Connection* connection READ connection CONSTANT) Q_PROPERTY(User* localUser READ localUser CONSTANT) @@ -146,8 +136,7 @@ public: using rev_iter_t = Timeline::const_reverse_iterator; using timeline_iter_t = Timeline::const_iterator; - enum Change : uint - { + enum Change : uint { NoChange = 0x0, NameChange = 0x1, CanonicalAliasChange = 0x2, @@ -663,12 +652,9 @@ private: void setJoinState(JoinState state); }; -class MemberSorter -{ +class MemberSorter { public: - explicit MemberSorter(const Room* r) - : room(r) - {} + explicit MemberSorter(const Room* r) : room(r) {} bool operator()(User* u1, User* u2) const; bool operator()(User* u1, const QString& u2name) const; diff --git a/lib/settings.h b/lib/settings.h index e1ca0866..6747631e 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -24,10 +24,8 @@ class QVariant; -namespace QMatrixClient -{ -class Settings : public QSettings -{ +namespace QMatrixClient { +class Settings : public QSettings { Q_OBJECT public: /** @@ -42,9 +40,7 @@ public: #if defined(_MSC_VER) && _MSC_VER < 1900 // VS 2013 (and probably older) aren't friends with 'using' statements // that involve private constructors - explicit Settings(QObject* parent = 0) - : QSettings(parent) - {} + explicit Settings(QObject* parent = 0) : QSettings(parent) {} #else using QSettings::QSettings; #endif @@ -71,8 +67,7 @@ protected: QSettings legacySettings { legacyOrganizationName, legacyApplicationName }; }; -class SettingsGroup : public Settings -{ +class SettingsGroup : public Settings { public: template explicit SettingsGroup(QString path, ArgTs&&... qsettingsArgs) @@ -121,8 +116,7 @@ private: setValue(QStringLiteral(qsettingname), std::move(newValue)); \ } -class AccountSettings : public SettingsGroup -{ +class AccountSettings : public SettingsGroup { Q_OBJECT Q_PROPERTY(QString userId READ userId CONSTANT) QMC_DECLARE_SETTING(QString, deviceId, setDeviceId) diff --git a/lib/syncdata.h b/lib/syncdata.h index 6932878d..ad9902e4 100644 --- a/lib/syncdata.h +++ b/lib/syncdata.h @@ -22,8 +22,7 @@ #include "events/stateevent.h" -namespace QMatrixClient -{ +namespace QMatrixClient { /// Room summary, as defined in MSC688 /** * Every member of this structure is an Omittable; as per the MSC, only @@ -32,8 +31,7 @@ namespace QMatrixClient * means that nothing has come from the server; heroes.value().isEmpty() * means a peculiar case of a room with the only member - the current user. */ -struct RoomSummary -{ +struct RoomSummary { Omittable joinedMemberCount; Omittable invitedMemberCount; Omittable heroes; //< mxids of users to take part in the room @@ -48,14 +46,12 @@ struct RoomSummary }; template <> -struct JsonObjectConverter -{ +struct JsonObjectConverter { static void dumpTo(QJsonObject& jo, const RoomSummary& rs); static void fillFrom(const QJsonObject& jo, RoomSummary& rs); }; -class SyncRoomData -{ +class SyncRoomData { public: QString roomId; JoinState joinState; @@ -82,8 +78,7 @@ public: // QVector cannot work with non-copiable objects, std::vector can. using SyncDataList = std::vector; -class SyncData -{ +class SyncData { public: SyncData() = default; explicit SyncData(const QString& cacheFileName); diff --git a/lib/user.cpp b/lib/user.cpp index f0216454..0705aee7 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -41,8 +41,7 @@ using namespace QMatrixClient; using namespace std::placeholders; using std::move; -class User::Private -{ +class User::Private { public: static Avatar makeAvatar(QUrl url) { return Avatar(move(url)); } @@ -184,8 +183,7 @@ void User::Private::setAvatarForRoom(const Room* r, const QUrl& newUrl, } User::User(QString userId, Connection* connection) - : QObject(connection) - , d(new Private(move(userId), connection)) + : QObject(connection), d(new Private(move(userId), connection)) { setObjectName(userId); } diff --git a/lib/user.h b/lib/user.h index f4d7cff3..779efb34 100644 --- a/lib/user.h +++ b/lib/user.h @@ -23,14 +23,12 @@ #include #include -namespace QMatrixClient -{ +namespace QMatrixClient { class Connection; class Room; class RoomMemberEvent; -class User : public QObject -{ +class User : public QObject { Q_OBJECT Q_PROPERTY(QString id READ id CONSTANT) Q_PROPERTY(bool isGuest READ isGuest CONSTANT) diff --git a/lib/util.cpp b/lib/util.cpp index 9e0807c6..1919e811 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -124,7 +124,8 @@ QString QMatrixClient::serverPart(const QString& mxId) % ServerPartRegEx % ")$"; static QRegularExpression parser( re, - QRegularExpression::UseUnicodePropertiesOption); // Because Asian digits + QRegularExpression::UseUnicodePropertiesOption); // Because Asian + // digits return parser.match(mxId).captured(1); } @@ -148,16 +149,14 @@ void f2(int, QString); static_assert(std::is_same, QString>::value, "Test fn_arg_t<>"); -struct S -{ +struct S { int mf(); }; static_assert(is_callable_v, "Test member function"); static_assert(returns(), "Test returns<> with member function"); -struct Fo -{ +struct Fo { int operator()(); }; static_assert(is_callable_v, "Test is_callable<> with function object"); @@ -165,8 +164,7 @@ static_assert(function_traits::arg_number == 0, "Test function object"); static_assert(std::is_same, int>::value, "Test return type of function object"); -struct Fo1 -{ +struct Fo1 { void operator()(int); }; static_assert(function_traits::arg_number == 1, "Test function object 1"); @@ -182,13 +180,11 @@ static_assert(std::is_same, int>::value, #endif template -struct fn_object -{ +struct fn_object { static int smf(double) { return 0; } }; template <> -struct fn_object -{ +struct fn_object { void operator()(QString); }; static_assert(is_callable_v>, "Test function object"); diff --git a/lib/util.h b/lib/util.h index a29f6253..d055fa46 100644 --- a/lib/util.h +++ b/lib/util.h @@ -63,8 +63,7 @@ static void qAsConst(const T&&) Q_DECL_EQ_DELETE; # define BROKEN_INITIALIZER_LISTS #endif -namespace QMatrixClient -{ +namespace QMatrixClient { // The below enables pretty-printing of enums in logs #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) # define REGISTER_ENUM(EnumName) Q_ENUM(EnumName) @@ -88,8 +87,7 @@ inline auto unique_ptr_cast(PtrT2&& p) return std::unique_ptr(static_cast(p.release())); } -struct NoneTag -{}; +struct NoneTag {}; constexpr NoneTag none {}; /** A crude substitute for `optional` while we're not C++17 @@ -97,27 +95,17 @@ constexpr NoneTag none {}; * Only works with default-constructible types. */ template -class Omittable -{ +class Omittable { static_assert(!std::is_reference::value, "You cannot make an Omittable<> with a reference type"); public: using value_type = std::decay_t; - explicit Omittable() - : Omittable(none) - {} - Omittable(NoneTag) - : _value(value_type()) - , _omitted(true) - {} - Omittable(const value_type& val) - : _value(val) - {} - Omittable(value_type&& val) - : _value(std::move(val)) - {} + explicit Omittable() : Omittable(none) {} + Omittable(NoneTag) : _value(value_type()), _omitted(true) {} + Omittable(const value_type& val) : _value(val) {} + Omittable(value_type&& val) : _value(std::move(val)) {} Omittable& operator=(const value_type& val) { _value = val; @@ -192,8 +180,7 @@ private: bool _omitted = false; }; -namespace _impl -{ +namespace _impl { template struct fn_traits; } @@ -205,13 +192,11 @@ namespace _impl * https://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda#7943765 */ template -struct function_traits : public _impl::fn_traits -{}; +struct function_traits : public _impl::fn_traits {}; // Specialisation for a function template -struct function_traits -{ +struct function_traits { static constexpr auto is_callable = true; using return_type = ReturnT; using arg_types = std::tuple; @@ -219,30 +204,26 @@ struct function_traits static constexpr auto arg_number = std::tuple_size::value; }; -namespace _impl -{ +namespace _impl { template - struct fn_traits - { + struct fn_traits { static constexpr auto is_callable = false; }; template struct fn_traits - : public fn_traits - {}; // A generic function object that has (non-overloaded) operator() + : public fn_traits { + }; // A generic function object that has (non-overloaded) operator() // Specialisation for a member function template struct fn_traits - : function_traits - {}; + : function_traits {}; // Specialisation for a const member function template struct fn_traits - : function_traits - {}; + : function_traits {}; } // namespace _impl template @@ -272,22 +253,15 @@ inline auto operator"" _ls(const char* s, std::size_t size) * are at least ForwardIterators. Inspired by Ranges TS. */ template -class Range -{ +class Range { // Looking forward for Ranges TS to produce something (in C++23?..) using iterator = typename ArrayT::iterator; using const_iterator = typename ArrayT::const_iterator; using size_type = typename ArrayT::size_type; public: - Range(ArrayT& arr) - : from(std::begin(arr)) - , to(std::end(arr)) - {} - Range(iterator from, iterator to) - : from(from) - , to(to) - {} + Range(ArrayT& arr) : from(std::begin(arr)), to(std::end(arr)) {} + Range(iterator from, iterator to) : from(from), to(to) {} size_type size() const { -- cgit v1.2.3 From 7a5b359b8823646ce97cbaf05c251cb04c291466 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 7 Jul 2019 18:16:30 +0900 Subject: Rename zero-impact strings --- .travis.yml | 2 +- CMakeLists.txt | 2 +- examples/qmc-example.cpp | 2 +- lib/connection.cpp | 5 ++--- lib/jobs/basejob.cpp | 4 ++-- lib/settings.h | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) (limited to 'lib/jobs') diff --git a/.travis.yml b/.travis.yml index d02c5058..6c8d8ceb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,7 +48,7 @@ install: - pushd 3rdparty/libQtOlm - git clone https://gitlab.matrix.org/matrix-org/olm.git - popd -- git clone https://github.com/QMatrixClient/matrix-doc.git +- git clone https://github.com/quotient-im/matrix-doc.git - git clone --recursive https://github.com/KitsuneRal/gtad.git - pushd gtad - cmake $USE_NINJA -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} . diff --git a/CMakeLists.txt b/CMakeLists.txt index 996e76d4..44f4df9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ endif() message( STATUS ) message( STATUS "=============================================================================" ) -message( STATUS " libqmatrixclient Build Information" ) +message( STATUS " libQuotient Build Information" ) message( STATUS "=============================================================================" ) message( STATUS "Version: ${PROJECT_VERSION}, API version: ${API_VERSION}") if (CMAKE_BUILD_TYPE) diff --git a/examples/qmc-example.cpp b/examples/qmc-example.cpp index f649ac3f..4a06d9b8 100644 --- a/examples/qmc-example.cpp +++ b/examples/qmc-example.cpp @@ -435,7 +435,7 @@ void QMCTest::setTopic() void QMCTest::addAndRemoveTag() { running.push_back("Tagging test"); - static const auto TestTag = QStringLiteral("org.qmatrixclient.test"); + static const auto TestTag = QStringLiteral("org.quotient.test"); // Pre-requisite if (targetRoom->tags().contains(TestTag)) targetRoom->removeTag(TestTag); diff --git a/lib/connection.cpp b/lib/connection.cpp index 6cd6ad0b..58d2e01a 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -95,8 +95,7 @@ public: DirectChatsMap directChats; DirectChatUsersMap directChatUsers; // The below two variables track local changes between sync completions. - // See also: - // https://github.com/QMatrixClient/libqmatrixclient/wiki/Handling-direct-chat-events + // See https://github.com/quotient-im/libQuotient/wiki/Handling-direct-chat-events DirectChatsMap dcLocalAdditions; DirectChatsMap dcLocalRemovals; std::unordered_map accountData; @@ -435,7 +434,7 @@ void Connection::onSyncSuccess(SyncData&& data, bool fromCache) visit( *eventPtr, [this](const DirectChatEvent& dce) { - // https://github.com/QMatrixClient/libqmatrixclient/wiki/Handling-direct-chat-events + // https://github.com/quotient-im/libQuotient/wiki/Handling-direct-chat-events const auto& usersToDCs = dce.usersToDirectChats(); DirectChatsMap remoteRemovals = erase_if(d->directChats, [&usersToDCs, this](auto it) { diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index a6471ece..5615736e 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -321,7 +321,7 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const { // QNetworkReply error codes seem to be flawed when it comes to HTTP; - // see, e.g., https://github.com/QMatrixClient/libqmatrixclient/issues/200 + // see, e.g., https://github.com/quotient-im/libQuotient/issues/200 // so check genuine HTTP codes. The below processing is based on // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes const auto httpCodeHeader = @@ -576,7 +576,7 @@ QUrl BaseJob::errorUrl() const { return d->errorUrl; } void BaseJob::setStatus(Status s) { // The crash that led to this code has been reported in - // https://github.com/QMatrixClient/Quaternion/issues/566 - basically, + // https://github.com/quotient-im/Quaternion/issues/566 - basically, // when cleaning up childrent of a deleted Connection, there's a chance // of pending jobs being abandoned, calling setStatus(Abandoned). // There's nothing wrong with this; however, the safety check for diff --git a/lib/settings.h b/lib/settings.h index 6747631e..427f5494 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -140,7 +140,7 @@ public: /** \deprecated \sa setToken */ QString accessToken() const; /** \deprecated Storing accessToken in QSettings is unsafe, - * see QMatrixClient/Quaternion#181 */ + * see quotient-im/Quaternion#181 */ void setAccessToken(const QString& accessToken); Q_INVOKABLE void clearAccessToken(); -- cgit v1.2.3 From 27ca32a1e5a56e09b9cc1d94224d2831004dcf3d Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 7 Jul 2019 19:32:34 +0900 Subject: Namespace: QMatrixClient -> Quotient (with back comp alias) --- examples/qmc-example.cpp | 2 +- lib/application-service/definitions/location.cpp | 2 +- lib/application-service/definitions/location.h | 4 ++-- lib/application-service/definitions/protocol.cpp | 2 +- lib/application-service/definitions/protocol.h | 4 ++-- lib/application-service/definitions/user.cpp | 2 +- lib/application-service/definitions/user.h | 4 ++-- lib/avatar.cpp | 2 +- lib/avatar.h | 6 ++++-- lib/connection.cpp | 6 +++--- lib/connection.h | 6 +++--- lib/connectiondata.cpp | 2 +- lib/connectiondata.h | 4 ++-- lib/converters.cpp | 2 +- lib/converters.h | 4 ++-- lib/csapi/account-data.cpp | 2 +- lib/csapi/account-data.h | 4 ++-- lib/csapi/admin.cpp | 6 +++--- lib/csapi/admin.h | 4 ++-- lib/csapi/administrative_contact.cpp | 10 +++++----- lib/csapi/administrative_contact.h | 4 ++-- lib/csapi/appservice_room_directory.cpp | 2 +- lib/csapi/appservice_room_directory.h | 4 ++-- lib/csapi/banning.cpp | 2 +- lib/csapi/banning.h | 4 ++-- lib/csapi/capabilities.cpp | 6 +++--- lib/csapi/capabilities.h | 4 ++-- lib/csapi/content-repo.cpp | 2 +- lib/csapi/content-repo.h | 4 ++-- lib/csapi/create_room.cpp | 6 +++--- lib/csapi/create_room.h | 4 ++-- lib/csapi/definitions/auth_data.cpp | 2 +- lib/csapi/definitions/auth_data.h | 4 ++-- lib/csapi/definitions/client_device.cpp | 2 +- lib/csapi/definitions/client_device.h | 4 ++-- lib/csapi/definitions/device_keys.cpp | 2 +- lib/csapi/definitions/device_keys.h | 4 ++-- lib/csapi/definitions/event_filter.cpp | 2 +- lib/csapi/definitions/event_filter.h | 4 ++-- lib/csapi/definitions/public_rooms_response.cpp | 2 +- lib/csapi/definitions/public_rooms_response.h | 4 ++-- lib/csapi/definitions/push_condition.cpp | 2 +- lib/csapi/definitions/push_condition.h | 4 ++-- lib/csapi/definitions/push_rule.cpp | 2 +- lib/csapi/definitions/push_rule.h | 4 ++-- lib/csapi/definitions/push_ruleset.cpp | 2 +- lib/csapi/definitions/push_ruleset.h | 4 ++-- lib/csapi/definitions/room_event_filter.cpp | 2 +- lib/csapi/definitions/room_event_filter.h | 4 ++-- lib/csapi/definitions/sync_filter.cpp | 2 +- lib/csapi/definitions/sync_filter.h | 4 ++-- lib/csapi/definitions/user_identifier.cpp | 2 +- lib/csapi/definitions/user_identifier.h | 4 ++-- lib/csapi/definitions/wellknown/full.cpp | 2 +- lib/csapi/definitions/wellknown/full.h | 4 ++-- lib/csapi/definitions/wellknown/homeserver.cpp | 2 +- lib/csapi/definitions/wellknown/homeserver.h | 4 ++-- lib/csapi/definitions/wellknown/identity_server.cpp | 2 +- lib/csapi/definitions/wellknown/identity_server.h | 4 ++-- lib/csapi/device_management.cpp | 2 +- lib/csapi/device_management.h | 4 ++-- lib/csapi/directory.cpp | 2 +- lib/csapi/directory.h | 4 ++-- lib/csapi/event_context.cpp | 2 +- lib/csapi/event_context.h | 4 ++-- lib/csapi/filter.cpp | 2 +- lib/csapi/filter.h | 4 ++-- lib/csapi/inviting.cpp | 2 +- lib/csapi/inviting.h | 4 ++-- lib/csapi/joining.cpp | 10 +++++----- lib/csapi/joining.h | 4 ++-- lib/csapi/keys.cpp | 6 +++--- lib/csapi/keys.h | 4 ++-- lib/csapi/kicking.cpp | 2 +- lib/csapi/kicking.h | 4 ++-- lib/csapi/leaving.cpp | 2 +- lib/csapi/leaving.h | 4 ++-- lib/csapi/list_joined_rooms.cpp | 2 +- lib/csapi/list_joined_rooms.h | 4 ++-- lib/csapi/list_public_rooms.cpp | 6 +++--- lib/csapi/list_public_rooms.h | 4 ++-- lib/csapi/login.cpp | 6 +++--- lib/csapi/login.h | 4 ++-- lib/csapi/logout.cpp | 2 +- lib/csapi/logout.h | 4 ++-- lib/csapi/message_pagination.cpp | 2 +- lib/csapi/message_pagination.h | 4 ++-- lib/csapi/notifications.cpp | 6 +++--- lib/csapi/notifications.h | 4 ++-- lib/csapi/openid.cpp | 2 +- lib/csapi/openid.h | 4 ++-- lib/csapi/peeking_events.cpp | 2 +- lib/csapi/peeking_events.h | 4 ++-- lib/csapi/presence.cpp | 2 +- lib/csapi/presence.h | 4 ++-- lib/csapi/profile.cpp | 2 +- lib/csapi/profile.h | 4 ++-- lib/csapi/pusher.cpp | 10 +++++----- lib/csapi/pusher.h | 4 ++-- lib/csapi/pushrules.cpp | 2 +- lib/csapi/pushrules.h | 4 ++-- lib/csapi/read_markers.cpp | 2 +- lib/csapi/read_markers.h | 4 ++-- lib/csapi/receipts.cpp | 2 +- lib/csapi/receipts.h | 4 ++-- lib/csapi/redaction.cpp | 2 +- lib/csapi/redaction.h | 4 ++-- lib/csapi/registration.cpp | 2 +- lib/csapi/registration.h | 4 ++-- lib/csapi/report_content.cpp | 2 +- lib/csapi/report_content.h | 4 ++-- lib/csapi/room_send.cpp | 2 +- lib/csapi/room_send.h | 4 ++-- lib/csapi/room_state.cpp | 2 +- lib/csapi/room_state.h | 4 ++-- lib/csapi/room_upgrades.cpp | 2 +- lib/csapi/room_upgrades.h | 4 ++-- lib/csapi/rooms.cpp | 6 +++--- lib/csapi/rooms.h | 4 ++-- lib/csapi/search.cpp | 6 +++--- lib/csapi/search.h | 4 ++-- lib/csapi/sso_login_redirect.cpp | 2 +- lib/csapi/sso_login_redirect.h | 4 ++-- lib/csapi/tags.cpp | 6 +++--- lib/csapi/tags.h | 4 ++-- lib/csapi/third_party_lookup.cpp | 2 +- lib/csapi/third_party_lookup.h | 4 ++-- lib/csapi/third_party_membership.cpp | 2 +- lib/csapi/third_party_membership.h | 4 ++-- lib/csapi/to_device.cpp | 2 +- lib/csapi/to_device.h | 4 ++-- lib/csapi/typing.cpp | 2 +- lib/csapi/typing.h | 4 ++-- lib/csapi/users.cpp | 6 +++--- lib/csapi/users.h | 4 ++-- lib/csapi/versions.cpp | 2 +- lib/csapi/versions.h | 4 ++-- lib/csapi/voip.cpp | 2 +- lib/csapi/voip.h | 4 ++-- lib/csapi/wellknown.cpp | 2 +- lib/csapi/wellknown.h | 4 ++-- lib/csapi/whoami.cpp | 2 +- lib/csapi/whoami.h | 4 ++-- lib/csapi/{{base}}.cpp.mustache | 4 ++-- lib/csapi/{{base}}.h.mustache | 4 ++-- lib/e2ee.h | 4 ++-- lib/encryptionmanager.cpp | 2 +- lib/encryptionmanager.h | 4 ++-- lib/eventitem.cpp | 2 +- lib/eventitem.h | 6 +++--- lib/events/accountdataevents.h | 4 ++-- lib/events/callanswerevent.cpp | 2 +- lib/events/callanswerevent.h | 4 ++-- lib/events/callcandidatesevent.h | 4 ++-- lib/events/callhangupevent.cpp | 2 +- lib/events/callhangupevent.h | 4 ++-- lib/events/callinviteevent.cpp | 2 +- lib/events/callinviteevent.h | 4 ++-- lib/events/directchatevent.cpp | 2 +- lib/events/directchatevent.h | 4 ++-- lib/events/encryptedevent.h | 4 ++-- lib/events/encryptionevent.cpp | 6 +++--- lib/events/encryptionevent.h | 4 ++-- lib/events/event.cpp | 2 +- lib/events/event.h | 10 +++++----- lib/events/eventcontent.cpp | 2 +- lib/events/eventcontent.h | 4 ++-- lib/events/eventloader.h | 4 ++-- lib/events/reactionevent.cpp | 4 ++-- lib/events/reactionevent.h | 4 ++-- lib/events/receiptevent.cpp | 2 +- lib/events/receiptevent.h | 4 ++-- lib/events/redactionevent.h | 4 ++-- lib/events/roomavatarevent.h | 4 ++-- lib/events/roomcreateevent.cpp | 2 +- lib/events/roomcreateevent.h | 4 ++-- lib/events/roomevent.cpp | 4 ++-- lib/events/roomevent.h | 8 ++++---- lib/events/roommemberevent.cpp | 6 +++--- lib/events/roommemberevent.h | 4 ++-- lib/events/roommessageevent.cpp | 6 +++--- lib/events/roommessageevent.h | 4 ++-- lib/events/roomtombstoneevent.cpp | 2 +- lib/events/roomtombstoneevent.h | 4 ++-- lib/events/simplestateevents.h | 6 +++--- lib/events/stateevent.cpp | 2 +- lib/events/stateevent.h | 8 ++++---- lib/events/typingevent.cpp | 2 +- lib/events/typingevent.h | 4 ++-- lib/identity/definitions/request_email_validation.cpp | 2 +- lib/identity/definitions/request_email_validation.h | 4 ++-- lib/identity/definitions/request_msisdn_validation.cpp | 2 +- lib/identity/definitions/request_msisdn_validation.h | 4 ++-- lib/identity/definitions/sid.cpp | 2 +- lib/identity/definitions/sid.h | 4 ++-- lib/jobs/basejob.cpp | 2 +- lib/jobs/basejob.h | 4 ++-- lib/jobs/downloadfilejob.cpp | 2 +- lib/jobs/downloadfilejob.h | 4 ++-- lib/jobs/mediathumbnailjob.cpp | 2 +- lib/jobs/mediathumbnailjob.h | 4 ++-- lib/jobs/postreadmarkersjob.h | 2 +- lib/jobs/requestdata.cpp | 2 +- lib/jobs/requestdata.h | 6 ++++-- lib/jobs/syncjob.cpp | 2 +- lib/jobs/syncjob.h | 4 ++-- lib/joinstate.h | 6 +++--- lib/logging.h | 6 ++++-- lib/networkaccessmanager.cpp | 2 +- lib/networkaccessmanager.h | 4 ++-- lib/networksettings.cpp | 2 +- lib/networksettings.h | 2 +- lib/qt_connection_util.h | 4 ++-- lib/room.cpp | 4 ++-- lib/room.h | 10 +++++----- lib/settings.cpp | 2 +- lib/settings.h | 4 ++-- lib/syncdata.cpp | 4 ++-- lib/syncdata.h | 4 ++-- lib/user.cpp | 2 +- lib/user.h | 6 +++--- lib/util.cpp | 14 +++++++------- lib/util.h | 6 ++++-- 223 files changed, 414 insertions(+), 406 deletions(-) (limited to 'lib/jobs') diff --git a/examples/qmc-example.cpp b/examples/qmc-example.cpp index 4a06d9b8..bf4d04c7 100644 --- a/examples/qmc-example.cpp +++ b/examples/qmc-example.cpp @@ -19,7 +19,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; using std::cout; using std::endl; using namespace std::placeholders; diff --git a/lib/application-service/definitions/location.cpp b/lib/application-service/definitions/location.cpp index 2ab83ae9..0a054029 100644 --- a/lib/application-service/definitions/location.cpp +++ b/lib/application-service/definitions/location.cpp @@ -4,7 +4,7 @@ #include "location.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo( QJsonObject& jo, const ThirdPartyLocation& pod) diff --git a/lib/application-service/definitions/location.h b/lib/application-service/definitions/location.h index caf28615..77512514 100644 --- a/lib/application-service/definitions/location.h +++ b/lib/application-service/definitions/location.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -30,4 +30,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, ThirdPartyLocation& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/application-service/definitions/protocol.cpp b/lib/application-service/definitions/protocol.cpp index e87001fb..8c66aa4d 100644 --- a/lib/application-service/definitions/protocol.cpp +++ b/lib/application-service/definitions/protocol.cpp @@ -4,7 +4,7 @@ #include "protocol.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const FieldType& pod) diff --git a/lib/application-service/definitions/protocol.h b/lib/application-service/definitions/protocol.h index 0d227851..ab99264f 100644 --- a/lib/application-service/definitions/protocol.h +++ b/lib/application-service/definitions/protocol.h @@ -10,7 +10,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -85,4 +85,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, ThirdPartyProtocol& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/application-service/definitions/user.cpp b/lib/application-service/definitions/user.cpp index 0f3c3130..17d15a20 100644 --- a/lib/application-service/definitions/user.cpp +++ b/lib/application-service/definitions/user.cpp @@ -4,7 +4,7 @@ #include "user.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const ThirdPartyUser& pod) diff --git a/lib/application-service/definitions/user.h b/lib/application-service/definitions/user.h index 3fd099d0..34c6829c 100644 --- a/lib/application-service/definitions/user.h +++ b/lib/application-service/definitions/user.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -30,4 +30,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, ThirdPartyUser& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/avatar.cpp b/lib/avatar.cpp index 614f008d..cb734984 100644 --- a/lib/avatar.cpp +++ b/lib/avatar.cpp @@ -29,7 +29,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; using std::move; class Avatar::Private { diff --git a/lib/avatar.h b/lib/avatar.h index c33e1982..7a566bfa 100644 --- a/lib/avatar.h +++ b/lib/avatar.h @@ -24,7 +24,7 @@ #include #include -namespace QMatrixClient { +namespace Quotient { class Connection; class Avatar { @@ -56,4 +56,6 @@ private: class Private; std::unique_ptr d; }; -} // namespace QMatrixClient +} // namespace Quotient +/// \deprecated Use namespace Quotient instead +namespace QMatrixClient = Quotient; \ No newline at end of file diff --git a/lib/connection.cpp b/lib/connection.cpp index 58d2e01a..22db8e3d 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -53,7 +53,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; // This is very much Qt-specific; STL iterators don't have key() and value() template @@ -1349,9 +1349,9 @@ void Connection::setCacheState(bool newValue) } } -bool QMatrixClient::Connection::lazyLoading() const { return d->lazyLoading; } +bool Connection::lazyLoading() const { return d->lazyLoading; } -void QMatrixClient::Connection::setLazyLoading(bool newValue) +void Connection::setLazyLoading(bool newValue) { if (d->lazyLoading != newValue) { d->lazyLoading = newValue; diff --git a/lib/connection.h b/lib/connection.h index b89c0c65..c807b827 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -36,7 +36,7 @@ namespace QtOlm { class Account; } -namespace QMatrixClient { +namespace Quotient { class Room; class User; class ConnectionData; @@ -778,5 +778,5 @@ private: static room_factory_t _roomFactory; static user_factory_t _userFactory; }; -} // namespace QMatrixClient -Q_DECLARE_METATYPE(QMatrixClient::Connection*) +} // namespace Quotient +Q_DECLARE_METATYPE(Quotient::Connection*) diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index df4cece2..486de03d 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -21,7 +21,7 @@ #include "logging.h" #include "networkaccessmanager.h" -using namespace QMatrixClient; +using namespace Quotient; struct ConnectionData::Private { explicit Private(QUrl url) : baseUrl(std::move(url)) {} diff --git a/lib/connectiondata.h b/lib/connectiondata.h index 9b579b1c..80ace08c 100644 --- a/lib/connectiondata.h +++ b/lib/connectiondata.h @@ -24,7 +24,7 @@ class QNetworkAccessManager; -namespace QMatrixClient { +namespace Quotient { class ConnectionData { public: explicit ConnectionData(QUrl baseUrl); @@ -50,4 +50,4 @@ private: struct Private; std::unique_ptr d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/converters.cpp b/lib/converters.cpp index ef58c85e..9f4b9360 100644 --- a/lib/converters.cpp +++ b/lib/converters.cpp @@ -20,7 +20,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; QJsonValue JsonConverter::dump(const QVariant& v) { diff --git a/lib/converters.h b/lib/converters.h index 0085fa4b..587e4544 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -55,7 +55,7 @@ struct hash { class QVariant; -namespace QMatrixClient { +namespace Quotient { template struct JsonObjectConverter { static void dumpTo(QJsonObject& jo, const T& pod) { jo = pod.toJson(); } @@ -439,4 +439,4 @@ inline void addParam(ContT& container, const QString& key, ValT&& value) _impl::AddNode, Force>::impl(container, key, std::forward(value)); } -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/account-data.cpp b/lib/csapi/account-data.cpp index 7d4f1ad7..2e466fa3 100644 --- a/lib/csapi/account-data.cpp +++ b/lib/csapi/account-data.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/account-data.h b/lib/csapi/account-data.h index 75bb9ce3..7417da0d 100644 --- a/lib/csapi/account-data.h +++ b/lib/csapi/account-data.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -122,4 +122,4 @@ public: const QString& roomId, const QString& type); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/admin.cpp b/lib/csapi/admin.cpp index 58334118..d2c20ba8 100644 --- a/lib/csapi/admin.cpp +++ b/lib/csapi/admin.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -46,7 +46,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class GetWhoIsJob::Private { diff --git a/lib/csapi/admin.h b/lib/csapi/admin.h index bc27c025..472ccf72 100644 --- a/lib/csapi/admin.h +++ b/lib/csapi/admin.h @@ -11,7 +11,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -94,4 +94,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/administrative_contact.cpp b/lib/csapi/administrative_contact.cpp index 067fb68a..32bc8c86 100644 --- a/lib/csapi/administrative_contact.cpp +++ b/lib/csapi/administrative_contact.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -29,7 +29,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class GetAccount3PIDsJob::Private { @@ -67,7 +67,7 @@ BaseJob::Status GetAccount3PIDsJob::parseJson(const QJsonDocument& data) } // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -82,7 +82,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient static const auto Post3PIDsJobName = QStringLiteral("Post3PIDsJob"); diff --git a/lib/csapi/administrative_contact.h b/lib/csapi/administrative_contact.h index 7f2d0cdc..4ccd7596 100644 --- a/lib/csapi/administrative_contact.h +++ b/lib/csapi/administrative_contact.h @@ -12,7 +12,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -256,4 +256,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/appservice_room_directory.cpp b/lib/csapi/appservice_room_directory.cpp index 74e037cd..87221aa4 100644 --- a/lib/csapi/appservice_room_directory.cpp +++ b/lib/csapi/appservice_room_directory.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/appservice_room_directory.h b/lib/csapi/appservice_room_directory.h index d1c3f89f..e19bf320 100644 --- a/lib/csapi/appservice_room_directory.h +++ b/lib/csapi/appservice_room_directory.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -42,4 +42,4 @@ public: const QString& visibility); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/banning.cpp b/lib/csapi/banning.cpp index a46e78f1..eac09d5a 100644 --- a/lib/csapi/banning.cpp +++ b/lib/csapi/banning.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/banning.h b/lib/csapi/banning.h index 0aa5785b..5df878a8 100644 --- a/lib/csapi/banning.h +++ b/lib/csapi/banning.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -58,4 +58,4 @@ public: explicit UnbanJob(const QString& roomId, const QString& userId); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/capabilities.cpp b/lib/csapi/capabilities.cpp index 9a054fe9..6a544a1e 100644 --- a/lib/csapi/capabilities.cpp +++ b/lib/csapi/capabilities.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -49,7 +49,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class GetCapabilitiesJob::Private { diff --git a/lib/csapi/capabilities.h b/lib/csapi/capabilities.h index f6e7ad06..b608a2f2 100644 --- a/lib/csapi/capabilities.h +++ b/lib/csapi/capabilities.h @@ -11,7 +11,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -84,4 +84,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/content-repo.cpp b/lib/csapi/content-repo.cpp index c2720d63..395337f3 100644 --- a/lib/csapi/content-repo.cpp +++ b/lib/csapi/content-repo.cpp @@ -9,7 +9,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/media/r0"); diff --git a/lib/csapi/content-repo.h b/lib/csapi/content-repo.h index 9f267f6c..83069490 100644 --- a/lib/csapi/content-repo.h +++ b/lib/csapi/content-repo.h @@ -10,7 +10,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -282,4 +282,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/create_room.cpp b/lib/csapi/create_room.cpp index e94cb008..68741f13 100644 --- a/lib/csapi/create_room.cpp +++ b/lib/csapi/create_room.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -38,7 +38,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class CreateRoomJob::Private { diff --git a/lib/csapi/create_room.h b/lib/csapi/create_room.h index a066a3f3..e7000155 100644 --- a/lib/csapi/create_room.h +++ b/lib/csapi/create_room.h @@ -11,7 +11,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -235,4 +235,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/auth_data.cpp b/lib/csapi/definitions/auth_data.cpp index 3bb51626..edeb7111 100644 --- a/lib/csapi/definitions/auth_data.cpp +++ b/lib/csapi/definitions/auth_data.cpp @@ -4,7 +4,7 @@ #include "auth_data.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo( QJsonObject& jo, const AuthenticationData& pod) diff --git a/lib/csapi/definitions/auth_data.h b/lib/csapi/definitions/auth_data.h index 9e46812c..1aeea6c2 100644 --- a/lib/csapi/definitions/auth_data.h +++ b/lib/csapi/definitions/auth_data.h @@ -9,7 +9,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -34,4 +34,4 @@ struct JsonObjectConverter static void fillFrom(QJsonObject jo, AuthenticationData& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/client_device.cpp b/lib/csapi/definitions/client_device.cpp index c9e6a223..09544138 100644 --- a/lib/csapi/definitions/client_device.cpp +++ b/lib/csapi/definitions/client_device.cpp @@ -4,7 +4,7 @@ #include "client_device.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const Device& pod) { diff --git a/lib/csapi/definitions/client_device.h b/lib/csapi/definitions/client_device.h index e4accc35..f076c4da 100644 --- a/lib/csapi/definitions/client_device.h +++ b/lib/csapi/definitions/client_device.h @@ -6,7 +6,7 @@ #include "converters.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -34,4 +34,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, Device& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/device_keys.cpp b/lib/csapi/definitions/device_keys.cpp index cc5262b7..0583840d 100644 --- a/lib/csapi/definitions/device_keys.cpp +++ b/lib/csapi/definitions/device_keys.cpp @@ -4,7 +4,7 @@ #include "device_keys.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const DeviceKeys& pod) diff --git a/lib/csapi/definitions/device_keys.h b/lib/csapi/definitions/device_keys.h index 6bd96584..d1d8abef 100644 --- a/lib/csapi/definitions/device_keys.h +++ b/lib/csapi/definitions/device_keys.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -41,4 +41,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, DeviceKeys& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/event_filter.cpp b/lib/csapi/definitions/event_filter.cpp index 9b2c7a33..b21e08b5 100644 --- a/lib/csapi/definitions/event_filter.cpp +++ b/lib/csapi/definitions/event_filter.cpp @@ -4,7 +4,7 @@ #include "event_filter.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const EventFilter& pod) diff --git a/lib/csapi/definitions/event_filter.h b/lib/csapi/definitions/event_filter.h index 9b9b3fa3..b41e2e9e 100644 --- a/lib/csapi/definitions/event_filter.h +++ b/lib/csapi/definitions/event_filter.h @@ -6,7 +6,7 @@ #include "converters.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -40,4 +40,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, EventFilter& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/public_rooms_response.cpp b/lib/csapi/definitions/public_rooms_response.cpp index d07b1494..b6009718 100644 --- a/lib/csapi/definitions/public_rooms_response.cpp +++ b/lib/csapi/definitions/public_rooms_response.cpp @@ -4,7 +4,7 @@ #include "public_rooms_response.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const PublicRoomsChunk& pod) diff --git a/lib/csapi/definitions/public_rooms_response.h b/lib/csapi/definitions/public_rooms_response.h index e86e306f..1cb3aad5 100644 --- a/lib/csapi/definitions/public_rooms_response.h +++ b/lib/csapi/definitions/public_rooms_response.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -67,4 +67,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, PublicRoomsResponse& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/push_condition.cpp b/lib/csapi/definitions/push_condition.cpp index 5bcb845e..343b4f1a 100644 --- a/lib/csapi/definitions/push_condition.cpp +++ b/lib/csapi/definitions/push_condition.cpp @@ -4,7 +4,7 @@ #include "push_condition.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const PushCondition& pod) diff --git a/lib/csapi/definitions/push_condition.h b/lib/csapi/definitions/push_condition.h index 2c17023e..34a183de 100644 --- a/lib/csapi/definitions/push_condition.h +++ b/lib/csapi/definitions/push_condition.h @@ -6,7 +6,7 @@ #include "converters.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -36,4 +36,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, PushCondition& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/push_rule.cpp b/lib/csapi/definitions/push_rule.cpp index fc2be2c7..eae7e446 100644 --- a/lib/csapi/definitions/push_rule.cpp +++ b/lib/csapi/definitions/push_rule.cpp @@ -4,7 +4,7 @@ #include "push_rule.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const PushRule& pod) { diff --git a/lib/csapi/definitions/push_rule.h b/lib/csapi/definitions/push_rule.h index fe6eb0e6..e64d6ba8 100644 --- a/lib/csapi/definitions/push_rule.h +++ b/lib/csapi/definitions/push_rule.h @@ -12,7 +12,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -43,4 +43,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, PushRule& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/push_ruleset.cpp b/lib/csapi/definitions/push_ruleset.cpp index 6f48d27b..a2db35d9 100644 --- a/lib/csapi/definitions/push_ruleset.cpp +++ b/lib/csapi/definitions/push_ruleset.cpp @@ -4,7 +4,7 @@ #include "push_ruleset.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const PushRuleset& pod) diff --git a/lib/csapi/definitions/push_ruleset.h b/lib/csapi/definitions/push_ruleset.h index f9aedad8..b6b9670e 100644 --- a/lib/csapi/definitions/push_ruleset.h +++ b/lib/csapi/definitions/push_ruleset.h @@ -10,7 +10,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -36,4 +36,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, PushRuleset& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/room_event_filter.cpp b/lib/csapi/definitions/room_event_filter.cpp index bd38ebc7..5613d8d2 100644 --- a/lib/csapi/definitions/room_event_filter.cpp +++ b/lib/csapi/definitions/room_event_filter.cpp @@ -4,7 +4,7 @@ #include "room_event_filter.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const RoomEventFilter& pod) diff --git a/lib/csapi/definitions/room_event_filter.h b/lib/csapi/definitions/room_event_filter.h index 72bf34d3..ae06a615 100644 --- a/lib/csapi/definitions/room_event_filter.h +++ b/lib/csapi/definitions/room_event_filter.h @@ -8,7 +8,7 @@ #include "csapi/definitions/event_filter.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -35,4 +35,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, RoomEventFilter& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/sync_filter.cpp b/lib/csapi/definitions/sync_filter.cpp index 87274a06..15c4bdc1 100644 --- a/lib/csapi/definitions/sync_filter.cpp +++ b/lib/csapi/definitions/sync_filter.cpp @@ -4,7 +4,7 @@ #include "sync_filter.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const StateFilter& pod) diff --git a/lib/csapi/definitions/sync_filter.h b/lib/csapi/definitions/sync_filter.h index 1d6a845c..9ea39a65 100644 --- a/lib/csapi/definitions/sync_filter.h +++ b/lib/csapi/definitions/sync_filter.h @@ -9,7 +9,7 @@ #include "csapi/definitions/event_filter.h" #include "csapi/definitions/room_event_filter.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -104,4 +104,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, Filter& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/user_identifier.cpp b/lib/csapi/definitions/user_identifier.cpp index 52bb1ae6..9e9b4fe9 100644 --- a/lib/csapi/definitions/user_identifier.cpp +++ b/lib/csapi/definitions/user_identifier.cpp @@ -4,7 +4,7 @@ #include "user_identifier.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const UserIdentifier& pod) diff --git a/lib/csapi/definitions/user_identifier.h b/lib/csapi/definitions/user_identifier.h index 51c47cca..74e6ce2b 100644 --- a/lib/csapi/definitions/user_identifier.h +++ b/lib/csapi/definitions/user_identifier.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -31,4 +31,4 @@ struct JsonObjectConverter static void fillFrom(QJsonObject jo, UserIdentifier& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/wellknown/full.cpp b/lib/csapi/definitions/wellknown/full.cpp index 34d3bfbe..595db0e5 100644 --- a/lib/csapi/definitions/wellknown/full.cpp +++ b/lib/csapi/definitions/wellknown/full.cpp @@ -4,7 +4,7 @@ #include "full.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo( QJsonObject& jo, const DiscoveryInformation& pod) diff --git a/lib/csapi/definitions/wellknown/full.h b/lib/csapi/definitions/wellknown/full.h index ddc06653..92c8afff 100644 --- a/lib/csapi/definitions/wellknown/full.h +++ b/lib/csapi/definitions/wellknown/full.h @@ -12,7 +12,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Data structures @@ -39,4 +39,4 @@ struct JsonObjectConverter static void fillFrom(QJsonObject jo, DiscoveryInformation& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/wellknown/homeserver.cpp b/lib/csapi/definitions/wellknown/homeserver.cpp index f5746ede..7b87aa95 100644 --- a/lib/csapi/definitions/wellknown/homeserver.cpp +++ b/lib/csapi/definitions/wellknown/homeserver.cpp @@ -4,7 +4,7 @@ #include "homeserver.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo( QJsonObject& jo, const HomeserverInformation& pod) diff --git a/lib/csapi/definitions/wellknown/homeserver.h b/lib/csapi/definitions/wellknown/homeserver.h index b73cee17..606df88b 100644 --- a/lib/csapi/definitions/wellknown/homeserver.h +++ b/lib/csapi/definitions/wellknown/homeserver.h @@ -6,7 +6,7 @@ #include "converters.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -25,4 +25,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, HomeserverInformation& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/definitions/wellknown/identity_server.cpp b/lib/csapi/definitions/wellknown/identity_server.cpp index 922d4665..3b2a5720 100644 --- a/lib/csapi/definitions/wellknown/identity_server.cpp +++ b/lib/csapi/definitions/wellknown/identity_server.cpp @@ -4,7 +4,7 @@ #include "identity_server.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo( QJsonObject& jo, const IdentityServerInformation& pod) diff --git a/lib/csapi/definitions/wellknown/identity_server.h b/lib/csapi/definitions/wellknown/identity_server.h index a35644fc..b4304ef7 100644 --- a/lib/csapi/definitions/wellknown/identity_server.h +++ b/lib/csapi/definitions/wellknown/identity_server.h @@ -6,7 +6,7 @@ #include "converters.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -25,4 +25,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, IdentityServerInformation& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/device_management.cpp b/lib/csapi/device_management.cpp index 9135c22d..0889089e 100644 --- a/lib/csapi/device_management.cpp +++ b/lib/csapi/device_management.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/device_management.h b/lib/csapi/device_management.h index 01838c6f..d380a44f 100644 --- a/lib/csapi/device_management.h +++ b/lib/csapi/device_management.h @@ -13,7 +13,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -145,4 +145,4 @@ public: const Omittable& auth = none); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/directory.cpp b/lib/csapi/directory.cpp index 992d1da5..b2689d1e 100644 --- a/lib/csapi/directory.cpp +++ b/lib/csapi/directory.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0/directory"); diff --git a/lib/csapi/directory.h b/lib/csapi/directory.h index f5331db8..7863aa1a 100644 --- a/lib/csapi/directory.h +++ b/lib/csapi/directory.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -93,4 +93,4 @@ public: static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomAlias); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/event_context.cpp b/lib/csapi/event_context.cpp index 936b2430..d233eedb 100644 --- a/lib/csapi/event_context.cpp +++ b/lib/csapi/event_context.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/event_context.h b/lib/csapi/event_context.h index ca06f4b9..755fc662 100644 --- a/lib/csapi/event_context.h +++ b/lib/csapi/event_context.h @@ -9,7 +9,7 @@ #include "events/eventloader.h" #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -71,4 +71,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/filter.cpp b/lib/csapi/filter.cpp index 79dd5ea5..b4160ba4 100644 --- a/lib/csapi/filter.cpp +++ b/lib/csapi/filter.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/filter.h b/lib/csapi/filter.h index 0a5a98ae..5001a492 100644 --- a/lib/csapi/filter.h +++ b/lib/csapi/filter.h @@ -10,7 +10,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -88,4 +88,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/inviting.cpp b/lib/csapi/inviting.cpp index 4ddbe5d0..b60df6f8 100644 --- a/lib/csapi/inviting.cpp +++ b/lib/csapi/inviting.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/inviting.h b/lib/csapi/inviting.h index b0911ea8..faf315b1 100644 --- a/lib/csapi/inviting.h +++ b/lib/csapi/inviting.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -44,4 +44,4 @@ public: explicit InviteUserJob(const QString& roomId, const QString& userId); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/joining.cpp b/lib/csapi/joining.cpp index cb40cb96..2dd617bb 100644 --- a/lib/csapi/joining.cpp +++ b/lib/csapi/joining.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -29,7 +29,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class JoinRoomByIdJob::Private { @@ -67,7 +67,7 @@ BaseJob::Status JoinRoomByIdJob::parseJson(const QJsonDocument& data) } // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -91,7 +91,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class JoinRoomJob::Private { diff --git a/lib/csapi/joining.h b/lib/csapi/joining.h index a96f323d..cf456da9 100644 --- a/lib/csapi/joining.h +++ b/lib/csapi/joining.h @@ -10,7 +10,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -165,4 +165,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/keys.cpp b/lib/csapi/keys.cpp index 1752b865..cd33ad19 100644 --- a/lib/csapi/keys.cpp +++ b/lib/csapi/keys.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); @@ -50,7 +50,7 @@ BaseJob::Status UploadKeysJob::parseJson(const QJsonDocument& data) } // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -74,7 +74,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class QueryKeysJob::Private { diff --git a/lib/csapi/keys.h b/lib/csapi/keys.h index f69028fd..27867b8c 100644 --- a/lib/csapi/keys.h +++ b/lib/csapi/keys.h @@ -14,7 +14,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -231,4 +231,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/kicking.cpp b/lib/csapi/kicking.cpp index 05c4c581..ce7fcdad 100644 --- a/lib/csapi/kicking.cpp +++ b/lib/csapi/kicking.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/kicking.h b/lib/csapi/kicking.h index 9566a9a4..d51edb47 100644 --- a/lib/csapi/kicking.h +++ b/lib/csapi/kicking.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -39,4 +39,4 @@ public: const QString& reason = {}); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/leaving.cpp b/lib/csapi/leaving.cpp index 325b1e04..abf04888 100644 --- a/lib/csapi/leaving.cpp +++ b/lib/csapi/leaving.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/leaving.h b/lib/csapi/leaving.h index 2ed6c8e7..280545b0 100644 --- a/lib/csapi/leaving.h +++ b/lib/csapi/leaving.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -73,4 +73,4 @@ public: static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/list_joined_rooms.cpp b/lib/csapi/list_joined_rooms.cpp index 43c948f7..1260499a 100644 --- a/lib/csapi/list_joined_rooms.cpp +++ b/lib/csapi/list_joined_rooms.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/list_joined_rooms.h b/lib/csapi/list_joined_rooms.h index 1b64a004..5dab9dfc 100644 --- a/lib/csapi/list_joined_rooms.h +++ b/lib/csapi/list_joined_rooms.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -43,4 +43,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/list_public_rooms.cpp b/lib/csapi/list_public_rooms.cpp index 4d96dac3..0e065440 100644 --- a/lib/csapi/list_public_rooms.cpp +++ b/lib/csapi/list_public_rooms.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); @@ -108,7 +108,7 @@ BaseJob::Status GetPublicRoomsJob::parseJson(const QJsonDocument& data) } // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -121,7 +121,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class QueryPublicRoomsJob::Private { diff --git a/lib/csapi/list_public_rooms.h b/lib/csapi/list_public_rooms.h index da68416d..e68030ad 100644 --- a/lib/csapi/list_public_rooms.h +++ b/lib/csapi/list_public_rooms.h @@ -10,7 +10,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -189,4 +189,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/login.cpp b/lib/csapi/login.cpp index 29ee4ab5..02730ff0 100644 --- a/lib/csapi/login.cpp +++ b/lib/csapi/login.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -26,7 +26,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class GetLoginFlowsJob::Private { diff --git a/lib/csapi/login.h b/lib/csapi/login.h index 3ab0648f..dc944782 100644 --- a/lib/csapi/login.h +++ b/lib/csapi/login.h @@ -13,7 +13,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -143,4 +143,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/logout.cpp b/lib/csapi/logout.cpp index d0bef20e..4b391967 100644 --- a/lib/csapi/logout.cpp +++ b/lib/csapi/logout.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/logout.h b/lib/csapi/logout.h index c03af180..34d5a441 100644 --- a/lib/csapi/logout.h +++ b/lib/csapi/logout.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -55,4 +55,4 @@ public: static QUrl makeRequestUrl(QUrl baseUrl); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/message_pagination.cpp b/lib/csapi/message_pagination.cpp index 3f09bd85..b612ee91 100644 --- a/lib/csapi/message_pagination.cpp +++ b/lib/csapi/message_pagination.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/message_pagination.h b/lib/csapi/message_pagination.h index 03b3d42a..271e1dd9 100644 --- a/lib/csapi/message_pagination.h +++ b/lib/csapi/message_pagination.h @@ -9,7 +9,7 @@ #include "events/eventloader.h" #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -80,4 +80,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/notifications.cpp b/lib/csapi/notifications.cpp index 3a05a0b2..da568a0f 100644 --- a/lib/csapi/notifications.cpp +++ b/lib/csapi/notifications.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -31,7 +31,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class GetNotificationsJob::Private { diff --git a/lib/csapi/notifications.h b/lib/csapi/notifications.h index 4170d539..eeec5d4e 100644 --- a/lib/csapi/notifications.h +++ b/lib/csapi/notifications.h @@ -13,7 +13,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -94,4 +94,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/openid.cpp b/lib/csapi/openid.cpp index 39ba3b9e..8c00df97 100644 --- a/lib/csapi/openid.cpp +++ b/lib/csapi/openid.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/openid.h b/lib/csapi/openid.h index 40f1bc40..b2f003e5 100644 --- a/lib/csapi/openid.h +++ b/lib/csapi/openid.h @@ -10,7 +10,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -64,4 +64,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/peeking_events.cpp b/lib/csapi/peeking_events.cpp index 6962d363..bc29b682 100644 --- a/lib/csapi/peeking_events.cpp +++ b/lib/csapi/peeking_events.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/peeking_events.h b/lib/csapi/peeking_events.h index 1fe63c4d..c5cc07f6 100644 --- a/lib/csapi/peeking_events.h +++ b/lib/csapi/peeking_events.h @@ -9,7 +9,7 @@ #include "events/eventloader.h" #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -74,4 +74,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/presence.cpp b/lib/csapi/presence.cpp index b6e8caf2..0f019026 100644 --- a/lib/csapi/presence.cpp +++ b/lib/csapi/presence.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/presence.h b/lib/csapi/presence.h index 82c3a300..c5ecb987 100644 --- a/lib/csapi/presence.h +++ b/lib/csapi/presence.h @@ -8,7 +8,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -78,4 +78,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/profile.cpp b/lib/csapi/profile.cpp index 630452f6..27168f77 100644 --- a/lib/csapi/profile.cpp +++ b/lib/csapi/profile.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/profile.h b/lib/csapi/profile.h index 95d3ec97..54dc53aa 100644 --- a/lib/csapi/profile.h +++ b/lib/csapi/profile.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -164,4 +164,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/pusher.cpp b/lib/csapi/pusher.cpp index 41a0cffe..90877a95 100644 --- a/lib/csapi/pusher.cpp +++ b/lib/csapi/pusher.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -43,7 +43,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class GetPushersJob::Private { @@ -79,7 +79,7 @@ BaseJob::Status GetPushersJob::parseJson(const QJsonDocument& data) } // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -92,7 +92,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient static const auto PostPusherJobName = QStringLiteral("PostPusherJob"); diff --git a/lib/csapi/pusher.h b/lib/csapi/pusher.h index a909b9a0..65f8aa15 100644 --- a/lib/csapi/pusher.h +++ b/lib/csapi/pusher.h @@ -10,7 +10,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -169,4 +169,4 @@ public: Omittable append = none); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/pushrules.cpp b/lib/csapi/pushrules.cpp index 5842369f..eae5445f 100644 --- a/lib/csapi/pushrules.cpp +++ b/lib/csapi/pushrules.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/pushrules.h b/lib/csapi/pushrules.h index 9074addb..cb94fe7b 100644 --- a/lib/csapi/pushrules.h +++ b/lib/csapi/pushrules.h @@ -14,7 +14,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -297,4 +297,4 @@ public: const QStringList& actions); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/read_markers.cpp b/lib/csapi/read_markers.cpp index 5ea45f88..a07d09ce 100644 --- a/lib/csapi/read_markers.cpp +++ b/lib/csapi/read_markers.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/read_markers.h b/lib/csapi/read_markers.h index e1fbc263..35c428b2 100644 --- a/lib/csapi/read_markers.h +++ b/lib/csapi/read_markers.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -34,4 +34,4 @@ public: const QString& mRead = {}); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/receipts.cpp b/lib/csapi/receipts.cpp index 28d7032f..f9a45912 100644 --- a/lib/csapi/receipts.cpp +++ b/lib/csapi/receipts.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/receipts.h b/lib/csapi/receipts.h index bb037c08..376d4006 100644 --- a/lib/csapi/receipts.h +++ b/lib/csapi/receipts.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -37,4 +37,4 @@ public: const QJsonObject& receipt = {}); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/redaction.cpp b/lib/csapi/redaction.cpp index f944cdd4..d2dbe19b 100644 --- a/lib/csapi/redaction.cpp +++ b/lib/csapi/redaction.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/redaction.h b/lib/csapi/redaction.h index c75421cb..42022930 100644 --- a/lib/csapi/redaction.h +++ b/lib/csapi/redaction.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -53,4 +53,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/registration.cpp b/lib/csapi/registration.cpp index 52b4098d..270011e1 100644 --- a/lib/csapi/registration.cpp +++ b/lib/csapi/registration.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/registration.h b/lib/csapi/registration.h index 40f1caa6..89aecb80 100644 --- a/lib/csapi/registration.h +++ b/lib/csapi/registration.h @@ -11,7 +11,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -480,4 +480,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/report_content.cpp b/lib/csapi/report_content.cpp index eb62cd12..352f52c9 100644 --- a/lib/csapi/report_content.cpp +++ b/lib/csapi/report_content.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/report_content.h b/lib/csapi/report_content.h index c545d800..c86a4301 100644 --- a/lib/csapi/report_content.h +++ b/lib/csapi/report_content.h @@ -8,7 +8,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -36,4 +36,4 @@ public: int score, const QString& reason); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/room_send.cpp b/lib/csapi/room_send.cpp index a29dd99a..5e970d65 100644 --- a/lib/csapi/room_send.cpp +++ b/lib/csapi/room_send.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/room_send.h b/lib/csapi/room_send.h index aa2efd79..110fc83b 100644 --- a/lib/csapi/room_send.h +++ b/lib/csapi/room_send.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -62,4 +62,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/room_state.cpp b/lib/csapi/room_state.cpp index ef4afcd0..bfcd6e17 100644 --- a/lib/csapi/room_state.cpp +++ b/lib/csapi/room_state.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/room_state.h b/lib/csapi/room_state.h index 6ddd5594..80619d63 100644 --- a/lib/csapi/room_state.h +++ b/lib/csapi/room_state.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -126,4 +126,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/room_upgrades.cpp b/lib/csapi/room_upgrades.cpp index a72304d1..1d6006ef 100644 --- a/lib/csapi/room_upgrades.cpp +++ b/lib/csapi/room_upgrades.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/room_upgrades.h b/lib/csapi/room_upgrades.h index 94520aca..5f9262f1 100644 --- a/lib/csapi/room_upgrades.h +++ b/lib/csapi/room_upgrades.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -41,4 +41,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/rooms.cpp b/lib/csapi/rooms.cpp index 280e8d59..5bfbe44d 100644 --- a/lib/csapi/rooms.cpp +++ b/lib/csapi/rooms.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); @@ -168,7 +168,7 @@ BaseJob::Status GetMembersByRoomJob::parseJson(const QJsonDocument& data) } // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -182,7 +182,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class GetJoinedMembersByRoomJob::Private { diff --git a/lib/csapi/rooms.h b/lib/csapi/rooms.h index 29d7808e..1020fdb1 100644 --- a/lib/csapi/rooms.h +++ b/lib/csapi/rooms.h @@ -12,7 +12,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -269,4 +269,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/search.cpp b/lib/csapi/search.cpp index ee1fa70c..9619f340 100644 --- a/lib/csapi/search.cpp +++ b/lib/csapi/search.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -144,7 +144,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class SearchJob::Private { diff --git a/lib/csapi/search.h b/lib/csapi/search.h index f965a72a..079ac8e9 100644 --- a/lib/csapi/search.h +++ b/lib/csapi/search.h @@ -16,7 +16,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -200,4 +200,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/sso_login_redirect.cpp b/lib/csapi/sso_login_redirect.cpp index b1dc3674..c2cc81cf 100644 --- a/lib/csapi/sso_login_redirect.cpp +++ b/lib/csapi/sso_login_redirect.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/sso_login_redirect.h b/lib/csapi/sso_login_redirect.h index af9e7780..b932a15e 100644 --- a/lib/csapi/sso_login_redirect.h +++ b/lib/csapi/sso_login_redirect.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -37,4 +37,4 @@ public: static QUrl makeRequestUrl(QUrl baseUrl, const QString& redirectUrl); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/tags.cpp b/lib/csapi/tags.cpp index 13c933e5..3df38074 100644 --- a/lib/csapi/tags.cpp +++ b/lib/csapi/tags.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -26,7 +26,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class GetRoomTagsJob::Private { diff --git a/lib/csapi/tags.h b/lib/csapi/tags.h index dc20cd3d..8ddebd6b 100644 --- a/lib/csapi/tags.h +++ b/lib/csapi/tags.h @@ -11,7 +11,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -123,4 +123,4 @@ public: const QString& roomId, const QString& tag); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/third_party_lookup.cpp b/lib/csapi/third_party_lookup.cpp index 986ead01..678f6b3c 100644 --- a/lib/csapi/third_party_lookup.cpp +++ b/lib/csapi/third_party_lookup.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/third_party_lookup.h b/lib/csapi/third_party_lookup.h index d25c1cf3..63607549 100644 --- a/lib/csapi/third_party_lookup.h +++ b/lib/csapi/third_party_lookup.h @@ -15,7 +15,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -253,4 +253,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/third_party_membership.cpp b/lib/csapi/third_party_membership.cpp index 9fe702aa..7e401163 100644 --- a/lib/csapi/third_party_membership.cpp +++ b/lib/csapi/third_party_membership.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/third_party_membership.h b/lib/csapi/third_party_membership.h index 36622c94..bd4c6896 100644 --- a/lib/csapi/third_party_membership.h +++ b/lib/csapi/third_party_membership.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -74,4 +74,4 @@ public: const QString& medium, const QString& address); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/to_device.cpp b/lib/csapi/to_device.cpp index 3fb17109..3f6e8097 100644 --- a/lib/csapi/to_device.cpp +++ b/lib/csapi/to_device.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/to_device.h b/lib/csapi/to_device.h index e0bbbe28..14445439 100644 --- a/lib/csapi/to_device.h +++ b/lib/csapi/to_device.h @@ -9,7 +9,7 @@ #include #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -39,4 +39,4 @@ public: const QHash>& messages = {}); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/typing.cpp b/lib/csapi/typing.cpp index 03499c76..064ebe39 100644 --- a/lib/csapi/typing.cpp +++ b/lib/csapi/typing.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/typing.h b/lib/csapi/typing.h index 0c3f75a8..350c209d 100644 --- a/lib/csapi/typing.h +++ b/lib/csapi/typing.h @@ -8,7 +8,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -38,4 +38,4 @@ public: bool typing, Omittable timeout = none); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/users.cpp b/lib/csapi/users.cpp index 39b05a77..77c297dd 100644 --- a/lib/csapi/users.cpp +++ b/lib/csapi/users.cpp @@ -8,12 +8,12 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); // Converters -namespace QMatrixClient +namespace Quotient { template <> @@ -28,7 +28,7 @@ struct JsonObjectConverter } }; -} // namespace QMatrixClient +} // namespace Quotient class SearchUserDirectoryJob::Private { diff --git a/lib/csapi/users.h b/lib/csapi/users.h index 2e86c009..d9a16a9d 100644 --- a/lib/csapi/users.h +++ b/lib/csapi/users.h @@ -10,7 +10,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -80,4 +80,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/versions.cpp b/lib/csapi/versions.cpp index 1d66b94f..9607a1b6 100644 --- a/lib/csapi/versions.cpp +++ b/lib/csapi/versions.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client"); diff --git a/lib/csapi/versions.h b/lib/csapi/versions.h index 513e7f27..aa8cbac6 100644 --- a/lib/csapi/versions.h +++ b/lib/csapi/versions.h @@ -10,7 +10,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -70,4 +70,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/voip.cpp b/lib/csapi/voip.cpp index 0e83c915..c95afe16 100644 --- a/lib/csapi/voip.cpp +++ b/lib/csapi/voip.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/voip.h b/lib/csapi/voip.h index ab34dcad..38abfa27 100644 --- a/lib/csapi/voip.h +++ b/lib/csapi/voip.h @@ -8,7 +8,7 @@ #include -namespace QMatrixClient +namespace Quotient { // Operations @@ -46,4 +46,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/wellknown.cpp b/lib/csapi/wellknown.cpp index c2bd7822..9a52a2a5 100644 --- a/lib/csapi/wellknown.cpp +++ b/lib/csapi/wellknown.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/.well-known"); diff --git a/lib/csapi/wellknown.h b/lib/csapi/wellknown.h index 66917806..bce67d00 100644 --- a/lib/csapi/wellknown.h +++ b/lib/csapi/wellknown.h @@ -10,7 +10,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -54,4 +54,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/whoami.cpp b/lib/csapi/whoami.cpp index 2ca9c435..fb7f54dc 100644 --- a/lib/csapi/whoami.cpp +++ b/lib/csapi/whoami.cpp @@ -8,7 +8,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); diff --git a/lib/csapi/whoami.h b/lib/csapi/whoami.h index e62b7dad..bbbb3899 100644 --- a/lib/csapi/whoami.h +++ b/lib/csapi/whoami.h @@ -6,7 +6,7 @@ #include "jobs/basejob.h" -namespace QMatrixClient +namespace Quotient { // Operations @@ -50,4 +50,4 @@ private: QScopedPointer d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/csapi/{{base}}.cpp.mustache b/lib/csapi/{{base}}.cpp.mustache index 8ebac6ef..6cbd1b65 100644 --- a/lib/csapi/{{base}}.cpp.mustache +++ b/lib/csapi/{{base}}.cpp.mustache @@ -8,7 +8,7 @@ {{/producesNonJson?}} #include {{/operations}} -using namespace QMatrixClient; +using namespace Quotient; {{#models.model}} {{#in?}} void JsonObjectConverter<{{qualifiedName}}>::dumpTo(QJsonObject& jo, const {{qualifiedName}}& pod) @@ -38,7 +38,7 @@ void JsonObjectConverter<{{qualifiedName}}>::fillFrom({{>maybeCrefJsonObject}} j static const auto basePath = QStringLiteral("{{basePathWithoutHost}}"); {{#operation}}{{#models}} // Converters -namespace QMatrixClient +namespace Quotient { {{#model}} template <> struct JsonObjectConverter<{{qualifiedName}}> diff --git a/lib/csapi/{{base}}.h.mustache b/lib/csapi/{{base}}.h.mustache index 61380ec6..56044e7d 100644 --- a/lib/csapi/{{base}}.h.mustache +++ b/lib/csapi/{{base}}.h.mustache @@ -8,7 +8,7 @@ {{#imports}} #include {{_}}{{/imports}} -namespace QMatrixClient +namespace Quotient { {{#models}} // Data structures @@ -92,4 +92,4 @@ private: }; {{/ operation}} {{/operations}} -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/e2ee.h b/lib/e2ee.h index c85211be..5a9b83c5 100644 --- a/lib/e2ee.h +++ b/lib/e2ee.h @@ -4,7 +4,7 @@ #include -namespace QMatrixClient { +namespace Quotient { static const auto CiphertextKeyL = "ciphertext"_ls; static const auto SenderKeyKeyL = "sender_key"_ls; static const auto DeviceIdKeyL = "device_id"_ls; @@ -28,4 +28,4 @@ static const auto MegolmV1AesSha2AlgoKey = QStringLiteral("m.megolm.v1.aes-sha2"); static const QStringList SupportedAlgorithms = { OlmV1Curve25519AesSha2AlgoKey, MegolmV1AesSha2AlgoKey }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/encryptionmanager.cpp b/lib/encryptionmanager.cpp index 15723688..22387cf9 100644 --- a/lib/encryptionmanager.cpp +++ b/lib/encryptionmanager.cpp @@ -12,7 +12,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; using namespace QtOlm; using std::move; diff --git a/lib/encryptionmanager.h b/lib/encryptionmanager.h index 79c25a00..b210a85a 100644 --- a/lib/encryptionmanager.h +++ b/lib/encryptionmanager.h @@ -9,7 +9,7 @@ namespace QtOlm { class Account; } -namespace QMatrixClient { +namespace Quotient { class Connection; class EncryptionManager : public QObject { @@ -35,4 +35,4 @@ private: std::unique_ptr d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/eventitem.cpp b/lib/eventitem.cpp index de0a5c9f..2e2b11c0 100644 --- a/lib/eventitem.cpp +++ b/lib/eventitem.cpp @@ -21,7 +21,7 @@ #include "events/roomavatarevent.h" #include "events/roommessageevent.h" -using namespace QMatrixClient; +using namespace Quotient; void PendingEventItem::setFileUploaded(const QUrl& remoteUrl) { diff --git a/lib/eventitem.h b/lib/eventitem.h index 68d1ae06..3a7061d3 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -22,7 +22,7 @@ #include -namespace QMatrixClient { +namespace Quotient { class StateEventBase; class EventStatus { @@ -153,5 +153,5 @@ inline QDebug& operator<<(QDebug& d, const TimelineItem& ti) d.nospace() << "(" << ti.index() << "|" << ti->id() << ")"; return d; } -} // namespace QMatrixClient -Q_DECLARE_METATYPE(QMatrixClient::EventStatus) +} // namespace Quotient +Q_DECLARE_METATYPE(Quotient::EventStatus) diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h index 3f519668..600fa5be 100644 --- a/lib/events/accountdataevents.h +++ b/lib/events/accountdataevents.h @@ -24,7 +24,7 @@ #include "event.h" #include "eventcontent.h" -namespace QMatrixClient { +namespace Quotient { constexpr const char* FavouriteTag = "m.favourite"; constexpr const char* LowPriorityTag = "m.lowpriority"; @@ -93,4 +93,4 @@ DEFINE_SIMPLE_EVENT(IgnoredUsersEvent, "m.ignored_user_list", QSet, DEFINE_EVENTTYPE_ALIAS(Tag, TagEvent) DEFINE_EVENTTYPE_ALIAS(ReadMarker, ReadMarkerEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/callanswerevent.cpp b/lib/events/callanswerevent.cpp index 7ab4a6fb..d6622b30 100644 --- a/lib/events/callanswerevent.cpp +++ b/lib/events/callanswerevent.cpp @@ -44,7 +44,7 @@ m.call.answer } */ -using namespace QMatrixClient; +using namespace Quotient; CallAnswerEvent::CallAnswerEvent(const QJsonObject& obj) : CallEventBase(typeId(), obj) diff --git a/lib/events/callanswerevent.h b/lib/events/callanswerevent.h index 052f732d..e01b39db 100644 --- a/lib/events/callanswerevent.h +++ b/lib/events/callanswerevent.h @@ -20,7 +20,7 @@ #include "roomevent.h" -namespace QMatrixClient { +namespace Quotient { class CallAnswerEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.answer", CallAnswerEvent) @@ -43,4 +43,4 @@ public: REGISTER_EVENT_TYPE(CallAnswerEvent) DEFINE_EVENTTYPE_ALIAS(CallAnswer, CallAnswerEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/callcandidatesevent.h b/lib/events/callcandidatesevent.h index 2a915a43..3d13ba8a 100644 --- a/lib/events/callcandidatesevent.h +++ b/lib/events/callcandidatesevent.h @@ -20,7 +20,7 @@ #include "roomevent.h" -namespace QMatrixClient { +namespace Quotient { class CallCandidatesEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.candidates", CallCandidatesEvent) @@ -43,4 +43,4 @@ public: REGISTER_EVENT_TYPE(CallCandidatesEvent) DEFINE_EVENTTYPE_ALIAS(CallCandidates, CallCandidatesEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/callhangupevent.cpp b/lib/events/callhangupevent.cpp index 2a4fd3da..d41849c3 100644 --- a/lib/events/callhangupevent.cpp +++ b/lib/events/callhangupevent.cpp @@ -39,7 +39,7 @@ m.call.hangup } */ -using namespace QMatrixClient; +using namespace Quotient; CallHangupEvent::CallHangupEvent(const QJsonObject& obj) : CallEventBase(typeId(), obj) diff --git a/lib/events/callhangupevent.h b/lib/events/callhangupevent.h index 97fa2f52..d23e29db 100644 --- a/lib/events/callhangupevent.h +++ b/lib/events/callhangupevent.h @@ -20,7 +20,7 @@ #include "roomevent.h" -namespace QMatrixClient { +namespace Quotient { class CallHangupEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.hangup", CallHangupEvent) @@ -31,4 +31,4 @@ public: REGISTER_EVENT_TYPE(CallHangupEvent) DEFINE_EVENTTYPE_ALIAS(CallHangup, CallHangupEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/callinviteevent.cpp b/lib/events/callinviteevent.cpp index f565fc3e..54faac8d 100644 --- a/lib/events/callinviteevent.cpp +++ b/lib/events/callinviteevent.cpp @@ -44,7 +44,7 @@ m.call.invite } */ -using namespace QMatrixClient; +using namespace Quotient; CallInviteEvent::CallInviteEvent(const QJsonObject& obj) : CallEventBase(typeId(), obj) diff --git a/lib/events/callinviteevent.h b/lib/events/callinviteevent.h index 9b9d0ae5..3e39e0ba 100644 --- a/lib/events/callinviteevent.h +++ b/lib/events/callinviteevent.h @@ -20,7 +20,7 @@ #include "roomevent.h" -namespace QMatrixClient { +namespace Quotient { class CallInviteEvent : public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.invite", CallInviteEvent) @@ -42,4 +42,4 @@ public: REGISTER_EVENT_TYPE(CallInviteEvent) DEFINE_EVENTTYPE_ALIAS(CallInvite, CallInviteEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/directchatevent.cpp b/lib/events/directchatevent.cpp index 4ba098c2..b4027e16 100644 --- a/lib/events/directchatevent.cpp +++ b/lib/events/directchatevent.cpp @@ -20,7 +20,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; QMultiHash DirectChatEvent::usersToDirectChats() const { diff --git a/lib/events/directchatevent.h b/lib/events/directchatevent.h index 94857a93..b4981f2e 100644 --- a/lib/events/directchatevent.h +++ b/lib/events/directchatevent.h @@ -20,7 +20,7 @@ #include "event.h" -namespace QMatrixClient { +namespace Quotient { class DirectChatEvent : public Event { public: DEFINE_EVENT_TYPEID("m.direct", DirectChatEvent) @@ -31,4 +31,4 @@ public: }; REGISTER_EVENT_TYPE(DirectChatEvent) DEFINE_EVENTTYPE_ALIAS(DirectChat, DirectChatEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h index 67298a27..235b2aa4 100644 --- a/lib/events/encryptedevent.h +++ b/lib/events/encryptedevent.h @@ -3,7 +3,7 @@ #include "e2ee.h" #include "roomevent.h" -namespace QMatrixClient { +namespace Quotient { class Room; /* * While the specification states: @@ -63,4 +63,4 @@ public: }; REGISTER_EVENT_TYPE(EncryptedEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/encryptionevent.cpp b/lib/events/encryptionevent.cpp index 0c732a51..945e6696 100644 --- a/lib/events/encryptionevent.cpp +++ b/lib/events/encryptionevent.cpp @@ -12,10 +12,10 @@ #include static const std::array encryptionStrings = { - { QMatrixClient::MegolmV1AesSha2AlgoKey } + { Quotient::MegolmV1AesSha2AlgoKey } }; -namespace QMatrixClient { +namespace Quotient { template <> struct JsonConverter { static EncryptionType load(const QJsonValue& jv) @@ -32,7 +32,7 @@ struct JsonConverter { }; } // namespace QMatrixClient -using namespace QMatrixClient; +using namespace Quotient; EncryptionEventContent::EncryptionEventContent(const QJsonObject& json) : encryption(fromJson(json["algorithm"_ls])) diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h index debabcae..68e41719 100644 --- a/lib/events/encryptionevent.h +++ b/lib/events/encryptionevent.h @@ -21,7 +21,7 @@ #include "eventcontent.h" #include "stateevent.h" -namespace QMatrixClient { +namespace Quotient { class EncryptionEventContent : public EventContent::Base { public: enum EncryptionType : size_t { MegolmV1AesSha2 = 0, Undefined }; @@ -71,4 +71,4 @@ private: REGISTER_EVENT_TYPE(EncryptionEvent) DEFINE_EVENTTYPE_ALIAS(Encryption, EncryptionEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/event.cpp b/lib/events/event.cpp index 694254fe..96e33864 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -22,7 +22,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; event_type_t EventTypeRegistry::initializeTypeId(event_mtype_t matrixTypeId) { diff --git a/lib/events/event.h b/lib/events/event.h index 686bd8e0..e96d6897 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -25,7 +25,7 @@ # define USE_EVENTTYPE_ALIAS 1 #endif -namespace QMatrixClient { +namespace Quotient { // === event_ptr_tt<> and type casting facilities === template @@ -292,7 +292,7 @@ using Events = EventsArray; // provide matrixTypeId() and typeId(). #define DEFINE_EVENT_TYPEID(_Id, _Type) \ static constexpr event_mtype_t matrixTypeId() { return _Id; } \ - static auto typeId() { return QMatrixClient::typeId<_Type>(); } \ + static auto typeId() { return Quotient::typeId<_Type>(); } \ // End of macro // This macro should be put after an event class definition (in .h or .cpp) @@ -406,6 +406,6 @@ visit(const BaseEventT& event, FnT1&& visitor1, FnT2&& visitor2, return visit(event, std::forward(visitor2), std::forward(visitors)...); } -} // namespace QMatrixClient -Q_DECLARE_METATYPE(QMatrixClient::Event*) -Q_DECLARE_METATYPE(const QMatrixClient::Event*) +} // namespace Quotient +Q_DECLARE_METATYPE(Quotient::Event*) +Q_DECLARE_METATYPE(const Quotient::Event*) diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index 814f2787..802d8176 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -23,7 +23,7 @@ #include -using namespace QMatrixClient::EventContent; +using namespace Quotient::EventContent; QJsonObject Base::toJson() const { diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 5c0f92d1..c26cb931 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -26,7 +26,7 @@ #include #include -namespace QMatrixClient { +namespace Quotient { namespace EventContent { /** * A base class for all content types that can be stored @@ -275,4 +275,4 @@ namespace EventContent { */ using FileContent = UrlWithThumbnailContent; } // namespace EventContent -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/eventloader.h b/lib/events/eventloader.h index 9e8bb410..ebb96441 100644 --- a/lib/events/eventloader.h +++ b/lib/events/eventloader.h @@ -20,7 +20,7 @@ #include "stateevent.h" -namespace QMatrixClient { +namespace Quotient { namespace _impl { template static inline auto loadEvent(const QJsonObject& json, @@ -83,4 +83,4 @@ struct JsonConverter> { return loadEvent(jd.object()); } }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/reactionevent.cpp b/lib/events/reactionevent.cpp index 0a080607..df8910fe 100644 --- a/lib/events/reactionevent.cpp +++ b/lib/events/reactionevent.cpp @@ -20,7 +20,7 @@ using namespace QMatrixClient; -void QMatrixClient::JsonObjectConverter::dumpTo( +void JsonObjectConverter::dumpTo( QJsonObject& jo, const EventRelation& pod) { if (pod.type.isEmpty()) { @@ -33,7 +33,7 @@ void QMatrixClient::JsonObjectConverter::dumpTo( jo.insert(QStringLiteral("key"), pod.key); } -void QMatrixClient::JsonObjectConverter::fillFrom( +void JsonObjectConverter::fillFrom( const QJsonObject& jo, EventRelation& pod) { // The experimental logic for generic relationships (MSC1849) diff --git a/lib/events/reactionevent.h b/lib/events/reactionevent.h index b1e04561..75c6528c 100644 --- a/lib/events/reactionevent.h +++ b/lib/events/reactionevent.h @@ -20,7 +20,7 @@ #include "roomevent.h" -namespace QMatrixClient { +namespace Quotient { struct EventRelation { using reltypeid_t = const char*; @@ -70,4 +70,4 @@ private: }; REGISTER_EVENT_TYPE(ReactionEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/receiptevent.cpp b/lib/events/receiptevent.cpp index 4a54b744..bf050cb2 100644 --- a/lib/events/receiptevent.cpp +++ b/lib/events/receiptevent.cpp @@ -38,7 +38,7 @@ Example of a Receipt Event: #include "converters.h" #include "logging.h" -using namespace QMatrixClient; +using namespace Quotient; ReceiptEvent::ReceiptEvent(const QJsonObject& obj) : Event(typeId(), obj) { diff --git a/lib/events/receiptevent.h b/lib/events/receiptevent.h index c32e0543..71cd5de0 100644 --- a/lib/events/receiptevent.h +++ b/lib/events/receiptevent.h @@ -23,7 +23,7 @@ #include #include -namespace QMatrixClient { +namespace Quotient { struct Receipt { QString userId; QDateTime timestamp; @@ -49,4 +49,4 @@ private: }; REGISTER_EVENT_TYPE(ReceiptEvent) DEFINE_EVENTTYPE_ALIAS(Receipt, ReceiptEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/redactionevent.h b/lib/events/redactionevent.h index 3628fb33..eac627d5 100644 --- a/lib/events/redactionevent.h +++ b/lib/events/redactionevent.h @@ -20,7 +20,7 @@ #include "roomevent.h" -namespace QMatrixClient { +namespace Quotient { class RedactionEvent : public RoomEvent { public: DEFINE_EVENT_TYPEID("m.room.redaction", RedactionEvent) @@ -36,4 +36,4 @@ public: }; REGISTER_EVENT_TYPE(RedactionEvent) DEFINE_EVENTTYPE_ALIAS(Redaction, RedactionEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h index 16aeb070..109f4014 100644 --- a/lib/events/roomavatarevent.h +++ b/lib/events/roomavatarevent.h @@ -21,7 +21,7 @@ #include "eventcontent.h" #include "stateevent.h" -namespace QMatrixClient { +namespace Quotient { class RoomAvatarEvent : public StateEvent { // It's a bit of an overkill to use a full-fledged ImageContent // because in reality m.room.avatar usually only has a single URL, @@ -35,4 +35,4 @@ public: }; REGISTER_EVENT_TYPE(RoomAvatarEvent) DEFINE_EVENTTYPE_ALIAS(RoomAvatar, RoomAvatarEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/roomcreateevent.cpp b/lib/events/roomcreateevent.cpp index cb575f24..c72b5bc2 100644 --- a/lib/events/roomcreateevent.cpp +++ b/lib/events/roomcreateevent.cpp @@ -18,7 +18,7 @@ #include "roomcreateevent.h" -using namespace QMatrixClient; +using namespace Quotient; bool RoomCreateEvent::isFederated() const { diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h index c8ba8c40..91aefe9e 100644 --- a/lib/events/roomcreateevent.h +++ b/lib/events/roomcreateevent.h @@ -20,7 +20,7 @@ #include "stateevent.h" -namespace QMatrixClient { +namespace Quotient { class RoomCreateEvent : public StateEventBase { public: DEFINE_EVENT_TYPEID("m.room.create", RoomCreateEvent) @@ -41,4 +41,4 @@ public: bool isUpgrade() const; }; REGISTER_EVENT_TYPE(RoomCreateEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/roomevent.cpp b/lib/events/roomevent.cpp index 543640ca..e19c03ce 100644 --- a/lib/events/roomevent.cpp +++ b/lib/events/roomevent.cpp @@ -22,7 +22,7 @@ #include "logging.h" #include "redactionevent.h" -using namespace QMatrixClient; +using namespace Quotient; [[gnu::unused]] static auto roomEventTypeInitialised = Event::factory_t::chainFactory(); @@ -48,7 +48,7 @@ QString RoomEvent::id() const { return fullJson()[EventIdKeyL].toString(); } QDateTime RoomEvent::timestamp() const { - return QMatrixClient::fromJson(fullJson()["origin_server_ts"_ls]); + return Quotient::fromJson(fullJson()["origin_server_ts"_ls]); } QString RoomEvent::roomId() const diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h index 155d4600..f943bce4 100644 --- a/lib/events/roomevent.h +++ b/lib/events/roomevent.h @@ -22,7 +22,7 @@ #include -namespace QMatrixClient { +namespace Quotient { class RedactionEvent; /** This class corresponds to m.room.* events */ @@ -102,6 +102,6 @@ public: QString callId() const { return content("call_id"_ls); } int version() const { return content("version"_ls); } }; -} // namespace QMatrixClient -Q_DECLARE_METATYPE(QMatrixClient::RoomEvent*) -Q_DECLARE_METATYPE(const QMatrixClient::RoomEvent*) +} // namespace Quotient +Q_DECLARE_METATYPE(Quotient::RoomEvent*) +Q_DECLARE_METATYPE(const Quotient::RoomEvent*) diff --git a/lib/events/roommemberevent.cpp b/lib/events/roommemberevent.cpp index 3cbf6685..d0787170 100644 --- a/lib/events/roommemberevent.cpp +++ b/lib/events/roommemberevent.cpp @@ -28,7 +28,7 @@ static const std::array membershipStrings = { QStringLiteral("leave"), QStringLiteral("ban") } }; -namespace QMatrixClient { +namespace Quotient { template <> struct JsonConverter { static MembershipType load(const QJsonValue& jv) @@ -43,9 +43,9 @@ struct JsonConverter { return MembershipType::Undefined; } }; -} // namespace QMatrixClient +} // namespace Quotient -using namespace QMatrixClient; +using namespace Quotient; MemberEventContent::MemberEventContent(const QJsonObject& json) : membership(fromJson(json["membership"_ls])) diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index 59d59e3a..2a16617a 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -21,7 +21,7 @@ #include "eventcontent.h" #include "stateevent.h" -namespace QMatrixClient { +namespace Quotient { class MemberEventContent : public EventContent::Base { public: enum MembershipType : size_t { @@ -107,4 +107,4 @@ public: REGISTER_EVENT_TYPE(RoomMemberEvent) DEFINE_EVENTTYPE_ALIAS(RoomMember, RoomMemberEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 991931de..09562d65 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -25,7 +25,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; using namespace EventContent; using MsgType = RoomMessageEvent::MsgType; @@ -279,7 +279,7 @@ TextContent::TextContent(const QString& text, const QString& contentType, mimeType = QMimeDatabase().mimeTypeForName("text/html"); } -namespace QMatrixClient { +namespace Quotient { // Overload the default fromJson<> logic that defined in converters.h // as we want template <> @@ -295,7 +295,7 @@ Omittable fromJson(const QJsonValue& jv) return RelatesTo { jo.value("rel_type"_ls).toString(), jo.value(EventIdKeyL).toString() }; } -} // namespace QMatrixClient +} // namespace Quotient TextContent::TextContent(const QJsonObject& json) : relatesTo(fromJson>(json[RelatesToKeyL])) diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index c7a5cb47..aa515c71 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -23,7 +23,7 @@ class QFileInfo; -namespace QMatrixClient { +namespace Quotient { namespace MessageEventContent = EventContent; // Back-compatibility /** @@ -217,4 +217,4 @@ namespace EventContent { */ using AudioContent = PlayableContent>; } // namespace EventContent -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/roomtombstoneevent.cpp b/lib/events/roomtombstoneevent.cpp index a74bb367..f93eb60d 100644 --- a/lib/events/roomtombstoneevent.cpp +++ b/lib/events/roomtombstoneevent.cpp @@ -18,7 +18,7 @@ #include "roomtombstoneevent.h" -using namespace QMatrixClient; +using namespace Quotient; QString RoomTombstoneEvent::serverMessage() const { diff --git a/lib/events/roomtombstoneevent.h b/lib/events/roomtombstoneevent.h index 95fed998..2c2f0663 100644 --- a/lib/events/roomtombstoneevent.h +++ b/lib/events/roomtombstoneevent.h @@ -20,7 +20,7 @@ #include "stateevent.h" -namespace QMatrixClient { +namespace Quotient { class RoomTombstoneEvent : public StateEventBase { public: DEFINE_EVENT_TYPEID("m.room.tombstone", RoomTombstoneEvent) @@ -34,4 +34,4 @@ public: QString successorRoomId() const; }; REGISTER_EVENT_TYPE(RoomTombstoneEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 6dad8020..520f6b4b 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -20,7 +20,7 @@ #include "stateevent.h" -namespace QMatrixClient { +namespace Quotient { namespace EventContent { template class SimpleContent { @@ -37,7 +37,7 @@ namespace EventContent { {} QJsonObject toJson() const { - return { { key, QMatrixClient::toJson(value) } }; + return { { key, Quotient::toJson(value) } }; } public: @@ -92,4 +92,4 @@ public: QStringList aliases() const { return content().value; } }; REGISTER_EVENT_TYPE(RoomAliasesEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index bd228abd..c0bb0794 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -18,7 +18,7 @@ #include "stateevent.h" -using namespace QMatrixClient; +using namespace Quotient; // Aside from the normal factory to instantiate StateEventBase inheritors // StateEventBase itself can be instantiated if there's a state_key JSON key diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index 757c94ee..74e36e74 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -20,7 +20,7 @@ #include "roomevent.h" -namespace QMatrixClient { +namespace Quotient { /// Make a minimal correct Matrix state event JSON template @@ -128,12 +128,12 @@ private: ContentT _content; std::unique_ptr> _prev; }; -} // namespace QMatrixClient +} // namespace Quotient namespace std { template <> -struct hash { - size_t operator()(const QMatrixClient::StateEventKey& k) const Q_DECL_NOEXCEPT +struct hash { + size_t operator()(const Quotient::StateEventKey& k) const Q_DECL_NOEXCEPT { return qHash(k); } diff --git a/lib/events/typingevent.cpp b/lib/events/typingevent.cpp index ee3d6b67..0c5fc6ba 100644 --- a/lib/events/typingevent.cpp +++ b/lib/events/typingevent.cpp @@ -20,7 +20,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; TypingEvent::TypingEvent(const QJsonObject& obj) : Event(typeId(), obj) { diff --git a/lib/events/typingevent.h b/lib/events/typingevent.h index c8170865..d659c597 100644 --- a/lib/events/typingevent.h +++ b/lib/events/typingevent.h @@ -20,7 +20,7 @@ #include "event.h" -namespace QMatrixClient { +namespace Quotient { class TypingEvent : public Event { public: DEFINE_EVENT_TYPEID("m.typing", TypingEvent) @@ -34,4 +34,4 @@ private: }; REGISTER_EVENT_TYPE(TypingEvent) DEFINE_EVENTTYPE_ALIAS(Typing, TypingEvent) -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/identity/definitions/request_email_validation.cpp b/lib/identity/definitions/request_email_validation.cpp index 131b9488..22cb0072 100644 --- a/lib/identity/definitions/request_email_validation.cpp +++ b/lib/identity/definitions/request_email_validation.cpp @@ -4,7 +4,7 @@ #include "request_email_validation.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo( QJsonObject& jo, const RequestEmailValidation& pod) diff --git a/lib/identity/definitions/request_email_validation.h b/lib/identity/definitions/request_email_validation.h index 2496d7f5..99487073 100644 --- a/lib/identity/definitions/request_email_validation.h +++ b/lib/identity/definitions/request_email_validation.h @@ -6,7 +6,7 @@ #include "converters.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -39,4 +39,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, RequestEmailValidation& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/identity/definitions/request_msisdn_validation.cpp b/lib/identity/definitions/request_msisdn_validation.cpp index 0087d202..6024bf61 100644 --- a/lib/identity/definitions/request_msisdn_validation.cpp +++ b/lib/identity/definitions/request_msisdn_validation.cpp @@ -4,7 +4,7 @@ #include "request_msisdn_validation.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo( QJsonObject& jo, const RequestMsisdnValidation& pod) diff --git a/lib/identity/definitions/request_msisdn_validation.h b/lib/identity/definitions/request_msisdn_validation.h index f8060cfc..ecccf567 100644 --- a/lib/identity/definitions/request_msisdn_validation.h +++ b/lib/identity/definitions/request_msisdn_validation.h @@ -6,7 +6,7 @@ #include "converters.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -43,4 +43,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, RequestMsisdnValidation& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/identity/definitions/sid.cpp b/lib/identity/definitions/sid.cpp index cc6973f2..99fe9b59 100644 --- a/lib/identity/definitions/sid.cpp +++ b/lib/identity/definitions/sid.cpp @@ -4,7 +4,7 @@ #include "sid.h" -using namespace QMatrixClient; +using namespace Quotient; void JsonObjectConverter::dumpTo(QJsonObject& jo, const Sid& pod) { diff --git a/lib/identity/definitions/sid.h b/lib/identity/definitions/sid.h index 752d62bb..0f7ce58a 100644 --- a/lib/identity/definitions/sid.h +++ b/lib/identity/definitions/sid.h @@ -6,7 +6,7 @@ #include "converters.h" -namespace QMatrixClient +namespace Quotient { // Data structures @@ -27,4 +27,4 @@ struct JsonObjectConverter static void fillFrom(const QJsonObject& jo, Sid& pod); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 5615736e..ec6b8375 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -30,7 +30,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; struct NetworkReplyDeleter : public QScopedPointerDeleteLater { static inline void cleanup(QNetworkReply* reply) diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index c85d2d90..90c20c37 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -28,7 +28,7 @@ class QNetworkReply; class QSslError; -namespace QMatrixClient { +namespace Quotient { class ConnectionData; enum class HttpVerb { Get, Put, Post, Delete }; @@ -364,4 +364,4 @@ inline bool isJobRunning(BaseJob* job) { return job && job->error() == BaseJob::Pending; } -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 9722186c..3a03efde 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -4,7 +4,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; class DownloadFileJob::Private { public: diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index ebfe5a0d..fa697219 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -2,7 +2,7 @@ #include "csapi/content-repo.h" -namespace QMatrixClient { +namespace Quotient { class DownloadFileJob : public GetContentJob { public: enum { FileError = BaseJob::UserDefinedError + 1 }; @@ -24,4 +24,4 @@ private: void beforeAbandon(QNetworkReply*) override; Status parseReply(QNetworkReply*) override; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/jobs/mediathumbnailjob.cpp b/lib/jobs/mediathumbnailjob.cpp index db2bbc13..0a346392 100644 --- a/lib/jobs/mediathumbnailjob.cpp +++ b/lib/jobs/mediathumbnailjob.cpp @@ -18,7 +18,7 @@ #include "mediathumbnailjob.h" -using namespace QMatrixClient; +using namespace Quotient; QUrl MediaThumbnailJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri, QSize requestedSize) diff --git a/lib/jobs/mediathumbnailjob.h b/lib/jobs/mediathumbnailjob.h index df0a7f31..75e2e55a 100644 --- a/lib/jobs/mediathumbnailjob.h +++ b/lib/jobs/mediathumbnailjob.h @@ -22,7 +22,7 @@ #include -namespace QMatrixClient { +namespace Quotient { class MediaThumbnailJob : public GetContentThumbnailJob { public: using GetContentThumbnailJob::makeRequestUrl; @@ -42,4 +42,4 @@ protected: private: QImage _thumbnail; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/jobs/postreadmarkersjob.h b/lib/jobs/postreadmarkersjob.h index cf482a9a..5a4d942c 100644 --- a/lib/jobs/postreadmarkersjob.h +++ b/lib/jobs/postreadmarkersjob.h @@ -22,7 +22,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; class PostReadMarkersJob : public BaseJob { public: diff --git a/lib/jobs/requestdata.cpp b/lib/jobs/requestdata.cpp index 6ad7c007..0c70f085 100644 --- a/lib/jobs/requestdata.cpp +++ b/lib/jobs/requestdata.cpp @@ -6,7 +6,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; auto fromData(const QByteArray& data) { diff --git a/lib/jobs/requestdata.h b/lib/jobs/requestdata.h index 55987a3b..020d5ef2 100644 --- a/lib/jobs/requestdata.h +++ b/lib/jobs/requestdata.h @@ -26,7 +26,7 @@ class QJsonArray; class QJsonDocument; class QIODevice; -namespace QMatrixClient { +namespace Quotient { /** * A simple wrapper that represents the request body. * Provides a unified interface to dump an unstructured byte stream @@ -52,4 +52,6 @@ public: private: std::unique_ptr _source; }; -} // namespace QMatrixClient +} // namespace Quotient +/// \deprecated Use namespace Quotient instead +namespace QMatrixClient = Quotient; diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index f660e1b6..cd7709e1 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -18,7 +18,7 @@ #include "syncjob.h" -using namespace QMatrixClient; +using namespace Quotient; static size_t jobId = 0; diff --git a/lib/jobs/syncjob.h b/lib/jobs/syncjob.h index 8f925414..df419ba8 100644 --- a/lib/jobs/syncjob.h +++ b/lib/jobs/syncjob.h @@ -22,7 +22,7 @@ #include "../syncdata.h" #include "basejob.h" -namespace QMatrixClient { +namespace Quotient { class SyncJob : public BaseJob { public: explicit SyncJob(const QString& since = {}, const QString& filter = {}, @@ -38,4 +38,4 @@ protected: private: SyncData d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/joinstate.h b/lib/joinstate.h index fcf840ae..718ae3fd 100644 --- a/lib/joinstate.h +++ b/lib/joinstate.h @@ -22,7 +22,7 @@ #include -namespace QMatrixClient { +namespace Quotient { enum class JoinState : unsigned int { Join = 0x1, Invite = 0x2, @@ -43,5 +43,5 @@ inline const char* toCString(JoinState js) ++index; return JoinStateStrings[index]; } -} // namespace QMatrixClient -Q_DECLARE_OPERATORS_FOR_FLAGS(QMatrixClient::JoinStates) +} // namespace Quotient +Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::JoinStates) diff --git a/lib/logging.h b/lib/logging.h index 24799752..3d13569a 100644 --- a/lib/logging.h +++ b/lib/logging.h @@ -28,7 +28,7 @@ Q_DECLARE_LOGGING_CATEGORY(EPHEMERAL) Q_DECLARE_LOGGING_CATEGORY(JOBS) Q_DECLARE_LOGGING_CATEGORY(SYNCJOB) -namespace QMatrixClient { +namespace Quotient { // QDebug manipulators using QDebugManip = QDebug (*)(QDebug); @@ -75,7 +75,9 @@ inline qint64 profilerMinNsecs() #endif * 1000; } -} // namespace QMatrixClient +} // namespace Quotient +/// \deprecated Use namespace Quotient instead +namespace QMatrixClient = Quotient; inline QDebug operator<<(QDebug debug_object, const QElapsedTimer& et) { diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 7bff654c..8ee080bf 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -21,7 +21,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; class NetworkAccessManager::Private { public: diff --git a/lib/networkaccessmanager.h b/lib/networkaccessmanager.h index dfa388f0..a678b80f 100644 --- a/lib/networkaccessmanager.h +++ b/lib/networkaccessmanager.h @@ -22,7 +22,7 @@ #include -namespace QMatrixClient { +namespace Quotient { class NetworkAccessManager : public QNetworkAccessManager { Q_OBJECT public: @@ -43,4 +43,4 @@ private: class Private; std::unique_ptr d; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/networksettings.cpp b/lib/networksettings.cpp index f5655975..cb071483 100644 --- a/lib/networksettings.cpp +++ b/lib/networksettings.cpp @@ -18,7 +18,7 @@ #include "networksettings.h" -using namespace QMatrixClient; +using namespace Quotient; void NetworkSettings::setupApplicationProxy() const { diff --git a/lib/networksettings.h b/lib/networksettings.h index 75bf726d..a82a44d0 100644 --- a/lib/networksettings.h +++ b/lib/networksettings.h @@ -24,7 +24,7 @@ Q_DECLARE_METATYPE(QNetworkProxy::ProxyType) -namespace QMatrixClient { +namespace Quotient { class NetworkSettings : public SettingsGroup { Q_OBJECT QMC_DECLARE_SETTING(QNetworkProxy::ProxyType, proxyType, setProxyType) diff --git a/lib/qt_connection_util.h b/lib/qt_connection_util.h index 94c1ec60..159e7522 100644 --- a/lib/qt_connection_util.h +++ b/lib/qt_connection_util.h @@ -22,7 +22,7 @@ #include -namespace QMatrixClient { +namespace Quotient { namespace _impl { template inline QMetaObject::Connection @@ -102,4 +102,4 @@ public: private: QObject* subscriber; }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/room.cpp b/lib/room.cpp index 52f86616..d8fee5aa 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -71,7 +71,7 @@ #include // QtOlm #include // QtOlm -using namespace QMatrixClient; +using namespace Quotient; using namespace std::placeholders; using std::move; #if !(defined __GLIBCXX__ && __GLIBCXX__ <= 20150123) @@ -1085,7 +1085,7 @@ QUrl Room::fileSource(const QString& id) const QString Room::prettyPrint(const QString& plainText) const { - return QMatrixClient::prettyPrint(plainText); + return Quotient::prettyPrint(plainText); } QList Room::usersTyping() const { return d->usersTyping; } diff --git a/lib/room.h b/lib/room.h index d6fb8a61..8448815d 100644 --- a/lib/room.h +++ b/lib/room.h @@ -35,7 +35,7 @@ #include #include -namespace QMatrixClient { +namespace Quotient { class Event; class Avatar; class SyncRoomData; @@ -423,7 +423,7 @@ public: Q_INVOKABLE QUrl fileSource(const QString& id) const; /** Pretty-prints plain text into HTML - * As of now, it's exactly the same as QMatrixClient::prettyPrint(); + * As of now, it's exactly the same as Quotient::prettyPrint(); * in the future, it will also linkify room aliases, mxids etc. * using the room context. */ @@ -668,6 +668,6 @@ public: private: const Room* room; }; -} // namespace QMatrixClient -Q_DECLARE_METATYPE(QMatrixClient::FileTransferInfo) -Q_DECLARE_OPERATORS_FOR_FLAGS(QMatrixClient::Room::Changes) +} // namespace Quotient +Q_DECLARE_METATYPE(Quotient::FileTransferInfo) +Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::Room::Changes) diff --git a/lib/settings.cpp b/lib/settings.cpp index 1278fe33..9c61ab5e 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -4,7 +4,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; QString Settings::legacyOrganizationName {}; QString Settings::legacyApplicationName {}; diff --git a/lib/settings.h b/lib/settings.h index 427f5494..4dcbbea0 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -24,7 +24,7 @@ class QVariant; -namespace QMatrixClient { +namespace Quotient { class Settings : public QSettings { Q_OBJECT public: @@ -148,4 +148,4 @@ public: void setEncryptionAccountPickle(const QByteArray& encryptionAccountPickle); Q_INVOKABLE void clearEncryptionAccountPickle(); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/syncdata.cpp b/lib/syncdata.cpp index 0c39b438..c784cd7d 100644 --- a/lib/syncdata.cpp +++ b/lib/syncdata.cpp @@ -23,7 +23,7 @@ #include #include -using namespace QMatrixClient; +using namespace Quotient; const QString SyncRoomData::UnreadCountKey = QStringLiteral("x-qmatrixclient.unread_count"); @@ -42,7 +42,7 @@ bool RoomSummary::merge(const RoomSummary& other) | heroes.merge(other.heroes); } -QDebug QMatrixClient::operator<<(QDebug dbg, const RoomSummary& rs) +QDebug Quotient::operator<<(QDebug dbg, const RoomSummary& rs) { QDebugStateSaver _(dbg); QStringList sl; diff --git a/lib/syncdata.h b/lib/syncdata.h index ad9902e4..d55438d7 100644 --- a/lib/syncdata.h +++ b/lib/syncdata.h @@ -22,7 +22,7 @@ #include "events/stateevent.h" -namespace QMatrixClient { +namespace Quotient { /// Room summary, as defined in MSC688 /** * Every member of this structure is an Omittable; as per the MSC, only @@ -111,4 +111,4 @@ private: static QJsonObject loadJson(const QString& fileName); }; -} // namespace QMatrixClient +} // namespace Quotient diff --git a/lib/user.cpp b/lib/user.cpp index 0705aee7..5dea3942 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -37,7 +37,7 @@ #include -using namespace QMatrixClient; +using namespace Quotient; using namespace std::placeholders; using std::move; diff --git a/lib/user.h b/lib/user.h index 779efb34..c9e3dbc1 100644 --- a/lib/user.h +++ b/lib/user.h @@ -23,7 +23,7 @@ #include #include -namespace QMatrixClient { +namespace Quotient { class Connection; class Room; class RoomMemberEvent; @@ -160,5 +160,5 @@ private: class Private; QScopedPointer d; }; -} // namespace QMatrixClient -Q_DECLARE_METATYPE(QMatrixClient::User*) +} // namespace Quotient +Q_DECLARE_METATYPE(Quotient::User*) diff --git a/lib/util.cpp b/lib/util.cpp index 1919e811..be9656f8 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -32,7 +32,7 @@ static const auto RegExpOptions = | QRegularExpression::UseUnicodePropertiesOption; // Converts all that looks like a URL into HTML links -void QMatrixClient::linkifyUrls(QString& htmlEscapedText) +void Quotient::linkifyUrls(QString& htmlEscapedText) { // Note: outer parentheses are a part of C++ raw string delimiters, not of // the regex (see http://en.cppreference.com/w/cpp/language/string_literal). @@ -70,7 +70,7 @@ void QMatrixClient::linkifyUrls(QString& htmlEscapedText) QStringLiteral(R"(\1\2)")); } -QString QMatrixClient::sanitized(const QString& plainText) +QString Quotient::sanitized(const QString& plainText) { auto text = plainText; text.remove(QChar(0x202e)); // RLO @@ -79,7 +79,7 @@ QString QMatrixClient::sanitized(const QString& plainText) return text; } -QString QMatrixClient::prettyPrint(const QString& plainText) +QString Quotient::prettyPrint(const QString& plainText) { auto pt = plainText.toHtmlEscaped(); linkifyUrls(pt); @@ -88,7 +88,7 @@ QString QMatrixClient::prettyPrint(const QString& plainText) + QStringLiteral(""); } -QString QMatrixClient::cacheLocation(const QString& dirName) +QString Quotient::cacheLocation(const QString& dirName) { const QString cachePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) % '/' @@ -99,7 +99,7 @@ QString QMatrixClient::cacheLocation(const QString& dirName) return cachePath; } -qreal QMatrixClient::stringToHueF(const QString& string) +qreal Quotient::stringToHueF(const QString& string) { Q_ASSERT(!string.isEmpty()); QByteArray hash = QCryptographicHash::hash(string.toUtf8(), @@ -118,7 +118,7 @@ static const auto ServerPartRegEx = QStringLiteral( "(?::(\\d{1,5}))?" // Optional port ); -QString QMatrixClient::serverPart(const QString& mxId) +QString Quotient::serverPart(const QString& mxId) { static QString re = "^[@!#$+].+?:(" // Localpart and colon % ServerPartRegEx % ")$"; @@ -135,7 +135,7 @@ QString QMatrixClient::serverPart(const QString& mxId) # pragma clang diagnostic push # pragma ide diagnostic ignored "OCSimplifyInspection" #endif -using namespace QMatrixClient; +using namespace Quotient; int f(); static_assert(std::is_same, int>::value, diff --git a/lib/util.h b/lib/util.h index d055fa46..d94c7321 100644 --- a/lib/util.h +++ b/lib/util.h @@ -63,7 +63,7 @@ static void qAsConst(const T&&) Q_DECL_EQ_DELETE; # define BROKEN_INITIALIZER_LISTS #endif -namespace QMatrixClient { +namespace Quotient { // The below enables pretty-printing of enums in logs #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) # define REGISTER_ENUM(EnumName) Q_ENUM(EnumName) @@ -330,4 +330,6 @@ qreal stringToHueF(const QString& string); /** Extract the serverpart from MXID */ QString serverPart(const QString& mxId); -} // namespace QMatrixClient +} // namespace Quotient +/// \deprecated Use namespace Quotient instead +namespace QMatrixClient = Quotient; \ No newline at end of file -- cgit v1.2.3 From fadce11be92abe76cecfe6356b3b38f25dd93e8d Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 13 Aug 2019 20:28:56 +0900 Subject: Support for server notices rooms (MSC1452) Closes #326. --- lib/events/accountdataevents.h | 1 + lib/jobs/basejob.cpp | 3 +++ lib/jobs/basejob.h | 1 + lib/room.cpp | 5 +++++ lib/room.h | 2 ++ 5 files changed, 12 insertions(+) (limited to 'lib/jobs') diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h index a8df08a5..31176766 100644 --- a/lib/events/accountdataevents.h +++ b/lib/events/accountdataevents.h @@ -27,6 +27,7 @@ namespace Quotient { constexpr const char* FavouriteTag = "m.favourite"; constexpr const char* LowPriorityTag = "m.lowpriority"; +constexpr const char* ServerNoticeTag = "m.server_notice"; struct TagRecord { using order_type = Omittable; diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index ec6b8375..5930e8b8 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -426,6 +426,9 @@ BaseJob::Status BaseJob::parseError(QNetworkReply* reply, ? tr("Requested room version: %1") .arg(errorJson.value("room_version"_ls).toString()) : errorJson.value("error"_ls).toString() }; + if (errCode == "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM") + return { CannotLeaveRoom, + tr("It's not allowed to leave a server notices room") }; // Not localisable on the client side if (errorJson.contains("error"_ls)) diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 90c20c37..68467d48 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -76,6 +76,7 @@ public: NetworkAuthRequiredError = NetworkAuthRequired, UserConsentRequired, UserConsentRequiredError = UserConsentRequired, + CannotLeaveRoom, UserDefinedError = 256 }; diff --git a/lib/room.cpp b/lib/room.cpp index f70e0b0e..bee9e9cb 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -951,6 +951,11 @@ bool Room::isFavourite() const { return d->tags.contains(FavouriteTag); } bool Room::isLowPriority() const { return d->tags.contains(LowPriorityTag); } +bool Room::isServerNoticeRoom() const +{ + return d->tags.contains(ServerNoticeTag); +} + bool Room::isDirectChat() const { return connection()->isDirectChat(id()); } QList Room::directChatUsers() const diff --git a/lib/room.h b/lib/room.h index 8448815d..2139f28b 100644 --- a/lib/room.h +++ b/lib/room.h @@ -389,6 +389,8 @@ public: bool isFavourite() const; /// Check whether the list of tags has m.lowpriority bool isLowPriority() const; + /// Check whether this room is for server notices (MSC1452) + bool isServerNoticeRoom() const; /// Check whether this room is a direct chat Q_INVOKABLE bool isDirectChat() const; -- cgit v1.2.3 From 8663c2e78407a0c0df872eaf9bb6b41de2fbdc9e Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 16 Aug 2019 13:40:09 +0900 Subject: BaseJob: support M_USER_DEACTIVATED error code Closes #344. --- lib/jobs/basejob.cpp | 2 ++ lib/jobs/basejob.h | 1 + 2 files changed, 3 insertions(+) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 5930e8b8..f3ba00b5 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -429,6 +429,8 @@ BaseJob::Status BaseJob::parseError(QNetworkReply* reply, if (errCode == "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM") return { CannotLeaveRoom, tr("It's not allowed to leave a server notices room") }; + if (errCode == "M_USER_DEACTIVATED") + return { UserDeactivated }; // Not localisable on the client side if (errorJson.contains("error"_ls)) diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 68467d48..fd7beca0 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -77,6 +77,7 @@ public: UserConsentRequired, UserConsentRequiredError = UserConsentRequired, CannotLeaveRoom, + UserDeactivated, UserDefinedError = 256 }; -- cgit v1.2.3 From ad159b5206de615762e22f95e97ae61400f11761 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 20 Aug 2019 19:56:54 +0900 Subject: BaseJob: Status/StatusCode tweaks, cleanup, mo' comments Notably, recovered Status::fromHttpCode() that was introduced in 5722ceaf4bd10c29f1091e3dc5a87f5650ea8c71 but fell victim of a careless merge (so much for introducing non-topical changes in feature branches). --- lib/jobs/basejob.cpp | 135 ++++++++++++++++++++++++++++----------------------- lib/jobs/basejob.h | 37 ++++++++------ 2 files changed, 97 insertions(+), 75 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index f3ba00b5..621762be 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -77,6 +77,8 @@ public: QByteArray rawResponse; QUrl errorUrl; //< May contain a URL to help with some errors + LoggingCategory logCat = JOBS; + QTimer timer; QTimer retryTimer; @@ -86,7 +88,12 @@ public: int maxRetries = errorStrategy.size(); int retriesTaken = 0; - LoggingCategory logCat = JOBS; + QString urlForLog() const + { + return reply + ? reply->url().toString(QUrl::RemoveQuery) + : makeRequestUrl(connection->baseUrl(), apiEndpoint).toString(); + } }; BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, @@ -112,7 +119,7 @@ BaseJob::~BaseJob() QUrl BaseJob::requestUrl() const { - return d->reply ? d->reply->request().url() : QUrl(); + return d->reply ? d->reply->url() : QUrl(); } bool BaseJob::isBackground() const @@ -193,17 +200,13 @@ void BaseJob::Private::sendRequest(bool inBackground) req.setRawHeader("Authorization", QByteArray("Bearer ") + connection->accessToken()); req.setAttribute(QNetworkRequest::BackgroundRequestAttribute, inBackground); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); req.setMaximumRedirectsAllowed(10); -#endif req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) - // some sources claim that there are issues with QT 5.8 req.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); -#endif for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) req.setRawHeader(it.key(), it.value()); + switch (verb) { case HttpVerb::Get: reply.reset(connection->nam()->get(req)); @@ -318,6 +321,47 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) return false; } +BaseJob::Status BaseJob::Status::fromHttpCode(int httpCode, QString msg) +{ + // clang-format off + return { [httpCode]() -> StatusCode { + if (httpCode / 10 == 41) // 41x errors + return httpCode == 410 ? IncorrectRequestError : NotFoundError; + switch (httpCode) { + case 401: case 403: case 407: + return ContentAccessError; + case 404: + return NotFoundError; + case 400: case 405: case 406: case 426: case 428: case 505: + case 494: // Unofficial nginx "Request header too large" + case 497: // Unofficial nginx "HTTP request sent to HTTPS port" + return IncorrectRequestError; + case 429: + return TooManyRequestsError; + case 501: case 510: + return RequestNotImplementedError; + case 511: + return NetworkAuthRequiredError; + default: + return NetworkError; + } + }(), std::move(msg) }; + // clang-format on +} + +QDebug BaseJob::Status::dumpToLog(QDebug dbg) const +{ + QDebugStateSaver _s(dbg); + dbg.noquote().nospace(); + if (auto* const k = QMetaEnum::fromType().valueToKey(code)) { + const QByteArray b = k; + dbg << b.mid(b.lastIndexOf(':')); + } else + dbg << code; + return dbg << ": " << message; + +} + BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const { // QNetworkReply error codes seem to be flawed when it comes to HTTP; @@ -327,62 +371,30 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const const auto httpCodeHeader = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); if (!httpCodeHeader.isValid()) { - qCWarning(d->logCat) << this << "didn't get valid HTTP headers"; + qCWarning(d->logCat) << "No valid HTTP headers from" << d->urlForLog(); return { NetworkError, reply->errorString() }; } - const QString replyState = reply->isRunning() - ? QStringLiteral("(tentative)") - : QStringLiteral("(final)"); - const auto urlString = '|' + d->reply->url().toDisplayString(); const auto httpCode = httpCodeHeader.toInt(); - const auto reason = - reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); if (httpCode / 100 == 2) // 2xx { - qCDebug(d->logCat).noquote().nospace() << this << urlString; - qCDebug(d->logCat).noquote() << " " << httpCode << reason << replyState; + if (reply->isFinished()) + qCInfo(d->logCat) << httpCode << "<-" << d->urlForLog(); if (!checkContentType(reply->rawHeader("Content-Type"), d->expectedContentTypes)) return { UnexpectedResponseTypeWarning, "Unexpected content type of the response" }; return NoError; } + if (reply->isFinished()) + qCWarning(d->logCat) << httpCode << "<-" << d->urlForLog(); - qCWarning(d->logCat).noquote().nospace() << this << urlString; - qCWarning(d->logCat).noquote() << " " << httpCode << reason << replyState; - return { [httpCode]() -> StatusCode { - if (httpCode / 10 == 41) - return httpCode == 410 ? IncorrectRequestError - : NotFoundError; - switch (httpCode) { - case 401: - case 403: - case 407: - return ContentAccessError; - case 404: - return NotFoundError; - case 400: - case 405: - case 406: - case 426: - case 428: - case 505: - case 494: // Unofficial nginx "Request header too large" - case 497: // Unofficial nginx "HTTP request sent to HTTPS port" - return IncorrectRequestError; - case 429: - return TooManyRequestsError; - case 501: - case 510: - return RequestNotImplementedError; - case 511: - return NetworkAuthRequiredError; - default: - return NetworkError; - } - }(), - reply->errorString() }; + auto message = reply->errorString(); + if (message.isEmpty()) + message = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute) + .toString(); + + return Status::fromHttpCode(httpCode, message); } BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) @@ -398,7 +410,7 @@ BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) BaseJob::Status BaseJob::parseJson(const QJsonDocument&) { return Success; } -BaseJob::Status BaseJob::parseError(QNetworkReply* reply, +BaseJob::Status BaseJob::parseError(QNetworkReply* /*reply*/, const QJsonObject& errorJson) { const auto errCode = errorJson.value("errcode"_ls).toString(); @@ -441,7 +453,7 @@ BaseJob::Status BaseJob::parseError(QNetworkReply* reply, void BaseJob::stop() { - // This method is used to semi-finalise the job before retrying; so + // This method is (also) used to semi-finalise the job before retrying; so // stop the timeout timer but keep the retry timer running. d->timer.stop(); if (d->reply) { @@ -449,7 +461,7 @@ void BaseJob::stop() if (d->reply->isRunning()) { qCWarning(d->logCat) << this << "stopped without ready network reply"; - d->reply->abort(); + d->reply->abort(); // Keep the reply object in case clients need it } } else qCWarning(d->logCat) << this << "stopped with empty network reply"; @@ -474,10 +486,10 @@ void BaseJob::finishJob() return; } - // Notify those interested in any completion of the job (including killing) + // Notify those interested in any completion of the job including abandon() emit finished(this); - emit result(this); + emit result(this); // abandon() doesn't emit this if (error()) emit failure(this); else @@ -582,21 +594,22 @@ void BaseJob::setStatus(Status s) { // The crash that led to this code has been reported in // https://github.com/quotient-im/Quaternion/issues/566 - basically, - // when cleaning up childrent of a deleted Connection, there's a chance + // when cleaning up children of a deleted Connection, there's a chance // of pending jobs being abandoned, calling setStatus(Abandoned). // There's nothing wrong with this; however, the safety check for // cleartext access tokens below uses d->connection - which is a dangling // pointer. // To alleviate that, a stricter condition is applied, that for Abandoned // and to-be-Abandoned jobs the status message will be disregarded entirely. - // For 0.6 we might rectify the situation by making d->connection - // a QPointer<> (and derive ConnectionData from QObject, respectively). - if (d->status.code == Abandoned || s.code == Abandoned) - s.message.clear(); - + // We could rectify the situation by making d->connection a QPointer<> + // (and deriving ConnectionData from QObject, respectively) but it's + // a too edge case for the hassle. if (d->status == s) return; + if (d->status.code == Abandoned || s.code == Abandoned) + s.message.clear(); + if (!s.message.isEmpty() && d->connection && !d->connection->accessToken().isEmpty()) s.message.replace(d->connection->accessToken(), "(REDACTED)"); diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index fd7beca0..9de7b49d 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -24,6 +24,7 @@ #include #include #include +#include class QNetworkReply; class QSslError; @@ -43,18 +44,23 @@ class BaseJob : public QObject { Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries) public: + /*! The status code of a job + * + * Every job is created in Unprepared status; upon calling prepare() + * from Connection (if things are fine) it go to Pending status. After + * that, the next transition comes after the reply arrives and its contents + * are analysed. At any point in time the job can be abandon()ed, causing + * it to switch to status Abandoned for a brief period before deletion. + */ enum StatusCode { - NoError = 0 // To be compatible with Qt conventions - , Success = 0, + NoError = Success, // To be compatible with Qt conventions Pending = 1, - WarningLevel = 20, + WarningLevel = 20, //< Warnings have codes starting from this UnexpectedResponseType = 21, UnexpectedResponseTypeWarning = UnexpectedResponseType, - Abandoned = 50 //< A tiny period between abandoning and object deletion - , - ErrorLevel = 100 //< Errors have codes starting from this - , + Abandoned = 50, //< A tiny period between abandoning and object deletion + ErrorLevel = 100, //< Errors have codes starting from this NetworkError = 100, Timeout, TimeoutError = Timeout, @@ -64,10 +70,12 @@ public: IncorrectRequestError = IncorrectRequest, IncorrectResponse, IncorrectResponseError = IncorrectResponse, - JsonParseError //< deprecated; Use IncorrectResponse instead + JsonParseError + Q_DECL_ENUMERATOR_DEPRECATED_X("Use IncorrectResponse instead") = IncorrectResponse, TooManyRequests, TooManyRequestsError = TooManyRequests, + RateLimited = TooManyRequests, RequestNotImplemented, RequestNotImplementedError = RequestNotImplemented, UnsupportedRoomVersion, @@ -80,6 +88,7 @@ public: UserDeactivated, UserDefinedError = 256 }; + Q_ENUM(StatusCode) /** * A simple wrapper around QUrlQuery that allows its creation from @@ -97,7 +106,7 @@ public: using Data = RequestData; - /** + /*! * This structure stores the status of a server call job. The status * consists of a code, that is described (but not delimited) by the * respective enum, and a freeform message. @@ -106,16 +115,16 @@ public: * along the lines of StatusCode, with additional values * starting at UserDefinedError */ - class Status { - public: + struct Status { Status(StatusCode c) : code(c) {} Status(int c, QString m) : code(c), message(std::move(m)) {} + static Status fromHttpCode(int httpCode, QString msg = {}); bool good() const { return code < ErrorLevel; } - friend QDebug operator<<(QDebug dbg, const Status& s) + QDebug dumpToLog(QDebug dbg) const; + friend QDebug operator<<(const QDebug& dbg, const Status& s) { - QDebugStateSaver _s(dbg); - return dbg.noquote().nospace() << s.code << ": " << s.message; + return s.dumpToLog(dbg); } bool operator==(const Status& other) const -- cgit v1.2.3 From 59c4996a602e9eeae4e3bfc0210ff15f957df38f Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 20 Aug 2019 20:09:09 +0900 Subject: BaseJob/ConnectionData: connection-wide rate-limiting As before, completely transparent for clients, driven by 529 errors from the server (but cases of rate limiting are signalled by BaseJob::rateLimited). That brings changes to BaseJob API: timeouts now use int64_t and also can be handled in std::chrono terms; aboutToStart() -> aboutToSendRequest(); started() -> sentRequest(). Closes #292. --- lib/connection.cpp | 2 +- lib/connectiondata.cpp | 70 ++++++++++++++++++- lib/connectiondata.h | 6 ++ lib/jobs/basejob.cpp | 159 ++++++++++++++++++++++++------------------- lib/jobs/basejob.h | 63 +++++++++++------ lib/jobs/downloadfilejob.cpp | 4 +- lib/jobs/downloadfilejob.h | 4 +- lib/room.cpp | 2 +- 8 files changed, 212 insertions(+), 98 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index 5f90ed55..5ebdcf6c 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -1358,7 +1358,7 @@ void Connection::setLazyLoading(bool newValue) void Connection::run(BaseJob* job, RunningPolicy runningPolicy) const { connect(job, &BaseJob::failure, this, &Connection::requestFailed); - job->start(d->data.get(), runningPolicy & BackgroundRequest); + job->prepare(d->data.get(), runningPolicy & BackgroundRequest); d->data->submit(job); } diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index 41d97b87..e241e376 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -20,11 +20,21 @@ #include "logging.h" #include "networkaccessmanager.h" +#include "jobs/basejob.h" + +#include +#include + +#include using namespace Quotient; -struct ConnectionData::Private { - explicit Private(QUrl url) : baseUrl(std::move(url)) {} +class ConnectionData::Private { +public: + explicit Private(QUrl url) : baseUrl(std::move(url)) + { + rateLimiter.setSingleShot(true); + } QUrl baseUrl; QByteArray accessToken; @@ -34,14 +44,68 @@ struct ConnectionData::Private { mutable unsigned int txnCounter = 0; const qint64 txnBase = QDateTime::currentMSecsSinceEpoch(); + + QString id() const { return userId + '/' + deviceId; } + + using job_queue_t = std::queue>; + std::array jobs; // 0 - foreground, 1 - background + QTimer rateLimiter; }; ConnectionData::ConnectionData(QUrl baseUrl) : d(std::make_unique(std::move(baseUrl))) -{} +{ + // Each lambda invocation below takes no more than one job from the + // queues (first foreground, then background) and resumes it; then + // restarts the rate limiter timer with duration 0, effectively yielding + // to the event loop and then resuming until both queues are empty. + QObject::connect(&d->rateLimiter, &QTimer::timeout, [this] { + // TODO: Consider moving out all job->sendRequest() invocations to + // a dedicated thread + d->rateLimiter.setInterval(0); + for (auto& q : d->jobs) + while (!q.empty()) { + auto& job = q.front(); + q.pop(); + if (!job || job->error() == BaseJob::Abandoned) + continue; + if (job->error() != BaseJob::Pending) { + qCCritical(MAIN) + << "Job" << job + << "is in the wrong status:" << job->status(); + Q_ASSERT(false); + job->setStatus(BaseJob::Pending); + } + job->sendRequest(); + d->rateLimiter.start(); + return; + } + qCDebug(MAIN) << d->id() << "job queues are empty"; + }); +} ConnectionData::~ConnectionData() = default; +void ConnectionData::submit(BaseJob* job) +{ + Q_ASSERT(job->error() == BaseJob::Pending); + if (!d->rateLimiter.isActive()) { + job->sendRequest(); + return; + } + d->jobs[size_t(job->isBackground())].emplace(job); + qCDebug(MAIN) << job << "queued," << d->jobs.front().size() << "+" + << d->jobs.back().size() << "total jobs in" << d->id() + << "queues"; +} + +void ConnectionData::limitRate(std::chrono::milliseconds nextCallAfter) +{ + qCDebug(MAIN) << "Jobs for" << (d->userId + "/" + d->deviceId) + << "suspended for" << nextCallAfter.count() << "ms"; + d->rateLimiter.start(nextCallAfter); +} + QByteArray ConnectionData::accessToken() const { return d->accessToken; } QUrl ConnectionData::baseUrl() const { return d->baseUrl; } diff --git a/lib/connectiondata.h b/lib/connectiondata.h index 561893df..5cd7c3c7 100644 --- a/lib/connectiondata.h +++ b/lib/connectiondata.h @@ -21,15 +21,21 @@ #include #include +#include class QNetworkAccessManager; namespace Quotient { +class BaseJob; + class ConnectionData { public: explicit ConnectionData(QUrl baseUrl); virtual ~ConnectionData(); + void submit(BaseJob* job); + void limitRate(std::chrono::milliseconds nextCallAfter); + QByteArray accessToken() const; QUrl baseUrl() const; const QString& deviceId() const; diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 621762be..0a17431c 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -31,6 +31,8 @@ #include using namespace Quotient; +using std::chrono::seconds, std::chrono::milliseconds; +using std::chrono_literals::operator""s; struct NetworkReplyDeleter : public QScopedPointerDeleteLater { static inline void cleanup(QNetworkReply* reply) @@ -43,6 +45,11 @@ struct NetworkReplyDeleter : public QScopedPointerDeleteLater { class BaseJob::Private { public: + struct JobTimeoutConfig { + seconds jobTimeout; + seconds nextRetryInterval; + }; + // 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, Data&& data, @@ -52,12 +59,14 @@ public: , requestQuery(q) , requestData(std::move(data)) , needsToken(nt) - {} + { + timer.setSingleShot(true); + retryTimer.setSingleShot(true); + } - void sendRequest(bool inBackground); - const JobTimeoutConfig& getCurrentTimeoutConfig() const; + void sendRequest(); - const ConnectionData* connection = nullptr; + ConnectionData* connection = nullptr; // Contents for the network request HttpVerb verb; @@ -67,13 +76,15 @@ public: Data requestData; bool needsToken; + bool inBackground = false; + // There's no use of QMimeType here because we don't want to match // content types against the known MIME type hierarchy; and at the same // type QMimeType is of little help with MIME type globs (`text/*` etc.) - QByteArrayList expectedContentTypes; + QByteArrayList expectedContentTypes { "application/json" }; QScopedPointer reply; - Status status = Pending; + Status status = Unprepared; QByteArray rawResponse; QUrl errorUrl; //< May contain a URL to help with some errors @@ -82,12 +93,18 @@ public: QTimer timer; QTimer retryTimer; - QVector errorStrategy = { { 90, 5 }, - { 90, 10 }, - { 120, 30 } }; - int maxRetries = errorStrategy.size(); + static constexpr std::array errorStrategy { + { { 90s, 5s }, { 90s, 10s }, { 120s, 30s } } + }; + int maxRetries = int(errorStrategy.size()); int retriesTaken = 0; + const JobTimeoutConfig& getCurrentTimeoutConfig() const + { + return errorStrategy[std::min(size_t(retriesTaken), + errorStrategy.size() - 1)]; + } + QString urlForLog() const { return reply @@ -106,9 +123,11 @@ BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, : d(new Private(verb, endpoint, query, std::move(data), needsToken)) { setObjectName(name); - setExpectedContentTypes({ "application/json" }); - d->timer.setSingleShot(true); connect(&d->timer, &QTimer::timeout, this, &BaseJob::timeout); + connect(&d->retryTimer, &QTimer::timeout, this, [this] { + setStatus(Pending); + sendRequest(); + }); } BaseJob::~BaseJob() @@ -124,10 +143,7 @@ QUrl BaseJob::requestUrl() const bool BaseJob::isBackground() const { - return d->reply - && d->reply->request() - .attribute(QNetworkRequest::BackgroundRequestAttribute) - .toBool(); + return d->inBackground; } const QString& BaseJob::apiEndpoint() const { return d->apiEndpoint; } @@ -191,7 +207,7 @@ QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QString& path, return baseUrl; } -void BaseJob::Private::sendRequest(bool inBackground) +void BaseJob::Private::sendRequest() { QNetworkRequest req { makeRequestUrl(connection->baseUrl(), apiEndpoint, requestQuery) }; @@ -223,36 +239,31 @@ void BaseJob::Private::sendRequest(bool inBackground) } } -void BaseJob::beforeStart(const ConnectionData*) {} +void BaseJob::doPrepare() {} -void BaseJob::afterStart(const ConnectionData*, QNetworkReply*) {} +void BaseJob::onSentRequest(QNetworkReply*) {} void BaseJob::beforeAbandon(QNetworkReply*) {} -void BaseJob::start(const ConnectionData* connData, bool inBackground) +void BaseJob::prepare(ConnectionData* connData, bool inBackground) { + d->inBackground = inBackground; d->connection = connData; - d->retryTimer.setSingleShot(true); - connect(&d->retryTimer, &QTimer::timeout, this, - [this, inBackground] { sendRequest(inBackground); }); - - beforeStart(connData); - if (status().good()) - sendRequest(inBackground); - if (status().good()) - afterStart(connData, d->reply.data()); - if (!status().good()) + doPrepare(); + if (status().code != Unprepared && status().code != Pending) QTimer::singleShot(0, this, &BaseJob::finishJob); + setStatus(Pending); } -void BaseJob::sendRequest(bool inBackground) +void BaseJob::sendRequest() { - emit aboutToStart(); - d->retryTimer.stop(); // In case we were counting down at the moment - qCDebug(d->logCat) << this << "sending request to" << d->apiEndpoint; - if (!d->requestQuery.isEmpty()) - qCDebug(d->logCat) << " query:" << d->requestQuery.toString(); - d->sendRequest(inBackground); + if (status().code == Abandoned) + return; + Q_ASSERT(d->connection && status().code == Pending); + qCDebug(d->logCat) << "Making request to" << d->urlForLog(); + emit aboutToSendRequest(); + d->sendRequest(); + Q_ASSERT(d->reply); connect(d->reply.data(), &QNetworkReply::finished, this, &BaseJob::gotReply); if (d->reply->isRunning()) { connect(d->reply.data(), &QNetworkReply::metaDataChanged, this, @@ -262,10 +273,12 @@ void BaseJob::sendRequest(bool inBackground) connect(d->reply.data(), &QNetworkReply::downloadProgress, this, &BaseJob::downloadProgress); d->timer.start(getCurrentTimeout()); - qCDebug(d->logCat) << this << "request has been sent"; - emit started(); + qCInfo(d->logCat).noquote() << "Request sent to" << d->urlForLog(); + onSentRequest(d->reply.data()); + emit sentRequest(); } else - qCWarning(d->logCat) << this << "request could not start"; + qCWarning(d->logCat).noquote() + << "Request could not start:" << d->urlForLog(); } void BaseJob::checkReply() { setStatus(doCheckReply(d->reply.data())); } @@ -286,13 +299,7 @@ void BaseJob::gotReply() parseError(d->reply.data(), QJsonDocument::fromJson(d->rawResponse).object())); } - - if (status().code != TooManyRequestsError) - finishJob(); - else { - stop(); - emit retryScheduled(d->retriesTaken, d->retryTimer.interval()); - } + finishJob(); } bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) @@ -416,14 +423,13 @@ BaseJob::Status BaseJob::parseError(QNetworkReply* /*reply*/, const auto errCode = errorJson.value("errcode"_ls).toString(); if (error() == TooManyRequestsError || errCode == "M_LIMIT_EXCEEDED") { QString msg = tr("Too many requests"); - auto retryInterval = errorJson.value("retry_after_ms"_ls).toInt(-1); - if (retryInterval != -1) - msg += tr(", next retry advised after %1 ms").arg(retryInterval); + int64_t retryAfterMs = errorJson.value("retry_after_ms"_ls).toInt(-1); + if (retryAfterMs >= 0) + msg += tr(", next retry advised after %1 ms").arg(retryAfterMs); else // We still have to figure some reasonable interval - retryInterval = getNextRetryInterval(); + retryAfterMs = getNextRetryMs(); - qCWarning(d->logCat) << this << "will retry in" << retryInterval << "ms"; - d->retryTimer.start(retryInterval); + d->connection->limitRate(milliseconds(retryAfterMs)); return { TooManyRequestsError, msg }; } @@ -470,19 +476,23 @@ void BaseJob::stop() void BaseJob::finishJob() { stop(); - if ((error() == NetworkError || error() == TimeoutError) + if (error() == TooManyRequests) { + emit rateLimited(); + setStatus(Pending); + d->connection->submit(this); + return; + } + if ((error() == NetworkError || error() == Timeout) && d->retriesTaken < d->maxRetries) { - // TODO: The whole retrying thing should be put to ConnectionManager + // TODO: The whole retrying thing should be put to Connection(Manager) // otherwise independently retrying jobs make a bit of notification // storm towards the UI. - const auto retryInterval = error() == TimeoutError - ? 0 - : getNextRetryInterval(); + const seconds retryIn = error() == Timeout ? 0s : getNextRetryInterval(); ++d->retriesTaken; qCWarning(d->logCat).nospace() << this << ": retry #" << d->retriesTaken - << " in " << retryInterval / 1000 << " s"; - d->retryTimer.start(retryInterval); - emit retryScheduled(d->retriesTaken, retryInterval); + << " in " << retryIn.count() << " s"; + d->retryTimer.start(retryIn); + emit retryScheduled(d->retriesTaken, milliseconds(retryIn).count()); return; } @@ -498,24 +508,35 @@ void BaseJob::finishJob() deleteLater(); } -const JobTimeoutConfig& BaseJob::Private::getCurrentTimeoutConfig() const +seconds BaseJob::getCurrentTimeout() const +{ + return d->getCurrentTimeoutConfig().jobTimeout; +} + +BaseJob::duration_ms_t BaseJob::getCurrentTimeoutMs() const +{ + return milliseconds(getCurrentTimeout()).count(); +} + +seconds BaseJob::getNextRetryInterval() const { - return errorStrategy[std::min(retriesTaken, errorStrategy.size() - 1)]; + return d->getCurrentTimeoutConfig().nextRetryInterval; } -BaseJob::duration_t BaseJob::getCurrentTimeout() const +BaseJob::duration_ms_t BaseJob::getNextRetryMs() const { - return d->getCurrentTimeoutConfig().jobTimeout * 1000; + return milliseconds(getNextRetryInterval()).count(); } -BaseJob::duration_t BaseJob::getNextRetryInterval() const +milliseconds BaseJob::timeToRetry() const { - return d->getCurrentTimeoutConfig().nextRetryInterval * 1000; + return d->retryTimer.isActive() ? d->retryTimer.remainingTimeAsDuration() + : 0s; } -BaseJob::duration_t BaseJob::millisToRetry() const +BaseJob::duration_ms_t BaseJob::millisToRetry() const { - return d->retryTimer.isActive() ? d->retryTimer.remainingTime() : 0; + return timeToRetry().count(); } int BaseJob::maxRetries() const { return d->maxRetries; } diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 9de7b49d..4dc287f8 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -34,11 +34,6 @@ class ConnectionData; enum class HttpVerb { Get, Put, Post, Delete }; -struct JobTimeoutConfig { - int jobTimeout; - int nextRetryInterval; -}; - class BaseJob : public QObject { Q_OBJECT Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) @@ -59,6 +54,7 @@ public: WarningLevel = 20, //< Warnings have codes starting from this UnexpectedResponseType = 21, UnexpectedResponseTypeWarning = UnexpectedResponseType, + Unprepared = 25, //< Initial job state is incomplete, hence warning level Abandoned = 50, //< A tiny period between abandoning and object deletion ErrorLevel = 100, //< Errors have codes starting from this NetworkError = 100, @@ -140,8 +136,6 @@ public: QString message; }; - using duration_t = int; // milliseconds - public: BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, bool needsToken = true); @@ -153,13 +147,16 @@ public: /** Current status of the job */ Status status() const; + /** Short human-friendly message on the job status */ QString statusCaption() const; + /** Get raw response body as received from the server * \param bytesAtMost return this number of leftmost bytes, or -1 * to return the entire response */ QByteArray rawData(int bytesAtMost = -1) const; + /** Get UI-friendly sample of raw data * * This is almost the same as rawData but appends the "truncated" @@ -175,17 +172,24 @@ public: * \sa status */ int error() const; + /** Error-specific message, as returned by the server */ virtual QString errorString() const; + /** A URL to help/clarify the error, if provided by the server */ QUrl errorUrl() const; int maxRetries() const; void setMaxRetries(int newMaxRetries); - Q_INVOKABLE duration_t getCurrentTimeout() const; - Q_INVOKABLE duration_t getNextRetryInterval() const; - Q_INVOKABLE duration_t millisToRetry() const; + using duration_ms_t = std::chrono::milliseconds::rep; // normally int64_t + + std::chrono::seconds getCurrentTimeout() const; + Q_INVOKABLE duration_ms_t getCurrentTimeoutMs() const; + std::chrono::seconds getNextRetryInterval() const; + Q_INVOKABLE duration_ms_t getNextRetryMs() const; + std::chrono::milliseconds timeToRetry() const; + Q_INVOKABLE duration_ms_t millisToRetry() const; friend QDebug operator<<(QDebug dbg, const BaseJob* j) { @@ -193,7 +197,7 @@ public: } public slots: - void start(const ConnectionData* connData, bool inBackground = false); + void prepare(ConnectionData* connData, bool inBackground); /** * Abandons the result of this job, arrived or unarrived. @@ -206,10 +210,10 @@ public slots: signals: /** The job is about to send a network request */ - void aboutToStart(); + void aboutToSendRequest(); /** The job has sent a network request */ - void started(); + void sentRequest(); /** The job has changed its status */ void statusChanged(Status newStatus); @@ -222,7 +226,14 @@ signals: * @param inMilliseconds the interval after which the next attempt will be * taken */ - void retryScheduled(int nextAttempt, int inMilliseconds); + void retryScheduled(int nextAttempt, duration_ms_t inMilliseconds); + + /** + * The previous network request has been rate-limited; the next attempt + * will be queued and run sometime later. Since other jobs may already + * wait in the queue, it's not possible to predict the wait time. + */ + void rateLimited(); /** * Emitted when the job is finished, in any case. It is used to notify @@ -297,9 +308,20 @@ protected: static QUrl makeRequestUrl(QUrl baseUrl, const QString& path, const QUrlQuery& query = {}); - virtual void beforeStart(const ConnectionData* connData); - virtual void afterStart(const ConnectionData* connData, - QNetworkReply* reply); + /*! Prepares the job for execution + * + * This method is called no more than once per job lifecycle, + * when it's first scheduled for execution; in particular, it is not called + * on retries. + */ + virtual void doPrepare(); + /*! Postprocessing after the network request has been sent + * + * This method is called every time the job receives a running + * QNetworkReply object from NetworkAccessManager - basically, after + * successfully sending a network request (including retries). + */ + virtual void onSentRequest(QNetworkReply*); virtual void beforeAbandon(QNetworkReply*); /** @@ -341,8 +363,7 @@ protected: * @param reply the HTTP reply from the server * @param errorJson the JSON payload describing the error */ - virtual Status parseError(QNetworkReply* reply, - const QJsonObject& errorJson); + virtual Status parseError(QNetworkReply*, const QJsonObject& errorJson); void setStatus(Status s); void setStatus(int code, QString message); @@ -359,10 +380,12 @@ protected slots: void timeout(); private slots: - void sendRequest(bool inBackground); + void sendRequest(); void checkReply(); void gotReply(); + friend class ConnectionData; // to provide access to sendRequest() + private: void stop(); void finishJob(); diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 3a03efde..4e997326 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -39,7 +39,7 @@ QString DownloadFileJob::targetFileName() const return (d->targetFile ? d->targetFile : d->tempFile)->fileName(); } -void DownloadFileJob::beforeStart(const ConnectionData*) +void DownloadFileJob::doPrepare() { if (d->targetFile && !d->targetFile->isReadable() && !d->targetFile->open(QIODevice::WriteOnly)) { @@ -57,7 +57,7 @@ void DownloadFileJob::beforeStart(const ConnectionData*) qCDebug(JOBS) << "Downloading to" << d->tempFile->fileName(); } -void DownloadFileJob::afterStart(const ConnectionData*, QNetworkReply* reply) +void DownloadFileJob::onSentRequest(QNetworkReply* reply) { connect(reply, &QNetworkReply::metaDataChanged, this, [this, reply] { if (!status().good()) diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index fa697219..b7d2d75b 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -19,8 +19,8 @@ private: class Private; QScopedPointer d; - void beforeStart(const ConnectionData*) override; - void afterStart(const ConnectionData*, QNetworkReply* reply) override; + void doPrepare() override; + void onSentRequest(QNetworkReply* reply) override; void beforeAbandon(QNetworkReply*) override; Status parseReply(QNetworkReply*) override; }; diff --git a/lib/room.cpp b/lib/room.cpp index 2e2f73c4..b0829252 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1440,7 +1440,7 @@ QString Room::Private::doSendEvent(const RoomEvent* pEvent) connection->callApi(BackgroundRequest, id, pEvent->matrixType(), txnId, pEvent->contentJson())) { - Room::connect(call, &BaseJob::started, q, [this, txnId] { + Room::connect(call, &BaseJob::sentRequest, q, [this, txnId] { auto it = q->findPendingEvent(txnId); if (it == unsyncedEvents.end()) { qWarning(EVENTS) << "Pending event for transaction" << txnId -- cgit v1.2.3 From c4a20a6d9a5f6bfbd4315450ccaff8195a3f521a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 21 Aug 2019 08:17:09 +0900 Subject: Don't use enumerator attributes Anything after enumerators is a problem for moc before Qt 5.12; so we can't use enumerator attributes before then. --- lib/jobs/basejob.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 4dc287f8..6c1b802c 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -66,8 +66,7 @@ public: IncorrectRequestError = IncorrectRequest, IncorrectResponse, IncorrectResponseError = IncorrectResponse, - JsonParseError - Q_DECL_ENUMERATOR_DEPRECATED_X("Use IncorrectResponse instead") + JsonParseError //< \deprecated Use IncorrectResponse instead = IncorrectResponse, TooManyRequests, TooManyRequestsError = TooManyRequests, -- cgit v1.2.3 From 97cac4b919735eb59493dd1cd528992ba90e611b Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 27 Aug 2019 17:22:22 +0900 Subject: More compliant 'using' for chrono_literals Compilers warn on using 'using ...::operator""s' because they think we're redefining the reserved suffix. --- lib/jobs/basejob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 0a17431c..54931c83 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -32,7 +32,7 @@ using namespace Quotient; using std::chrono::seconds, std::chrono::milliseconds; -using std::chrono_literals::operator""s; +using namespace std::chrono_literals; struct NetworkReplyDeleter : public QScopedPointerDeleteLater { static inline void cleanup(QNetworkReply* reply) -- cgit v1.2.3 From f9c0e04259be9fd3be70486bc1eb76bf8f2612fe Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 29 Sep 2019 18:05:17 +0900 Subject: Rename pieces with qmc/qmatrixclient --- .appveyor.yml | 6 +++--- lib/jobs/downloadfilejob.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/jobs') diff --git a/.appveyor.yml b/.appveyor.yml index 1dbdf237..a9f67ee4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,7 +1,7 @@ image: Visual Studio 2017 environment: - #DEPLOY_DIR: libqmatrixclient-%APPVEYOR_BUILD_VERSION% + #DEPLOY_DIR: quotient-%APPVEYOR_BUILD_VERSION% matrix: - QTDIR: C:\Qt\5.13\msvc2017_64 VCVARS: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat" @@ -30,7 +30,7 @@ build_script: #after_build: #- cmake --build build --target install -#- 7z a libqmatrixclient.zip "%DEPLOY_DIR%\" +#- 7z a quotient.zip "%DEPLOY_DIR%\" # Uncomment this to connect to the AppVeyor build worker #on_finish: @@ -39,4 +39,4 @@ build_script: test: off #artifacts: -#- path: libqmatrixclient.zip +#- path: quotient.zip diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 4e997326..3e037680 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -12,7 +12,7 @@ public: explicit Private(const QString& localFilename) : targetFile(new QFile(localFilename)) - , tempFile(new QFile(targetFile->fileName() + ".qmcdownload")) + , tempFile(new QFile(targetFile->fileName() + ".qtntdownload")) {} QScopedPointer targetFile; -- cgit v1.2.3 From 7802bcb4dd44c7523cbc687b52dd2e65b900c636 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 29 Sep 2019 18:11:35 +0900 Subject: BaseJob, urlForLog() -> dumpRequest(): include HTTP verb into log lines --- lib/jobs/basejob.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 54931c83..6a70bc40 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -105,11 +106,17 @@ public: errorStrategy.size() - 1)]; } - QString urlForLog() const + QString dumpRequest() const { - return reply - ? reply->url().toString(QUrl::RemoveQuery) - : makeRequestUrl(connection->baseUrl(), apiEndpoint).toString(); + // Thanks to C++17, std::array's type and bounds are deduced + static const auto verbs = + std::array { QStringLiteral("GET"), QStringLiteral("PUT"), + QStringLiteral("POST"), QStringLiteral("DELETE") }; + const auto verbWord = verbs.at(size_t(verb)); + return verbWord % ' ' + % (reply ? reply->url().toString(QUrl::RemoveQuery) + : makeRequestUrl(connection->baseUrl(), apiEndpoint) + .toString()); } }; @@ -260,7 +267,7 @@ void BaseJob::sendRequest() if (status().code == Abandoned) return; Q_ASSERT(d->connection && status().code == Pending); - qCDebug(d->logCat) << "Making request to" << d->urlForLog(); + qCDebug(d->logCat).noquote() << "Making" << d->dumpRequest(); emit aboutToSendRequest(); d->sendRequest(); Q_ASSERT(d->reply); @@ -273,12 +280,12 @@ void BaseJob::sendRequest() connect(d->reply.data(), &QNetworkReply::downloadProgress, this, &BaseJob::downloadProgress); d->timer.start(getCurrentTimeout()); - qCInfo(d->logCat).noquote() << "Request sent to" << d->urlForLog(); + qCInfo(d->logCat).noquote() << "Sent" << d->dumpRequest(); onSentRequest(d->reply.data()); emit sentRequest(); } else qCWarning(d->logCat).noquote() - << "Request could not start:" << d->urlForLog(); + << "Request could not start:" << d->dumpRequest(); } void BaseJob::checkReply() { setStatus(doCheckReply(d->reply.data())); } @@ -378,7 +385,8 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const const auto httpCodeHeader = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); if (!httpCodeHeader.isValid()) { - qCWarning(d->logCat) << "No valid HTTP headers from" << d->urlForLog(); + qCWarning(d->logCat).noquote() + << "No valid HTTP headers from" << d->dumpRequest(); return { NetworkError, reply->errorString() }; } @@ -386,7 +394,7 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const if (httpCode / 100 == 2) // 2xx { if (reply->isFinished()) - qCInfo(d->logCat) << httpCode << "<-" << d->urlForLog(); + qCInfo(d->logCat).noquote() << httpCode << "<-" << d->dumpRequest(); if (!checkContentType(reply->rawHeader("Content-Type"), d->expectedContentTypes)) return { UnexpectedResponseTypeWarning, @@ -394,7 +402,7 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const return NoError; } if (reply->isFinished()) - qCWarning(d->logCat) << httpCode << "<-" << d->urlForLog(); + qCWarning(d->logCat).noquote() << httpCode << "<-" << d->dumpRequest(); auto message = reply->errorString(); if (message.isEmpty()) -- cgit v1.2.3 From a2badac44d94294d9404224a55b3193c87cc201d Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 2 Oct 2019 11:36:54 +0900 Subject: More fixes for Apple not having deduction guides in stdlib --- lib/jobs/basejob.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 6a70bc40..7336fc47 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -44,6 +44,12 @@ struct NetworkReplyDeleter : public QScopedPointerDeleteLater { } }; +template +constexpr auto make_array(Ts&&... items) +{ + return std::array, sizeof...(Ts)>({items...}); +} + class BaseJob::Private { public: struct JobTimeoutConfig { @@ -108,10 +114,10 @@ public: QString dumpRequest() const { - // Thanks to C++17, std::array's type and bounds are deduced + // FIXME: use std::array {} when Apple stdlib gets deduction guides for it static const auto verbs = - std::array { QStringLiteral("GET"), QStringLiteral("PUT"), - QStringLiteral("POST"), QStringLiteral("DELETE") }; + make_array(QStringLiteral("GET"), QStringLiteral("PUT"), + QStringLiteral("POST"), QStringLiteral("DELETE")); const auto verbWord = verbs.at(size_t(verb)); return verbWord % ' ' % (reply ? reply->url().toString(QUrl::RemoveQuery) -- cgit v1.2.3 From 4623632e14ee9367e5728daf745d5323eb6a51d5 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 2 Oct 2019 12:04:32 +0900 Subject: BaseJob::Private: experiment with [[nodiscard]] --- lib/jobs/basejob.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 7336fc47..13e65188 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -106,13 +106,13 @@ public: int maxRetries = int(errorStrategy.size()); int retriesTaken = 0; - const JobTimeoutConfig& getCurrentTimeoutConfig() const + [[nodiscard]] const JobTimeoutConfig& getCurrentTimeoutConfig() const { return errorStrategy[std::min(size_t(retriesTaken), errorStrategy.size() - 1)]; } - QString dumpRequest() const + [[nodiscard]] QString dumpRequest() const { // FIXME: use std::array {} when Apple stdlib gets deduction guides for it static const auto verbs = -- cgit v1.2.3 From 8b9207d5a04386957d8eab8dd251421eaaa7c0d2 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 20 Oct 2019 19:13:56 +0900 Subject: Qualify types in signals and Q_INVOKABLEs Because https://doc.qt.io/qt-5/moc.html#limitations . For direct connections that doesn't matter but it very much does for queued ones. Along with this DirectChatsMap and IgnoredUsersList have been moved from Connection:: to Quotient::. --- lib/connection.cpp | 6 ++-- lib/connection.h | 82 ++++++++++++++++++++++++++++-------------------------- lib/jobs/basejob.h | 19 +++++++------ lib/room.h | 64 ++++++++++++++++++++++-------------------- lib/user.h | 13 +++++---- 5 files changed, 97 insertions(+), 87 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index 25f1c3f6..af85d066 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -385,7 +385,7 @@ void Connection::syncLoop(int timeout) syncLoopIteration(); // initial sync to start the loop } -QJsonObject toJson(const Connection::DirectChatsMap& directChats) +QJsonObject toJson(const DirectChatsMap& directChats) { QJsonObject json; for (auto it = directChats.begin(); it != directChats.end();) { @@ -1050,7 +1050,7 @@ QVector Connection::roomsWithTag(const QString& tagName) const return rooms; } -Connection::DirectChatsMap Connection::directChats() const +DirectChatsMap Connection::directChats() const { return d->directChats; } @@ -1117,7 +1117,7 @@ bool Connection::isIgnored(const User* user) const return ignoredUsers().contains(user->id()); } -Connection::IgnoredUsersList Connection::ignoredUsers() const +IgnoredUsersList Connection::ignoredUsers() const { const auto* event = d->unpackAccountData(); return event ? event->ignored_users() : IgnoredUsersList(); diff --git a/lib/connection.h b/lib/connection.h index 1f1d4cd5..e4109fd4 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -97,6 +97,14 @@ enum RunningPolicy { ForegroundRequest = 0x0, BackgroundRequest = 0x1 }; Q_ENUM_NS(RunningPolicy) +// Room ids, rather than room pointers, are used in the direct chat +// map types because the library keeps Invite rooms separate from +// rooms in Join and Leave state; and direct chats in account data +// are stored with no regard to their state. +using DirectChatsMap = QMultiHash; +using DirectChatUsersMap = QMultiHash; +using IgnoredUsersList = IgnoredUsersEvent::content_type; + class Connection : public QObject { Q_OBJECT @@ -115,14 +123,6 @@ class Connection : public QObject { lazyLoadingChanged) public: - // Room ids, rather than room pointers, are used in the direct chat - // map types because the library keeps Invite rooms separate from - // rooms in Join and Leave state; and direct chats in account data - // are stored with no regard to their state. - using DirectChatsMap = QMultiHash; - using DirectChatUsersMap = QMultiHash; - using IgnoredUsersList = IgnoredUsersEvent::content_type; - using UsersToDevicesToEvents = UnorderedMap>; @@ -153,7 +153,7 @@ public: * from the server. * \sa rooms, room, roomsWithTag */ - Q_INVOKABLE QVector allRooms() const; + Q_INVOKABLE QVector allRooms() const; /// Get rooms that have either of the given join state(s) /*! @@ -163,10 +163,11 @@ public: * Leave rooms from the server. * \sa allRooms, room, roomsWithTag */ - Q_INVOKABLE QVector rooms(JoinStates joinStates) const; + Q_INVOKABLE QVector + rooms(Quotient::JoinStates joinStates) const; /// Get the total number of rooms in the given join state(s) - Q_INVOKABLE int roomsCount(JoinStates joinStates) const; + Q_INVOKABLE int roomsCount(Quotient::JoinStates joinStates) const; /** Check whether the account has data of the given type * Direct chats map is not supported by this method _yet_. @@ -253,10 +254,10 @@ public: QList directChatUsers(const Room* room) const; /** Check whether a particular user is in the ignore list */ - Q_INVOKABLE bool isIgnored(const User* user) const; + Q_INVOKABLE bool isIgnored(const Quotient::User* user) const; /** Get the whole list of ignored users */ - Q_INVOKABLE IgnoredUsersList ignoredUsers() const; + Q_INVOKABLE Quotient::IgnoredUsersList ignoredUsers() const; /** Add the user to the ignore list * The change signal is emitted synchronously, without waiting @@ -264,14 +265,14 @@ public: * * \sa ignoredUsersListChanged */ - Q_INVOKABLE void addToIgnoredUsers(const User* user); + Q_INVOKABLE void addToIgnoredUsers(const Quotient::User* user); /** Remove the user from the ignore list */ /** Similar to adding, the change signal is emitted synchronously. * * \sa ignoredUsersListChanged */ - Q_INVOKABLE void removeFromIgnoredUsers(const User* user); + Q_INVOKABLE void removeFromIgnoredUsers(const Quotient::User* user); /** Get the full list of users known to this account */ QMap users() const; @@ -281,13 +282,14 @@ public: /** Get the domain name used for ids/aliases on the server */ QString domain() const; /** Find a room by its id and a mask of applicable states */ - Q_INVOKABLE Room* room(const QString& roomId, - JoinStates states = JoinState::Invite - | JoinState::Join) const; + Q_INVOKABLE Quotient::Room* + room(const QString& roomId, + Quotient::JoinStates states = JoinState::Invite | JoinState::Join) const; /** Find a room by its alias and a mask of applicable states */ - Q_INVOKABLE Room* roomByAlias(const QString& roomAlias, - JoinStates states = JoinState::Invite - | JoinState::Join) const; + Q_INVOKABLE Quotient::Room* + roomByAlias(const QString& roomAlias, + Quotient::JoinStates states = JoinState::Invite + | JoinState::Join) const; /** Update the internal map of room aliases to IDs */ /// This is used to maintain the internal index of room aliases. /// It does NOT change aliases on the server, @@ -295,15 +297,15 @@ public: void updateRoomAliases(const QString& roomId, const QString& aliasServer, const QStringList& previousRoomAliases, const QStringList& roomAliases); - Q_INVOKABLE Room* invitation(const QString& roomId) const; - Q_INVOKABLE User* user(const QString& userId); + Q_INVOKABLE Quotient::Room* invitation(const QString& roomId) const; + Q_INVOKABLE Quotient::User* user(const QString& userId); const User* user() const; User* user(); QString userId() const; QString deviceId() const; QByteArray accessToken() const; QtOlm::Account* olmAccount() const; - Q_INVOKABLE SyncJob* syncJob() const; + Q_INVOKABLE Quotient::SyncJob* syncJob() const; Q_INVOKABLE int millisToReconnect() const; Q_INVOKABLE void getTurnServers(); @@ -589,6 +591,7 @@ public slots: /** @deprecated Use callApi() or Room::postReceipt() instead */ virtual PostReceiptJob* postReceipt(Room* room, RoomEvent* event) const; + signals: /** * @deprecated @@ -622,7 +625,7 @@ signals: * * @param request - the pointer to the failed job */ - void requestFailed(BaseJob* request); + void requestFailed(Quotient::BaseJob* request); /** A network request (job) failed due to network problems * @@ -640,7 +643,7 @@ signals: void syncDone(); void syncError(QString message, QString details); - void newUser(User* user); + void newUser(Quotient::User* user); /** * \group Signals emitted on room transitions @@ -672,7 +675,7 @@ signals: */ /** A new room object has been created */ - void newRoom(Room* room); + void newRoom(Quotient::Room* room); /** A room invitation is seen for the first time * @@ -680,7 +683,7 @@ signals: * that initial sync will trigger this signal for all rooms in * Invite state. */ - void invitedRoom(Room* room, Room* prev); + void invitedRoom(Quotient::Room* room, Quotient::Room* prev); /** A joined room is seen for the first time * @@ -691,7 +694,7 @@ signals: * this room was in Invite state before, the respective object is * passed in prev (and it will be deleted shortly afterwards). */ - void joinedRoom(Room* room, Room* prev); + void joinedRoom(Quotient::Room* room, Quotient::Room* prev); /** A room has just been left * @@ -702,10 +705,10 @@ signals: * Left rooms upon initial sync (not only those that were left * right before the sync). */ - void leftRoom(Room* room, Room* prev); + void leftRoom(Quotient::Room* room, Quotient::Room* prev); /** The room object is about to be deleted */ - void aboutToDeleteRoom(Room* room); + void aboutToDeleteRoom(Quotient::Room* room); /** The room has just been created by createRoom or requestDirectChat * @@ -716,7 +719,7 @@ signals: * use directChatAvailable signal if you just need to obtain * a direct chat room. */ - void createdRoom(Room* room); + void createdRoom(Quotient::Room* room); /** The first sync for the room has been completed * @@ -726,7 +729,7 @@ signals: * signals (newRoom, joinedRoom etc.) come earlier, when the room * has just been created. */ - void loadedRoomState(Room* room); + void loadedRoomState(Quotient::Room* room); /** Account data (except direct chats) have changed */ void accountDataChanged(QString type); @@ -735,18 +738,18 @@ signals: * This signal is emitted upon any successful outcome from * requestDirectChat. */ - void directChatAvailable(Room* directChat); + void directChatAvailable(Quotient::Room* directChat); /** The list of direct chats has changed * This signal is emitted every time when the mapping of users * to direct chat rooms is changed (because of either local updates * or a different list arrived from the server). */ - void directChatsListChanged(DirectChatsMap additions, - DirectChatsMap removals); + void directChatsListChanged(Quotient::DirectChatsMap additions, + Quotient::DirectChatsMap removals); - void ignoredUsersListChanged(IgnoredUsersList additions, - IgnoredUsersList removals); + void ignoredUsersListChanged(Quotient::IgnoredUsersList additions, + Quotient::IgnoredUsersList removals); void cacheStateChanged(); void lazyLoadingChanged(); @@ -812,4 +815,5 @@ private: static user_factory_t _userFactory; }; } // namespace Quotient -Q_DECLARE_METATYPE(Quotient::Connection*) +Q_DECLARE_METATYPE(Quotient::DirectChatsMap) +Q_DECLARE_METATYPE(Quotient::IgnoredUsersList) diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 6c1b802c..c4da40f5 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -184,11 +184,11 @@ public: using duration_ms_t = std::chrono::milliseconds::rep; // normally int64_t std::chrono::seconds getCurrentTimeout() const; - Q_INVOKABLE duration_ms_t getCurrentTimeoutMs() const; + Q_INVOKABLE Quotient::BaseJob::duration_ms_t getCurrentTimeoutMs() const; std::chrono::seconds getNextRetryInterval() const; - Q_INVOKABLE duration_ms_t getNextRetryMs() const; + Q_INVOKABLE Quotient::BaseJob::duration_ms_t getNextRetryMs() const; std::chrono::milliseconds timeToRetry() const; - Q_INVOKABLE duration_ms_t millisToRetry() const; + Q_INVOKABLE Quotient::BaseJob::duration_ms_t millisToRetry() const; friend QDebug operator<<(QDebug dbg, const BaseJob* j) { @@ -215,7 +215,7 @@ signals: void sentRequest(); /** The job has changed its status */ - void statusChanged(Status newStatus); + void statusChanged(Quotient::BaseJob::Status newStatus); /** * The previous network request has failed; the next attempt will @@ -225,7 +225,8 @@ signals: * @param inMilliseconds the interval after which the next attempt will be * taken */ - void retryScheduled(int nextAttempt, duration_ms_t inMilliseconds); + void retryScheduled(int nextAttempt, + Quotient::BaseJob::duration_ms_t inMilliseconds); /** * The previous network request has been rate-limited; the next attempt @@ -251,7 +252,7 @@ signals: * * @see result, success, failure */ - void finished(BaseJob* job); + void finished(Quotient::BaseJob* job); /** * Emitted when the job is finished (except when abandoned). @@ -262,14 +263,14 @@ signals: * * @see success, failure */ - void result(BaseJob* job); + void result(Quotient::BaseJob* job); /** * Emitted together with result() in case there's no error. * * @see result, failure */ - void success(BaseJob*); + void success(Quotient::BaseJob*); /** * Emitted together with result() if there's an error. @@ -277,7 +278,7 @@ signals: * * @see result, success */ - void failure(BaseJob*); + void failure(Quotient::BaseJob*); void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); void uploadProgress(qint64 bytesSent, qint64 bytesTotal); diff --git a/lib/room.h b/lib/room.h index cded7eb9..80e305f0 100644 --- a/lib/room.h +++ b/lib/room.h @@ -181,11 +181,11 @@ public: QString avatarMediaId() const; QUrl avatarUrl() const; const Avatar& avatarObject() const; - Q_INVOKABLE JoinState joinState() const; - Q_INVOKABLE QList usersTyping() const; + Q_INVOKABLE Quotient::JoinState joinState() const; + Q_INVOKABLE QList usersTyping() const; QList membersLeft() const; - Q_INVOKABLE QList users() const; + Q_INVOKABLE QList users() const; QStringList memberNames() const; [[deprecated("Use joinedCount(), invitedCount(), totalMemberCount()")]] int memberCount() const; @@ -228,7 +228,7 @@ public: * \note The method will return a valid user regardless of * the membership. */ - Q_INVOKABLE User* user(const QString& userId) const; + Q_INVOKABLE Quotient::User* user(const QString& userId) const; /** * \brief Check the join state of a given user in this room @@ -236,16 +236,15 @@ public: * \note Banned and invited users are not tracked for now (Leave * will be returned for them). * - * \return either of Join, Leave, depending on the given - * user's state in the room + * \return Join if the user is a room member; Leave otherwise */ - Q_INVOKABLE JoinState memberJoinState(User* user) const; + Q_INVOKABLE Quotient::JoinState memberJoinState(Quotient::User* user) const; /** * Get a disambiguated name for a given user in * the context of the room */ - Q_INVOKABLE QString roomMembername(const User* u) const; + Q_INVOKABLE QString roomMembername(const Quotient::User* u) const; /** * Get a disambiguated name for a user with this id in * the context of the room @@ -274,9 +273,10 @@ public: Timeline::const_iterator syncEdge() const; /// \deprecated Use historyEdge instead rev_iter_t timelineEdge() const; - Q_INVOKABLE TimelineItem::index_t minTimelineIndex() const; - Q_INVOKABLE TimelineItem::index_t maxTimelineIndex() const; - Q_INVOKABLE bool isValidIndex(TimelineItem::index_t timelineIndex) const; + Q_INVOKABLE Quotient::TimelineItem::index_t minTimelineIndex() const; + Q_INVOKABLE Quotient::TimelineItem::index_t maxTimelineIndex() const; + Q_INVOKABLE bool + isValidIndex(Quotient::TimelineItem::index_t timelineIndex) const; rev_iter_t findInTimeline(TimelineItem::index_t index) const; rev_iter_t findInTimeline(const QString& evtId) const; @@ -414,7 +414,8 @@ public: * the event is even sent), while downloads are using * the normal event id for identifier. */ - Q_INVOKABLE FileTransferInfo fileTransferInfo(const QString& id) const; + Q_INVOKABLE Quotient::FileTransferInfo + fileTransferInfo(const QString& id) const; /// Get the URL to the actual file source in a unified way /*! @@ -438,7 +439,7 @@ public: /*! This method returns a (potentially empty) state event corresponding * to the pair of event type \p evtType and state key \p stateKey. */ - Q_INVOKABLE const StateEventBase* + Q_INVOKABLE const Quotient::StateEventBase* getCurrentState(const QString& evtType, const QString& stateKey = {}) const; template @@ -549,7 +550,8 @@ signals: /// The remote echo has arrived with the sync and will be merged /// with its local counterpart /** NB: Requires a sync loop to be emitted */ - void pendingEventAboutToMerge(RoomEvent* serverEvent, int pendingEventIndex); + void pendingEventAboutToMerge(Quotient::RoomEvent* serverEvent, + int pendingEventIndex); /// The remote and local copies of the event have been merged /** NB: Requires a sync loop to be emitted */ void pendingEventMerged(); @@ -577,21 +579,21 @@ signals: * upon the last sync * \sa Changes */ - void changed(Changes changes); + void changed(Quotient::Room::Changes changes); /** * \brief The room name, the canonical alias or other aliases changed * * Not triggered when display name changes. */ - void namesChanged(Room* room); - void displaynameAboutToChange(Room* room); - void displaynameChanged(Room* room, QString oldName); + void namesChanged(Quotient::Room* room); + void displaynameAboutToChange(Quotient::Room* room); + void displaynameChanged(Quotient::Room* room, QString oldName); void topicChanged(); void avatarChanged(); - void userAdded(User* user); - void userRemoved(User* user); - void memberAboutToRename(User* user, QString newName); - void memberRenamed(User* user); + void userAdded(Quotient::User* user); + void userRemoved(Quotient::User* user); + void memberAboutToRename(Quotient::User* user, QString newName); + void memberRenamed(Quotient::User* user); /// The list of members has changed /** Emitted no more than once per sync, this is a good signal to * for cases when some action should be done upon any change in @@ -605,7 +607,8 @@ signals: void allMembersLoaded(); void encryption(); - void joinStateChanged(JoinState oldState, JoinState newState); + void joinStateChanged(Quotient::JoinState oldState, + Quotient::JoinState newState); void typingChanged(); void highlightCountChanged(); @@ -614,11 +617,11 @@ signals: void displayedChanged(bool displayed); void firstDisplayedEventChanged(); void lastDisplayedEventChanged(); - void lastReadEventChanged(User* user); + void lastReadEventChanged(Quotient::User* user); void readMarkerMoved(QString fromEventId, QString toEventId); - void readMarkerForUserMoved(User* user, QString fromEventId, + void readMarkerForUserMoved(Quotient::User* user, QString fromEventId, QString toEventId); - void unreadMessagesChanged(Room* room); + void unreadMessagesChanged(Quotient::Room* room); void accountDataAboutToChange(QString type); void accountDataChanged(QString type); @@ -626,7 +629,8 @@ signals: void tagsChanged(); void updatedEvent(QString eventId); - void replacedEvent(const RoomEvent* newEvent, const RoomEvent* oldEvent); + void replacedEvent(const Quotient::RoomEvent* newEvent, + const Quotient::RoomEvent* oldEvent); void newFileTransfer(QString id, QUrl localFile); void fileTransferProgress(QString id, qint64 progress, qint64 total); @@ -634,18 +638,18 @@ signals: void fileTransferFailed(QString id, QString errorMessage = {}); void fileTransferCancelled(QString id); - void callEvent(Room* room, const RoomEvent* event); + void callEvent(Quotient::Room* room, const Quotient::RoomEvent* event); /// The room's version stability may have changed void stabilityUpdated(QString recommendedDefault, QStringList stableVersions); /// This room has been upgraded and won't receive updates any more - void upgraded(QString serverMessage, Room* successor); + void upgraded(QString serverMessage, Quotient::Room* successor); /// An attempted room upgrade has failed void upgradeFailed(QString errorMessage); /// The room is about to be deleted - void beforeDestruction(Room*); + void beforeDestruction(Quotient::Room*); protected: virtual Changes processStateEvent(const RoomEvent& e); diff --git a/lib/user.h b/lib/user.h index c9e3dbc1..28ec841b 100644 --- a/lib/user.h +++ b/lib/user.h @@ -107,9 +107,10 @@ public: qreal hueF() const; const Avatar& avatarObject(const Room* room = nullptr) const; - Q_INVOKABLE QImage avatar(int dimension, const Room* room = nullptr); + Q_INVOKABLE QImage avatar(int dimension, + const Quotient::Room* room = nullptr); Q_INVOKABLE QImage avatar(int requestedWidth, int requestedHeight, - const Room* room = nullptr); + const Quotient::Room* room = nullptr); QImage avatar(int width, int height, const Room* room, const Avatar::get_callback_t& callback); @@ -145,9 +146,10 @@ public slots: signals: void nameAboutToChange(QString newName, QString oldName, - const Room* roomContext); - void nameChanged(QString newName, QString oldName, const Room* roomContext); - void avatarChanged(User* user, const Room* roomContext); + const Quotient::Room* roomContext); + void nameChanged(QString newName, QString oldName, + const Quotient::Room* roomContext); + void avatarChanged(Quotient::User* user, const Quotient::Room* roomContext); private slots: void updateName(const QString& newName, const Room* room = nullptr); @@ -161,4 +163,3 @@ private: QScopedPointer d; }; } // namespace Quotient -Q_DECLARE_METATYPE(Quotient::User*) -- cgit v1.2.3 From 5937127b73a82fc86f6546397373ce9dbaf4e560 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 19 Nov 2019 17:57:41 +0900 Subject: BaseJob: Don't send accessToken if not needed; send again on 401 The first part closes #358; the second part is a workaround for non-standard cases when endpoints without security by the spec turn out to be secured (in particular, the case of authenticating media servers). --- lib/connection.cpp | 9 ++++--- lib/connectiondata.cpp | 12 +++++++++ lib/connectiondata.h | 2 ++ lib/jobs/basejob.cpp | 66 ++++++++++++++++++++++++++++++-------------------- lib/jobs/basejob.h | 8 +++++- 5 files changed, 66 insertions(+), 31 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index 5ee7e84e..c830557c 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -343,7 +343,8 @@ void Connection::logout() } const auto* job = callApi(); connect(job, &LogoutJob::finished, this, [this, job, syncWasRunning] { - if (job->status().good() || job->error() == BaseJob::ContentAccessError) { + if (job->status().good() || job->error() == BaseJob::Unauthorised + || job->error() == BaseJob::ContentAccessError) { if (d->syncLoopConnection) disconnect(d->syncLoopConnection); d->data->setToken({}); @@ -380,9 +381,9 @@ void Connection::sync(int timeout) }); connect(job, &SyncJob::failure, this, [this, job] { d->syncJob = nullptr; - if (job->error() == BaseJob::ContentAccessError) { - qCWarning(SYNCJOB) << "Sync job failed with ContentAccessError - " - "login expired?"; + if (job->error() == BaseJob::Unauthorised) { + qCWarning(SYNCJOB) + << "Sync job failed with Unauthorised - login expired?"; emit loginError(job->errorString(), job->rawDataSample()); } else emit syncError(job->errorString(), job->rawDataSample()); diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index cbc36420..e2a0f06f 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -42,6 +42,7 @@ public: QString lastEvent; QString userId; QString deviceId; + std::vector needToken; mutable unsigned int txnCounter = 0; const qint64 txnBase = QDateTime::currentMSecsSinceEpoch(); @@ -143,6 +144,12 @@ const QString& ConnectionData::deviceId() const { return d->deviceId; } const QString& ConnectionData::userId() const { return d->userId; } +bool ConnectionData::needsToken(const QString& requestName) const +{ + return std::find(d->needToken.cbegin(), d->needToken.cend(), requestName) + != d->needToken.cend(); +} + void ConnectionData::setDeviceId(const QString& deviceId) { d->deviceId = deviceId; @@ -150,6 +157,11 @@ void ConnectionData::setDeviceId(const QString& deviceId) void ConnectionData::setUserId(const QString& userId) { d->userId = userId; } +void ConnectionData::setNeedsToken(const QString& requestName) +{ + d->needToken.push_back(requestName); +} + QString ConnectionData::lastEvent() const { return d->lastEvent; } void ConnectionData::setLastEvent(QString identifier) diff --git a/lib/connectiondata.h b/lib/connectiondata.h index b367c977..000099d1 100644 --- a/lib/connectiondata.h +++ b/lib/connectiondata.h @@ -40,6 +40,7 @@ public: QUrl baseUrl() const; const QString& deviceId() const; const QString& userId() const; + bool needsToken(const QString& requestName) const; QNetworkAccessManager* nam() const; void setBaseUrl(QUrl baseUrl); @@ -50,6 +51,7 @@ public: void setPort(int port); void setDeviceId(const QString& deviceId); void setUserId(const QString& userId); + void setNeedsToken(const QString& requestName); QString lastEvent() const; void setLastEvent(QString identifier); diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 13e65188..7f558685 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -226,8 +226,9 @@ void BaseJob::Private::sendRequest() requestQuery) }; if (!requestHeaders.contains("Content-Type")) req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - req.setRawHeader("Authorization", - QByteArray("Bearer ") + connection->accessToken()); + if (needsToken) + req.setRawHeader("Authorization", + QByteArray("Bearer ") + connection->accessToken()); req.setAttribute(QNetworkRequest::BackgroundRequestAttribute, inBackground); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); req.setMaximumRedirectsAllowed(10); @@ -274,6 +275,7 @@ void BaseJob::sendRequest() return; Q_ASSERT(d->connection && status().code == Pending); qCDebug(d->logCat).noquote() << "Making" << d->dumpRequest(); + d->needsToken |= d->connection->needsToken(objectName()); emit aboutToSendRequest(); d->sendRequest(); Q_ASSERT(d->reply); @@ -341,32 +343,32 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) return false; } -BaseJob::Status BaseJob::Status::fromHttpCode(int httpCode, QString msg) +BaseJob::StatusCode BaseJob::Status::fromHttpCode(int httpCode) { + if (httpCode / 10 == 41) // 41x errors + return httpCode == 410 ? IncorrectRequestError : NotFoundError; + switch (httpCode) { + case 401: + return Unauthorised; // clang-format off - return { [httpCode]() -> StatusCode { - if (httpCode / 10 == 41) // 41x errors - return httpCode == 410 ? IncorrectRequestError : NotFoundError; - switch (httpCode) { - case 401: case 403: case 407: - return ContentAccessError; - case 404: - return NotFoundError; - case 400: case 405: case 406: case 426: case 428: case 505: - case 494: // Unofficial nginx "Request header too large" - case 497: // Unofficial nginx "HTTP request sent to HTTPS port" - return IncorrectRequestError; - case 429: - return TooManyRequestsError; - case 501: case 510: - return RequestNotImplementedError; - case 511: - return NetworkAuthRequiredError; - default: - return NetworkError; - } - }(), std::move(msg) }; - // clang-format on + case 403: case 407: // clang-format on + return ContentAccessError; + case 404: + return NotFoundError; + // clang-format off + case 400: case 405: case 406: case 426: case 428: case 505: // clang-format on + case 494: // Unofficial nginx "Request header too large" + case 497: // Unofficial nginx "HTTP request sent to HTTPS port" + return IncorrectRequestError; + case 429: + return TooManyRequestsError; + case 501: case 510: + return RequestNotImplementedError; + case 511: + return NetworkAuthRequiredError; + default: + return NetworkError; + } } QDebug BaseJob::Status::dumpToLog(QDebug dbg) const @@ -496,6 +498,16 @@ void BaseJob::finishJob() d->connection->submit(this); return; } + if (error() == Unauthorised && !d->needsToken + && !d->connection->accessToken().isEmpty()) { + // Rerun with access token (extension of the spec while + // https://github.com/matrix-org/matrix-doc/issues/701 is pending) + d->connection->setNeedsToken(objectName()); + qCWarning(d->logCat) << this << "re-running with authentication"; + emit retryScheduled(d->retriesTaken, 0); + setStatus(Pending); + sendRequest(); + } if ((error() == NetworkError || error() == Timeout) && d->retriesTaken < d->maxRetries) { // TODO: The whole retrying thing should be put to Connection(Manager) @@ -596,6 +608,8 @@ QString BaseJob::statusCaption() const return tr("Network problems"); case TimeoutError: return tr("Request timed out"); + case Unauthorised: + return tr("Unauthorised request"); case ContentAccessError: return tr("Access error"); case NotFoundError: diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index c4da40f5..ecbec74a 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -60,6 +60,7 @@ public: NetworkError = 100, Timeout, TimeoutError = Timeout, + Unauthorised, ContentAccessError, NotFoundError, IncorrectRequest, @@ -113,7 +114,12 @@ public: struct Status { Status(StatusCode c) : code(c) {} Status(int c, QString m) : code(c), message(std::move(m)) {} - static Status fromHttpCode(int httpCode, QString msg = {}); + + static StatusCode fromHttpCode(int httpCode); + static Status fromHttpCode(int httpCode, QString msg) + { + return { fromHttpCode(httpCode), std::move(msg) }; + } bool good() const { return code < ErrorLevel; } QDebug dumpToLog(QDebug dbg) const; -- cgit v1.2.3 From 7b5f65ba64ae4df54919336f4beec19493d1b5ee Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 11 Dec 2019 20:26:39 +0300 Subject: BaseJob::StatusCode: offset first error from ErrorLevel Q_ENUM seems to resolve int to the first enum identifier with that value so NetworkError == ErrorLevel looks confusing in logs. --- lib/jobs/basejob.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index ecbec74a..b4c4c136 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -57,7 +57,7 @@ public: Unprepared = 25, //< Initial job state is incomplete, hence warning level Abandoned = 50, //< A tiny period between abandoning and object deletion ErrorLevel = 100, //< Errors have codes starting from this - NetworkError = 100, + NetworkError = 101, Timeout, TimeoutError = Timeout, Unauthorised, -- cgit v1.2.3 From 1ffa6b96adeba8c1a00a0a32112c8b0aaeb2350e Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 12 Dec 2019 19:11:16 +0300 Subject: RequestData: optimise fromData() and preopen the buffer It was just a coincidence that QBuffer allowed reading from it without being isReadable() at the moment of starting a job. --- lib/jobs/requestdata.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/requestdata.cpp b/lib/jobs/requestdata.cpp index 0c70f085..cec15954 100644 --- a/lib/jobs/requestdata.cpp +++ b/lib/jobs/requestdata.cpp @@ -11,9 +11,8 @@ using namespace Quotient; auto fromData(const QByteArray& data) { auto source = std::make_unique(); - source->open(QIODevice::WriteOnly); - source->write(data); - source->close(); + source->setData(data); + source->open(QIODevice::ReadOnly); return source; } -- cgit v1.2.3 From ec3ddd6930991b04d13cdb12720f141482f9a6eb Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 12 Dec 2019 19:37:09 +0300 Subject: Move FileError definition from DownloadFileJob to BaseJob Will use it in BaseJob in a later commit. --- lib/jobs/basejob.h | 1 + lib/jobs/downloadfilejob.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index b4c4c136..e708ba8d 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -82,6 +82,7 @@ public: UserConsentRequiredError = UserConsentRequired, CannotLeaveRoom, UserDeactivated, + FileError, UserDefinedError = 256 }; Q_ENUM(StatusCode) diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index b7d2d75b..06dc145c 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -5,8 +5,6 @@ namespace Quotient { class DownloadFileJob : public GetContentJob { public: - enum { FileError = BaseJob::UserDefinedError + 1 }; - using GetContentJob::makeRequestUrl; static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri); -- cgit v1.2.3 From f6505a541fc0a2e02f9c79496488121a3e46fb01 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 12 Dec 2019 19:47:07 +0300 Subject: BaseJob: prepare() -> initiate() + refactoring around it * BaseJob::initiate() now calls ConnectionData::submit() without relying on Connection to do that * ConnectionData::submit() is now the only site where a job enters Pending state * No more shortcuts to BaseJob::sendRequest(), even retries are sent through the ConnectionData submission queue * Additional validation in BaseJob::initiate() that the request data device is actually open (because QtNetwork API officially requires that, even if you can get away passing a closed QBuffer to it) --- lib/connection.cpp | 3 +-- lib/connectiondata.cpp | 2 +- lib/jobs/basejob.cpp | 28 +++++++++++++++++++--------- lib/jobs/basejob.h | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index 999f4382..c13568f1 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -1414,8 +1414,7 @@ void Connection::setLazyLoading(bool newValue) void Connection::run(BaseJob* job, RunningPolicy runningPolicy) const { connect(job, &BaseJob::failure, this, &Connection::requestFailed); - job->prepare(d->data.get(), runningPolicy & BackgroundRequest); - d->data->submit(job); + job->initiate(d->data.get(), runningPolicy & BackgroundRequest); } void Connection::getTurnServers() diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index 94cab29b..753fa3ad 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -94,7 +94,7 @@ ConnectionData::~ConnectionData() void ConnectionData::submit(BaseJob* job) { - Q_ASSERT(job->error() == BaseJob::Pending); + job->setStatus(BaseJob::Pending); if (!d->rateLimiter.isActive()) { job->sendRequest(); return; diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 7f558685..4653e58a 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -138,8 +138,7 @@ BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, setObjectName(name); connect(&d->timer, &QTimer::timeout, this, &BaseJob::timeout); connect(&d->retryTimer, &QTimer::timeout, this, [this] { - setStatus(Pending); - sendRequest(); + d->connection->submit(this); }); } @@ -259,14 +258,27 @@ void BaseJob::onSentRequest(QNetworkReply*) {} void BaseJob::beforeAbandon(QNetworkReply*) {} -void BaseJob::prepare(ConnectionData* connData, bool inBackground) +void BaseJob::initiate(ConnectionData* connData, bool inBackground) { + Q_ASSERT(connData != nullptr); + d->inBackground = inBackground; d->connection = connData; doPrepare(); - if (status().code != Unprepared && status().code != Pending) + + if ((d->verb == HttpVerb::Post || d->verb == HttpVerb::Put) + && !d->requestData.source()->isReadable()) { + setStatus(FileError, "Request data not ready"); + } + Q_ASSERT(status().code != Pending); // doPrepare() must NOT set this + if (status().code == Unprepared) { + d->connection->submit(this); + } else { + qDebug(d->logCat).noquote() + << "Request failed preparation and won't be sent:" + << d->dumpRequest(); QTimer::singleShot(0, this, &BaseJob::finishJob); - setStatus(Pending); + } } void BaseJob::sendRequest() @@ -292,7 +304,7 @@ void BaseJob::sendRequest() onSentRequest(d->reply.data()); emit sentRequest(); } else - qCWarning(d->logCat).noquote() + qCCritical(d->logCat).noquote() << "Request could not start:" << d->dumpRequest(); } @@ -494,7 +506,6 @@ void BaseJob::finishJob() stop(); if (error() == TooManyRequests) { emit rateLimited(); - setStatus(Pending); d->connection->submit(this); return; } @@ -505,8 +516,7 @@ void BaseJob::finishJob() d->connection->setNeedsToken(objectName()); qCWarning(d->logCat) << this << "re-running with authentication"; emit retryScheduled(d->retriesTaken, 0); - setStatus(Pending); - sendRequest(); + d->connection->submit(this); } if ((error() == NetworkError || error() == Timeout) && d->retriesTaken < d->maxRetries) { diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index e708ba8d..c8046e9e 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -203,7 +203,7 @@ public: } public slots: - void prepare(ConnectionData* connData, bool inBackground); + void initiate(ConnectionData* connData, bool inBackground); /** * Abandons the result of this job, arrived or unarrived. -- cgit v1.2.3 From 38f45066a2304935550e2c5b6be21a9744f66bf1 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 12 Dec 2019 20:57:41 +0300 Subject: BaseJob::initiate(): fix nullptr dereferencing --- lib/jobs/basejob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 4653e58a..68adeaf6 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -267,7 +267,7 @@ void BaseJob::initiate(ConnectionData* connData, bool inBackground) doPrepare(); if ((d->verb == HttpVerb::Post || d->verb == HttpVerb::Put) - && !d->requestData.source()->isReadable()) { + && d->requestData.source() && !d->requestData.source()->isReadable()) { setStatus(FileError, "Request data not ready"); } Q_ASSERT(status().code != Pending); // doPrepare() must NOT set this -- cgit v1.2.3 From ecc31fc7a615faa516a03c07ebd96d0d2494c315 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 30 Mar 2020 19:12:06 +0200 Subject: BaseJob: shutdown timers on abandoning and destruction A part of the fix for #398. --- lib/jobs/basejob.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 68adeaf6..8b63f7e8 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -145,6 +145,7 @@ BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, BaseJob::~BaseJob() { stop(); + d->retryTimer.stop(); // See #398 qCDebug(d->logCat) << this << "destroyed"; } @@ -686,6 +687,8 @@ void BaseJob::setStatus(int code, QString message) void BaseJob::abandon() { beforeAbandon(d->reply ? d->reply.data() : nullptr); + d->timer.stop(); + d->retryTimer.stop(); // In case abandon() was called between retries setStatus(Abandoned); if (d->reply) d->reply->disconnect(this); -- cgit v1.2.3 From d38516e4e123474876e4fc7f850fe321ec5ccb54 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 30 Mar 2020 19:12:40 +0200 Subject: BaseJob: check the connection even harder --- lib/jobs/basejob.cpp | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 8b63f7e8..65668521 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -234,6 +234,7 @@ void BaseJob::Private::sendRequest() req.setMaximumRedirectsAllowed(10); req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); req.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); + Q_ASSERT(req.url().isValid()); for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) req.setRawHeader(it.key(), it.value()); @@ -261,25 +262,31 @@ void BaseJob::beforeAbandon(QNetworkReply*) {} void BaseJob::initiate(ConnectionData* connData, bool inBackground) { - Q_ASSERT(connData != nullptr); + if (connData && connData->baseUrl().isValid()) { + d->inBackground = inBackground; + d->connection = connData; + doPrepare(); - d->inBackground = inBackground; - d->connection = connData; - doPrepare(); - - if ((d->verb == HttpVerb::Post || d->verb == HttpVerb::Put) - && d->requestData.source() && !d->requestData.source()->isReadable()) { - setStatus(FileError, "Request data not ready"); - } - Q_ASSERT(status().code != Pending); // doPrepare() must NOT set this - if (status().code == Unprepared) { - d->connection->submit(this); - } else { - qDebug(d->logCat).noquote() + if ((d->verb == HttpVerb::Post || d->verb == HttpVerb::Put) + && d->requestData.source() && !d->requestData.source()->isReadable()) { + setStatus(FileError, "Request data not ready"); + } + Q_ASSERT(status().code != Pending); // doPrepare() must NOT set this + if (status().code == Unprepared) { + d->connection->submit(this); + return; + } + qCWarning(d->logCat).noquote() << "Request failed preparation and won't be sent:" << d->dumpRequest(); - QTimer::singleShot(0, this, &BaseJob::finishJob); + } else { + qCCritical(d->logCat) + << "Developers, ensure the Connection is valid before using it"; + Q_ASSERT(false); + setStatus(IncorrectRequestError, tr("Invalid server connection")); } + // The status is no good, finalise + QTimer::singleShot(0, this, &BaseJob::finishJob); } void BaseJob::sendRequest() @@ -338,7 +345,7 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) // ignore possible appendixes of the content type const auto ctype = type.split(';').front(); - for (const auto& pattern : patterns) { + for (const auto& pattern: patterns) { if (pattern.startsWith('*') || ctype == pattern) // Fast lane return true; -- cgit v1.2.3 From 3d04593f513916ee6e4fcb1ec2d18afa7b76590a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 5 Apr 2020 15:48:31 +0200 Subject: RequestData: create empty QByteArray by default May fix #380. Also: remove explicit copying disablers, the unique_ptr<> member disables copying just fine. --- lib/jobs/requestdata.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/requestdata.h b/lib/jobs/requestdata.h index 020d5ef2..9cb5ecaf 100644 --- a/lib/jobs/requestdata.h +++ b/lib/jobs/requestdata.h @@ -18,9 +18,10 @@ #pragma once +#include + #include -class QByteArray; class QJsonObject; class QJsonArray; class QJsonDocument; @@ -35,14 +36,11 @@ namespace Quotient { */ class RequestData { public: - RequestData() = default; - RequestData(const QByteArray& a); + RequestData(const QByteArray& a = {}); RequestData(const QJsonObject& jo); RequestData(const QJsonArray& ja); RequestData(QIODevice* source) : _source(std::unique_ptr(source)) {} - RequestData(const RequestData&) = delete; - RequestData& operator=(const RequestData&) = delete; RequestData(RequestData&&) = default; RequestData& operator=(RequestData&&) = default; ~RequestData(); -- cgit v1.2.3 From ab9996fc62767d61da779d869e68bfc966ffce8f Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 6 Apr 2020 20:53:26 +0200 Subject: CMakeLists: install header files to a subdirectory This is a Quotient part of #328 fix; QtOlm part is pending. --- 3rdparty/libQtOlm | 2 +- CMakeLists.txt | 43 +++++++++++++++++++++++++------------------ lib/jobs/basejob.cpp | 2 +- 3 files changed, 27 insertions(+), 20 deletions(-) (limited to 'lib/jobs') diff --git a/3rdparty/libQtOlm b/3rdparty/libQtOlm index f2d8e235..dc81e9f1 160000 --- a/3rdparty/libQtOlm +++ b/3rdparty/libQtOlm @@ -1 +1 @@ -Subproject commit f2d8e235a4af0625fdedaaf727fef5d51293bf1b +Subproject commit dc81e9f19021821eb07d43db555e5ae1ac3cf5b1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 46ce64c5..6fac4672 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,25 @@ option(${PROJECT_NAME}_INSTALL_TESTS "install quotest (former qmc-example) appli option(${PROJECT_NAME}_ENABLE_E2EE "end-to-end encryption (E2EE) support" OFF) include(CheckCXXCompilerFlag) -if (NOT WIN32) +if (WIN32) + if (NOT CMAKE_INSTALL_LIBDIR) + set(CMAKE_INSTALL_LIBDIR ".") + endif () + + if (NOT CMAKE_INSTALL_BINDIR) + set(CMAKE_INSTALL_BINDIR ".") + endif () + + if (NOT CMAKE_INSTALL_INCLUDEDIR) + set(CMAKE_INSTALL_INCLUDEDIR "include") + endif () +else() include(GNUInstallDirs) -endif(NOT WIN32) + set(INCLUDEDIR_INIT ${PROJECT_NAME}) +endif(WIN32) +set(${PROJECT_NAME}_INSTALL_INCLUDEDIR + "${CMAKE_INSTALL_INCLUDEDIR}/${INCLUDEDIR_INIT}" CACHE PATH + "directory to install ${PROJECT_NAME} include files to") # Instruct CMake to run moc automatically when needed. set(CMAKE_AUTOMOC ON) @@ -27,18 +43,6 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) "MinSizeRel" "RelWithDebInfo") endif() -if (NOT CMAKE_INSTALL_LIBDIR) - set(CMAKE_INSTALL_LIBDIR ".") -endif() - -if (NOT CMAKE_INSTALL_BINDIR) - set(CMAKE_INSTALL_BINDIR ".") -endif() - -if (NOT CMAKE_INSTALL_INCLUDEDIR) - set(CMAKE_INSTALL_INCLUDEDIR "include") -endif() - if (MSVC) add_compile_options(/EHsc /W4 /wd4100 /wd4127 /wd4242 /wd4244 /wd4245 /wd4267 /wd4365 /wd4456 /wd4459 @@ -67,6 +71,8 @@ if (${PROJECT_NAME}_ENABLE_E2EE) endif () endif () if (NOT USE_INTREE_LIBQOLM) + set(SAVED_CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) + set(CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) find_package(QtOlm 0.1.0 REQUIRED) if (NOT QtOlm_FOUND) message( WARNING "libQtOlm not found; configuration will most likely fail.") @@ -76,7 +82,7 @@ if (${PROJECT_NAME}_ENABLE_E2EE) endif () endif () else () - message( WARNING "End-to-end encryption (E2EE) support is turned off.") + message( STATUS "End-to-end encryption (E2EE) support is turned off.") endif () if (GTAD_PATH) @@ -102,6 +108,7 @@ if (CMAKE_BUILD_TYPE) endif(CMAKE_BUILD_TYPE) message( STATUS "Using compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}" ) message( STATUS "Install Prefix: ${CMAKE_INSTALL_PREFIX}" ) +message( STATUS " Header files will be installed to ${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_INCLUDEDIR}" ) message( STATUS "Using Qt ${Qt5_VERSION} at ${Qt5_Prefix}" ) if (ABS_API_DEF_PATH AND ABS_GTAD_PATH) message( STATUS "Generating API stubs enabled (use --target update-api)" ) @@ -248,7 +255,7 @@ target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) target_include_directories(${PROJECT_NAME} PUBLIC $ - $ + $ ) if (${PROJECT_NAME}_ENABLE_E2EE) target_link_libraries(${PROJECT_NAME} QtOlm) @@ -267,9 +274,9 @@ configure_file(${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + INCLUDES DESTINATION ${${PROJECT_NAME}_INSTALL_INCLUDEDIR} ) -install(DIRECTORY lib/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +install(DIRECTORY lib/ DESTINATION ${${PROJECT_NAME}_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h") include(CMakePackageConfigHelpers) diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 65668521..4ede073f 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -232,7 +232,7 @@ void BaseJob::Private::sendRequest() req.setAttribute(QNetworkRequest::BackgroundRequestAttribute, inBackground); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); req.setMaximumRedirectsAllowed(10); - req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); +// req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); req.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); Q_ASSERT(req.url().isValid()); for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) -- cgit v1.2.3 From a8572345e7a30c96b8ede47e95af65ff2cdef86c Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 6 Apr 2020 21:20:32 +0200 Subject: Revert changes accidentally sneaked in with the previous commit --- 3rdparty/libQtOlm | 2 +- lib/jobs/basejob.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/jobs') diff --git a/3rdparty/libQtOlm b/3rdparty/libQtOlm index dc81e9f1..f2d8e235 160000 --- a/3rdparty/libQtOlm +++ b/3rdparty/libQtOlm @@ -1 +1 @@ -Subproject commit dc81e9f19021821eb07d43db555e5ae1ac3cf5b1 +Subproject commit f2d8e235a4af0625fdedaaf727fef5d51293bf1b diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 4ede073f..65668521 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -232,7 +232,7 @@ void BaseJob::Private::sendRequest() req.setAttribute(QNetworkRequest::BackgroundRequestAttribute, inBackground); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); req.setMaximumRedirectsAllowed(10); -// req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); req.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); Q_ASSERT(req.url().isValid()); for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) -- cgit v1.2.3 From fc2614d88ccc3c938ea69fd6a8f4978bc9663e16 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 6 Apr 2020 21:58:26 +0200 Subject: BaseJob: disable pipelining Longer running on RHEL/CentOS 8 leads to crashes that no more occur with disabled pipelining. --- lib/jobs/basejob.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 65668521..dfc3d3dd 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -232,7 +232,9 @@ void BaseJob::Private::sendRequest() req.setAttribute(QNetworkRequest::BackgroundRequestAttribute, inBackground); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); req.setMaximumRedirectsAllowed(10); - req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + // Pipelining doesn't fly quite well with SSL, occasionally crashing at + // what seems like an attempt to write to a closed channel. +// req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); req.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); Q_ASSERT(req.url().isValid()); for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) -- cgit v1.2.3 From 160b11bdfe32c9983fe5f34eafa783148b2decbe Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 7 Apr 2020 16:14:21 +0200 Subject: BaseJob: don't finish and re-try at the same time Due to a missing return statement, a retry with auth case led to the job being finished and pending at the same time, with no good consequences. --- lib/jobs/basejob.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index dfc3d3dd..7cddc343 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -527,6 +527,7 @@ void BaseJob::finishJob() qCWarning(d->logCat) << this << "re-running with authentication"; emit retryScheduled(d->retriesTaken, 0); d->connection->submit(this); + return; } if ((error() == NetworkError || error() == Timeout) && d->retriesTaken < d->maxRetries) { @@ -542,6 +543,8 @@ void BaseJob::finishJob() return; } + Q_ASSERT(status().code != Pending); + // Notify those interested in any completion of the job including abandon() emit finished(this); -- cgit v1.2.3 From 4088ab4572c5b7cde603aeb1a89bc4515833beaf Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 14 Apr 2020 14:21:26 +0200 Subject: BaseJob::makeRequestUrl(): even more tolerance to slash separators The code is really defensive now, making sure there's exactly one slash between the base path and the endpoint. It's still very conservative about the path composition otherwise (no normalisation etc.). --- lib/connection.cpp | 2 +- lib/jobs/basejob.cpp | 7 +++++-- lib/jobs/basejob.h | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index 1c63adeb..41ecee67 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -280,7 +280,7 @@ void Connection::resolveServer(const QString& mxid) return; } qCInfo(MAIN) << ".well-known URL for" << maybeBaseUrl.host() - << "is" << baseUrl.authority(); + << "is" << baseUrl.toString(); setHomeserver(baseUrl); } else { qCInfo(MAIN) << "No .well-known file, using" << maybeBaseUrl diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 7cddc343..8e1a63aa 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -212,8 +212,11 @@ QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QString& path, const QUrlQuery& query) { auto pathBase = baseUrl.path(); - if (!pathBase.endsWith('/') && !path.startsWith('/')) - pathBase.push_back('/'); + // QUrl::adjusted(QUrl::StripTrailingSlashes) doesn't help with root '/' + while (pathBase.endsWith('/')) + pathBase.chop(1); + if (!path.startsWith('/')) // Normally API files do start with '/' + pathBase.push_back('/'); // so this shouldn't be needed these days baseUrl.setPath(pathBase + path, QUrl::TolerantMode); baseUrl.setQuery(query); diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index c8046e9e..2049f59c 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -308,9 +308,9 @@ protected: void setExpectedContentTypes(const QByteArrayList& contentTypes); /** Construct a URL out of baseUrl, path and query - * The function automatically adds '/' between baseUrl's path and - * \p path if necessary. The query component of \p baseUrl - * is ignored. + * + * 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, const QUrlQuery& query = {}); -- cgit v1.2.3 From 3c2f98375c4b82e7f1ee8a0f5d477e55c8685075 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 12 May 2020 21:23:56 +0200 Subject: basejob.cpp: nitpicks from clang-format --- lib/jobs/basejob.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 8e1a63aa..470250bf 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -149,15 +149,9 @@ BaseJob::~BaseJob() qCDebug(d->logCat) << this << "destroyed"; } -QUrl BaseJob::requestUrl() const -{ - return d->reply ? d->reply->url() : QUrl(); -} +QUrl BaseJob::requestUrl() const { return d->reply ? d->reply->url() : QUrl(); } -bool BaseJob::isBackground() const -{ - return d->inBackground; -} +bool BaseJob::isBackground() const { return d->inBackground; } const QString& BaseJob::apiEndpoint() const { return d->apiEndpoint; } @@ -215,7 +209,7 @@ QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QString& path, // QUrl::adjusted(QUrl::StripTrailingSlashes) doesn't help with root '/' while (pathBase.endsWith('/')) pathBase.chop(1); - if (!path.startsWith('/')) // Normally API files do start with '/' + if (!path.startsWith('/')) // Normally API files do start with '/' pathBase.push_back('/'); // so this shouldn't be needed these days baseUrl.setPath(pathBase + path, QUrl::TolerantMode); @@ -259,11 +253,11 @@ void BaseJob::Private::sendRequest() } } -void BaseJob::doPrepare() {} +void BaseJob::doPrepare() { } -void BaseJob::onSentRequest(QNetworkReply*) {} +void BaseJob::onSentRequest(QNetworkReply*) { } -void BaseJob::beforeAbandon(QNetworkReply*) {} +void BaseJob::beforeAbandon(QNetworkReply*) { } void BaseJob::initiate(ConnectionData* connData, bool inBackground) { @@ -273,7 +267,8 @@ void BaseJob::initiate(ConnectionData* connData, bool inBackground) doPrepare(); if ((d->verb == HttpVerb::Post || d->verb == HttpVerb::Put) - && d->requestData.source() && !d->requestData.source()->isReadable()) { + && d->requestData.source() + && !d->requestData.source()->isReadable()) { setStatus(FileError, "Request data not ready"); } Q_ASSERT(status().code != Pending); // doPrepare() must NOT set this -- cgit v1.2.3 From cf4d3d7ed82e62b57a11fbc7f491535a761dc75c Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 27 May 2020 19:03:52 +0200 Subject: Move around and format code No functional changes here. --- lib/connection.cpp | 4 +-- lib/jobs/basejob.cpp | 94 +++++++++++++++++++++++++++++----------------------- lib/jobs/basejob.h | 17 ++++++---- lib/syncdata.h | 2 +- 4 files changed, 66 insertions(+), 51 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index 9f4f7082..efc7163e 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -20,7 +20,7 @@ #include "connectiondata.h" #ifdef Quotient_E2EE_ENABLED -#include "encryptionmanager.h" +# include "encryptionmanager.h" #endif // Quotient_E2EE_ENABLED #include "room.h" #include "settings.h" @@ -45,7 +45,7 @@ #include "jobs/syncjob.h" #ifdef Quotient_E2EE_ENABLED -#include "account.h" // QtOlm +# include "account.h" // QtOlm #endif // Quotient_E2EE_ENABLED #include diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 470250bf..100c05f2 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -35,6 +35,47 @@ using namespace Quotient; using std::chrono::seconds, std::chrono::milliseconds; using namespace std::chrono_literals; +BaseJob::StatusCode BaseJob::Status::fromHttpCode(int httpCode) +{ + if (httpCode / 10 == 41) // 41x errors + return httpCode == 410 ? IncorrectRequestError : NotFoundError; + switch (httpCode) { + case 401: + return Unauthorised; + // clang-format off + case 403: case 407: // clang-format on + return ContentAccessError; + case 404: + return NotFoundError; + // clang-format off + case 400: case 405: case 406: case 426: case 428: case 505: // clang-format on + case 494: // Unofficial nginx "Request header too large" + case 497: // Unofficial nginx "HTTP request sent to HTTPS port" + return IncorrectRequestError; + case 429: + return TooManyRequestsError; + case 501: + case 510: + return RequestNotImplementedError; + case 511: + return NetworkAuthRequiredError; + default: + return NetworkError; + } +} + +QDebug BaseJob::Status::dumpToLog(QDebug dbg) const +{ + QDebugStateSaver _s(dbg); + dbg.noquote().nospace(); + if (auto* const k = QMetaEnum::fromType().valueToKey(code)) { + const QByteArray b = k; + dbg << b.mid(b.lastIndexOf(':')); + } else + dbg << code; + return dbg << ": " << message; +} + struct NetworkReplyDeleter : public QScopedPointerDeleteLater { static inline void cleanup(QNetworkReply* reply) { @@ -316,7 +357,15 @@ void BaseJob::sendRequest() << "Request could not start:" << d->dumpRequest(); } -void BaseJob::checkReply() { setStatus(doCheckReply(d->reply.data())); } +BaseJob::Status BaseJob::Private::parseJsonDocument() +{ + QJsonParseError error { 0, QJsonParseError::MissingObject }; + jsonResponse = QJsonDocument::fromJson(d->rawResponse, &error); + return { error.error == QJsonParseError::NoError + ? BaseJob::NoError + : BaseJob::IncorrectResponse, + error.errorString() }; +} void BaseJob::gotReply() { @@ -363,47 +412,6 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) return false; } -BaseJob::StatusCode BaseJob::Status::fromHttpCode(int httpCode) -{ - if (httpCode / 10 == 41) // 41x errors - return httpCode == 410 ? IncorrectRequestError : NotFoundError; - switch (httpCode) { - case 401: - return Unauthorised; - // clang-format off - case 403: case 407: // clang-format on - return ContentAccessError; - case 404: - return NotFoundError; - // clang-format off - case 400: case 405: case 406: case 426: case 428: case 505: // clang-format on - case 494: // Unofficial nginx "Request header too large" - case 497: // Unofficial nginx "HTTP request sent to HTTPS port" - return IncorrectRequestError; - case 429: - return TooManyRequestsError; - case 501: case 510: - return RequestNotImplementedError; - case 511: - return NetworkAuthRequiredError; - default: - return NetworkError; - } -} - -QDebug BaseJob::Status::dumpToLog(QDebug dbg) const -{ - QDebugStateSaver _s(dbg); - dbg.noquote().nospace(); - if (auto* const k = QMetaEnum::fromType().valueToKey(code)) { - const QByteArray b = k; - dbg << b.mid(b.lastIndexOf(':')); - } else - dbg << code; - return dbg << ": " << message; - -} - BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const { // QNetworkReply error codes seem to be flawed when it comes to HTTP; @@ -440,6 +448,8 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const return Status::fromHttpCode(httpCode, message); } +void BaseJob::checkReply() { setStatus(doCheckReply(d->reply.data())); } + BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) { d->rawResponse = reply->readAll(); diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 2049f59c..954b0777 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -170,6 +170,8 @@ public: * recommended to present a sample of raw data as "details" next to * error messages. Note that the default \p bytesAtMost value is * also tailored to UI cases. + * + * \sa rawData */ QString rawDataSample(int bytesAtMost = 65535) const; @@ -322,6 +324,7 @@ protected: * on retries. */ virtual void doPrepare(); + /*! Postprocessing after the network request has been sent * * This method is called every time the job receives a running @@ -331,13 +334,15 @@ protected: virtual void onSentRequest(QNetworkReply*); virtual void beforeAbandon(QNetworkReply*); - /** - * Used by gotReply() to check the received reply for general - * issues such as network errors or access denial. - * Returning anything except NoError/Success prevents - * further parseReply()/parseJson() invocation. + /*! \brief Check the pending or received reply for upfront issues + * + * This is invoked when headers are first received and also once + * the complete reply is obtained; the base implementation checks the HTTP + * headers to detect general issues such as network errors or access denial. + * It cannot read the response body (use parseReply/parseError to check + * for problems in the body). Returning anything except NoError/Success + * prevents further processing of the reply. * - * @param reply the reply received from the server * @return the result of checking the reply * * @see gotReply diff --git a/lib/syncdata.h b/lib/syncdata.h index 6e7183ee..41b8186e 100644 --- a/lib/syncdata.h +++ b/lib/syncdata.h @@ -75,7 +75,7 @@ public: static const QString UnreadCountKey; }; -// QVector cannot work with non-copiable objects, std::vector can. +// QVector cannot work with non-copyable objects, std::vector can. using SyncDataList = std::vector; class SyncData { -- cgit v1.2.3 From a9edfbd19a624aa4e882df2f5e577ba1831914a3 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 28 May 2020 08:42:04 +0200 Subject: BaseJob::rawData: overload for (even) quicker access No functional changes either. --- lib/jobs/basejob.cpp | 2 ++ lib/jobs/basejob.h | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 100c05f2..e649ea87 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -612,6 +612,8 @@ QByteArray BaseJob::rawData(int bytesAtMost) const : d->rawResponse; } +const QByteArray& BaseJob::rawData() const { return d->rawResponse; } + QString BaseJob::rawDataSample(int bytesAtMost) const { auto data = rawData(bytesAtMost); diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 954b0777..010aca78 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -157,11 +157,16 @@ public: /** Short human-friendly message on the job status */ QString statusCaption() const; - /** Get raw response body as received from the server - * \param bytesAtMost return this number of leftmost bytes, or -1 - * to return the entire response + /*! Get first bytes of the raw response body as received from the server + * + * \param bytesAtMost the number of leftmost bytes to return + * + * \sa rawDataSample */ - QByteArray rawData(int bytesAtMost = -1) const; + QByteArray rawData(int bytesAtMost) const; + + /*! Access the whole response body as received from the server */ + const QByteArray& rawData() const; /** Get UI-friendly sample of raw data * -- cgit v1.2.3 From 51ef6011d6dfc55ea0c8b0cdd1d9e7315087aad9 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 28 May 2020 13:24:16 +0200 Subject: BaseJob: use non-deprecated API for Qt 5.15 Qt 5.15 renamed HTTP2AllowedAttribute to Http2AllowedAttribute, deprecating the old spelling. --- lib/jobs/basejob.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index e649ea87..26782edc 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -273,7 +273,13 @@ void BaseJob::Private::sendRequest() // Pipelining doesn't fly quite well with SSL, occasionally crashing at // what seems like an attempt to write to a closed channel. // req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); - req.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); + req.setAttribute( +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + QNetworkRequest::Http2AllowedAttribute +#else + QNetworkRequest::HTTP2AllowedAttribute +#endif + , true); Q_ASSERT(req.url().isValid()); for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) req.setRawHeader(it.key(), it.value()); -- cgit v1.2.3 From 7ac93db4553aa624326a8e28b74151c784b937a7 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 1 Jun 2020 14:47:15 +0200 Subject: Remove the piece of code introduced too early on parseJsonDocument() will come later. --- lib/jobs/basejob.cpp | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 26782edc..2519713e 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -363,16 +363,6 @@ void BaseJob::sendRequest() << "Request could not start:" << d->dumpRequest(); } -BaseJob::Status BaseJob::Private::parseJsonDocument() -{ - QJsonParseError error { 0, QJsonParseError::MissingObject }; - jsonResponse = QJsonDocument::fromJson(d->rawResponse, &error); - return { error.error == QJsonParseError::NoError - ? BaseJob::NoError - : BaseJob::IncorrectResponse, - error.errorString() }; -} - void BaseJob::gotReply() { checkReply(); -- cgit v1.2.3 From 04956392c4b1102ac9ae627c324493f035887472 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 5 Jun 2020 18:09:52 +0200 Subject: BaseJob: expose statusCode as Q_PROPERTY --- lib/jobs/basejob.h | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 010aca78..6920ebc1 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -38,6 +38,7 @@ class BaseJob : public QObject { Q_OBJECT Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries) + Q_PROPERTY(int statusCode READ error NOTIFY statusChanged) public: /*! The status code of a job * -- cgit v1.2.3 From eccab6df7003bb9c20c48dfe0af57502383ba42e Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 5 Jun 2020 18:11:02 +0200 Subject: MediaThumbnailJob: be specific about the transform What's needed for a thumbnail is normally "scale", not "crop" (as these are defined in The Spec). --- lib/jobs/mediathumbnailjob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/mediathumbnailjob.cpp b/lib/jobs/mediathumbnailjob.cpp index 0a346392..df3763b2 100644 --- a/lib/jobs/mediathumbnailjob.cpp +++ b/lib/jobs/mediathumbnailjob.cpp @@ -31,7 +31,7 @@ QUrl MediaThumbnailJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri, MediaThumbnailJob::MediaThumbnailJob(const QString& serverName, const QString& mediaId, QSize requestedSize) : GetContentThumbnailJob(serverName, mediaId, requestedSize.width(), - requestedSize.height()) + requestedSize.height(), "scale") {} MediaThumbnailJob::MediaThumbnailJob(const QUrl& mxcUri, QSize requestedSize) -- cgit v1.2.3 From 21c04d5b035cec0b6378e60acc93523f52c1c973 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 5 Jun 2020 18:09:12 +0200 Subject: BaseJob: jsonData() and prepareResult/Error() * JSON response is stored internally in BaseJob, rather than passed around virtual response handlers. This allow to lazily deserialise parts of the JSON response when the client calls for them instead of deserialising upon arrival and storing POD pieces. This is incompatible with the current generated code, so temporarily FTBFS. * BaseJob::loadFromJson() and BaseJob::takeFromJson() have been added to facilitate picking parts of the result as described above in derived job classes. * BaseJob::jsonData(), BaseJob::jsonItems() and (protected) BaseJob::reply() for direct access to the response in its various forms. * To further eliminate boilerplate code in generated job classes, a group of *ExpectedKeys() methods has been added - this allows to reflect the API definition of required response keys in a more "declarative" way, delegating validation to BaseJob. * parseReply() and parseJson() pair turns to singular prepareResult(). Thanks to all the changes above, in most cases it will not need overriding, unlike before. * BaseJob::Private::parseJson() is introduced, to wrap QJsonDocument::parseJson() into something less verbose. This serves a completely different purpose to the former BaseJob::parseJson(). * BaseJob::doCheckReply() takes the place, and the name, of checkReply(). --- lib/jobs/basejob.cpp | 164 ++++++++++++++++++++++++++++++----------- lib/jobs/basejob.h | 134 +++++++++++++++++++++++---------- lib/jobs/downloadfilejob.cpp | 4 +- lib/jobs/downloadfilejob.h | 4 +- lib/jobs/mediathumbnailjob.cpp | 6 +- lib/jobs/mediathumbnailjob.h | 2 +- lib/jobs/syncjob.cpp | 4 +- lib/jobs/syncjob.h | 2 +- 8 files changed, 226 insertions(+), 94 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 2519713e..3978dbcb 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -19,12 +19,11 @@ #include "basejob.h" #include "connectiondata.h" -#include "util.h" -#include #include #include #include +#include #include #include #include @@ -37,6 +36,7 @@ using namespace std::chrono_literals; BaseJob::StatusCode BaseJob::Status::fromHttpCode(int httpCode) { + // Based on https://en.wikipedia.org/wiki/List_of_HTTP_status_codes if (httpCode / 10 == 41) // 41x errors return httpCode == 410 ? IncorrectRequestError : NotFoundError; switch (httpCode) { @@ -113,6 +113,13 @@ public: } void sendRequest(); + /*! \brief Parse the response byte array into JSON + * + * This calls QJsonDocument::fromJson() on rawResponse, converts + * the QJsonParseError result to BaseJob::Status and stores the resulting + * JSON in jsonResponse. + */ + Status parseJson(); ConnectionData* connection = nullptr; @@ -131,9 +138,17 @@ public: // type QMimeType is of little help with MIME type globs (`text/*` etc.) QByteArrayList expectedContentTypes { "application/json" }; + QByteArrayList expectedKeys; + QScopedPointer reply; Status status = Unprepared; QByteArray rawResponse; + /// Contains a null document in case of non-JSON body (for a successful + /// or unsuccessful response); a document with QJsonObject or QJsonArray + /// in case of a successful response with JSON payload, as per the API + /// definition (including an empty JSON object - QJsonObject{}); + /// and QJsonObject in case of an API error. + QJsonDocument jsonResponse; QUrl errorUrl; //< May contain a URL to help with some errors LoggingCategory logCat = JOBS; @@ -243,6 +258,19 @@ void BaseJob::setExpectedContentTypes(const QByteArrayList& contentTypes) d->expectedContentTypes = contentTypes; } +const QByteArrayList BaseJob::expectedKeys() const { return d->expectedKeys; } + +void BaseJob::addExpectedKey(const QByteArray& key) { d->expectedKeys << key; } + +void BaseJob::setExpectedKeys(const QByteArrayList& keys) +{ + d->expectedKeys = keys; +} + +const QNetworkReply* BaseJob::reply() const { return d->reply.data(); } + +QNetworkReply* BaseJob::reply() { return d->reply.data(); } + QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QString& path, const QUrlQuery& query) { @@ -304,7 +332,7 @@ void BaseJob::doPrepare() { } void BaseJob::onSentRequest(QNetworkReply*) { } -void BaseJob::beforeAbandon(QNetworkReply*) { } +void BaseJob::beforeAbandon() { } void BaseJob::initiate(ConnectionData* connData, bool inBackground) { @@ -346,40 +374,74 @@ void BaseJob::sendRequest() emit aboutToSendRequest(); d->sendRequest(); Q_ASSERT(d->reply); - connect(d->reply.data(), &QNetworkReply::finished, this, &BaseJob::gotReply); + connect(reply(), &QNetworkReply::finished, this, [this] { + gotReply(); + finishJob(); + }); if (d->reply->isRunning()) { - connect(d->reply.data(), &QNetworkReply::metaDataChanged, this, - &BaseJob::checkReply); - connect(d->reply.data(), &QNetworkReply::uploadProgress, this, + connect(reply(), &QNetworkReply::metaDataChanged, this, + [this] { checkReply(reply()); }); + connect(reply(), &QNetworkReply::uploadProgress, this, &BaseJob::uploadProgress); - connect(d->reply.data(), &QNetworkReply::downloadProgress, this, + connect(reply(), &QNetworkReply::downloadProgress, this, &BaseJob::downloadProgress); d->timer.start(getCurrentTimeout()); qCInfo(d->logCat).noquote() << "Sent" << d->dumpRequest(); - onSentRequest(d->reply.data()); + onSentRequest(reply()); emit sentRequest(); } else qCCritical(d->logCat).noquote() << "Request could not start:" << d->dumpRequest(); } +BaseJob::Status BaseJob::Private::parseJson() +{ + QJsonParseError error { 0, QJsonParseError::MissingObject }; + jsonResponse = QJsonDocument::fromJson(rawResponse, &error); + return { error.error == QJsonParseError::NoError + ? BaseJob::NoError + : BaseJob::IncorrectResponse, + error.errorString() }; +} + void BaseJob::gotReply() { - checkReply(); + setStatus(checkReply(reply())); + + if (status().good() + && d->expectedContentTypes == QByteArrayList { "application/json" }) { + d->rawResponse = reply()->readAll(); + setStatus(d->parseJson()); + if (status().good() && !expectedKeys().empty()) { + const auto& responseObject = jsonData(); + QByteArrayList missingKeys; + for (const auto& k: expectedKeys()) + if (!responseObject.contains(k)) + missingKeys.push_back(k); + if (!missingKeys.empty()) + setStatus(IncorrectResponse, tr("Required JSON keys missing: ") + + missingKeys.join()); + } + if (!status().good()) // Bad JSON in a "good" reply: bail out + return; + } // else { + // If the endpoint expects anything else than just (API-related) JSON + // reply()->readAll() is not performed and the whole reply processing + // is left to derived job classes: they may read it piecemeal or customise + // per content type in prepareResult(), or even have read it already + // (see, e.g., DownloadFileJob). + // } + if (status().good()) - setStatus(parseReply(d->reply.data())); + setStatus(prepareResult()); else { - d->rawResponse = d->reply->readAll(); - const auto jsonBody = d->reply->rawHeader("Content-Type") - == "application/json"; + d->rawResponse = reply()->readAll(); qCDebug(d->logCat).noquote() - << "Error body (truncated if long):" << d->rawResponse.left(500); - if (jsonBody) - setStatus( - parseError(d->reply.data(), - QJsonDocument::fromJson(d->rawResponse).object())); + << "Error body (truncated if long):" << rawDataSample(500); + // Parse the error payload and update the status if needed + if (const auto newStatus = prepareError(); !newStatus.good()) + setStatus(newStatus); } - finishJob(); } bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) @@ -408,12 +470,10 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) return false; } -BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const +BaseJob::Status BaseJob::checkReply(const QNetworkReply* reply) const { - // QNetworkReply error codes seem to be flawed when it comes to HTTP; - // see, e.g., https://github.com/quotient-im/libQuotient/issues/200 - // so check genuine HTTP codes. The below processing is based on - // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes + // QNetworkReply error codes are insufficient for our purposes (e.g. they + // don't allow to discern HTTP code 429) so check the original code instead const auto httpCodeHeader = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); if (!httpCodeHeader.isValid()) { @@ -444,24 +504,23 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const return Status::fromHttpCode(httpCode, message); } -void BaseJob::checkReply() { setStatus(doCheckReply(d->reply.data())); } +BaseJob::Status BaseJob::prepareResult() { return Success; } -BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) +BaseJob::Status BaseJob::prepareError() { - d->rawResponse = reply->readAll(); - QJsonParseError error { 0, QJsonParseError::MissingObject }; - const auto& json = QJsonDocument::fromJson(d->rawResponse, &error); - if (error.error == QJsonParseError::NoError) - return parseJson(json); + // Since it's an error, the expected content type is of no help; + // check the actually advertised content type instead + if (reply()->rawHeader("Content-Type") != "application/json") + return NoError; // Retain the status if the error payload is not JSON - return { IncorrectResponseError, error.errorString() }; -} + if (const auto status = d->parseJson(); !status.good()) + return status; -BaseJob::Status BaseJob::parseJson(const QJsonDocument&) { return Success; } + if (d->jsonResponse.isArray()) + return { IncorrectResponse, + tr("Malformed error JSON: an array instead of an object") }; -BaseJob::Status BaseJob::parseError(QNetworkReply* /*reply*/, - const QJsonObject& errorJson) -{ + const auto& errorJson = jsonData(); const auto errCode = errorJson.value("errcode"_ls).toString(); if (error() == TooManyRequestsError || errCode == "M_LIMIT_EXCEEDED") { QString msg = tr("Too many requests"); @@ -499,6 +558,16 @@ BaseJob::Status BaseJob::parseError(QNetworkReply* /*reply*/, return d->status; } +QJsonValue BaseJob::takeValueFromJson(const QString& key) +{ + if (!d->jsonResponse.isObject()) + return QJsonValue::Undefined; + auto o = d->jsonResponse.object(); + auto v = o.take(key); + d->jsonResponse.setObject(o); + return v; +} + void BaseJob::stop() { // This method is (also) used to semi-finalise the job before retrying; so @@ -616,10 +685,19 @@ QString BaseJob::rawDataSample(int bytesAtMost) const Q_ASSERT(data.size() <= d->rawResponse.size()); return data.size() == d->rawResponse.size() ? data - : data - + tr("...(truncated, %Ln bytes in total)", - "Comes after trimmed raw network response", - d->rawResponse.size()); + : data + tr("...(truncated, %Ln bytes in total)", + "Comes after trimmed raw network response", + d->rawResponse.size()); +} + +QJsonObject BaseJob::jsonData() const +{ + return d->jsonResponse.object(); +} + +QJsonArray BaseJob::jsonItems() const +{ + return d->jsonResponse.array(); } QString BaseJob::statusCaption() const @@ -704,7 +782,7 @@ void BaseJob::setStatus(int code, QString message) void BaseJob::abandon() { - beforeAbandon(d->reply ? d->reply.data() : nullptr); + beforeAbandon(); d->timer.stop(); d->retryTimer.stop(); // In case abandon() was called between retries setStatus(Abandoned); diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 6920ebc1..be2926be 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -18,13 +18,11 @@ #pragma once -#include "../logging.h" #include "requestdata.h" +#include "../logging.h" +#include "../converters.h" -#include #include -#include -#include class QNetworkReply; class QSslError; @@ -181,6 +179,49 @@ public: */ QString rawDataSample(int bytesAtMost = 65535) const; + /** Get the response body as a JSON object + * + * If the job's returned content type is not `application/json` + * or if the top-level JSON entity is not an object, an empty object + * is returned. + */ + QJsonObject jsonData() const; + + /** Get the response body as a JSON array + * + * If the job's returned content type is not `application/json` + * or if the top-level JSON entity is not an array, an empty array + * is returned. + */ + QJsonArray jsonItems() const; + + /** Load the property from the JSON response assuming a given C++ type + * + * If there's no top-level JSON object in the response or if there's + * no node with the key \p keyName, \p defaultValue is returned. + */ + template // Waiting for QStringViews... + T loadFromJson(const StrT& keyName, T&& defaultValue = {}) const + { + const auto& jv = jsonData().value(keyName); + return jv.isUndefined() ? std::forward(defaultValue) + : fromJson(jv); + } + + /** Load the property from the JSON response and delete it from JSON + * + * If there's no top-level JSON object in the response or if there's + * no node with the key \p keyName, \p defaultValue is returned. + */ + template + T takeFromJson(const QString& key, T&& defaultValue = {}) + { + if (const auto& jv = takeValueFromJson(key); !jv.isUndefined()) + return fromJson(jv); + + return std::forward(defaultValue); + } + /** Error (more generally, status) code * Equivalent to status().code * \sa status @@ -314,6 +355,12 @@ protected: const QByteArrayList& expectedContentTypes() const; void addExpectedContentType(const QByteArray& contentType); void setExpectedContentTypes(const QByteArrayList& contentTypes); + const QByteArrayList expectedKeys() const; + void addExpectedKey(const QByteArray &key); + void setExpectedKeys(const QByteArrayList &keys); + + const QNetworkReply* reply() const; + QNetworkReply* reply(); /** Construct a URL out of baseUrl, path and query * @@ -338,50 +385,42 @@ protected: * successfully sending a network request (including retries). */ virtual void onSentRequest(QNetworkReply*); - virtual void beforeAbandon(QNetworkReply*); + virtual void beforeAbandon(); - /*! \brief Check the pending or received reply for upfront issues + /*! \brief An extension point for additional reply processing. * - * This is invoked when headers are first received and also once - * the complete reply is obtained; the base implementation checks the HTTP - * headers to detect general issues such as network errors or access denial. - * It cannot read the response body (use parseReply/parseError to check - * for problems in the body). Returning anything except NoError/Success - * prevents further processing of the reply. - * - * @return the result of checking the reply + * The base implementation does nothing and returns Success. * - * @see gotReply + * \sa gotReply */ - virtual Status doCheckReply(QNetworkReply* reply) const; + virtual Status prepareResult(); - /** - * Processes the reply. By default, parses the reply into - * a QJsonDocument and calls parseJson() if it's a valid JSON. - * - * @param reply raw contents of a HTTP reply from the server + /*! \brief Process details of the error * - * @see gotReply, parseJson + * The function processes the reply in case when status from checkReply() + * was not good (usually because of an unsuccessful HTTP code). + * The base implementation assumes Matrix JSON error object in the body; + * overrides are strongly recommended to call it for all stock Matrix + * responses as early as possible but in addition can process custom errors, + * with JSON or non-JSON payload. */ - virtual Status parseReply(QNetworkReply* reply); + virtual Status prepareError(); - /** - * Processes the JSON document received from the Matrix server. - * By default returns successful status without analysing the JSON. + /*! \brief Get direct access to the JSON response object in the job * - * @param json valid JSON document received from the server + * This allows to implement deserialisation with "move" semantics for parts + * of the response. Assuming that the response body is a valid JSON object, + * the function calls QJsonObject::take(key) on it and returns the result. * - * @see parseReply - */ - virtual Status parseJson(const QJsonDocument&); - - /** - * Processes the reply in case of unsuccessful HTTP code. - * The body is already loaded from the reply object to errorJson. - * @param reply the HTTP reply from the server - * @param errorJson the JSON payload describing the error + * \return QJsonValue::Null, if the response content type is not + * advertised as `application/json`; + * QJsonValue::Undefined, if the response is a JSON object but + * doesn't have \p key; + * the value for \p key otherwise. + * + * \sa takeFromJson */ - virtual Status parseError(QNetworkReply*, const QJsonObject& errorJson); + QJsonValue takeValueFromJson(const QString& key); void setStatus(Status s); void setStatus(int code, QString message); @@ -397,9 +436,28 @@ protected: protected slots: void timeout(); + /*! \brief Check the pending or received reply for upfront issues + * + * This is invoked when headers are first received and also once + * the complete reply is obtained; the base implementation checks the HTTP + * headers to detect general issues such as network errors or access denial + * and it's strongly recommended to call it from overrides, + * as early as possible. + * This slot is const and cannot read the response body. If you need to read + * the body on the fly, override onSentRequest() and connect in it + * to reply->readyRead(); and if you only need to validate the body after + * it fully arrived, use prepareResult() for that). Returning anything + * except NoError/Success switches further processing from prepareResult() + * to prepareError(). + * + * @return the result of checking the reply + * + * @see gotReply + */ + virtual Status checkReply(const QNetworkReply *reply) const; + private slots: void sendRequest(); - void checkReply(); void gotReply(); friend class ConnectionData; // to provide access to sendRequest() diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 3e037680..7b4cf690 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -86,14 +86,14 @@ void DownloadFileJob::onSentRequest(QNetworkReply* reply) }); } -void DownloadFileJob::beforeAbandon(QNetworkReply*) +void DownloadFileJob::beforeAbandon() { if (d->targetFile) d->targetFile->remove(); d->tempFile->remove(); } -BaseJob::Status DownloadFileJob::parseReply(QNetworkReply*) +BaseJob::Status DownloadFileJob::prepareResult() { if (d->targetFile) { d->targetFile->close(); diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h index 06dc145c..e00fd9e4 100644 --- a/lib/jobs/downloadfilejob.h +++ b/lib/jobs/downloadfilejob.h @@ -19,7 +19,7 @@ private: void doPrepare() override; void onSentRequest(QNetworkReply* reply) override; - void beforeAbandon(QNetworkReply*) override; - Status parseReply(QNetworkReply*) override; + void beforeAbandon() override; + Status prepareResult() override; }; } // namespace Quotient diff --git a/lib/jobs/mediathumbnailjob.cpp b/lib/jobs/mediathumbnailjob.cpp index df3763b2..33f4236c 100644 --- a/lib/jobs/mediathumbnailjob.cpp +++ b/lib/jobs/mediathumbnailjob.cpp @@ -48,12 +48,8 @@ QImage MediaThumbnailJob::scaledThumbnail(QSize toSize) const Qt::SmoothTransformation); } -BaseJob::Status MediaThumbnailJob::parseReply(QNetworkReply* reply) +BaseJob::Status MediaThumbnailJob::prepareResult() { - auto result = GetContentThumbnailJob::parseReply(reply); - if (!result.good()) - return result; - if (_thumbnail.loadFromData(data()->readAll())) return Success; diff --git a/lib/jobs/mediathumbnailjob.h b/lib/jobs/mediathumbnailjob.h index 75e2e55a..e6d39085 100644 --- a/lib/jobs/mediathumbnailjob.h +++ b/lib/jobs/mediathumbnailjob.h @@ -37,7 +37,7 @@ public: QImage scaledThumbnail(QSize toSize) const; protected: - Status parseReply(QNetworkReply* reply) override; + Status prepareResult() override; private: QImage _thumbnail; diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index cd7709e1..6b8cfe4b 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -49,9 +49,9 @@ SyncJob::SyncJob(const QString& since, const Filter& filter, int timeout, timeout, presence) {} -BaseJob::Status SyncJob::parseJson(const QJsonDocument& data) +BaseJob::Status SyncJob::prepareResult() { - d.parseJson(data.object()); + d.parseJson(jsonData()); if (d.unresolvedRooms().isEmpty()) return BaseJob::Success; diff --git a/lib/jobs/syncjob.h b/lib/jobs/syncjob.h index df419ba8..bf139a7b 100644 --- a/lib/jobs/syncjob.h +++ b/lib/jobs/syncjob.h @@ -33,7 +33,7 @@ public: SyncData&& takeData() { return std::move(d); } protected: - Status parseJson(const QJsonDocument& data) override; + Status prepareResult() override; private: SyncData d; -- cgit v1.2.3 From 0db2db1d247a0a4e6e6545ec0d72879416e6226b Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 11 Jun 2020 19:24:39 +0200 Subject: BaseJob::prepareError(): be more tolerant to empty error payloads TooManyRequests can come without a payload, apparently. --- lib/jobs/basejob.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 3978dbcb..d7daa170 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -508,17 +508,13 @@ BaseJob::Status BaseJob::prepareResult() { return Success; } BaseJob::Status BaseJob::prepareError() { - // Since it's an error, the expected content type is of no help; - // check the actually advertised content type instead - if (reply()->rawHeader("Content-Type") != "application/json") - return NoError; // Retain the status if the error payload is not JSON - - if (const auto status = d->parseJson(); !status.good()) - return status; - - if (d->jsonResponse.isArray()) - return { IncorrectResponse, - tr("Malformed error JSON: an array instead of an object") }; + if (!d->rawResponse.isEmpty()) { + if (const auto status = d->parseJson(); !status.good()) + return status; // If there's anything there, it should be JSON + if (d->jsonResponse.isArray()) // ...specifically, a JSON object + return { IncorrectResponse, + tr("Malformed error JSON: an array instead of an object") }; + } const auto& errorJson = jsonData(); const auto errCode = errorJson.value("errcode"_ls).toString(); @@ -534,6 +530,7 @@ BaseJob::Status BaseJob::prepareError() return { TooManyRequestsError, msg }; } + if (errCode == "M_CONSENT_NOT_GIVEN") { d->errorUrl = errorJson.value("consent_uri"_ls).toString(); return { UserConsentRequiredError }; @@ -552,10 +549,10 @@ BaseJob::Status BaseJob::prepareError() return { UserDeactivated }; // Not localisable on the client side - if (errorJson.contains("error"_ls)) - d->status.message = errorJson.value("error"_ls).toString(); + if (errorJson.contains("error"_ls)) // Keep the code, update the message + return { d->status.code, errorJson.value("error"_ls).toString() }; - return d->status; + return NoError; // Retain the status if the error payload is not recognised } QJsonValue BaseJob::takeValueFromJson(const QString& key) -- cgit v1.2.3 From ebdb2ba9d15e6cdfb1458e7895032afd641aafe3 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 12 Jun 2020 20:20:10 +0200 Subject: BaseJob: fail early if the job needs token and there's none --- lib/jobs/basejob.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index d7daa170..7774a6e2 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -341,7 +341,9 @@ void BaseJob::initiate(ConnectionData* connData, bool inBackground) d->connection = connData; doPrepare(); - if ((d->verb == HttpVerb::Post || d->verb == HttpVerb::Put) + if (d->needsToken && d->connection->accessToken().isEmpty()) + setStatus(Unauthorised); + else if ((d->verb == HttpVerb::Post || d->verb == HttpVerb::Put) && d->requestData.source() && !d->requestData.source()->isReadable()) { setStatus(FileError, "Request data not ready"); -- cgit v1.2.3 From b1e84568dbb70dc4fa24a915c6d15438be958378 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 26 Jun 2020 19:05:36 +0200 Subject: Disable HTTP2; enable pipelining Long run tests over 2+ days kept crashing before this commit but stopped crashing with pipelining on and HTTP2 off. --- lib/jobs/basejob.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 7774a6e2..465287c6 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -298,16 +298,17 @@ void BaseJob::Private::sendRequest() req.setAttribute(QNetworkRequest::BackgroundRequestAttribute, inBackground); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); req.setMaximumRedirectsAllowed(10); - // Pipelining doesn't fly quite well with SSL, occasionally crashing at - // what seems like an attempt to write to a closed channel. -// req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); req.setAttribute( #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) QNetworkRequest::Http2AllowedAttribute #else QNetworkRequest::HTTP2AllowedAttribute #endif - , true); + // Qt doesn't combine HTTP2 with SSL quite right, occasionally crashing at + // what seems like an attempt to write to a closed channel. If/when that + // changes, false should be turned to true below. + , false); Q_ASSERT(req.url().isValid()); for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) req.setRawHeader(it.key(), it.value()); -- cgit v1.2.3 From 3648c6a40c585e718bcfc0068cfa431e46f24a52 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 4 Aug 2020 13:28:09 +0200 Subject: Cleanup around [BaseJob::]IncorrectResponse[Error] --- lib/jobs/basejob.cpp | 5 ++--- lib/jobs/mediathumbnailjob.cpp | 3 +-- lib/jobs/syncjob.cpp | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 465287c6..d6d48d2f 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -401,9 +401,8 @@ BaseJob::Status BaseJob::Private::parseJson() { QJsonParseError error { 0, QJsonParseError::MissingObject }; jsonResponse = QJsonDocument::fromJson(rawResponse, &error); - return { error.error == QJsonParseError::NoError - ? BaseJob::NoError - : BaseJob::IncorrectResponse, + return { error.error == QJsonParseError::NoError ? NoError + : IncorrectResponse, error.errorString() }; } diff --git a/lib/jobs/mediathumbnailjob.cpp b/lib/jobs/mediathumbnailjob.cpp index 33f4236c..a69f00e9 100644 --- a/lib/jobs/mediathumbnailjob.cpp +++ b/lib/jobs/mediathumbnailjob.cpp @@ -53,6 +53,5 @@ BaseJob::Status MediaThumbnailJob::prepareResult() if (_thumbnail.loadFromData(data()->readAll())) return Success; - return { IncorrectResponseError, - QStringLiteral("Could not read image data") }; + return { IncorrectResponse, QStringLiteral("Could not read image data") }; } diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index 6b8cfe4b..9087fe50 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -53,9 +53,9 @@ BaseJob::Status SyncJob::prepareResult() { d.parseJson(jsonData()); if (d.unresolvedRooms().isEmpty()) - return BaseJob::Success; + return Success; qCCritical(MAIN).noquote() << "Incomplete sync response, missing rooms:" << d.unresolvedRooms().join(','); - return BaseJob::IncorrectResponseError; + return IncorrectResponse; } -- cgit v1.2.3 From d88663890261c2c276cd76576655b137a8758670 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 4 Aug 2020 13:32:57 +0200 Subject: BaseJob: go for a retry on IncorrectResponse The most frequent occurence of IncorrectResponse so far is a proxy/CDN failure. This is not a grave error; there's a chance that the retry will succeed. In the worst case the job will fail after 3 identical errors (except SyncJob that will try to get through forever - but SyncJob failures should still be indicated in the client's UI in some non-intrusive way). --- lib/jobs/basejob.cpp | 55 +++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 24 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index d6d48d2f..1f0e84ba 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -586,33 +586,40 @@ void BaseJob::stop() void BaseJob::finishJob() { stop(); - if (error() == TooManyRequests) { + switch(error()) { + case TooManyRequests: emit rateLimited(); d->connection->submit(this); return; - } - if (error() == Unauthorised && !d->needsToken - && !d->connection->accessToken().isEmpty()) { - // Rerun with access token (extension of the spec while - // https://github.com/matrix-org/matrix-doc/issues/701 is pending) - d->connection->setNeedsToken(objectName()); - qCWarning(d->logCat) << this << "re-running with authentication"; - emit retryScheduled(d->retriesTaken, 0); - d->connection->submit(this); - return; - } - if ((error() == NetworkError || error() == Timeout) - && d->retriesTaken < d->maxRetries) { - // TODO: The whole retrying thing should be put to Connection(Manager) - // otherwise independently retrying jobs make a bit of notification - // storm towards the UI. - const seconds retryIn = error() == Timeout ? 0s : getNextRetryInterval(); - ++d->retriesTaken; - qCWarning(d->logCat).nospace() << this << ": retry #" << d->retriesTaken - << " in " << retryIn.count() << " s"; - d->retryTimer.start(retryIn); - emit retryScheduled(d->retriesTaken, milliseconds(retryIn).count()); - return; + case Unauthorised: + if (!d->needsToken && !d->connection->accessToken().isEmpty()) { + // Rerun with access token (extension of the spec while + // https://github.com/matrix-org/matrix-doc/issues/701 is pending) + d->connection->setNeedsToken(objectName()); + qCWarning(d->logCat) << this << "re-running with authentication"; + emit retryScheduled(d->retriesTaken, 0); + d->connection->submit(this); + return; + } + break; + case NetworkError: + case IncorrectResponse: + case Timeout: + if (d->retriesTaken < d->maxRetries) { + // TODO: The whole retrying thing should be put to + // Connection(Manager) otherwise independently retrying jobs make a + // bit of notification storm towards the UI. + const seconds retryIn = error() == Timeout ? 0s + : getNextRetryInterval(); + ++d->retriesTaken; + qCWarning(d->logCat).nospace() + << this << ": retry #" << d->retriesTaken << " in " + << retryIn.count() << " s"; + d->retryTimer.start(retryIn); + emit retryScheduled(d->retriesTaken, milliseconds(retryIn).count()); + return; + } + default:; } Q_ASSERT(status().code != Pending); -- cgit v1.2.3 From ff2cb9f8a3a3ba01c9881ee1b196c9397c91ee6d Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Thu, 10 Dec 2020 01:53:04 +0100 Subject: Fix DELETE jobs with json data DeleteDeviceJob requires authentication, but the JSON data is not added for DELETE requests. Since QNetworkAccessManager::deleteResource does not support body data, we need to send a custom request. --- lib/jobs/basejob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 1f0e84ba..b757854a 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -324,7 +324,7 @@ void BaseJob::Private::sendRequest() reply.reset(connection->nam()->put(req, requestData.source())); break; case HttpVerb::Delete: - reply.reset(connection->nam()->deleteResource(req)); + reply.reset(connection->nam()->sendCustomRequest(req, "DELETE", requestData.source())); break; } } -- cgit v1.2.3 From 9ef83e044ed4f8409156b19d529dfc7e45f565c1 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 23 Dec 2020 17:21:01 +0100 Subject: BaseJob: tolerate unexpected error payloads Proxy servers may return arbitrary HTML, for one example; so don't expect to find a valid JSON object in whatever non-empty payload next to a non-2xx HTTP code. Fixes #421. --- lib/jobs/basejob.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index b757854a..e16ba4ef 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -510,14 +510,15 @@ BaseJob::Status BaseJob::prepareResult() { return Success; } BaseJob::Status BaseJob::prepareError() { - if (!d->rawResponse.isEmpty()) { - if (const auto status = d->parseJson(); !status.good()) - return status; // If there's anything there, it should be JSON - if (d->jsonResponse.isArray()) // ...specifically, a JSON object - return { IncorrectResponse, - tr("Malformed error JSON: an array instead of an object") }; - } - + // Try to make sense of the error payload but be prepared for all kinds + // of unexpected stuff (raw HTML, plain text, foreign JSON among those) + if (!d->rawResponse.isEmpty() + && reply()->rawHeader("Content-Type") == "application/json") + d->parseJson(); + + // By now, if d->parseJson() above succeeded then jsonData() will return + // a valid JSON object - or an empty object otherwise (in which case most + // of if's below will fall through to `return NoError` at the end const auto& errorJson = jsonData(); const auto errCode = errorJson.value("errcode"_ls).toString(); if (error() == TooManyRequestsError || errCode == "M_LIMIT_EXCEEDED") { -- cgit v1.2.3 From 1a832ae9b6a0d679b551fd644136e4bc17e7db29 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 23 Dec 2020 17:21:44 +0100 Subject: BaseJob: add [[fallthrough]] as clang-tidy says --- lib/jobs/basejob.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index e16ba4ef..3fa1cd94 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -620,6 +620,7 @@ void BaseJob::finishJob() emit retryScheduled(d->retriesTaken, milliseconds(retryIn).count()); return; } + [[fallthrough]]; default:; } -- cgit v1.2.3 From 0a2acd750a4155969092be674ed3dd9a71b2354f Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 24 Dec 2020 18:20:04 +0100 Subject: Fix clang-tidy/clazy warnings --- lib/connection.cpp | 4 ++-- lib/converters.cpp | 4 ++-- lib/events/typingevent.cpp | 1 + lib/jobs/downloadfilejob.cpp | 2 +- lib/networkaccessmanager.cpp | 7 +++--- lib/room.cpp | 55 ++++++++++++++++++++++---------------------- lib/uri.cpp | 8 +++---- lib/uriresolver.cpp | 2 ++ lib/user.cpp | 4 ++-- lib/util.cpp | 5 +--- tests/quotest.cpp | 38 +++++++++++++++++------------- 11 files changed, 68 insertions(+), 62 deletions(-) (limited to 'lib/jobs') diff --git a/lib/connection.cpp b/lib/connection.cpp index 8c51c84c..b037bf49 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -929,8 +929,8 @@ void Connection::doInDirectChat(User* u, // There can be more than one DC; find the first valid (existing and // not left), and delete inexistent (forgotten?) ones along the way. DirectChatsMap removals; - for (auto it = std::as_const(d->directChats).find(u); - it != d->directChats.end() && it.key() == u; ++it) { + for (auto it = d->directChats.constFind(u); + it != d->directChats.cend() && it.key() == u; ++it) { const auto& roomId = *it; if (auto r = room(roomId, JoinState::Join)) { Q_ASSERT(r->id() == roomId); diff --git a/lib/converters.cpp b/lib/converters.cpp index e5236bb9..9f570087 100644 --- a/lib/converters.cpp +++ b/lib/converters.cpp @@ -32,9 +32,9 @@ QVariant JsonConverter::load(const QJsonValue& jv) return jv.toVariant(); } -QJsonObject JsonConverter::dump(const QVariantHash& map) +QJsonObject JsonConverter::dump(const QVariantHash& vh) { - return QJsonObject::fromVariantHash(map); + return QJsonObject::fromVariantHash(vh); } QVariantHash JsonConverter::load(const QJsonValue& jv) diff --git a/lib/events/typingevent.cpp b/lib/events/typingevent.cpp index 0c5fc6ba..a95d2f0d 100644 --- a/lib/events/typingevent.cpp +++ b/lib/events/typingevent.cpp @@ -25,6 +25,7 @@ using namespace Quotient; TypingEvent::TypingEvent(const QJsonObject& obj) : Event(typeId(), obj) { const auto& array = contentJson()["user_ids"_ls].toArray(); + _users.reserve(array.size()); for (const auto& user : array) _users.push_back(user.toString()); } diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 7b4cf690..0011a97c 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -64,7 +64,7 @@ void DownloadFileJob::onSentRequest(QNetworkReply* reply) return; auto sizeHeader = reply->header(QNetworkRequest::ContentLengthHeader); if (sizeHeader.isValid()) { - auto targetSize = sizeHeader.value(); + auto targetSize = sizeHeader.toLongLong(); if (targetSize != -1) if (!d->tempFile->resize(targetSize)) { qCWarning(JOBS) << "Failed to allocate" << targetSize diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index b9037bcc..e8aa85df 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -52,9 +52,10 @@ static NetworkAccessManager* createNam() auto nam = new NetworkAccessManager(QCoreApplication::instance()); #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) // See #109; in newer Qt, bearer management is deprecated altogether - nam->connect(nam, &QNetworkAccessManager::networkAccessibleChanged, [nam] { - nam->setNetworkAccessible(QNetworkAccessManager::Accessible); - }); + NetworkAccessManager::connect(nam, + &QNetworkAccessManager::networkAccessibleChanged, [nam] { + nam->setNetworkAccessible(QNetworkAccessManager::Accessible); + }); #endif return nam; } diff --git a/lib/room.cpp b/lib/room.cpp index a5ed76a8..fcc22436 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -366,7 +366,7 @@ public: */ bool processReplacement(const RoomMessageEvent& newEvent); - void setTags(TagsMap newTags); + void setTags(TagsMap&& newTags); QJsonObject toJson() const; @@ -1089,11 +1089,11 @@ void Room::setTags(TagsMap newTags, ActionScope applyOn) if (propagate) { for (auto* r = this; (r = r->successor(joinStates));) - r->setTags(newTags, ActionScope::ThisRoomOnly); + r->setTags(d->tags, ActionScope::ThisRoomOnly); } } -void Room::Private::setTags(TagsMap newTags) +void Room::Private::setTags(TagsMap&& newTags) { emit q->tagsAboutToChange(); const auto keys = newTags.keys(); @@ -1208,8 +1208,8 @@ QString Room::fileNameToDownload(const QString& eventId) const FileTransferInfo Room::fileTransferInfo(const QString& id) const { - auto infoIt = d->fileTransfers.find(id); - if (infoIt == d->fileTransfers.end()) + const auto infoIt = d->fileTransfers.constFind(id); + if (infoIt == d->fileTransfers.cend()) return {}; // FIXME: Add lib tests to make sure FileTransferInfo::status stays @@ -1238,8 +1238,8 @@ QUrl Room::fileSource(const QString& id) const return url; // No urlToDownload means it's a pending or completed upload. - auto infoIt = d->fileTransfers.find(id); - if (infoIt != d->fileTransfers.end()) + auto infoIt = d->fileTransfers.constFind(id); + if (infoIt != d->fileTransfers.cend()) return QUrl::fromLocalFile(infoIt->localFileInfo.absoluteFilePath()); qCWarning(MAIN) << "File source for identifier" << id << "not found"; @@ -1285,7 +1285,7 @@ const StateEventBase* Room::getCurrentState(const QString& evtType, RoomEventPtr Room::decryptMessage(const EncryptedEvent& encryptedEvent) { #ifndef Quotient_E2EE_ENABLED - Q_UNUSED(encryptedEvent); + Q_UNUSED(encryptedEvent) qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; return {}; #else // Quotient_E2EE_ENABLED @@ -1310,10 +1310,9 @@ void Room::handleRoomKeyEvent(const RoomKeyEvent& roomKeyEvent, const QString& senderKey) { #ifndef Quotient_E2EE_ENABLED - Q_UNUSED(roomKeyEvent); - Q_UNUSED(senderKey); + Q_UNUSED(roomKeyEvent) + Q_UNUSED(senderKey) qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; - return; #else // Quotient_E2EE_ENABLED if (roomKeyEvent.algorithm() != MegolmV1AesSha2AlgoKey) { qCWarning(E2EE) << "Ignoring unsupported algorithm" @@ -1433,7 +1432,7 @@ Room::Private::moveEventsToTimeline(RoomEventsRange events, } const auto insertedSize = (index - baseIndex) * placement; Q_ASSERT(insertedSize == int(events.size())); - return insertedSize; + return Timeline::size_type(insertedSize); } QString Room::roomMembername(const User* u) const @@ -1615,8 +1614,8 @@ QString Room::retryMessage(const QString& txnId) const auto it = findPendingEvent(txnId); Q_ASSERT(it != d->unsyncedEvents.end()); qCDebug(EVENTS) << "Retrying transaction" << txnId; - const auto& transferIt = d->fileTransfers.find(txnId); - if (transferIt != d->fileTransfers.end()) { + const auto& transferIt = d->fileTransfers.constFind(txnId); + if (transferIt != d->fileTransfers.cend()) { Q_ASSERT(transferIt->isUpload); if (transferIt->status == FileTransferInfo::Completed) { qCDebug(MESSAGES) @@ -1713,7 +1712,8 @@ QString Room::postFile(const QString& plainText, const QUrl& localPath, // to enable the preview while the event is pending. uploadFile(txnId, localPath); // Below, the upload job is used as a context object to clean up connections - connect(this, &Room::fileTransferCompleted, d->fileTransfers[txnId].job, + const auto& transferJob = d->fileTransfers.value(txnId).job; + connect(this, &Room::fileTransferCompleted, transferJob, [this, txnId](const QString& id, const QUrl&, const QUrl& mxcUri) { if (id == txnId) { auto it = findPendingEvent(txnId); @@ -1732,7 +1732,7 @@ QString Room::postFile(const QString& plainText, const QUrl& localPath, } } }); - connect(this, &Room::fileTransferCancelled, d->fileTransfers[txnId].job, + connect(this, &Room::fileTransferCancelled, transferJob, [this, txnId](const QString& id) { if (id == txnId) { auto it = findPendingEvent(txnId); @@ -1940,8 +1940,8 @@ void Room::uploadFile(const QString& id, const QUrl& localFilename, void Room::downloadFile(const QString& eventId, const QUrl& localFilename) { - auto ongoingTransfer = d->fileTransfers.find(eventId); - if (ongoingTransfer != d->fileTransfers.end() + if (auto ongoingTransfer = d->fileTransfers.constFind(eventId); + ongoingTransfer != d->fileTransfers.cend() && ongoingTransfer->status == FileTransferInfo::Started) { qCWarning(MAIN) << "Transfer for" << eventId << "is ongoing; download won't start"; @@ -1998,8 +1998,8 @@ void Room::downloadFile(const QString& eventId, const QUrl& localFilename) void Room::cancelFileTransfer(const QString& id) { - auto it = d->fileTransfers.find(id); - if (it == d->fileTransfers.end()) { + const auto it = d->fileTransfers.constFind(id); + if (it == d->fileTransfers.cend()) { qCWarning(MAIN) << "No information on file transfer" << id << "in room" << d->id; return; @@ -2101,8 +2101,8 @@ bool Room::Private::processRedaction(const RedactionEvent& redaction) { // Can't use findInTimeline because it returns a const iterator, and // we need to change the underlying TimelineItem. - const auto pIdx = eventsIndex.find(redaction.redactedEvent()); - if (pIdx == eventsIndex.end()) + const auto pIdx = eventsIndex.constFind(redaction.redactedEvent()); + if (pIdx == eventsIndex.cend()) return false; Q_ASSERT(q->isValidIndex(*pIdx)); @@ -2172,8 +2172,8 @@ bool Room::Private::processReplacement(const RoomMessageEvent& newEvent) { // Can't use findInTimeline because it returns a const iterator, and // we need to change the underlying TimelineItem. - const auto pIdx = eventsIndex.find(newEvent.replacedEvent()); - if (pIdx == eventsIndex.end()) + const auto pIdx = eventsIndex.constFind(newEvent.replacedEvent()); + if (pIdx == eventsIndex.cend()) return false; Q_ASSERT(q->isValidIndex(*pIdx)); @@ -2418,12 +2418,11 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) if (!e.isStateEvent()) return Change::NoChange; - // Find a value (create empty if necessary) and get a reference to it - // getCurrentState<> is not used here because it (creates and) returns + // Find a value (create an empty one if necessary) and get a reference + // to it. Can't use getCurrentState<>() because it (creates and) returns // a stub if a value is not found, and what's needed here is a "real" event // or nullptr. - const auto*& curStateEvent = - d->currentState[{ e.matrixType(), e.stateKey() }]; + auto& curStateEvent = d->currentState[{ e.matrixType(), e.stateKey() }]; // Prepare for the state change const auto oldRme = static_cast(curStateEvent); visit(e, [this, &oldRme](const RoomMemberEvent& rme) { diff --git a/lib/uri.cpp b/lib/uri.cpp index 0e2bcb87..e0912eb6 100644 --- a/lib/uri.cpp +++ b/lib/uri.cpp @@ -32,7 +32,7 @@ Uri::Uri(QByteArray primaryId, QByteArray secondaryId, QString query) primaryType_ = Type(p.sigil); auto safePrimaryId = primaryId.mid(1); safePrimaryId.replace('/', "%2F"); - pathToBe = p.uriString + std::move(safePrimaryId); + pathToBe = p.uriString + safePrimaryId; break; } if (!secondaryId.isEmpty()) { @@ -42,12 +42,12 @@ Uri::Uri(QByteArray primaryId, QByteArray secondaryId, QString query) } auto safeSecondaryId = secondaryId.mid(1); safeSecondaryId.replace('/', "%2F"); - pathToBe += "/event/" + std::move(safeSecondaryId); + pathToBe += "/event/" + safeSecondaryId; } setPath(pathToBe, QUrl::TolerantMode); } if (!query.isEmpty()) - setQuery(std::move(query)); + setQuery(query); } static inline auto encodedPath(const QUrl& url) @@ -156,7 +156,7 @@ QUrl Uri::toUrl(UriForm form) const return {}; if (form == CanonicalUri || type() == NonMatrix) - return *this; + return *this; // NOLINT(cppcoreguidelines-slicing): It's intentional QUrl url; url.setScheme("https"); diff --git a/lib/uriresolver.cpp b/lib/uriresolver.cpp index ec30512c..27360bcc 100644 --- a/lib/uriresolver.cpp +++ b/lib/uriresolver.cpp @@ -75,6 +75,8 @@ private: std::tuple fns_; }; +template +StaticUriDispatcher(FnTs&&... fns) -> StaticUriDispatcher; UriResolveResult Quotient::visitResource( Connection* account, const Uri& uri, diff --git a/lib/user.cpp b/lib/user.cpp index 3c9652b0..85f9d9a7 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -101,7 +101,7 @@ QString User::id() const { return d->id; } bool User::isGuest() const { Q_ASSERT(!d->id.isEmpty() && d->id.startsWith('@')); - auto it = std::find_if_not(d->id.begin() + 1, d->id.end(), + auto it = std::find_if_not(d->id.cbegin() + 1, d->id.cend(), [](QChar c) { return c.isDigit(); }); Q_ASSERT(it != d->id.end()); return *it == ':'; @@ -203,7 +203,7 @@ bool User::Private::doSetAvatar(SourceT&& source, User* q) return; } - defaultAvatar->updateUrl(move(newUrl)); + defaultAvatar->updateUrl(newUrl); emit q->avatarChanged(q, nullptr); }); }); diff --git a/lib/util.cpp b/lib/util.cpp index ffb36068..875d7522 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -161,9 +161,6 @@ static_assert(std::is_same, int>(), "Test fn_arg_t defaulting to first argument"); template -static QString ft(T&&) -{ - return {}; -} +static QString ft(T&&); static_assert(std::is_same)>, QString&&>(), "Test function templates"); diff --git a/tests/quotest.cpp b/tests/quotest.cpp index 19d5eec0..29b33edb 100644 --- a/tests/quotest.cpp +++ b/tests/quotest.cpp @@ -104,17 +104,21 @@ private slots: // Add more tests above here public: - Room* room() const { return targetRoom; } - Connection* connection() const { return targetRoom->connection(); } + [[nodiscard]] Room* room() const { return targetRoom; } + [[nodiscard]] Connection* connection() const + { + return targetRoom->connection(); + } private: - bool checkFileSendingOutcome(const TestToken& thisTest, - const QString& txnId, const QString& fileName); - bool checkRedactionOutcome(const QByteArray& thisTest, - const QString& evtIdToRedact); - - bool validatePendingEvent(const QString& txnId); - bool checkDirectChat() const; + [[nodiscard]] bool checkFileSendingOutcome(const TestToken& thisTest, + const QString& txnId, + const QString& fileName); + [[nodiscard]] bool checkRedactionOutcome(const QByteArray& thisTest, + const QString& evtIdToRedact); + + [[nodiscard]] bool validatePendingEvent(const QString& txnId); + [[nodiscard]] bool checkDirectChat() const; void finishTest(const TestToken& token, bool condition, const char* file, int line); @@ -185,7 +189,7 @@ TestManager::TestManager(int& argc, char** argv) [this](const QString& error) { clog << "Failed to resolve the server: " << error.toStdString() << endl; - this->exit(-2); + QCoreApplication::exit(-2); }, Qt::QueuedConnection); connect(c, &Connection::loginError, this, @@ -195,7 +199,7 @@ TestManager::TestManager(int& argc, char** argv) << message.toStdString() << endl << "Details:" << endl << details.toStdString() << endl; - this->exit(-2); + QCoreApplication::exit(-2); }, Qt::QueuedConnection); connect(c, &Connection::loadedRoomState, this, &TestManager::onNewRoom); @@ -320,7 +324,7 @@ TEST_IMPL(loadMembers) FAIL_TEST(); } r->setDisplayed(); - connect(r, &Room::allMembersLoaded, [this, thisTest, r] { + connect(r, &Room::allMembersLoaded, this, [this, thisTest, r] { FINISH_TEST(r->memberNames().size() >= r->joinedCount()); }); return false; @@ -748,7 +752,7 @@ TEST_IMPL(visitResources) static const QStringList viaServers { "matrix.org", "example.org" }; static const auto viaQuery = std::accumulate(viaServers.cbegin(), viaServers.cend(), joinQuery, - [](QString q, const QString& s) { + [](const QString& q, const QString& s) { return q + "&via=" + s; }); static const QStringList joinByIdUris { @@ -806,7 +810,8 @@ void TestManager::conclude() // Now just wait until all the pending events reach the server connectUntil(room, &Room::messageSent, this, [this, room, plainReport] { const auto& pendingEvents = room->pendingEvents(); - if (auto c = std::count_if(pendingEvents.begin(), pendingEvents.end(), + if (auto c = std::count_if(pendingEvents.cbegin(), + pendingEvents.cend(), [](const PendingEventItem& pe) { return pe.deliveryStatus() < EventStatus::ReachedServer; @@ -837,8 +842,8 @@ void TestManager::finalize() { clog << "Logging out" << endl; c->logout(); - connect(c, &Connection::loggedOut, - this, [this] { this->exit(failed.size() + running.size()); }, + connect(c, &Connection::loggedOut, this, + [this] { QCoreApplication::exit(failed.size() + running.size()); }, Qt::QueuedConnection); } @@ -850,6 +855,7 @@ int main(int argc, char* argv[]) << endl; return -1; } + // NOLINTNEXTLINE(readability-static-accessed-through-instance) return TestManager(argc, argv).exec(); } -- cgit v1.2.3 From f286ef4c5b3c71510d6ef15e8cc12cada84f3682 Mon Sep 17 00:00:00 2001 From: Nicolas Fella Date: Sun, 27 Dec 2020 21:24:06 +0100 Subject: Fix use-after-free of QNetworkReply in BaseJob Usually QNetworkAccessManager expects the user to delete the replies, but when the QNetworkAccessManager itself is deleted it deletes all pending replies (https://code.woboq.org/qt5/qtbase/src/network/access/qnetworkaccessmanager.cpp.html#529). This can lead to use-after-free crashes when d->reply is accessed. By putting the reply into a QPointer the exiting if(d->reply) checks can work properly. (cherry picked from commit 9d854e778d8d6ef8e03e1ea74fe958675b24fd45) --- lib/jobs/basejob.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 3fa1cd94..2ac942f5 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -76,15 +77,6 @@ QDebug BaseJob::Status::dumpToLog(QDebug dbg) const return dbg << ": " << message; } -struct NetworkReplyDeleter : public QScopedPointerDeleteLater { - static inline void cleanup(QNetworkReply* reply) - { - if (reply && reply->isRunning()) - reply->abort(); - QScopedPointerDeleteLater::cleanup(reply); - } -}; - template constexpr auto make_array(Ts&&... items) { @@ -112,6 +104,16 @@ public: retryTimer.setSingleShot(true); } + ~Private() + { + if (reply) { + if (reply->isRunning()) { + reply->abort(); + } + delete reply; + } + } + void sendRequest(); /*! \brief Parse the response byte array into JSON * @@ -140,7 +142,10 @@ public: QByteArrayList expectedKeys; - QScopedPointer reply; + // When the QNetworkAccessManager is destroyed it destroys all pending replies. + // Using QPointer allows us to know when that happend. + QPointer reply; + Status status = Unprepared; QByteArray rawResponse; /// Contains a null document in case of non-JSON body (for a successful @@ -315,16 +320,16 @@ void BaseJob::Private::sendRequest() switch (verb) { case HttpVerb::Get: - reply.reset(connection->nam()->get(req)); + reply = connection->nam()->get(req); break; case HttpVerb::Post: - reply.reset(connection->nam()->post(req, requestData.source())); + reply = connection->nam()->post(req, requestData.source()); break; case HttpVerb::Put: - reply.reset(connection->nam()->put(req, requestData.source())); + reply = connection->nam()->put(req, requestData.source()); break; case HttpVerb::Delete: - reply.reset(connection->nam()->sendCustomRequest(req, "DELETE", requestData.source())); + reply = connection->nam()->sendCustomRequest(req, "DELETE", requestData.source()); break; } } -- cgit v1.2.3 From 12c37cf3ce2aa397050fff6ce846d557524a3fe7 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 27 Dec 2020 23:32:18 +0100 Subject: BaseJob::initiate: add Q_LIKELY ...to show the sunny-day case. (cherry picked from commit 5d15e3b23649a54abdb3812c10f4a7d2ce07d7dd) --- lib/jobs/basejob.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 2ac942f5..135274d6 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -342,7 +342,7 @@ void BaseJob::beforeAbandon() { } void BaseJob::initiate(ConnectionData* connData, bool inBackground) { - if (connData && connData->baseUrl().isValid()) { + if (Q_LIKELY(connData && connData->baseUrl().isValid())) { d->inBackground = inBackground; d->connection = connData; doPrepare(); @@ -355,7 +355,7 @@ void BaseJob::initiate(ConnectionData* connData, bool inBackground) setStatus(FileError, "Request data not ready"); } Q_ASSERT(status().code != Pending); // doPrepare() must NOT set this - if (status().code == Unprepared) { + if (Q_LIKELY(status().code == Unprepared)) { d->connection->submit(this); return; } -- cgit v1.2.3 From 4f06d46d6d6062d6d17f69eeaddb7810edac5bbf Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 7 Jan 2021 21:15:28 +0100 Subject: BaseJob: more logging --- lib/jobs/basejob.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 135274d6..da66a9f2 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -199,6 +199,7 @@ BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, setObjectName(name); connect(&d->timer, &QTimer::timeout, this, &BaseJob::timeout); connect(&d->retryTimer, &QTimer::timeout, this, [this] { + qCDebug(d->logCat) << "Retrying" << this; d->connection->submit(this); }); } @@ -374,8 +375,11 @@ void BaseJob::initiate(ConnectionData* connData, bool inBackground) void BaseJob::sendRequest() { - if (status().code == Abandoned) + if (status().code == Abandoned) { + qCDebug(d->logCat) << "Won't proceed with the abandoned request:" + << d->dumpRequest(); return; + } Q_ASSERT(d->connection && status().code == Pending); qCDebug(d->logCat).noquote() << "Making" << d->dumpRequest(); d->needsToken |= d->connection->needsToken(objectName()); -- cgit v1.2.3 From 12e00b234e5c5f4ed57b5c400d06f780e71014f4 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 7 Jan 2021 21:18:01 +0100 Subject: BaseJob: setStatus(Pending) on scheduling a retry Fixes #437. --- lib/jobs/basejob.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/jobs') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index da66a9f2..5960203d 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -625,6 +625,7 @@ void BaseJob::finishJob() qCWarning(d->logCat).nospace() << this << ": retry #" << d->retriesTaken << " in " << retryIn.count() << " s"; + setStatus(Pending, "Pending retry"); d->retryTimer.start(retryIn); emit retryScheduled(d->retriesTaken, milliseconds(retryIn).count()); return; -- cgit v1.2.3