diff options
Diffstat (limited to 'lib')
87 files changed, 727 insertions, 1370 deletions
diff --git a/lib/avatar.cpp b/lib/avatar.cpp index c65aa25c..0573df5d 100644 --- a/lib/avatar.cpp +++ b/lib/avatar.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "avatar.h" @@ -37,9 +25,9 @@ public: explicit Private(QUrl url = {}) : _url(move(url)) {} ~Private() { - if (isJobRunning(_thumbnailRequest)) + if (isJobPending(_thumbnailRequest)) _thumbnailRequest->abandon(); - if (isJobRunning(_uploadRequest)) + if (isJobPending(_uploadRequest)) _uploadRequest->abandon(); } @@ -87,7 +75,7 @@ QImage Avatar::get(Connection* connection, int width, int height, bool Avatar::upload(Connection* connection, const QString& fileName, upload_callback_t callback) const { - if (isJobRunning(d->_uploadRequest)) + if (isJobPending(d->_uploadRequest)) return false; return d->upload(connection->uploadFile(fileName), move(callback)); } @@ -95,7 +83,7 @@ bool Avatar::upload(Connection* connection, const QString& fileName, bool Avatar::upload(Connection* connection, QIODevice* source, upload_callback_t callback) const { - if (isJobRunning(d->_uploadRequest) || !source->isReadable()) + if (isJobPending(d->_uploadRequest) || !source->isReadable()) return false; return d->upload(connection->uploadContent(source), move(callback)); } @@ -125,7 +113,7 @@ QImage Avatar::Private::get(Connection* connection, QSize size, && checkUrl(_url)) { qCDebug(MAIN) << "Getting avatar from" << _url.toString(); _requestedSize = size; - if (isJobRunning(_thumbnailRequest)) + if (isJobPending(_thumbnailRequest)) _thumbnailRequest->abandon(); if (callback) callbacks.emplace_back(move(callback)); @@ -157,7 +145,7 @@ QImage Avatar::Private::get(Connection* connection, QSize size, bool Avatar::Private::upload(UploadContentJob* job, upload_callback_t &&callback) { _uploadRequest = job; - if (!isJobRunning(_uploadRequest)) + if (!isJobPending(_uploadRequest)) return false; _uploadRequest->connect(_uploadRequest, &BaseJob::success, _uploadRequest, [job, callback] { callback(job->contentUri()); }); @@ -194,7 +182,7 @@ bool Avatar::updateUrl(const QUrl& newUrl) d->_url = newUrl; d->_imageSource = Private::Unknown; - if (isJobRunning(d->_thumbnailRequest)) + if (isJobPending(d->_thumbnailRequest)) d->_thumbnailRequest->abandon(); return true; } diff --git a/lib/avatar.h b/lib/avatar.h index 7a566bfa..111f565d 100644 --- a/lib/avatar.h +++ b/lib/avatar.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/connection.cpp b/lib/connection.cpp index 2a86d2eb..015e73c9 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "connection.h" @@ -37,6 +25,7 @@ #include "csapi/versions.h" #include "csapi/voip.h" #include "csapi/wellknown.h" +#include "csapi/whoami.h" #include "events/directchatevent.h" #include "events/eventloader.h" @@ -133,10 +122,27 @@ public: != "json"; bool lazyLoading = false; + /** \brief Check the homeserver and resolve it if needed, before connecting + * + * A single entry for functions that need to check whether the homeserver + * is valid before running. May execute connectFn either synchronously + * or asynchronously. In case of errors, emits resolveError() if + * the homeserver URL is not valid and cannot be resolved from userId, or + * the homeserver doesn't support the requested login flow. + * + * \param userId fully-qualified MXID to resolve HS from + * \param connectFn a function to execute once the HS URL is good + * \param flow optionally, a login flow that should be supported for + * connectFn to work; `none`, if there's no login flow + * requirements + * \sa resolveServer, resolveError + */ + void checkAndConnect(const QString &userId, + const std::function<void ()> &connectFn, + const std::optional<LoginFlow> &flow = none); template <typename... LoginArgTs> void loginToServer(LoginArgTs&&... loginArgs); - void assumeIdentity(const QString& userId, const QString& accessToken, - const QString& deviceId); + void completeSetup(const QString &mxId); void removeRoom(const QString& roomId); void consumeRoomData(SyncDataList&& roomDataList, bool fromCache); @@ -253,7 +259,7 @@ Connection::~Connection() void Connection::resolveServer(const QString& mxid) { - if (isJobRunning(d->resolverJob)) + if (isJobPending(d->resolverJob)) d->resolverJob->abandon(); auto maybeBaseUrl = QUrl::fromUserInput(serverPart(mxid)); @@ -264,14 +270,21 @@ void Connection::resolveServer(const QString& mxid) return; } - auto domain = maybeBaseUrl.host(); - qCDebug(MAIN) << "Finding the server" << domain; + qCDebug(MAIN) << "Finding the server" << maybeBaseUrl.host(); - d->data->setBaseUrl(maybeBaseUrl); // Just enough to check .well-known file + const auto& oldBaseUrl = d->data->baseUrl(); + d->data->setBaseUrl(maybeBaseUrl); // Temporarily set it for this one call d->resolverJob = callApi<GetWellknownJob>(); - connect(d->resolverJob, &BaseJob::finished, this, [this, maybeBaseUrl] { - if (d->resolverJob->status() != BaseJob::NotFoundError) { - if (d->resolverJob->status() != BaseJob::Success) { + // Connect to finished() to make sure baseUrl is restored in any case + connect(d->resolverJob, &BaseJob::finished, this, [this, maybeBaseUrl, oldBaseUrl] { + // Revert baseUrl so that setHomeserver() below triggers signals + // in case the base URL actually changed + d->data->setBaseUrl(oldBaseUrl); + if (d->resolverJob->error() == BaseJob::Abandoned) + return; + + if (d->resolverJob->error() != BaseJob::NotFoundError) { + if (!d->resolverJob->status().good()) { qCWarning(MAIN) << "Fetching .well-known file failed, FAIL_PROMPT"; emit resolveError(tr("Failed resolving the homeserver")); @@ -297,12 +310,12 @@ void Connection::resolveServer(const QString& mxid) << "for base URL"; setHomeserver(maybeBaseUrl); } + Q_ASSERT(d->loginFlowsJob != nullptr); // Ensured by setHomeserver() connect(d->loginFlowsJob, &BaseJob::success, this, &Connection::resolved); connect(d->loginFlowsJob, &BaseJob::failure, this, [this] { qCWarning(MAIN) << "Homeserver base URL sanity check failed"; - emit resolveError( - tr("The homeserver base URL doesn't seem to work")); + emit resolveError(tr("The homeserver doesn't seem to be working")); }); }); } @@ -325,10 +338,10 @@ void Connection::loginWithPassword(const QString& userId, const QString& initialDeviceName, const QString& deviceId) { - checkAndConnect(userId, [=] { + d->checkAndConnect(userId, [=] { d->loginToServer(LoginFlows::Password.type, makeUserIdentifier(userId), password, /*token*/ "", deviceId, initialDeviceName); - }); + }, LoginFlows::Password); } SsoSession* Connection::prepareForSso(const QString& initialDeviceName, @@ -341,17 +354,30 @@ void Connection::loginWithToken(const QByteArray& loginToken, const QString& initialDeviceName, const QString& deviceId) { + Q_ASSERT(d->data->baseUrl().isValid() && d->loginFlows.contains(LoginFlows::Token)); d->loginToServer(LoginFlows::Token.type, none /*user is encoded in loginToken*/, "" /*password*/, loginToken, deviceId, initialDeviceName); } -void Connection::assumeIdentity(const QString& userId, - const QString& accessToken, +void Connection::assumeIdentity(const QString& mxId, const QString& accessToken, const QString& deviceId) { - checkAndConnect(userId, - [=] { d->assumeIdentity(userId, accessToken, deviceId); }); + d->checkAndConnect(mxId, [this, mxId, accessToken, deviceId] { + d->data->setToken(accessToken.toLatin1()); + d->data->setDeviceId(deviceId); // Can't we deduce this from access_token? + auto* job = callApi<GetTokenOwnerJob>(); + connect(job, &BaseJob::success, this, [this, job, mxId] { + if (mxId != job->userId()) + qCWarning(MAIN).nospace() + << "The access_token owner (" << job->userId() + << ") is different from passed MXID (" << mxId << ")!"; + d->completeSetup(job->userId()); + }); + connect(job, &BaseJob::failure, this, [this, job] { + emit loginError(job->errorString(), job->rawDataSample()); + }); + }); } void Connection::reloadCapabilities() @@ -391,8 +417,9 @@ void Connection::Private::loginToServer(LoginArgTs&&... loginArgs) auto loginJob = q->callApi<LoginJob>(std::forward<LoginArgTs>(loginArgs)...); connect(loginJob, &BaseJob::success, q, [this, loginJob] { - assumeIdentity(loginJob->userId(), loginJob->accessToken(), - loginJob->deviceId()); + data->setToken(loginJob->accessToken().toLatin1()); + data->setDeviceId(loginJob->deviceId()); + completeSetup(loginJob->userId()); #ifndef Quotient_E2EE_ENABLED qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; #else // Quotient_E2EE_ENABLED @@ -405,21 +432,18 @@ void Connection::Private::loginToServer(LoginArgTs&&... loginArgs) }); } -void Connection::Private::assumeIdentity(const QString& userId, - const QString& accessToken, - const QString& deviceId) +void Connection::Private::completeSetup(const QString& mxId) { - data->setUserId(userId); + data->setUserId(mxId); q->user(); // Creates a User object for the local user - data->setToken(accessToken.toLatin1()); - data->setDeviceId(deviceId); - q->setObjectName(userId % '/' % deviceId); + q->setObjectName(data->userId() % '/' % data->deviceId()); qCDebug(MAIN) << "Using server" << data->baseUrl().toDisplayString() - << "by user" << userId << "from device" << deviceId; + << "by user" << data->userId() + << "from device" << data->deviceId(); #ifndef Quotient_E2EE_ENABLED qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; #else // Quotient_E2EE_ENABLED - AccountSettings accountSettings(userId); + AccountSettings accountSettings(data->userId()); encryptionManager.reset( new EncryptionManager(accountSettings.encryptionAccountPickle())); if (accountSettings.encryptionAccountPickle().isEmpty()) { @@ -432,22 +456,37 @@ void Connection::Private::assumeIdentity(const QString& userId, q->reloadCapabilities(); } -void Connection::checkAndConnect(const QString& userId, - std::function<void()> connectFn) +void Connection::Private::checkAndConnect(const QString& userId, + const std::function<void()>& connectFn, + const std::optional<LoginFlow>& flow) { - if (d->data->baseUrl().isValid()) { + if (data->baseUrl().isValid() && (!flow || loginFlows.contains(*flow))) { connectFn(); return; } - // Not good to go, try to fix the homeserver URL. + // Not good to go, try to ascertain the homeserver URL and flows if (userId.startsWith('@') && userId.indexOf(':') != -1) { - connectSingleShot(this, &Connection::homeserverChanged, this, connectFn); - // NB: doResolveServer can emit resolveError, so this is a part of - // checkAndConnect function contract. - resolveServer(userId); + q->resolveServer(userId); + if (flow) + connectSingleShot(q, &Connection::loginFlowsChanged, q, + [this, flow, connectFn] { + if (loginFlows.contains(*flow)) + connectFn(); + else + emit q->loginError( + tr("The homeserver at %1 does not support" + " the login flow '%2'") + .arg(data->baseUrl().toDisplayString()), + flow->type); + }); + else + connectSingleShot(q, &Connection::homeserverChanged, q, connectFn); } else - emit resolveError(tr("%1 is an invalid homeserver URL") - .arg(d->data->baseUrl().toString())); + emit q->resolveError(tr("Please provide the fully-qualified user id" + " (such as @user:example.org) so that the" + " homeserver could be resolved; the current" + " homeserver URL(%1) is not good") + .arg(data->baseUrl().toDisplayString())); } void Connection::logout() @@ -932,7 +971,7 @@ void Connection::doInDirectChat(User* u, // not left), and delete inexistent (forgotten?) ones along the way. DirectChatsMap removals; for (auto it = d->directChats.constFind(u); - it != d->directChats.constEnd() && it.key() == u; ++it) { + it != d->directChats.cend() && it.key() == u; ++it) { const auto& roomId = *it; if (auto r = room(roomId, JoinState::Join)) { Q_ASSERT(r->id() == roomId); @@ -1178,7 +1217,7 @@ QByteArray Connection::accessToken() const { // The logout job needs access token to do its job; so the token is // kept inside d->data but no more exposed to the outside world. - return isJobRunning(d->logoutJob) ? QByteArray() : d->data->accessToken(); + return isJobPending(d->logoutJob) ? QByteArray() : d->data->accessToken(); } bool Connection::isLoggedIn() const { return !accessToken().isEmpty(); } @@ -1493,12 +1532,10 @@ QByteArray Connection::generateTxnId() const void Connection::setHomeserver(const QUrl& url) { - if (isJobRunning(d->resolverJob)) + if (isJobPending(d->resolverJob)) d->resolverJob->abandon(); - d->resolverJob = nullptr; - if (isJobRunning(d->loginFlowsJob)) + if (isJobPending(d->loginFlowsJob)) d->loginFlowsJob->abandon(); - d->loginFlowsJob = nullptr; d->loginFlows.clear(); if (homeserver() != url) { @@ -1508,7 +1545,7 @@ void Connection::setHomeserver(const QUrl& url) // Whenever a homeserver is updated, retrieve available login flows from it d->loginFlowsJob = callApi<GetLoginFlowsJob>(BackgroundRequest); - connect(d->loginFlowsJob, &BaseJob::finished, this, [this] { + connect(d->loginFlowsJob, &BaseJob::result, this, [this] { if (d->loginFlowsJob->status().good()) d->loginFlows = d->loginFlowsJob->flows(); else diff --git a/lib/connection.h b/lib/connection.h index 6517b909..f3d7d725 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once @@ -62,28 +50,27 @@ class SendToDeviceJob; class SendMessageJob; class LeaveRoomJob; +using LoginFlow = GetLoginFlowsJob::LoginFlow; + +/// Predefined login flows +struct LoginFlows { + static inline const LoginFlow Password { "m.login.password" }; + static inline const LoginFlow SSO { "m.login.sso" }; + static inline const LoginFlow Token { "m.login.token" }; +}; + // To simplify comparisons of LoginFlows -inline bool operator==(const GetLoginFlowsJob::LoginFlow& lhs, - const GetLoginFlowsJob::LoginFlow& rhs) +inline bool operator==(const LoginFlow& lhs, const LoginFlow& rhs) { return lhs.type == rhs.type; } -inline bool operator!=(const GetLoginFlowsJob::LoginFlow& lhs, - const GetLoginFlowsJob::LoginFlow& rhs) +inline bool operator!=(const LoginFlow& lhs, const LoginFlow& rhs) { return !(lhs == rhs); } -/// Predefined login flows -struct LoginFlows { - using LoginFlow = GetLoginFlowsJob::LoginFlow; - static inline const LoginFlow Password { "m.login.password" }; - static inline const LoginFlow SSO { "m.login.sso" }; - static inline const LoginFlow Token { "m.login.token" }; -}; - class Connection; using room_factory_t = @@ -497,20 +484,42 @@ public: setUserFactory(defaultUserFactory<T>()); } -public slots: +public Q_SLOTS: /** Set the homeserver base URL */ void setHomeserver(const QUrl& baseUrl); /** Determine and set the homeserver from MXID */ void resolveServer(const QString& mxid); + /** \brief Log in using a username and password pair + * + * Before logging in, this method checks if the homeserver is valid and + * supports the password login flow. If the homeserver is invalid but + * a full user MXID is provided, this method calls resolveServer() using + * this MXID. + * + * \sa resolveServer, resolveError, loginError + */ void loginWithPassword(const QString& userId, const QString& password, const QString& initialDeviceName, const QString& deviceId = {}); + /** \brief Log in using a login token + * + * One usual case for this method is the final stage of logging in via SSO. + * Unlike loginWithPassword() and assumeIdentity(), this method cannot + * resolve the server from the user name because the full user MXID is + * encoded in the login token. Callers should ensure the homeserver + * sanity in advance. + */ void loginWithToken(const QByteArray& loginToken, const QString& initialDeviceName, const QString& deviceId = {}); - void assumeIdentity(const QString& userId, const QString& accessToken, + /** \brief Use an existing access token to connect to the homeserver + * + * Similar to loginWithPassword(), this method checks that the homeserver + * URL is valid and tries to resolve it from the MXID in case it is not. + */ + void assumeIdentity(const QString& mxId, const QString& accessToken, const QString& deviceId); /*! \deprecated Use loginWithPassword instead */ void connectToServer(const QString& userId, const QString& password, @@ -656,15 +665,15 @@ public slots: */ virtual PostReceiptJob* postReceipt(Room* room, RoomEvent* event); -signals: +Q_SIGNALS: /** * @deprecated * This was a signal resulting from a successful resolveServer(). * Since Connection now provides setHomeserver(), the HS URL * may change even without resolveServer() invocation. Use - * homeserverChanged() instead of resolved(). You can also use - * connectToServer and connectWithToken without the HS URL set in - * advance (i.e. without calling resolveServer), as they now trigger + * loginFLowsChanged() instead of resolved(). You can also use + * loginWith*() and assumeIdentity() without the HS URL set in + * advance (i.e. without calling resolveServer), as they trigger * server name resolution from MXID if the server URL is not valid. */ void resolved(); @@ -853,26 +862,13 @@ protected: */ void onSyncSuccess(SyncData&& data, bool fromCache = false); -protected slots: +protected Q_SLOTS: void syncLoopIteration(); private: class Private; QScopedPointer<Private> d; - /** - * A single entry for functions that need to check whether the - * homeserver is valid before running. May either execute connectFn - * synchronously or asynchronously (if tryResolve is true and - * a DNS lookup is initiated); in case of errors, emits resolveError - * if the homeserver URL is not valid and cannot be resolved from - * userId. - * - * @param userId - fully-qualified MXID to resolve HS from - * @param connectFn - a function to execute once the HS URL is good - */ - void checkAndConnect(const QString& userId, std::function<void()> connectFn); - static room_factory_t _roomFactory; static user_factory_t _userFactory; }; diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index d57363d0..25ab775a 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "connectiondata.h" diff --git a/lib/connectiondata.h b/lib/connectiondata.h index 000099d1..a3b2d39b 100644 --- a/lib/connectiondata.h +++ b/lib/connectiondata.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/converters.cpp b/lib/converters.cpp index e5236bb9..0df880a0 100644 --- a/lib/converters.cpp +++ b/lib/converters.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "converters.h" @@ -32,9 +20,9 @@ QVariant JsonConverter<QVariant>::load(const QJsonValue& jv) return jv.toVariant(); } -QJsonObject JsonConverter<QVariantHash>::dump(const QVariantHash& map) +QJsonObject JsonConverter<QVariantHash>::dump(const QVariantHash& vh) { - return QJsonObject::fromVariantHash(map); + return QJsonObject::fromVariantHash(vh); } QVariantHash JsonConverter<QVariantHash>::load(const QJsonValue& jv) diff --git a/lib/converters.h b/lib/converters.h index 81d7b6d8..d4f19b60 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once @@ -1,3 +1,8 @@ +// SPDX-FileCopyrightText: 2019 Alexey Andreyev <aa13q@ya.ru> +// SPDX-FileCopyrightText: 2019 Kitsune Ral <Kitsune-Ral@users.sf.net> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include "util.h" diff --git a/lib/encryptionmanager.cpp b/lib/encryptionmanager.cpp index 4a1025b2..8d241eb2 100644 --- a/lib/encryptionmanager.cpp +++ b/lib/encryptionmanager.cpp @@ -1,3 +1,8 @@ +// SPDX-FileCopyrightText: 2019 Alexey Andreyev <aa13q@ya.ru> +// SPDX-FileCopyrightText: 2019 Kitsune Ral <Kitsune-Ral@users.sf.net> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + #ifdef Quotient_E2EE_ENABLED #include "encryptionmanager.h" @@ -245,7 +250,7 @@ void EncryptionManager::uploadOneTimeKeys(Connection* connection, if (forceUpdate || d->oneTimeKeyCounts.isEmpty()) { d->uploadOneTimeKeysInitJob = connection->callApi<UploadKeysJob>(); connect(d->uploadOneTimeKeysInitJob, &BaseJob::success, this, [this] { - d->setOneTimeKeyCounts(d->uploadIdentityKeysJob->oneTimeKeyCounts()); + d->setOneTimeKeyCounts(d->uploadOneTimeKeysInitJob->oneTimeKeyCounts()); }); } diff --git a/lib/encryptionmanager.h b/lib/encryptionmanager.h index 5df15e83..0f507337 100644 --- a/lib/encryptionmanager.h +++ b/lib/encryptionmanager.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2019 Alexey Andreyev <aa13q@ya.ru> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + #ifdef Quotient_E2EE_ENABLED #pragma once diff --git a/lib/eventitem.cpp b/lib/eventitem.cpp index 2e2b11c0..9c47e50d 100644 --- a/lib/eventitem.cpp +++ b/lib/eventitem.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "eventitem.h" diff --git a/lib/eventitem.h b/lib/eventitem.h index 7b2c3c44..2d3d9ef6 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -1,25 +1,14 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include "events/stateevent.h" +#include <any> #include <utility> namespace Quotient { @@ -72,6 +61,12 @@ public: return std::exchange(evt, move(other)); } + /// Store arbitrary data with the event item + void setUserData(std::any userData) { data = userData; } + /// Obtain custom data previously stored with the event item + const std::any& userdata() const { return data; } + std::any& userData() { return data; } + protected: template <typename EventT> EventT* getAs() @@ -81,6 +76,7 @@ protected: private: RoomEventPtr evt; + std::any data; }; class TimelineItem : public EventItemBase { diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h index 0f240aa1..d0abf577 100644 --- a/lib/events/accountdataevents.h +++ b/lib/events/accountdataevents.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/callanswerevent.cpp b/lib/events/callanswerevent.cpp index bf096534..f3d0a9a0 100644 --- a/lib/events/callanswerevent.cpp +++ b/lib/events/callanswerevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Marius Gripsgard <marius@ubports.com> + * SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "callanswerevent.h" diff --git a/lib/events/callanswerevent.h b/lib/events/callanswerevent.h index 2709882b..d7214468 100644 --- a/lib/events/callanswerevent.h +++ b/lib/events/callanswerevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Marius Gripsgard <marius@ubports.com> + * SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/callcandidatesevent.cpp b/lib/events/callcandidatesevent.cpp index 24f0dd46..9b765064 100644 --- a/lib/events/callcandidatesevent.cpp +++ b/lib/events/callcandidatesevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Marius Gripsgard <marius@ubports.com> + * SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "callcandidatesevent.h" diff --git a/lib/events/callcandidatesevent.h b/lib/events/callcandidatesevent.h index e224f048..ae3bb150 100644 --- a/lib/events/callcandidatesevent.h +++ b/lib/events/callcandidatesevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Marius Gripsgard <marius@ubports.com> + * SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/callhangupevent.cpp b/lib/events/callhangupevent.cpp index f2117f38..45b84cd4 100644 --- a/lib/events/callhangupevent.cpp +++ b/lib/events/callhangupevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Marius Gripsgard <marius@ubports.com> + * SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "callhangupevent.h" diff --git a/lib/events/callhangupevent.h b/lib/events/callhangupevent.h index 5d73fb62..432f72f5 100644 --- a/lib/events/callhangupevent.h +++ b/lib/events/callhangupevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Marius Gripsgard <marius@ubports.com> + * SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/callinviteevent.cpp b/lib/events/callinviteevent.cpp index 63f331de..86478ada 100644 --- a/lib/events/callinviteevent.cpp +++ b/lib/events/callinviteevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Marius Gripsgard <marius@ubports.com> + * SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "callinviteevent.h" diff --git a/lib/events/callinviteevent.h b/lib/events/callinviteevent.h index b067a492..304c89ac 100644 --- a/lib/events/callinviteevent.h +++ b/lib/events/callinviteevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Marius Gripsgard <marius@ubports.com> + * SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/directchatevent.cpp b/lib/events/directchatevent.cpp index b4027e16..39d11072 100644 --- a/lib/events/directchatevent.cpp +++ b/lib/events/directchatevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "directchatevent.h" diff --git a/lib/events/directchatevent.h b/lib/events/directchatevent.h index bb091c5c..373e36dc 100644 --- a/lib/events/directchatevent.h +++ b/lib/events/directchatevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/encryptedevent.cpp b/lib/events/encryptedevent.cpp index 117aae37..dc9eaf2d 100644 --- a/lib/events/encryptedevent.cpp +++ b/lib/events/encryptedevent.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2019 Alexey Andreyev <aa13q@ya.ru> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + #include "encryptedevent.h" using namespace Quotient; diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h index 235b2aa4..9de08b00 100644 --- a/lib/events/encryptedevent.h +++ b/lib/events/encryptedevent.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2019 Alexey Andreyev <aa13q@ya.ru> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include "e2ee.h" diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h index cbb6d786..3431ddd8 100644 --- a/lib/events/encryptionevent.h +++ b/lib/events/encryptionevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/event.cpp b/lib/events/event.cpp index 96e33864..97edb4e0 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "event.h" @@ -61,11 +49,14 @@ QString Event::matrixType() const { return fullJson()[TypeKeyL].toString(); } QByteArray Event::originalJson() const { return QJsonDocument(_json).toJson(); } +// On const below: this is to catch accidental attempts to change event JSON +// NOLINTNEXTLINE(readability-const-return-type) const QJsonObject Event::contentJson() const { return fullJson()[ContentKeyL].toObject(); } +// NOLINTNEXTLINE(readability-const-return-type) const QJsonObject Event::unsignedJson() const { return fullJson()[UnsignedKeyL].toObject(); diff --git a/lib/events/event.h b/lib/events/event.h index 626a0229..c5752a7a 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once @@ -298,7 +286,7 @@ using Events = EventsArray<Event>; // === is<>(), eventCast<>() and visit<>() === -template <typename EventT> +template <class EventT> inline bool is(const Event& e) { return e.type() == typeId<EventT>(); @@ -309,7 +297,7 @@ inline bool isUnknown(const Event& e) return e.type() == unknownEventTypeId(); } -template <typename EventT, typename BasePtrT> +template <class EventT, typename BasePtrT> inline auto eventCast(const BasePtrT& eptr) -> decltype(static_cast<EventT*>(&*eptr)) { @@ -319,7 +307,7 @@ inline auto eventCast(const BasePtrT& eptr) } // A single generic catch-all visitor -template <typename BaseEventT, typename FnT> +template <class BaseEventT, typename FnT> inline auto visit(const BaseEventT& event, FnT&& visitor) -> decltype(visitor(event)) { @@ -327,18 +315,18 @@ inline auto visit(const BaseEventT& event, FnT&& visitor) } namespace _impl { - template <typename T, typename FnT> - constexpr auto needs_downcast() - { - return !std::is_convertible_v<T, fn_arg_t<FnT>>; - } + // Using bool instead of auto below because auto apparently upsets MSVC + template <class BaseT, typename FnT> + inline constexpr bool needs_downcast = + std::is_base_of_v<BaseT, std::decay_t<fn_arg_t<FnT>>> + && !std::is_same_v<BaseT, std::decay_t<fn_arg_t<FnT>>>; } // A single type-specific void visitor -template <typename BaseEventT, typename FnT> -inline std::enable_if_t<_impl::needs_downcast<BaseEventT, FnT>() +template <class BaseT, typename FnT> +inline auto visit(const BaseT& event, FnT&& visitor) + -> std::enable_if_t<_impl::needs_downcast<BaseT, FnT> && std::is_void_v<fn_return_t<FnT>>> -visit(const BaseEventT& event, FnT&& visitor) { using event_type = fn_arg_t<FnT>; if (is<std::decay_t<event_type>>(event)) @@ -347,10 +335,10 @@ visit(const BaseEventT& event, FnT&& visitor) // A single type-specific non-void visitor with an optional default value // non-voidness is guarded by defaultValue type -template <typename BaseEventT, typename FnT> -inline std::enable_if_t<_impl::needs_downcast<BaseEventT, FnT>(), fn_return_t<FnT>> -visit(const BaseEventT& event, FnT&& visitor, - fn_return_t<FnT>&& defaultValue = {}) +template <class BaseT, typename FnT> +inline auto visit(const BaseT& event, FnT&& visitor, + fn_return_t<FnT>&& defaultValue = {}) + -> std::enable_if_t<_impl::needs_downcast<BaseT, FnT>, fn_return_t<FnT>> { using event_type = fn_arg_t<FnT>; if (is<std::decay_t<event_type>>(event)) @@ -359,9 +347,10 @@ visit(const BaseEventT& event, FnT&& visitor, } // A chain of 2 or more visitors -template <typename BaseEventT, typename FnT1, typename FnT2, typename... FnTs> -inline fn_return_t<FnT1> visit(const BaseEventT& event, FnT1&& visitor1, - FnT2&& visitor2, FnTs&&... visitors) +template <class BaseT, typename FnT1, typename FnT2, typename... FnTs> +inline std::common_type_t<fn_return_t<FnT1>, fn_return_t<FnT2>> visit( + const BaseT& event, FnT1&& visitor1, FnT2&& visitor2, + FnTs&&... visitors) { using event_type1 = fn_arg_t<FnT1>; if (is<std::decay_t<event_type1>>(event)) @@ -374,8 +363,8 @@ inline fn_return_t<FnT1> visit(const BaseEventT& event, FnT1&& visitor1, // over a range of event pointers template <typename RangeT, typename... FnTs> inline auto visitEach(RangeT&& events, FnTs&&... visitors) - -> std::enable_if_t<std::is_convertible_v< - std::decay_t<decltype(**events.begin())>, Event>> + -> std::enable_if_t<std::is_void_v< + decltype(visit(**begin(events), std::forward<FnTs>(visitors)...))>> { for (auto&& evtPtr: events) visit(*evtPtr, std::forward<FnTs>(visitors)...); diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index 0cb9e292..18b1b94b 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "eventcontent.h" diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 9c167d4b..e247adbf 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/eventloader.h b/lib/events/eventloader.h index ebb96441..0d95daf5 100644 --- a/lib/events/eventloader.h +++ b/lib/events/eventloader.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/reactionevent.cpp b/lib/events/reactionevent.cpp index 003c8ead..9b43e372 100644 --- a/lib/events/reactionevent.cpp +++ b/lib/events/reactionevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2019 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2019 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "reactionevent.h" diff --git a/lib/events/reactionevent.h b/lib/events/reactionevent.h index 48b0bc6c..09166b24 100644 --- a/lib/events/reactionevent.h +++ b/lib/events/reactionevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2019 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2019 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/receiptevent.cpp b/lib/events/receiptevent.cpp index deb3c4e8..b6f0fcdd 100644 --- a/lib/events/receiptevent.cpp +++ b/lib/events/receiptevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2016 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ /* diff --git a/lib/events/receiptevent.h b/lib/events/receiptevent.h index b7adea44..ec297a6c 100644 --- a/lib/events/receiptevent.h +++ b/lib/events/receiptevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2016 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/redactionevent.cpp b/lib/events/redactionevent.cpp index bf467718..5889773c 100644 --- a/lib/events/redactionevent.cpp +++ b/lib/events/redactionevent.cpp @@ -1 +1,5 @@ +// SPDX-FileCopyrightText: 2019 Kitsune Ral <Kitsune-Ral@users.sf.net> +// +// SPDX-License-Identifier: CC0-1.0 + #include "redactionevent.h" diff --git a/lib/events/redactionevent.h b/lib/events/redactionevent.h index 3b3af18e..320db6f2 100644 --- a/lib/events/redactionevent.h +++ b/lib/events/redactionevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h index c2100eaa..649412e8 100644 --- a/lib/events/roomavatarevent.h +++ b/lib/events/roomavatarevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/roomcanonicalaliasevent.h b/lib/events/roomcanonicalaliasevent.h index 4a21b7cc..eda94d2d 100644 --- a/lib/events/roomcanonicalaliasevent.h +++ b/lib/events/roomcanonicalaliasevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2020 QMatrixClient project + * SPDX-FileCopyrightText: 2020 QMatrixClient project * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/roomcreateevent.cpp b/lib/events/roomcreateevent.cpp index 0fc7d6b9..3d9ec4a3 100644 --- a/lib/events/roomcreateevent.cpp +++ b/lib/events/roomcreateevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2019 QMatrixClient project + * SPDX-FileCopyrightText: 2019 QMatrixClient project * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "roomcreateevent.h" diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h index 91aefe9e..8328d38a 100644 --- a/lib/events/roomcreateevent.h +++ b/lib/events/roomcreateevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2019 QMatrixClient project + * SPDX-FileCopyrightText: 2019 QMatrixClient project * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/roomevent.cpp b/lib/events/roomevent.cpp index a2dbc07d..2b6ac2be 100644 --- a/lib/events/roomevent.cpp +++ b/lib/events/roomevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "roomevent.h" diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h index 084cb524..3fafecfd 100644 --- a/lib/events/roomevent.h +++ b/lib/events/roomevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/roommemberevent.cpp b/lib/events/roommemberevent.cpp index 913bde74..d093286c 100644 --- a/lib/events/roommemberevent.cpp +++ b/lib/events/roommemberevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "roommemberevent.h" diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index cebaaf10..b7a7c9df 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 616a034f..19d460b8 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "roommessageevent.h" diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index 2501d097..ebc9d564 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/roomtombstoneevent.cpp b/lib/events/roomtombstoneevent.cpp index f93eb60d..163e1d3a 100644 --- a/lib/events/roomtombstoneevent.cpp +++ b/lib/events/roomtombstoneevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2019 QMatrixClient project + * SPDX-FileCopyrightText: 2019 QMatrixClient project * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "roomtombstoneevent.h" diff --git a/lib/events/roomtombstoneevent.h b/lib/events/roomtombstoneevent.h index 2c2f0663..8d50aba0 100644 --- a/lib/events/roomtombstoneevent.h +++ b/lib/events/roomtombstoneevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2019 QMatrixClient project + * SPDX-FileCopyrightText: 2019 QMatrixClient project * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index cde5b0fd..58ba3b5a 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index 5909e8a6..7bde12bb 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "stateevent.h" diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index 20a85f83..0db37767 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/events/stickerevent.cpp b/lib/events/stickerevent.cpp new file mode 100644 index 00000000..ea4dff3f --- /dev/null +++ b/lib/events/stickerevent.cpp @@ -0,0 +1,26 @@ +// SDPX-FileCopyrightText: 2020 Carl Schwan <carlschwan@kde.org> +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "stickerevent.h" + +using namespace Quotient; + +StickerEvent::StickerEvent(const QJsonObject &obj) + : RoomEvent(typeId(), obj) + , m_imageContent(EventContent::ImageContent(obj["content"_ls].toObject())) +{} + +QString StickerEvent::body() const +{ + return content<QString>("body"_ls); +} + +const EventContent::ImageContent &StickerEvent::image() const +{ + return m_imageContent; +} + +QUrl StickerEvent::url() const +{ + return m_imageContent.url; +} diff --git a/lib/events/stickerevent.h b/lib/events/stickerevent.h new file mode 100644 index 00000000..93671086 --- /dev/null +++ b/lib/events/stickerevent.h @@ -0,0 +1,38 @@ +// SDPX-FileCopyrightText: 2020 Carl Schwan <carlschwan@kde.org> +// SPDX-License-Identifier: LGPL-2.1-or-later + +#pragma once + +#include "roomevent.h" +#include "eventcontent.h" + +namespace Quotient { + +/// Sticker messages are specialised image messages that are displayed without +/// controls (e.g. no "download" link, or light-box view on click, as would be +/// displayed for for m.image events). +class StickerEvent : public RoomEvent +{ +public: + DEFINE_EVENT_TYPEID("m.sticker", StickerEvent) + + explicit StickerEvent(const QJsonObject &obj); + + /// \brief A textual representation or associated description of the + /// sticker image. + /// + /// This could be the alt text of the original image, or a message to + /// accompany and further describe the sticker. + QString body() const; + + /// \brief Metadata about the image referred to in url including a + /// thumbnail representation. + const EventContent::ImageContent &image() const; + + /// \brief The URL to the sticker image. This must be a valid mxc:// URI. + QUrl url() const; +private: + EventContent::ImageContent m_imageContent; +}; +REGISTER_EVENT_TYPE(StickerEvent) +} // namespace Quotient diff --git a/lib/events/typingevent.cpp b/lib/events/typingevent.cpp index e102fc79..7d3f71e5 100644 --- a/lib/events/typingevent.cpp +++ b/lib/events/typingevent.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "typingevent.h" diff --git a/lib/events/typingevent.h b/lib/events/typingevent.h index 97e1f9cc..8ca4f8e4 100644 --- a/lib/events/typingevent.h +++ b/lib/events/typingevent.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 422931ee..a0c88581 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "basejob.h" @@ -24,6 +12,7 @@ #include <QtCore/QTimer> #include <QtCore/QStringBuilder> #include <QtCore/QMetaEnum> +#include <QtCore/QPointer> #include <QtNetwork/QNetworkAccessManager> #include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkRequest> @@ -76,15 +65,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 <typename... Ts> constexpr auto make_array(Ts&&... items) { @@ -112,6 +92,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 +130,10 @@ public: QByteArrayList expectedKeys; - QScopedPointer<QNetworkReply, NetworkReplyDeleter> reply; + // When the QNetworkAccessManager is destroyed it destroys all pending replies. + // Using QPointer allows us to know when that happend. + QPointer<QNetworkReply> reply; + Status status = Unprepared; QByteArray rawResponse; /// Contains a null document in case of non-JSON body (for a successful @@ -194,6 +187,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); }); } @@ -258,7 +252,7 @@ void BaseJob::setExpectedContentTypes(const QByteArrayList& contentTypes) d->expectedContentTypes = contentTypes; } -const QByteArrayList BaseJob::expectedKeys() const { return d->expectedKeys; } +QByteArrayList BaseJob::expectedKeys() const { return d->expectedKeys; } void BaseJob::addExpectedKey(const QByteArray& key) { d->expectedKeys << key; } @@ -315,16 +309,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()->deleteResource(req)); + reply = connection->nam()->sendCustomRequest(req, "DELETE", requestData.source()); break; } } @@ -337,7 +331,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(); @@ -350,7 +344,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; } @@ -369,8 +363,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()); @@ -510,14 +507,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") { @@ -615,10 +613,12 @@ 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; } + [[fallthrough]]; default:; } diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index be2926be..3165edd3 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once @@ -136,6 +124,14 @@ public: { return !operator==(other); } + bool operator==(int otherCode) const + { + return code == otherCode; + } + bool operator!=(int otherCode) const + { + return !operator==(otherCode); + } int code; QString message; @@ -251,7 +247,7 @@ public: return dbg << j->objectName(); } -public slots: +public Q_SLOTS: void initiate(ConnectionData* connData, bool inBackground); /** @@ -263,7 +259,7 @@ public slots: */ void abandon(); -signals: +Q_SIGNALS: /** The job is about to send a network request */ void aboutToSendRequest(); @@ -355,7 +351,7 @@ protected: const QByteArrayList& expectedContentTypes() const; void addExpectedContentType(const QByteArray& contentType); void setExpectedContentTypes(const QByteArrayList& contentTypes); - const QByteArrayList expectedKeys() const; + QByteArrayList expectedKeys() const; void addExpectedKey(const QByteArray &key); void setExpectedKeys(const QByteArrayList &keys); @@ -433,7 +429,7 @@ protected: // Job objects should only be deleted via QObject::deleteLater ~BaseJob() override; -protected slots: +protected Q_SLOTS: void timeout(); /*! \brief Check the pending or received reply for upfront issues @@ -456,7 +452,7 @@ protected slots: */ virtual Status checkReply(const QNetworkReply *reply) const; -private slots: +private Q_SLOTS: void sendRequest(); void gotReply(); @@ -470,7 +466,7 @@ private: QScopedPointer<Private> d; }; -inline bool isJobRunning(BaseJob* job) +inline bool isJobPending(BaseJob* job) { return job && job->error() == BaseJob::Pending; } 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<qint64>(); + auto targetSize = sizeHeader.toLongLong(); if (targetSize != -1) if (!d->tempFile->resize(targetSize)) { qCWarning(JOBS) << "Failed to allocate" << targetSize diff --git a/lib/jobs/mediathumbnailjob.cpp b/lib/jobs/mediathumbnailjob.cpp index a69f00e9..fbea8797 100644 --- a/lib/jobs/mediathumbnailjob.cpp +++ b/lib/jobs/mediathumbnailjob.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2016 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "mediathumbnailjob.h" diff --git a/lib/jobs/mediathumbnailjob.h b/lib/jobs/mediathumbnailjob.h index e6d39085..cb55a0b0 100644 --- a/lib/jobs/mediathumbnailjob.h +++ b/lib/jobs/mediathumbnailjob.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2016 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/jobs/postreadmarkersjob.h b/lib/jobs/postreadmarkersjob.h deleted file mode 100644 index 5a4d942c..00000000 --- a/lib/jobs/postreadmarkersjob.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 - */ - -#pragma once - -#include "basejob.h" - -#include <QtCore/QJsonObject> - -using namespace Quotient; - -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 } }); - } -}; diff --git a/lib/jobs/requestdata.h b/lib/jobs/requestdata.h index 9cb5ecaf..2a227646 100644 --- a/lib/jobs/requestdata.h +++ b/lib/jobs/requestdata.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index 9087fe50..beb0a535 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2016 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "syncjob.h" diff --git a/lib/jobs/syncjob.h b/lib/jobs/syncjob.h index bf139a7b..a7d10ed8 100644 --- a/lib/jobs/syncjob.h +++ b/lib/jobs/syncjob.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2016 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/joinstate.h b/lib/joinstate.h index 31c2b6a7..1a7b1add 100644 --- a/lib/joinstate.h +++ b/lib/joinstate.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/logging.cpp b/lib/logging.cpp index c346fbf1..3f757393 100644 --- a/lib/logging.cpp +++ b/lib/logging.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Elvis Angelaccio <elvid.angelaccio@kde.org> + * SPDX-FileCopyrightText: 2017 Elvis Angelaccio <elvid.angelaccio@kde.org> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "logging.h" @@ -24,6 +12,7 @@ LOGGING_CATEGORY(MAIN, "quotient.main") LOGGING_CATEGORY(EVENTS, "quotient.events") LOGGING_CATEGORY(STATE, "quotient.events.state") +LOGGING_CATEGORY(MEMBERS, "quotient.events.members") LOGGING_CATEGORY(MESSAGES, "quotient.events.messages") LOGGING_CATEGORY(EPHEMERAL, "quotient.events.ephemeral") LOGGING_CATEGORY(E2EE, "quotient.e2ee") diff --git a/lib/logging.h b/lib/logging.h index ce4131bb..21d05d8b 100644 --- a/lib/logging.h +++ b/lib/logging.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once @@ -23,6 +11,7 @@ Q_DECLARE_LOGGING_CATEGORY(MAIN) Q_DECLARE_LOGGING_CATEGORY(STATE) +Q_DECLARE_LOGGING_CATEGORY(MEMBERS) Q_DECLARE_LOGGING_CATEGORY(MESSAGES) Q_DECLARE_LOGGING_CATEGORY(EVENTS) Q_DECLARE_LOGGING_CATEGORY(EPHEMERAL) diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index b9037bcc..43a8287a 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "networkaccessmanager.h" @@ -52,9 +40,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/networkaccessmanager.h b/lib/networkaccessmanager.h index a678b80f..6075767a 100644 --- a/lib/networkaccessmanager.h +++ b/lib/networkaccessmanager.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/networksettings.cpp b/lib/networksettings.cpp index 40ecba11..db16034a 100644 --- a/lib/networksettings.cpp +++ b/lib/networksettings.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "networksettings.h" diff --git a/lib/networksettings.h b/lib/networksettings.h index 2399cf5f..31602734 100644 --- a/lib/networksettings.h +++ b/lib/networksettings.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2017 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/qt_connection_util.h b/lib/qt_connection_util.h index 699735d4..158d7a40 100644 --- a/lib/qt_connection_util.h +++ b/lib/qt_connection_util.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2019 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2019 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/quotient_common.h b/lib/quotient_common.h index bb05af05..e2384f12 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2019 Kitsune Ral <Kitsune-Ral@users.sf.net> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include <qobjectdefs.h> diff --git a/lib/room.cpp b/lib/room.cpp index a309cd24..bc89464d 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "room.h" @@ -36,6 +24,7 @@ #include "csapi/room_state.h" #include "csapi/room_upgrades.h" #include "csapi/rooms.h" +#include "csapi/read_markers.h" #include "csapi/tags.h" #include "events/callanswerevent.h" @@ -55,7 +44,6 @@ #include "events/roompowerlevelsevent.h" #include "jobs/downloadfilejob.h" #include "jobs/mediathumbnailjob.h" -#include "jobs/postreadmarkersjob.h" #include "events/roomcanonicalaliasevent.h" #include <QtCore/QDir> @@ -192,7 +180,7 @@ public: // void inviteUser(User* u); // We might get it at some point in time. void insertMemberIntoMap(User* u); - void removeMemberFromMap(const QString& username, User* u); + void removeMemberFromMap(User* u); // This updates the room displayname field (which is the way a room // should be shown in the room list); called whenever the list of @@ -263,10 +251,11 @@ public: for (auto&& eptr : events) { const auto& evt = *eptr; Q_ASSERT(evt.isStateEvent()); - // Update baseState afterwards to make sure that the old state - // is valid and usable inside processStateEvent - changes |= q->processStateEvent(evt); - baseState[{ evt.matrixType(), evt.stateKey() }] = move(eptr); + auto change = q->processStateEvent(evt); + if (change != NoChange) { + changes |= change; + baseState[{ evt.matrixType(), evt.stateKey() }] = move(eptr); + } } if (events.size() > 9 || et.nsecsElapsed() >= profilerMinNsecs()) qCDebug(PROFILER) @@ -350,7 +339,7 @@ public: */ bool processReplacement(const RoomMessageEvent& newEvent); - void setTags(TagsMap newTags); + void setTags(TagsMap&& newTags); QJsonObject toJson() const; @@ -632,8 +621,8 @@ Room::Changes Room::Private::setLastReadEvent(User* u, QString eventId) emit q->readMarkerForUserMoved(u, eventId, storedId); if (isLocalUser(u)) { if (storedId != serverReadMarker) - connection->callApi<PostReadMarkersJob>(BackgroundRequest, id, - storedId); + connection->callApi<SetReadMarkerJob>(BackgroundRequest, id, + storedId); emit q->readMarkerMoved(eventId, storedId); return Change::ReadMarkerChange; } @@ -857,7 +846,7 @@ const Room::RelatedEvents Room::relatedEvents(const RoomEvent& evt, void Room::Private::getAllMembers() { // If already loaded or already loading, there's nothing to do here. - if (q->joinedCount() <= membersMap.size() || isJobRunning(allMembersJob)) + if (q->joinedCount() <= membersMap.size() || isJobPending(allMembersJob)) return; allMembersJob = connection->callApi<GetMembersByRoomJob>( @@ -1010,11 +999,11 @@ TagRecord Room::tag(const QString& name) const { return d->tags.value(name); } std::pair<bool, QString> validatedTag(QString name) { - if (name.contains('.')) + if (name.isEmpty() || name.indexOf('.', 1) != -1) return { false, name }; qCWarning(MAIN) << "The tag" << name - << "doesn't follow the CS API conventions"; + << "doesn't follow the CS API conventions"; name.prepend("u."); qCWarning(MAIN) << "Using " << name << "instead"; @@ -1073,20 +1062,20 @@ 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(); for (const auto& k : keys) - if (const auto& checkRes = validatedTag(k); checkRes.first) { - if (newTags.contains(checkRes.second)) + if (const auto& [adjusted, adjustedTag] = validatedTag(k); adjusted) { + if (newTags.contains(adjustedTag)) newTags.remove(k); else - newTags.insert(checkRes.second, newTags.take(k)); + newTags.insert(adjustedTag, newTags.take(k)); } tags = move(newTags); @@ -1192,8 +1181,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 @@ -1222,8 +1211,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"; @@ -1312,7 +1301,6 @@ void Room::handleRoomKeyEvent(const RoomKeyEvent& roomKeyEvent, 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" @@ -1354,14 +1342,27 @@ Room::Changes Room::Private::setSummary(RoomSummary&& newSummary) void Room::Private::insertMemberIntoMap(User* u) { - const auto userName = u->name(q); - // If there is exactly one namesake of the added user, signal member - // renaming for that other one because the two should be disambiguated now. + const auto maybeUserName = + getCurrentState<RoomMemberEvent>(u->id())->newDisplayName(); + if (!maybeUserName) + qCWarning(MEMBERS) << "insertMemberIntoMap():" << u->id() + << "has no name (even empty)"; + const auto userName = maybeUserName.value_or(QString()); const auto namesakes = membersMap.values(userName); + qCDebug(MEMBERS) << "insertMemberIntoMap(), user" << u->id() + << "with name" << userName << '-' + << namesakes.size() << "namesake(s) found"; - // Callers should check they are not adding an existing user once more. + // Callers should make sure they are not adding an existing user once more Q_ASSERT(!namesakes.contains(u)); + if (namesakes.contains(u)) { // Release version whines but continues + qCCritical(MEMBERS) << "Trying to add a user" << u->id() << "to room" + << q->objectName() << "but that's already in it"; + return; + } + // If there is exactly one namesake of the added user, signal member + // renaming for that other one because the two should be disambiguated now if (namesakes.size() == 1) emit q->memberAboutToRename(namesakes.front(), namesakes.front()->fullName(q)); @@ -1370,18 +1371,43 @@ void Room::Private::insertMemberIntoMap(User* u) emit q->memberRenamed(namesakes.front()); } -void Room::Private::removeMemberFromMap(const QString& username, User* u) +void Room::Private::removeMemberFromMap(User* u) { + const auto userName = + getCurrentState<RoomMemberEvent>( + u->id())->newDisplayName().value_or(QString()); + + qCDebug(MEMBERS) << "removeMemberFromMap(), username" << userName + << "for user" << u->id(); User* namesake = nullptr; - auto namesakes = membersMap.values(username); + auto namesakes = membersMap.values(userName); + // If there was one namesake besides the removed user, signal member + // renaming for it because it doesn't need to be disambiguated any more. if (namesakes.size() == 2) { - namesake = namesakes.front() == u ? namesakes.back() : namesakes.front(); + namesake = + namesakes.front() == u ? namesakes.back() : namesakes.front(); Q_ASSERT_X(namesake != u, __FUNCTION__, "Room members list is broken"); - emit q->memberAboutToRename(namesake, username); + emit q->memberAboutToRename(namesake, userName); + } + if (membersMap.remove(userName, u) == 0) { + qCDebug(MEMBERS) << "No entries removed; checking the whole list"; + // Unless at the stage of initial filling, this no removed entries + // is suspicious; double-check that this user is not found in + // the whole map, and stop (for debug builds) or shout in the logs + // (for release builds) if there's one. That search is O(n), which + // may come rather expensive for larger rooms. + QElapsedTimer et; + auto it = std::find(membersMap.cbegin(), membersMap.cend(), u); + if (et.nsecsElapsed() > profilerMinNsecs() / 10) + qCDebug(MEMBERS) << "...done in" << et; + if (it != membersMap.cend()) { + Q_ASSERT_X(false, __FUNCTION__, + "Mismatched name in the room members list"); + qCCritical(MEMBERS) << "Mismatched name in the room members list;" + " avoiding the list corruption"; + membersMap.remove(it.key(), u); + } } - membersMap.remove(username, u); - // If there was one namesake besides the removed user, signal member - // renaming for it because it doesn't need to be disambiguated any more. if (namesake) emit q->memberRenamed(namesake); } @@ -1423,7 +1449,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::memberName(const QString& mxId) const @@ -1639,15 +1665,15 @@ 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) << "File for transaction" << txnId << "has already been uploaded, bypassing re-upload"; } else { - if (isJobRunning(transferIt->job)) { + if (isJobPending(transferIt->job)) { qCDebug(MESSAGES) << "Abandoning the upload job for transaction" << txnId << "and starting again"; transferIt->job->abandon(); @@ -1680,7 +1706,7 @@ void Room::discardMessage(const QString& txnId) const auto& transferIt = d->fileTransfers.find(txnId); if (transferIt != d->fileTransfers.end()) { Q_ASSERT(transferIt->isUpload); - if (isJobRunning(transferIt->job)) { + if (isJobPending(transferIt->job)) { transferIt->status = FileTransferInfo::Cancelled; transferIt->job->abandon(); emit fileTransferFailed(txnId, tr("File upload cancelled")); @@ -1737,7 +1763,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); @@ -1756,7 +1783,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); @@ -1885,7 +1912,7 @@ void Room::getPreviousContent(int limit, const QString &filter) { d->getPrevious void Room::Private::getPreviousContent(int limit, const QString &filter) { - if (isJobRunning(eventsHistoryJob)) + if (isJobPending(eventsHistoryJob)) return; eventsHistoryJob = @@ -1938,7 +1965,7 @@ void Room::uploadFile(const QString& id, const QUrl& localFilename, "localFilename should point at a local file"); auto fileName = localFilename.toLocalFile(); auto job = connection()->uploadFile(fileName, overrideContentType); - if (isJobRunning(job)) { + if (isJobPending(job)) { d->fileTransfers[id] = { job, fileName, true }; connect(job, &BaseJob::uploadProgress, this, [this, id](qint64 sent, qint64 total) { @@ -1958,8 +1985,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"; @@ -1994,7 +2021,7 @@ void Room::downloadFile(const QString& eventId, const QUrl& localFilename) qDebug(MAIN) << "File path:" << filePath; } auto job = connection()->downloadFile(fileUrl, filePath); - if (isJobRunning(job)) { + if (isJobPending(job)) { // If there was a previous transfer (completed or failed), overwrite it. d->fileTransfers[eventId] = { job, job->targetFileName() }; connect(job, &BaseJob::downloadProgress, this, @@ -2016,13 +2043,13 @@ 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; } - if (isJobRunning(it->job)) + if (isJobPending(it->job)) it->job->abandon(); d->fileTransfers.remove(id); emit fileTransferCancelled(id); @@ -2119,8 +2146,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)); @@ -2190,8 +2217,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)); @@ -2434,57 +2461,95 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events) Room::Changes Room::processStateEvent(const RoomEvent& e) { if (!e.isStateEvent()) - return Change::NoChange; + return 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 - visit(e, [this, oldRme = static_cast<const RoomMemberEvent*>(curStateEvent)]( - const RoomMemberEvent& rme) { - auto* u = user(rme.userId()); - if (!u) { // ??? - qCCritical(MAIN) - << "Could not get a user object for" << rme.userId(); - return; - } - const auto prevMembership = oldRme ? oldRme->membership() - : MembershipType::Leave; - switch (prevMembership) { - case MembershipType::Invite: - if (rme.membership() != prevMembership) { - d->usersInvited.removeOne(u); - Q_ASSERT(!d->usersInvited.contains(u)); + // clang-format off + const bool proceed = visit(e + , [this, curStateEvent](const RoomMemberEvent& rme) { + // clang-format on + auto* oldRme = static_cast<const RoomMemberEvent*>(curStateEvent); + auto* u = user(rme.userId()); + if (!u) { // Some terribly malformed user id? + qCCritical(MAIN) << "Could not get a user object for" + << rme.userId(); + return false; // Stay low and hope for the best... } - break; - case MembershipType::Join: - switch (rme.membership()) { - case MembershipType::Join: // rename/avatar change or no-op - if (rme.newDisplayName()) { - emit memberAboutToRename(u, *rme.newDisplayName()); - d->removeMemberFromMap(u->name(this), u); + const auto prevMembership = oldRme ? oldRme->membership() + : MembershipType::Leave; + switch (prevMembership) { + case MembershipType::Invite: + if (rme.membership() != prevMembership) { + d->usersInvited.removeOne(u); + Q_ASSERT(!d->usersInvited.contains(u)); } break; - case MembershipType::Invite: - qCWarning(MAIN) << "Membership change from Join to Invite:" - << rme; - [[fallthrough]]; - default: // whatever the new membership, it's no more Join - d->removeMemberFromMap(u->name(this), u); - emit userRemoved(u); + case MembershipType::Join: + if (rme.membership() == MembershipType::Join) { + // rename/avatar change or no-op + if (rme.newDisplayName()) { + emit memberAboutToRename(u, *rme.newDisplayName()); + d->removeMemberFromMap(u); + } + if (!rme.newDisplayName() && !rme.newAvatarUrl()) { + qCWarning(MEMBERS) + << "No-op membership event for" << rme.userId() + << "- retaining the state"; + qCWarning(MEMBERS) << "The event dump:" << rme; + return false; + } + } else { + if (rme.membership() == MembershipType::Invite) + qCWarning(MAIN) + << "Membership change from Join to Invite:" << rme; + // whatever the new membership, it's no more Join + d->removeMemberFromMap(u); + emit userRemoved(u); + } + break; + case MembershipType::Ban: + case MembershipType::Knock: + case MembershipType::Leave: + if (rme.membership() == MembershipType::Invite + || rme.membership() == MembershipType::Join) { + d->membersLeft.removeOne(u); + Q_ASSERT(!d->membersLeft.contains(u)); + } + break; + case MembershipType::Undefined: + ; // A warning will be dropped in the post-processing block below } - break; - default: - if (rme.membership() == MembershipType::Invite - || rme.membership() == MembershipType::Join) { - d->membersLeft.removeOne(u); - Q_ASSERT(!d->membersLeft.contains(u)); + return true; + // clang-format off + } + , [this, curStateEvent]( const EncryptionEvent& ee) { + // clang-format on + auto* oldEncEvt = + static_cast<const EncryptionEvent*>(curStateEvent); + if (ee.algorithm().isEmpty()) { + qWarning(STATE) + << "The encryption event for room" << objectName() + << "doesn't have 'algorithm' specified - ignoring"; + return false; } + if (oldEncEvt + && oldEncEvt->encryption() != EncryptionEventContent::Undefined) { + qCWarning(STATE) << "The room is already encrypted but a new" + " room encryption event arrived - ignoring"; + return false; + } + return true; + // clang-format off } - }); + , true); // By default, go forward with the state change + // clang-format on + if (!proceed) + return NoChange; // Change the state const auto* const oldStateEvent = @@ -2492,47 +2557,35 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) Q_ASSERT(!oldStateEvent || (oldStateEvent->matrixType() == e.matrixType() && oldStateEvent->stateKey() == e.stateKey())); - if (!is<RoomMemberEvent>(e)) // Room member events are too numerous + if (is<RoomMemberEvent>(e)) + qCDebug(MEMBERS) << "Updated room member state:" << e; + else qCDebug(STATE) << "Updated room state:" << e; // Update internal structures as per the change and work out the return value // clang-format off - return visit(e + const auto result = visit(e , [] (const RoomNameEvent&) { return NameChange; } - , [] (const RoomAliasesEvent&) { - return NoChange; // This event has been removed by MSC2432 - } , [this, oldStateEvent] (const RoomCanonicalAliasEvent& cae) { // clang-format on setObjectName(cae.alias().isEmpty() ? d->id : cae.alias()); - QString previousCanonicalAlias = - oldStateEvent - ? static_cast<const RoomCanonicalAliasEvent*>(oldStateEvent) - ->alias() - : QString(); - - auto previousAltAliases = - oldStateEvent - ? static_cast<const RoomCanonicalAliasEvent*>(oldStateEvent) - ->altAliases() - : QStringList(); - - if (!previousCanonicalAlias.isEmpty()) { - previousAltAliases.push_back(previousCanonicalAlias); + const auto* oldCae = + static_cast<const RoomCanonicalAliasEvent*>(oldStateEvent); + QStringList previousAltAliases {}; + if (oldCae) { + previousAltAliases = oldCae->altAliases(); + if (!oldCae->alias().isEmpty()) + previousAltAliases.push_back(oldCae->alias()); } - const auto previousAliases = std::move(previousAltAliases); - auto newAliases = cae.altAliases(); - - if (!cae.alias().isEmpty()) { + if (!cae.alias().isEmpty()) newAliases.push_front(cae.alias()); - } - connection()->updateRoomAliases(id(), previousAliases, newAliases); + connection()->updateRoomAliases(id(), previousAltAliases, newAliases); return AliasesChange; // clang-format off } @@ -2572,33 +2625,23 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) if (u == localUser() && evt.isDirect()) connection()->addToDirectChats(this, user(evt.senderId())); break; - default: + case MembershipType::Knock: + case MembershipType::Ban: + case MembershipType::Leave: if (!d->membersLeft.contains(u)) d->membersLeft.append(u); + break; + case MembershipType::Undefined: + qCWarning(MEMBERS) << "Ignored undefined membership type"; } return MembersChange; // clang-format off } - , [this, oldEncEvt = static_cast<const EncryptionEvent*>(oldStateEvent)]( - const EncryptionEvent& ee) { - // clang-format on - if (ee.algorithm().isEmpty()) { - qWarning(STATE) - << "The encryption event for room" << objectName() - << "doesn't have 'algorithm' specified - ignoring"; - return NoChange; - } - if (oldEncEvt - && oldEncEvt->encryption() != EncryptionEventContent::Undefined) { - qCWarning(STATE) << "The room is already encrypted but a new" - " room encryption event arrived - ignoring"; - return NoChange; - } + , [this] (const EncryptionEvent&) { // As encryption can only be switched on once, emit the signal here // instead of aggregating and emitting in updateData() emit encryption(); return OtherChange; - // clang-format off } , [this] (const RoomTombstoneEvent& evt) { const auto successorId = evt.successorRoomId(); @@ -2615,9 +2658,12 @@ Room::Changes Room::processStateEvent(const RoomEvent& e) }); return OtherChange; + // clang-format off } - ); + , OtherChange); // clang-format on + Q_ASSERT(result != NoChange); + return result; } Room::Changes Room::processEphemeralEvent(EventPtr&& event) @@ -2779,7 +2825,7 @@ QString Room::Private::calculateDisplayname() const const bool localUserIsIn = joinState == JoinState::Join; const bool emptyRoom = membersMap.isEmpty() - || (membersMap.size() == 1 && isLocalUser(*membersMap.begin())); + || (membersMap.size() == 1 && isLocalUser(*membersMap.cbegin())); const bool nonEmptySummary = summary.heroes && !summary.heroes->empty(); auto shortlist = nonEmptySummary ? buildShortlist(*summary.heroes) : !emptyRoom ? buildShortlist(membersMap) @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once @@ -547,7 +535,7 @@ public: return setState(EvT(std::forward<ArgTs>(args)...)); } -public slots: +public Q_SLOTS: /** Check whether the room should be upgraded */ void checkVersion(); @@ -611,7 +599,7 @@ public slots: void answerCall(const QString& callId, const QString& sdp); void hangupCall(const QString& callId); -signals: +Q_SIGNALS: /// Initial set of state events has been loaded /** * The initial set is what comes from the initial sync for the room. diff --git a/lib/settings.h b/lib/settings.h index c45764a6..badabec2 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2016 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2016 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/syncdata.cpp b/lib/syncdata.cpp index e6472e18..f67ab6c7 100644 --- a/lib/syncdata.cpp +++ b/lib/syncdata.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "syncdata.h" diff --git a/lib/syncdata.h b/lib/syncdata.h index 67d04557..d9868e46 100644 --- a/lib/syncdata.h +++ b/lib/syncdata.h @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once diff --git a/lib/uri.cpp b/lib/uri.cpp index 8370d83a..e0912eb6 100644 --- a/lib/uri.cpp +++ b/lib/uri.cpp @@ -30,7 +30,9 @@ Uri::Uri(QByteArray primaryId, QByteArray secondaryId, QString query) for (const auto& p: replacePairs) if (primaryId[0] == p.sigil) { primaryType_ = Type(p.sigil); - pathToBe = p.uriString + primaryId.mid(1); + auto safePrimaryId = primaryId.mid(1); + safePrimaryId.replace('/', "%2F"); + pathToBe = p.uriString + safePrimaryId; break; } if (!secondaryId.isEmpty()) { @@ -38,11 +40,40 @@ Uri::Uri(QByteArray primaryId, QByteArray secondaryId, QString query) primaryType_ = Invalid; return; } - pathToBe += "/event/" + secondaryId.mid(1); + auto safeSecondaryId = secondaryId.mid(1); + safeSecondaryId.replace('/', "%2F"); + pathToBe += "/event/" + safeSecondaryId; } - setPath(pathToBe); + setPath(pathToBe, QUrl::TolerantMode); } - setQuery(std::move(query)); + if (!query.isEmpty()) + setQuery(query); +} + +static inline auto encodedPath(const QUrl& url) +{ + return url.path(QUrl::EncodeDelimiters | QUrl::EncodeUnicode); +} + +static QString pathSegment(const QUrl& url, int which) +{ + return QUrl::fromPercentEncoding( + encodedPath(url).section('/', which, which).toUtf8()); +} + +static auto decodeFragmentPart(const QStringRef& part) +{ + return QUrl::fromPercentEncoding(part.toLatin1()).toUtf8(); +} + +static auto matrixToUrlRegexInit() +{ + // See https://matrix.org/docs/spec/appendices#matrix-to-navigation + const QRegularExpression MatrixToUrlRE { + "^/(?<main>[^:]+:[^/?]+)(/(?<sec>(\\$|%24)[^?]+))?(\\?(?<query>.+))?$" + }; + Q_ASSERT(MatrixToUrlRE.isValid()); + return MatrixToUrlRE; } Uri::Uri(QUrl url) : QUrl(std::move(url)) @@ -51,14 +82,13 @@ Uri::Uri(QUrl url) : QUrl(std::move(url)) if (isEmpty()) return; // primaryType_ == Empty - if (!QUrl::isValid()) { // MatrixUri::isValid() checks primaryType_ - primaryType_ = Invalid; + primaryType_ = Invalid; + if (!QUrl::isValid()) // MatrixUri::isValid() checks primaryType_ return; - } if (scheme() == "matrix") { // Check sanity as per https://github.com/matrix-org/matrix-doc/pull/2312 - const auto& urlPath = path(); + const auto& urlPath = encodedPath(*this); const auto& splitPath = urlPath.splitRef('/'); switch (splitPath.size()) { case 2: @@ -83,17 +113,15 @@ Uri::Uri(QUrl url) : QUrl(std::move(url)) primaryType_ = NonMatrix; // Default, unless overridden by the code below if (scheme() == "https" && authority() == "matrix.to") { - // See https://matrix.org/docs/spec/appendices#matrix-to-navigation - static const QRegularExpression MatrixToUrlRE { - R"(^/(?<main>[^/?]+)(/(?<sec>[^?]+))?(\?(?<query>.+))?$)" - }; + static const auto MatrixToUrlRE = matrixToUrlRegexInit(); // matrix.to accepts both literal sigils (as well as & and ? used in // its "query" substitute) and their %-encoded forms; // so force QUrl to decode everything. - auto f = fragment(QUrl::FullyDecoded); + auto f = fragment(QUrl::EncodeUnicode); if (auto&& m = MatrixToUrlRE.match(f); m.hasMatch()) - *this = Uri { m.captured("main").toUtf8(), - m.captured("sec").toUtf8(), m.captured("query") }; + *this = Uri { decodeFragmentPart(m.capturedRef("main")), + decodeFragmentPart(m.capturedRef("sec")), + decodeFragmentPart(m.capturedRef("query")) }; } } @@ -119,7 +147,7 @@ Uri::Type Uri::type() const { return primaryType_; } Uri::SecondaryType Uri::secondaryType() const { - return path().section('/', 2, 2) == "event" ? EventId : NoSecondaryId; + return pathSegment(*this, 2) == "event" ? EventId : NoSecondaryId; } QUrl Uri::toUrl(UriForm form) const @@ -128,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"); @@ -148,13 +176,13 @@ QString Uri::primaryId() const if (primaryType_ == Empty || primaryType_ == Invalid) return {}; - const auto& idStem = path().section('/', 1, 1); + const auto& idStem = pathSegment(*this, 1); return idStem.isEmpty() ? idStem : primaryType_ + idStem; } QString Uri::secondaryId() const { - const auto& idStem = path().section('/', 3); + const auto& idStem = pathSegment(*this, 3); return idStem.isEmpty() ? idStem : secondaryType() + idStem; } 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<FnTs...> fns_; }; +template <typename... FnTs> +StaticUriDispatcher(FnTs&&... fns) -> StaticUriDispatcher<FnTs...>; UriResolveResult Quotient::visitResource( Connection* account, const Uri& uri, diff --git a/lib/uriresolver.h b/lib/uriresolver.h index 9b2ced9d..428ce04c 100644 --- a/lib/uriresolver.h +++ b/lib/uriresolver.h @@ -141,7 +141,7 @@ public: return UriResolverBase::visitResource(account, uri); } -signals: +Q_SIGNALS: /// An action on a user has been requested void userAction(Quotient::User* user, QString action); diff --git a/lib/user.cpp b/lib/user.cpp index 45a9c121..9c2b76b5 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "user.h" @@ -78,7 +66,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 == ':'; @@ -138,7 +126,7 @@ inline bool User::doSetAvatar(SourceT&& source) connect(j, &BaseJob::success, this, [this, newUrl = QUrl(contentUri)] { if (newUrl == d->defaultAvatar.url()) { - d->defaultAvatar.updateUrl(move(newUrl)); + d->defaultAvatar.updateUrl(newUrl); emit defaultAvatarChanged(); } else qCWarning(MAIN) << "User" << id() @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> + * SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once @@ -122,7 +110,7 @@ public: QString avatarMediaId(const Room* room = nullptr) const; QUrl avatarUrl(const Room* room = nullptr) const; -public slots: +public Q_SLOTS: /// Set a new name in the global user profile void rename(const QString& newName); /// Set a new name for the user in one room @@ -143,7 +131,7 @@ public slots: /// Check whether the user is in ignore list bool isIgnored() const; -signals: +Q_SIGNALS: void defaultNameChanged(); void defaultAvatarChanged(); diff --git a/lib/util.cpp b/lib/util.cpp index 0c1c54ff..14492ba6 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "util.h" @@ -161,9 +149,6 @@ static_assert(std::is_same<fn_arg_t<Fo1>, int>(), "Test fn_arg_t defaulting to first argument"); template <typename T> -static QString ft(T&&) -{ - return {}; -} +static QString ft(T&&); static_assert(std::is_same<fn_arg_t<decltype(ft<QString>)>, QString&&>(), "Test function templates"); @@ -1,19 +1,7 @@ /****************************************************************************** - * Copyright (C) 2016 Kitsune Ral <kitsune-ral@users.sf.net> + * SPDX-FileCopyrightText: 2016 Kitsune Ral <kitsune-ral@users.sf.net> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 + * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once @@ -148,7 +136,7 @@ public: namespace _impl { template <typename AlwaysVoid, typename> - struct fn_traits; + struct fn_traits {}; } /// Determine traits of an arbitrary function/lambda/functor |