From 26c51455901a6c0112531d86d61d65d31a70dfaa Mon Sep 17 00:00:00 2001 From: Ville Ranki Date: Thu, 4 Apr 2019 11:45:41 +0300 Subject: Ignore some errors on leaving rooms, add new error enum. Fixes #307 --- lib/connection.cpp | 56 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 17 deletions(-) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index a7eae30f..5bf89815 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -110,6 +110,7 @@ class Connection::Private void connectWithToken(const QString& user, const QString& accessToken, const QString& deviceId); + void removeRoom(const QString& roomId); template EventT* unpackAccountData() const @@ -790,29 +791,36 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) if (room && room->joinState() != JoinState::Leave) { auto leaveJob = room->leaveRoom(); - connect(leaveJob, &BaseJob::success, this, [this, forgetJob, room] { - forgetJob->start(connectionData()); - // If the matching /sync response hasn't arrived yet, mark the room - // for explicit deletion - if (room->joinState() != JoinState::Leave) - d->roomIdsToForget.push_back(room->id()); + connect(leaveJob, &BaseJob::result, this, [this, leaveJob, forgetJob, room] { + // After leave, continue if there is no error or the room id is not found (IncorrectRequestError) + if(!leaveJob->error() || leaveJob->error() == BaseJob::StatusCode::UnknownObjectError) { + forgetJob->start(connectionData()); + // If the matching /sync response hasn't arrived yet, mark the room + // for explicit deletion + if (room->joinState() != JoinState::Leave) + d->roomIdsToForget.push_back(room->id()); + } else { + qCWarning(MAIN) << "Error leaving room " + << room->name() << ":" + << leaveJob->errorString(); + forgetJob->abandon(); + } }); connect(leaveJob, &BaseJob::failure, forgetJob, &BaseJob::abandon); } else forgetJob->start(connectionData()); - connect(forgetJob, &BaseJob::success, this, [this, id] + connect(forgetJob, &BaseJob::result, this, [this, id, forgetJob] { - // Delete whatever instances of the room are still in the map. - for (auto f: {false, true}) - if (auto r = d->roomMap.take({ id, f })) - { - qCDebug(MAIN) << "Room" << r->objectName() - << "in state" << toCString(r->joinState()) - << "will be deleted"; - emit r->beforeDestruction(r); - r->deleteLater(); - } + // Leave room in case of success, or room not known by server + if(!forgetJob->error() || forgetJob->error() == BaseJob::StatusCode::IncorrectRequestError || forgetJob->error() == BaseJob::StatusCode::UnknownObjectError) { + // Delete the room from roomMap + d->removeRoom(id); + } else { + qCWarning(MAIN) << "Error forgetting room " + << id << ":" + << forgetJob->errorString(); + } }); return forgetJob; } @@ -1056,6 +1064,20 @@ Connection::DirectChatsMap Connection::directChats() const return d->directChats; } +// Removes room with given id from roomMap +void Connection::Private::removeRoom(const QString& roomId) +{ + for (auto f: {false, true}) + if (auto r = roomMap.take({ roomId, f })) + { + qCDebug(MAIN) << "Room" << r->objectName() + << "in state" << toCString(r->joinState()) + << "will be deleted"; + emit r->beforeDestruction(r); + r->deleteLater(); + } +} + void Connection::addToDirectChats(const Room* room, User* user) { Q_ASSERT(room != nullptr && user != nullptr); -- cgit v1.2.3 From 7591ec34cee15a58611408a996bdb1b92b6ffb98 Mon Sep 17 00:00:00 2001 From: Ville Ranki Date: Tue, 11 Jun 2019 11:58:57 +0300 Subject: Remove unnecessary error checks in lib/connection.cpp Co-Authored-By: Kitsune Ral --- lib/connection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index 5bf89815..27211a77 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -813,7 +813,7 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) connect(forgetJob, &BaseJob::result, this, [this, id, forgetJob] { // Leave room in case of success, or room not known by server - if(!forgetJob->error() || forgetJob->error() == BaseJob::StatusCode::IncorrectRequestError || forgetJob->error() == BaseJob::StatusCode::UnknownObjectError) { + if(!forgetJob->error() || forgetJob->error() == BaseJob::UnknownObjectError) { // Delete the room from roomMap d->removeRoom(id); } else { -- cgit v1.2.3 From a19e12544d174588bb99d1d9d5b2576f0ea1e037 Mon Sep 17 00:00:00 2001 From: Ville Ranki Date: Tue, 11 Jun 2019 11:59:40 +0300 Subject: Comment change as requested Co-Authored-By: Kitsune Ral --- lib/connection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index 27211a77..af2aa2ab 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -792,7 +792,7 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) { auto leaveJob = room->leaveRoom(); connect(leaveJob, &BaseJob::result, this, [this, leaveJob, forgetJob, room] { - // After leave, continue if there is no error or the room id is not found (IncorrectRequestError) + // After leave, continue if there is no error or the room id is not found if(!leaveJob->error() || leaveJob->error() == BaseJob::StatusCode::UnknownObjectError) { forgetJob->start(connectionData()); // If the matching /sync response hasn't arrived yet, mark the room -- cgit v1.2.3 From 12478cf7330727083103d22f76de92c4aa476f5b Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 1 Jul 2019 16:10:35 +0900 Subject: Handle M_UNKNOWN as The Spec says; factor out BaseJob::parseError() --- lib/connection.cpp | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index af2aa2ab..4c068b8f 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -791,21 +791,23 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) if (room && room->joinState() != JoinState::Leave) { auto leaveJob = room->leaveRoom(); - connect(leaveJob, &BaseJob::result, this, [this, leaveJob, forgetJob, room] { - // After leave, continue if there is no error or the room id is not found - if(!leaveJob->error() || leaveJob->error() == BaseJob::StatusCode::UnknownObjectError) { - forgetJob->start(connectionData()); - // If the matching /sync response hasn't arrived yet, mark the room - // for explicit deletion - if (room->joinState() != JoinState::Leave) - d->roomIdsToForget.push_back(room->id()); - } else { - qCWarning(MAIN) << "Error leaving room " - << room->name() << ":" - << leaveJob->errorString(); - forgetJob->abandon(); - } - }); + connect(leaveJob, &BaseJob::result, this, + [this, leaveJob, forgetJob, room] { + if (leaveJob->error() == BaseJob::Success + || leaveJob->error() == BaseJob::NotFoundError) + { + forgetJob->start(connectionData()); + // If the matching /sync response hasn't arrived yet, + // mark the room for explicit deletion + if (room->joinState() != JoinState::Leave) + d->roomIdsToForget.push_back(room->id()); + } else { + qCWarning(MAIN).nospace() + << "Error leaving room " << room->objectName() + << ": " << leaveJob->errorString(); + forgetJob->abandon(); + } + }); connect(leaveJob, &BaseJob::failure, forgetJob, &BaseJob::abandon); } else @@ -813,14 +815,12 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) connect(forgetJob, &BaseJob::result, this, [this, id, forgetJob] { // Leave room in case of success, or room not known by server - if(!forgetJob->error() || forgetJob->error() == BaseJob::UnknownObjectError) { - // Delete the room from roomMap - d->removeRoom(id); - } else { - qCWarning(MAIN) << "Error forgetting room " - << id << ":" - << forgetJob->errorString(); - } + if(forgetJob->error() == BaseJob::Success + || forgetJob->error() == BaseJob::NotFoundError) + d->removeRoom(id); // Delete the room from roomMap + else + qCWarning(MAIN).nospace() << "Error forgetting room " << id << ": " + << forgetJob->errorString(); }); return forgetJob; } -- cgit v1.2.3 From 6a6857b9d4dbf22402f2871494bdd06cdccdf366 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 3 Jul 2019 23:28:09 +0900 Subject: Room/Connection: make room aliases work properly Closes #301. --- lib/connection.cpp | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index 4c068b8f..783e12c0 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -82,8 +82,9 @@ class Connection::Private // separately; specifically, we should keep objects for Invite and // Leave state of the same room if the two happen to co-exist. QHash, Room*> roomMap; - // Mapping from aliases to room ids, as per the last sync - QHash roomAliasMap; + /// Mapping from serverparts to alias/room id mappings, + /// as of the last sync + QHash> roomAliasMap; QVector roomIdsToForget; QVector firstTimeRooms; QVector pendingStateRoomIds; @@ -158,20 +159,31 @@ Connection::~Connection() stopSync(); } -void Connection::resolveServer(const QString& mxidOrDomain) +static const auto ServerPartRegEx = QStringLiteral( + "(\\[[^]]+\\]|[^:@]+)" // Either IPv6 address or hostname/IPv4 address + "(?::(\\d{1,5}))?" // Optional port +); + +QString serverPart(const QString& mxId) { - // At this point we may have something as complex as - // @username:[IPv6:address]:port, or as simple as a plain domain name. + static auto re = "^[@!#$+].+?:(" // Localpart and colon + % ServerPartRegEx % ")$"; + static QRegularExpression parser(re, + QRegularExpression::UseUnicodePropertiesOption); // Because Asian digits + return parser.match(mxId).captured(1); +} - // Try to parse as an FQID; if there's no @ part, assume it's a domain name. - QRegularExpression parser( +void Connection::resolveServer(const QString& mxidOrDomain) +{ + // mxIdOrDomain may be something as complex as + // @username:[IPv6:address]:port, or as simple as a plain serverpart. + static QRegularExpression parser( "^(@.+?:)?" // Optional username (allow everything for compatibility) - "(\\[[^]]+\\]|[^:@]+)" // Either IPv6 address or hostname/IPv4 address - "(:\\d{1,5})?$", // Optional port - QRegularExpression::UseUnicodePropertiesOption); // Because asian digits + % ServerPartRegEx % '$', + QRegularExpression::UseUnicodePropertiesOption); // Because Asian digits auto match = parser.match(mxidOrDomain); - QUrl maybeBaseUrl = QUrl::fromUserInput(match.captured(2)); + auto maybeBaseUrl = QUrl::fromUserInput(match.captured(2)); maybeBaseUrl.setScheme("https"); // Instead of the Qt-default "http" if (!match.hasMatch() || !maybeBaseUrl.isValid()) { @@ -883,33 +895,36 @@ Room* Connection::room(const QString& roomId, JoinStates states) const Room* Connection::roomByAlias(const QString& roomAlias, JoinStates states) const { - const auto id = d->roomAliasMap.value(roomAlias); + const auto id = + d->roomAliasMap.value(serverPart(roomAlias)).value(roomAlias); if (!id.isEmpty()) return room(id, states); + qCWarning(MAIN) << "Room for alias" << roomAlias << "is not found under account" << userId(); return nullptr; } void Connection::updateRoomAliases(const QString& roomId, + const QString& aliasServer, const QStringList& previousRoomAliases, const QStringList& roomAliases) { + auto& aliasMap = d->roomAliasMap[aliasServer]; // Allocate if necessary for (const auto& a: previousRoomAliases) - if (d->roomAliasMap.remove(a) == 0) + if (aliasMap.remove(a) == 0) qCWarning(MAIN) << "Alias" << a << "is not found (already deleted?)"; for (const auto& a: roomAliases) { - auto& mappedId = d->roomAliasMap[a]; + auto& mappedId = aliasMap[a]; if (!mappedId.isEmpty()) { if (mappedId == roomId) - qCDebug(MAIN) << "Alias" << a << "is already mapped to room" + qCDebug(MAIN) << "Alias" << a << "is already mapped to" << roomId; else - qCWarning(MAIN) << "Alias" << a - << "will be force-remapped from room" + qCWarning(MAIN) << "Alias" << a << "will be force-remapped from" << mappedId << "to" << roomId; } mappedId = roomId; -- cgit v1.2.3 From fe82533860a327fbbaa0c980188ccd56d8463b1c Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 4 Jul 2019 13:17:36 +0900 Subject: Connection::token() is no more Use Connection::accessToken() instead. --- lib/connection.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index 783e12c0..cd02f6d7 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -973,11 +973,6 @@ QString Connection::deviceId() const return d->data->deviceId(); } -QString Connection::token() const -{ - return accessToken(); -} - QByteArray Connection::accessToken() const { return d->data->accessToken(); -- cgit v1.2.3 From 69ba71cca36b4a90328d169c845195f39c041a3a Mon Sep 17 00:00:00 2001 From: Alexey Andreyev Date: Sat, 22 Jun 2019 19:57:18 +0300 Subject: Add EncryptionManager class. Add AccountSettings::encryptionAccountPickle logic. --- lib/connection.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index a7eae30f..d7c3d78f 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -23,6 +23,7 @@ #include "events/eventloader.h" #include "room.h" #include "settings.h" +#include "encryptionmanager.h" #include "csapi/login.h" #include "csapi/capabilities.h" #include "csapi/logout.h" @@ -101,6 +102,8 @@ class Connection::Private GetCapabilitiesJob* capabilitiesJob = nullptr; GetCapabilitiesJob::Capabilities capabilities; + QScopedPointer encryptionManager; + SyncJob* syncJob = nullptr; bool cacheState = true; @@ -235,6 +238,13 @@ void Connection::doConnectToServer(const QString& user, const QString& password, [this, loginJob] { d->connectWithToken(loginJob->userId(), loginJob->accessToken(), loginJob->deviceId()); + + AccountSettings accountSettings(loginJob->userId()); + d->encryptionManager.reset(new EncryptionManager(accountSettings.encryptionAccountPickle())); + + d->encryptionManager->uploadIdentityKeys(this); + d->encryptionManager->uploadOneTimeKeys(this); + }); connect(loginJob, &BaseJob::failure, this, [this, loginJob] { -- cgit v1.2.3 From 281e3235d3d4618afd9f01049b8a2acbe1c8475c Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 6 Jul 2019 11:41:08 +0900 Subject: Connection::serverPart: replace auto with QString because of QStringBuilder See https://github.com/KDE/clazy/blob/master/docs/checks/README-auto-unexpected-qstringbuilder.md Closes #613. --- lib/connection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index cd02f6d7..5d377173 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -166,7 +166,7 @@ static const auto ServerPartRegEx = QStringLiteral( QString serverPart(const QString& mxId) { - static auto re = "^[@!#$+].+?:(" // Localpart and colon + static QString re = "^[@!#$+].+?:(" // Localpart and colon % ServerPartRegEx % ")$"; static QRegularExpression parser(re, QRegularExpression::UseUnicodePropertiesOption); // Because Asian digits -- cgit v1.2.3 From 0bfb1c1c69c02c7936cb018ead496616322a1cf7 Mon Sep 17 00:00:00 2001 From: Alexey Andreyev Date: Sun, 7 Jul 2019 21:53:22 +0300 Subject: E2EE: add new account generation logic --- lib/connection.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index 20fb367c..ff066def 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -254,6 +254,9 @@ void Connection::doConnectToServer(const QString& user, const QString& password, AccountSettings accountSettings(loginJob->userId()); d->encryptionManager.reset(new EncryptionManager(accountSettings.encryptionAccountPickle())); + if (accountSettings.encryptionAccountPickle().isEmpty()) { + accountSettings.setEncryptionAccountPickle(d->encryptionManager->olmAccountPickle()); + } d->encryptionManager->uploadIdentityKeys(this); d->encryptionManager->uploadOneTimeKeys(this); -- cgit v1.2.3 From 651478c1681ba6f93e22c20328a048dbbc263ffe Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 8 Jul 2019 21:31:40 +0900 Subject: Move serverPart() to the public API Also: Connection::resolveServer() now only accepts MXIDs, not domains. --- lib/connection.cpp | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) (limited to 'lib/connection.cpp') diff --git a/lib/connection.cpp b/lib/connection.cpp index ff066def..6d06c603 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -162,33 +162,11 @@ Connection::~Connection() stopSync(); } -static const auto ServerPartRegEx = QStringLiteral( - "(\\[[^]]+\\]|[^:@]+)" // Either IPv6 address or hostname/IPv4 address - "(?::(\\d{1,5}))?" // Optional port -); - -QString serverPart(const QString& mxId) +void Connection::resolveServer(const QString& mxid) { - static QString re = "^[@!#$+].+?:(" // Localpart and colon - % ServerPartRegEx % ")$"; - static QRegularExpression parser(re, - QRegularExpression::UseUnicodePropertiesOption); // Because Asian digits - return parser.match(mxId).captured(1); -} - -void Connection::resolveServer(const QString& mxidOrDomain) -{ - // mxIdOrDomain may be something as complex as - // @username:[IPv6:address]:port, or as simple as a plain serverpart. - static QRegularExpression parser( - "^(@.+?:)?" // Optional username (allow everything for compatibility) - % ServerPartRegEx % '$', - QRegularExpression::UseUnicodePropertiesOption); // Because Asian digits - auto match = parser.match(mxidOrDomain); - - auto maybeBaseUrl = QUrl::fromUserInput(match.captured(2)); + auto maybeBaseUrl = QUrl::fromUserInput(serverPart(mxid)); maybeBaseUrl.setScheme("https"); // Instead of the Qt-default "http" - if (!match.hasMatch() || !maybeBaseUrl.isValid()) + if (maybeBaseUrl.isEmpty() || !maybeBaseUrl.isValid()) { emit resolveError( tr("%1 is not a valid homeserver address") -- cgit v1.2.3