diff options
-rw-r--r-- | lib/connection.cpp | 156 | ||||
-rw-r--r-- | lib/database.cpp | 4 |
2 files changed, 67 insertions, 93 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index dbc6261d..54d79674 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -442,10 +442,9 @@ void Connection::Private::loginToServer(LoginArgTs&&... loginArgs) completeSetup(loginJob->userId()); #ifndef Quotient_E2EE_ENABLED qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; -#else // Quotient_E2EE_ENABLED +#endif // Quotient_E2EE_ENABLED database = new Database(loginJob->userId(), q); database->clear(); -#endif // Quotient_E2EE_ENABLED }); connect(loginJob, &BaseJob::failure, q, [this, loginJob] { emit q->loginError(loginJob->errorString(), loginJob->rawDataSample()); @@ -1891,7 +1890,6 @@ QVector<Connection::SupportedRoomVersion> Connection::availableRoomVersions() co return result; } -#ifdef Quotient_E2EE_ENABLED void Connection::Private::loadOutdatedUserDevices() { QHash<QString, QStringList> users; @@ -1930,112 +1928,84 @@ void Connection::Private::loadOutdatedUserDevices() }); } -void Connection::encryptionUpdate(Room *room) -{ - for(const auto &user : room->users()) { - if(!d->trackedUsers.contains(user->id())) { - d->trackedUsers += user->id(); - d->outdatedUsers += user->id(); - d->encryptionUpdateRequired = true; - } - } -} - void Connection::Private::saveDevicesList() { - if (!cacheState) - return; - - QElapsedTimer et; - et.start(); + q->database()->transaction(); + auto query = q->database()->prepareQuery(QStringLiteral("DELETE FROM tracked_users")); + q->database()->execute(query); + query.prepare(QStringLiteral("INSERT INTO tracked_users(matrixId) VALUES(:matrixId);")); + for (const auto& user : trackedUsers) { + query.bindValue(":matrixId", user); + q->database()->execute(query); + } - QFile outFile { q->e2eeDataDir() % "/deviceslist.json" }; - if (!outFile.open(QFile::WriteOnly)) { - qCWarning(E2EE) << "Error opening" << outFile.fileName() << ":" - << outFile.errorString(); - qCWarning(E2EE) << "Caching the rooms state disabled"; - cacheState = false; - return; + query.prepare(QStringLiteral("DELETE FROM outdated_users")); + q->database()->execute(query); + query.prepare(QStringLiteral("INSERT INTO outdated_users(matrixId) VALUES(:matrixId);")); + for (const auto& user : outdatedUsers) { + query.bindValue(":matrixId", user); + q->database()->execute(query); } - QJsonObject rootObj { - { QStringLiteral("cache_version"), - QJsonObject { - { QStringLiteral("major"), SyncData::cacheVersion().first }, - { QStringLiteral("minor"), SyncData::cacheVersion().second } } } - }; - { - QJsonArray trackedUsersJson; - QJsonArray outdatedUsersJson; - for (const auto &user : trackedUsers) { - trackedUsersJson += user; - } - for (const auto &user : outdatedUsers) { - outdatedUsersJson += user; + query.prepare(QStringLiteral("INSERT INTO tracked_devices(matrixId, deviceId, curveKeyId, curveKey, edKeyId, edKey) VALUES(:matrixId, :deviceId, :curveKeyId, :curveKey, :edKeyId, :edKey);")); + for (const auto& user : deviceKeys.keys()) { + for (const auto& device : deviceKeys[user]) { + auto keys = device.keys.keys(); + auto curveKeyId = keys[0].startsWith(QLatin1String("curve")) ? keys[0] : keys[1]; + auto edKeyId = keys[0].startsWith(QLatin1String("ed")) ? keys[0] : keys[1]; + + query.bindValue(":matrixId", user); + query.bindValue(":deviceId", device.deviceId); + query.bindValue(":curveKeyId", curveKeyId); + query.bindValue(":curveKey", device.keys[curveKeyId]); + query.bindValue(":edKeyId", edKeyId); + query.bindValue(":edKey", device.keys[edKeyId]); + + q->database()->execute(query); } - rootObj.insert(QStringLiteral("tracked_users"), trackedUsersJson); - rootObj.insert(QStringLiteral("outdated_users"), outdatedUsersJson); - const auto devicesList = toJson(deviceKeys); - rootObj.insert(QStringLiteral("devices_list"), devicesList); - rootObj.insert(QStringLiteral("sync_token"), q->nextBatchToken()); } - -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - const auto data = - cacheToBinary - ? QCborValue::fromJsonValue(rootObj).toCbor() - : QJsonDocument(rootObj).toJson(QJsonDocument::Compact); -#else - QJsonDocument json { rootObj }; - const auto data = cacheToBinary ? json.toBinaryData() - : json.toJson(QJsonDocument::Compact); -#endif - qCDebug(PROFILER) << "DeviceList generated in" << et; - - outFile.write(data.data(), data.size()); - qCDebug(E2EE) << "DevicesList saved to" << outFile.fileName(); + q->database()->commit(); } void Connection::Private::loadDevicesList() { - QFile file { q->e2eeDataDir() % "/deviceslist.json" }; - if(!file.exists() || !file.open(QIODevice::ReadOnly)) { - qCDebug(E2EE) << "No devicesList cache exists. Creating new"; - return; - } - auto data = file.readAll(); - const auto json = data.startsWith('{') - ? QJsonDocument::fromJson(data).object() -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - : QCborValue::fromCbor(data).toJsonValue().toObject() -#else - : QJsonDocument::fromBinaryData(data).object() -#endif - ; - if (json.isEmpty()) { - qCWarning(MAIN) << "DevicesList cache is broken or empty, discarding"; - return; + auto query = q->database()->prepareQuery(QStringLiteral("SELECT * FROM tracked_users;")); + q->database()->execute(query); + while(query.next()) { + trackedUsers += query.value(0).toString(); } - for(const auto &user : json["tracked_users"].toArray()) { - trackedUsers += user.toString(); + + query = q->database()->prepareQuery(QStringLiteral("SELECT * FROM outdated_users;")); + q->database()->execute(query); + while(query.next()) { + outdatedUsers += query.value(0).toString(); } - for(const auto &user : json["outdated_users"].toArray()) { - outdatedUsers += user.toString(); + + query = q->database()->prepareQuery(QStringLiteral("SELECT * FROM tracked_devices;")); + q->database()->execute(query); + while(query.next()) { + deviceKeys[query.value("matrixId").toString()][query.value("deviceId").toString()] = DeviceKeys { + query.value("matrixId").toString(), + query.value("deviceId").toString(), + { "m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"}, + {{query.value("curveKeyId").toString(), query.value("curveKey").toString()}, + {query.value("edKeyId").toString(), query.value("edKey").toString()}}, + {} // Signatures are not saved/loaded as they are not needed after initial validation + }; } - fromJson(json["devices_list"], deviceKeys); - auto oldToken = json["sync_token"].toString(); - auto changesJob = q->callApi<GetKeysChangesJob>(oldToken, q->nextBatchToken()); - connect(changesJob, &BaseJob::success, q, [this, changesJob](){ - bool hasNewOutdatedUser = false; - for(const auto &user : changesJob->changed()) { - outdatedUsers += user; - hasNewOutdatedUser = true; - } - if(hasNewOutdatedUser) { - loadOutdatedUserDevices(); +} + +#ifdef Quotient_E2EE_ENABLED +void Connection::encryptionUpdate(Room *room) +{ + for(const auto &user : room->users()) { + if(!d->trackedUsers.contains(user->id())) { + d->trackedUsers += user->id(); + d->outdatedUsers += user->id(); + d->encryptionUpdateRequired = true; } - }); + } } PicklingMode Connection::picklingMode() const diff --git a/lib/database.cpp b/lib/database.cpp index a5df22af..535920e2 100644 --- a/lib/database.cpp +++ b/lib/database.cpp @@ -86,6 +86,10 @@ void Database::migrateTo1() execute(QStringLiteral("CREATE TABLE inbound_megolm_sessions (roomId TEXT, senderKey TEXT, sessionId TEXT, pickle TEXT);")); execute(QStringLiteral("CREATE TABLE outbound_megolm_sessions (roomId TEXT, senderKey TEXT, sessionId TEXT, pickle TEXT);")); execute(QStringLiteral("CREATE TABLE group_session_record_index (roomId TEXT, sessionId TEXT, i INTEGER, eventId TEXT, ts INTEGER);")); + execute(QStringLiteral("CREATE TABLE tracked_users (matrixId TEXT);")); + execute(QStringLiteral("CREATE TABLE outdated_users (matrixId TEXT);")); + execute(QStringLiteral("CREATE TABLE tracked_devices (matrixId TEXT, deviceId TEXT, curveKeyId TEXT, curveKey TEXT, edKeyId TEXT, edKey TEXT);")); + execute(QStringLiteral("PRAGMA user_version = 1;")); commit(); } |