#include "omemo_db.h" #include #include #include #include #include #include #include #include #include static const QString service_ns = "xxcc/omemo/"; OmemoDb::OmemoDb(const QString &jid) : jid(jid) { } QString OmemoDb::service() const { return service_ns + jid; } QXmppTask OmemoDb::allData() { return QXmpp::Private::makeReadyTask(QXmppOmemoStorage::OmemoData()); } int OmemoDb::storeOwnKeyId(const QString &service, const uint32_t id) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/keyid"); job.setTextData(QString::number(id, 16)); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store own key ID: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } int OmemoDb::storePrivateIdentityKey(const QString &service, const QByteArray &privateIdentityKey) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/privateIdentityKey"); job.setBinaryData(privateIdentityKey); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store private identity key: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } int OmemoDb::storePublicIdentityKey(const QString &service, const QByteArray &publicIdentityKey) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/publicIdentityKey"); job.setBinaryData(publicIdentityKey); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store public identity key: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } int OmemoDb::storeLatestSignedPreKeyId(const QString &service, const uint32_t latestSignedPreKeyId) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/latestSignedPreKeyId"); job.setTextData(QString::number(latestSignedPreKeyId, 16)); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store latest signed prekey ID: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } int OmemoDb::storeLatestPreKeyId(const QString &service, const uint32_t latestPreKeyId) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/latestPreKeyId"); job.setTextData(QString::number(latestPreKeyId, 16)); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store latest prekey ID: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } QXmppTask OmemoDb::setOwnDevice(const std::optional &device) { if (!device.has_value()) return QXmpp::Private::makeReadyTask(); QXmppPromise promise; auto future = QtConcurrent::run( [=] () mutable { const auto &d = device.value(); const auto srv = service(); storeDeviceLabel(srv, d.label) || storeOwnKeyId(srv, d.id) || storePrivateIdentityKey(srv, d.privateIdentityKey) || storePublicIdentityKey(srv, d.publicIdentityKey) || storeLatestSignedPreKeyId(srv, d.latestSignedPreKeyId) || storeLatestPreKeyId(srv, d.latestPreKeyId); promise.finish(); }); return promise.task(); } QXmppTask OmemoDb::addSignedPreKeyPair(const uint32_t keyId, const SignedPreKeyPair &keyPair) { return QXmpp::Private::makeReadyTask(); } QXmppTask OmemoDb::removeSignedPreKeyPair(uint32_t keyId) { return QXmpp::Private::makeReadyTask(); } QXmppTask OmemoDb::addPreKeyPairs( const QHash &keyPairs) { return QXmpp::Private::makeReadyTask(); } QXmppTask OmemoDb::removePreKeyPair(const uint32_t keyId) { return QXmpp::Private::makeReadyTask(); } int OmemoDb::storeDeviceLabel(const QString &service, const QString &label) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/label"); job.setTextData(label); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store device label: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } int OmemoDb::storeKeyId(const QString &service, const QByteArray &keyId) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/key_id"); job.setBinaryData(keyId); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store device keyID: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } int OmemoDb::storeSession(const QString &service, const QByteArray &session) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/session"); job.setBinaryData(session); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store device session: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } int OmemoDb::storeUnrespondedSentStanzasCount(const QString &service, const int count) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/unresponded_sent_stanzas"); job.setTextData(QString::number(count)); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store device unresponded sent stanzas: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } int OmemoDb::storeUnrespondedReceivedStanzasCount(const QString &service, const int count) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/unresponded_received_stanzas"); job.setTextData(QString::number(count)); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store device unresponded received stanzas: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } int OmemoDb::storeRemovalFromDeviceListDate(const QString &service, const QDateTime &dt) { QKeychain::WritePasswordJob job(service); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/unresponded_received_stanzas"); job.setTextData(QString::number(dt.currentMSecsSinceEpoch())); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store device unresponded received stanzas: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; } QXmppTask OmemoDb::addDevice(const QString &jid, const uint32_t deviceId, const Device &device) { const QString fullservice = service_ns + jid; QXmppPromise promise; auto future = QtConcurrent::run( [=] () mutable { storeDeviceLabel(fullservice, device.label) || storeKeyId(fullservice, device.keyId) || storeSession(fullservice, device.session) || storeUnrespondedSentStanzasCount(fullservice, device.unrespondedSentStanzasCount) || storeUnrespondedReceivedStanzasCount(fullservice, device.unrespondedSentStanzasCount) || storeRemovalFromDeviceListDate(fullservice, device.removalFromDeviceListDate); promise.finish(); }); return promise.task(); } QXmppTask OmemoDb::removeDevice(const QString &jid, const uint32_t deviceId) { #if 0 const QString fullservice = service_ns + jid; QKeychain::DeletePasswordJob job(fullservice); QEventLoop loop; loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.setKey("device/unresponded_received_stanzas"); job.setTextData(QString::number(dt.currentMSecsSinceEpoch())); job.start(); loop.exec(); if (job.error()) { std::cerr << "Failed to store device unresponded received stanzas: " << qPrintable(job.errorString()) << std::endl; return -1; } return 0; #endif return QXmpp::Private::makeReadyTask(); } QXmppTask OmemoDb::removeDevices(const QString &jid) { return QXmpp::Private::makeReadyTask(); } QXmppTask OmemoDb::resetAll() { return QXmpp::Private::makeReadyTask(); }