WIP OMEMO
This commit is contained in:
parent
5edd3047ab
commit
b9163a3146
|
@ -23,6 +23,7 @@ set(PROJECT_SOURCES
|
|||
account.ui
|
||||
accounts.cpp
|
||||
accounts.ui
|
||||
atm_db.cpp
|
||||
client.cpp
|
||||
contact.cpp
|
||||
contact.ui
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#include "atm_db.h"
|
||||
#include <QXmppFutureUtils_p.h>
|
||||
|
||||
AtmDb::AtmDb(const QString &jid, const JidDb &db) :
|
||||
TrustDb(jid, db)
|
||||
{}
|
||||
|
||||
QXmppTask<void> AtmDb::addKeysForPostponedTrustDecisions(
|
||||
const QString &encryption, const QByteArray &senderKeyId,
|
||||
const QList<QXmppTrustMessageKeyOwner> &keyOwners)
|
||||
{
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
QXmppTask<void> AtmDb::removeKeysForPostponedTrustDecisions(
|
||||
const QString &encryption,
|
||||
const QList<QByteArray> &keyIdsForAuthentication,
|
||||
const QList<QByteArray> &keyIdsForDistrusting)
|
||||
{
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
QXmppTask<void> AtmDb::removeKeysForPostponedTrustDecisions(
|
||||
const QString &encryption,
|
||||
const QList<QByteArray> &senderKeyIds)
|
||||
{
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
QXmppTask<void> AtmDb::removeKeysForPostponedTrustDecisions(
|
||||
const QString &encryption)
|
||||
{
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
QXmppTask<QHash<bool, QMultiHash<QString, QByteArray>>>
|
||||
AtmDb::keysForPostponedTrustDecisions(const QString &encryption,
|
||||
const QList<QByteArray> &senderKeyIds)
|
||||
{
|
||||
return QXmpp::Private::makeReadyTask(
|
||||
QHash<bool, QMultiHash<QString, QByteArray>>());
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef ATM_DB_H
|
||||
#define ATM_DB_H
|
||||
|
||||
#include "jiddb.h"
|
||||
#include "trust_db.h"
|
||||
#include <QXmppAtmTrustStorage.h>
|
||||
#include <QXmppTask.h>
|
||||
#include <QXmppTrustMessageKeyOwner.h>
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QMultiHash>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
class AtmDb : public TrustDb, virtual public QXmppAtmTrustStorage
|
||||
{
|
||||
public:
|
||||
AtmDb(const QString &jid, const JidDb &db);
|
||||
|
||||
QXmppTask<void> addKeysForPostponedTrustDecisions(
|
||||
const QString &encryption, const QByteArray &senderKeyId,
|
||||
const QList<QXmppTrustMessageKeyOwner> &keyOwners) override;
|
||||
QXmppTask<void> removeKeysForPostponedTrustDecisions(
|
||||
const QString &encryption,
|
||||
const QList<QByteArray> &keyIdsForAuthentication,
|
||||
const QList<QByteArray> &keyIdsForDistrusting) override;
|
||||
QXmppTask<void> removeKeysForPostponedTrustDecisions(
|
||||
const QString &encryption,
|
||||
const QList<QByteArray> &senderKeyIds) override;
|
||||
QXmppTask<void> removeKeysForPostponedTrustDecisions(
|
||||
const QString &encryption) override;
|
||||
QXmppTask<QHash<bool, QMultiHash<QString, QByteArray>>>
|
||||
keysForPostponedTrustDecisions(const QString &encryption,
|
||||
const QList<QByteArray> &senderKeyIds = {}) override;
|
||||
};
|
||||
|
||||
#endif
|
30
client.cpp
30
client.cpp
|
@ -1,18 +1,38 @@
|
|||
#include "client.h"
|
||||
#include <QXmppTask.h>
|
||||
#include <QDebug>
|
||||
|
||||
Client::Client(const QString &jid, QObject *const parent) :
|
||||
QXmppClient(parent),
|
||||
jid(jid),
|
||||
db(jid),
|
||||
trust_db(jid, db),
|
||||
trust(&trust_db),
|
||||
omemo_db(jid),
|
||||
db(this->jid),
|
||||
atm_db(this->jid, db),
|
||||
atm(&atm_db),
|
||||
omemo_db(this->jid),
|
||||
omemo(&omemo_db)
|
||||
{
|
||||
addExtension(&trust);
|
||||
addExtension(&atm);
|
||||
addExtension(&carbon);
|
||||
addExtension(&mam);
|
||||
addExtension(&pubsub);
|
||||
addExtension(&omemo);
|
||||
|
||||
connect(this, &QXmppClient::connected, this,
|
||||
[this]()
|
||||
{
|
||||
omemo.setUp().then(this,
|
||||
[](const bool &&result)
|
||||
{
|
||||
qDebug() << "setUp result: " << result;
|
||||
});
|
||||
});
|
||||
|
||||
omemo.setSecurityPolicy(QXmpp::TrustSecurityPolicy::Toakafa);
|
||||
omemo.load().then(this,
|
||||
[=](const bool &&result)
|
||||
{
|
||||
qDebug() << "load result: " << result;
|
||||
});
|
||||
}
|
||||
|
||||
QString Client::jidBare()
|
||||
|
|
12
client.h
12
client.h
|
@ -1,12 +1,16 @@
|
|||
#ifndef CLIENT_H
|
||||
#define CLIENT_H
|
||||
|
||||
#include "omemo_db.h"
|
||||
#include "atm_db.h"
|
||||
#include "jiddb.h"
|
||||
#include "omemo_db.h"
|
||||
#include "trust_db.h"
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QXmppAtmManager.h>
|
||||
#include <QXmppCarbonManagerV2.h>
|
||||
#include <QXmppClient.h>
|
||||
#include <QXmppMamManager.h>
|
||||
#include <QXmppOmemoManager.h>
|
||||
#include <QXmppOmemoStorage.h>
|
||||
#include <QXmppPubSubManager.h>
|
||||
|
@ -22,10 +26,12 @@ public:
|
|||
JidDb &database();
|
||||
|
||||
private:
|
||||
QXmppCarbonManagerV2 carbon;
|
||||
QXmppMamManager mam;
|
||||
const QString jid;
|
||||
JidDb db;
|
||||
TrustDb trust_db;
|
||||
QXmppTrustManager trust;
|
||||
AtmDb atm_db;
|
||||
QXmppAtmManager atm;
|
||||
QXmppPubSubManager pubsub;
|
||||
OmemoDb omemo_db;
|
||||
QXmppOmemoManager omemo;
|
||||
|
|
|
@ -86,7 +86,7 @@ int JidDb::ensureContactTable(const QString &jid) const
|
|||
|
||||
static QString securityPolicyTableName(const QString &encryption)
|
||||
{
|
||||
return "securityPolicy/" + encryption;;
|
||||
return "securityPolicy/" + encryption;
|
||||
}
|
||||
|
||||
int JidDb::ensureSecurityPolicyTable(const QString &encryption,
|
||||
|
@ -109,7 +109,8 @@ int JidDb::ensureSecurityPolicyTable(const QString &encryption,
|
|||
|
||||
static QString keysTableName(const QString &encryption)
|
||||
{
|
||||
return "keys/" + encryption;
|
||||
// return "keys/" + encryption;
|
||||
return "keys";
|
||||
}
|
||||
|
||||
int JidDb::ensureKeysTable(const QString &encryption, QString &table) const
|
||||
|
|
381
omemo_db.cpp
381
omemo_db.cpp
|
@ -8,141 +8,38 @@
|
|||
#include <QString>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
static const QString service_ns = "xxcc/omemo/";
|
||||
static const QString service = "xxcc", key_namespace = "omemo";
|
||||
|
||||
OmemoDb::OmemoDb(const QString &jid) :
|
||||
jid(jid)
|
||||
{
|
||||
}
|
||||
|
||||
QString OmemoDb::service() const
|
||||
{
|
||||
return service_ns + jid;
|
||||
}
|
||||
|
||||
QXmppTask<QXmppOmemoStorage::OmemoData> OmemoDb::allData()
|
||||
{
|
||||
return QXmpp::Private::makeReadyTask(QXmppOmemoStorage::OmemoData());
|
||||
}
|
||||
|
||||
int OmemoDb::storeOwnKeyId(const QString &service, const uint32_t id)
|
||||
QXmppTask<OmemoDb::Result> OmemoDb::storeOwnKeyId(const QString &key,
|
||||
const uint32_t id) const
|
||||
{
|
||||
QKeychain::WritePasswordJob job(service);
|
||||
QEventLoop loop;
|
||||
const auto str = QString::number(id, 16);
|
||||
|
||||
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;
|
||||
return store(key + "/device/ownkeyid", str);
|
||||
}
|
||||
|
||||
QXmppTask<void> OmemoDb::setOwnDevice(const std::optional<OwnDevice> &device)
|
||||
{
|
||||
#if 0
|
||||
if (!device.has_value())
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
|
||||
QXmppPromise<void> promise;
|
||||
auto task = promise.task();
|
||||
|
||||
auto future = QtConcurrent::run(
|
||||
task.then(this,
|
||||
[=] () mutable
|
||||
{
|
||||
const auto &d = device.value();
|
||||
|
@ -158,7 +55,10 @@ QXmppTask<void> OmemoDb::setOwnDevice(const std::optional<OwnDevice> &device)
|
|||
promise.finish();
|
||||
});
|
||||
|
||||
return promise.task();
|
||||
return task;
|
||||
#else
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
#endif
|
||||
}
|
||||
|
||||
QXmppTask<void> OmemoDb::addSignedPreKeyPair(const uint32_t keyId,
|
||||
|
@ -183,158 +83,175 @@ QXmppTask<void> OmemoDb::removePreKeyPair(const uint32_t keyId)
|
|||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
int OmemoDb::storeDeviceLabel(const QString &service, const QString &label)
|
||||
OmemoDb::Store OmemoDb::storeCommon() const
|
||||
{
|
||||
QKeychain::WritePasswordJob job(service);
|
||||
QEventLoop loop;
|
||||
const auto job = new QKeychain::WritePasswordJob(service);
|
||||
QXmppPromise<Result> promise;
|
||||
|
||||
loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
|
||||
job.setKey("device/label");
|
||||
job.setTextData(label);
|
||||
job.start();
|
||||
loop.exec();
|
||||
|
||||
if (job.error())
|
||||
connect(job, &QKeychain::Job::finished, this,
|
||||
[=](QKeychain::Job *job) mutable
|
||||
{
|
||||
std::cerr << "Failed to store device label: "
|
||||
<< qPrintable(job.errorString()) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
if (job->error())
|
||||
{
|
||||
const auto str = "Failed to store device label: "
|
||||
+ job->errorString();
|
||||
std::cerr << qPrintable(str) << std::endl;
|
||||
promise.finish(Error{str});
|
||||
}
|
||||
else
|
||||
promise.finish(QXmpp::Success());
|
||||
});
|
||||
|
||||
return 0;
|
||||
return Store(promise.task(), job);
|
||||
}
|
||||
|
||||
int OmemoDb::storeKeyId(const QString &service, const QByteArray &keyId)
|
||||
QXmppTask<OmemoDb::Result> OmemoDb::store(const QString &key,
|
||||
const QByteArray &data) const
|
||||
{
|
||||
QKeychain::WritePasswordJob job(service);
|
||||
QEventLoop loop;
|
||||
const auto result = storeCommon();
|
||||
const auto job = result.job;
|
||||
|
||||
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;
|
||||
job->setKey(key);
|
||||
job->setBinaryData(data);
|
||||
job->start();
|
||||
return result.task;
|
||||
}
|
||||
|
||||
int OmemoDb::storeSession(const QString &service, const QByteArray &session)
|
||||
QXmppTask<OmemoDb::Result> OmemoDb::store(const QString &key,
|
||||
const QString &data) const
|
||||
{
|
||||
QKeychain::WritePasswordJob job(service);
|
||||
QEventLoop loop;
|
||||
const auto result = storeCommon();
|
||||
const auto job = result.job;
|
||||
|
||||
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;
|
||||
job->setKey(key);
|
||||
job->setTextData(data);
|
||||
job->start();
|
||||
return result.task;
|
||||
}
|
||||
|
||||
int OmemoDb::storeUnrespondedSentStanzasCount(const QString &service,
|
||||
const int count)
|
||||
/* TODO: move to SQLite database. */
|
||||
QXmppTask<OmemoDb::Result> OmemoDb::storeDeviceLabel(const QString &key,
|
||||
const QString &label) const
|
||||
{
|
||||
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;
|
||||
return store(key, label);
|
||||
}
|
||||
|
||||
int OmemoDb::storeUnrespondedReceivedStanzasCount(const QString &service,
|
||||
const int count)
|
||||
QXmppTask<OmemoDb::Result> OmemoDb::storeKeyId(const QString &key,
|
||||
const QByteArray &keyId) const
|
||||
{
|
||||
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;
|
||||
return store(key, keyId);
|
||||
}
|
||||
|
||||
int OmemoDb::storeRemovalFromDeviceListDate(const QString &service,
|
||||
const QDateTime &dt)
|
||||
/* TODO: move to SQLite database. */
|
||||
QXmppTask<OmemoDb::Result> OmemoDb::storeSession(const QString &key,
|
||||
const QByteArray &session) const
|
||||
{
|
||||
QKeychain::WritePasswordJob job(service);
|
||||
QEventLoop loop;
|
||||
return store(key, session);
|
||||
}
|
||||
|
||||
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();
|
||||
QXmppTask<OmemoDb::Result> OmemoDb::storeRemovalFromDeviceListDate(
|
||||
const QString &key, const QDateTime &dt) const
|
||||
{
|
||||
const auto str = QString::number(dt.currentMSecsSinceEpoch());
|
||||
|
||||
if (job.error())
|
||||
return store(key, str);
|
||||
}
|
||||
|
||||
QXmppTask<OmemoDb::Result> OmemoDb::storeUnrespondedReceivedStanzasCount(
|
||||
const QString &key, int count) const
|
||||
{
|
||||
const auto str = QString::number(count, 10);
|
||||
|
||||
return store(key, str);
|
||||
}
|
||||
|
||||
QXmppTask<OmemoDb::Result> OmemoDb::storeUnrespondedSentStanzasCount(
|
||||
const QString &key, int count) const
|
||||
{
|
||||
const auto str = QString::number(count, 10);
|
||||
|
||||
return store(key, str);
|
||||
}
|
||||
|
||||
template<typename T, typename Q> bool OmemoDb::runTask(
|
||||
QXmppPromise<void> &promise, QList<StoreArgs>::const_iterator it,
|
||||
QList<StoreArgs>::const_iterator end)
|
||||
{
|
||||
const auto task = it->fn;
|
||||
|
||||
if (std::holds_alternative<T>(task))
|
||||
{
|
||||
std::cerr << "Failed to store device unresponded received stanzas: "
|
||||
<< qPrintable(job.errorString()) << std::endl;
|
||||
return -1;
|
||||
const auto &fn = std::get<T>(task);
|
||||
auto t = (*this.*fn)(it->key, std::get<Q>(it->data));
|
||||
|
||||
t.then(this,
|
||||
[=](const Result &&result) mutable
|
||||
{
|
||||
if (std::holds_alternative<QXmpp::Success>(result))
|
||||
{
|
||||
std::cerr << "runTask " << qPrintable(it->key)
|
||||
<< " successful" << std::endl;
|
||||
runTask(promise, ++it, end);
|
||||
}
|
||||
else if (std::holds_alternative<Error>(result))
|
||||
{
|
||||
const auto &error = std::get<Error>(result);
|
||||
|
||||
std::cerr << "runTask " << qPrintable(it->key) << " failed: "
|
||||
<< qPrintable(error.description) << std::endl;
|
||||
promise.finish();
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
QXmppTask<void> OmemoDb::runTask(QXmppPromise<void> &promise,
|
||||
QList<OmemoDb::StoreArgs>::const_iterator it,
|
||||
const QList<StoreArgs>::const_iterator end)
|
||||
{
|
||||
if (it != end)
|
||||
{
|
||||
runTask<TaskBA, QByteArray>(promise, it, end)
|
||||
|| runTask<TaskStr, QString>(promise, it, end)
|
||||
|| runTask<TaskInt, int>(promise, it, end)
|
||||
|| runTask<TaskUint32, uint32_t>(promise, it, end);
|
||||
}
|
||||
else
|
||||
promise.finish();
|
||||
|
||||
return promise.task();
|
||||
}
|
||||
|
||||
QXmppTask<void> OmemoDb::addDevice(const QString &jid,
|
||||
const uint32_t deviceId, const Device &device)
|
||||
{
|
||||
const QString fullservice = service_ns + jid;
|
||||
const auto ns = key_namespace + "/" + jid + "/"
|
||||
+ QString::number(deviceId, 16);
|
||||
auto functions = new QList<StoreArgs>;
|
||||
|
||||
*functions << StoreArgs{ns + "/device/label", &OmemoDb::storeDeviceLabel,
|
||||
device.label};
|
||||
*functions << StoreArgs{ns + "/device/keyid", &OmemoDb::storeKeyId,
|
||||
device.keyId};
|
||||
*functions << StoreArgs{ns + "/device/session", &OmemoDb::storeSession,
|
||||
device.session};
|
||||
*functions << StoreArgs{ns + "/device/unrespondedSentStanzas",
|
||||
&OmemoDb::storeUnrespondedSentStanzasCount,
|
||||
device.unrespondedSentStanzasCount};
|
||||
*functions << StoreArgs{ns + "/device/unrespondedReceivedStanzas",
|
||||
&OmemoDb::storeUnrespondedReceivedStanzasCount,
|
||||
device.unrespondedReceivedStanzasCount};
|
||||
*functions << StoreArgs{ns + "removalFromDeviceListDate",
|
||||
&OmemoDb::storeRemovalFromDeviceListDate,
|
||||
device.removalFromDeviceListDate};
|
||||
|
||||
QXmppPromise<void> 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();
|
||||
return runTask(promise, functions->cbegin(), functions->cend());
|
||||
}
|
||||
|
||||
QXmppTask<void> OmemoDb::removeDevice(const QString &jid,
|
||||
|
|
93
omemo_db.h
93
omemo_db.h
|
@ -1,15 +1,20 @@
|
|||
#ifndef OMEMO_DB_H
|
||||
#define OMEMO_DB_H
|
||||
|
||||
#include <QXmppGlobal.h>
|
||||
#include <QXmppOmemoStorage.h>
|
||||
#include <QXmppPromise.h>
|
||||
#include <QXmppTask.h>
|
||||
#include <qt5keychain/keychain.h>
|
||||
#include <QDateTime>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <cstdint>
|
||||
|
||||
class OmemoDb : public QXmppOmemoStorage
|
||||
class OmemoDb : public QObject, public QXmppOmemoStorage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OmemoDb(const QString &jid);
|
||||
QXmppTask<OmemoData> allData() override;
|
||||
|
@ -29,26 +34,74 @@ public:
|
|||
QXmppTask<void> resetAll() override;
|
||||
|
||||
private:
|
||||
struct Error
|
||||
{
|
||||
QString description;
|
||||
};
|
||||
|
||||
using Result = std::variant<QXmpp::Success, Error>;
|
||||
|
||||
struct Store
|
||||
{
|
||||
Store(const QXmppTask<Result> &task, QKeychain::WritePasswordJob *job) :
|
||||
task(task), job(job) {}
|
||||
QXmppTask<Result> task;
|
||||
QKeychain::WritePasswordJob *job;
|
||||
};
|
||||
|
||||
const QString &jid;
|
||||
QString service() const;
|
||||
static int storeOwnKeyId(const QString &service, uint32_t id);
|
||||
static int storePrivateIdentityKey(const QString &service,
|
||||
const QByteArray &privateIdentityKey);
|
||||
static int storePublicIdentityKey(const QString &service,
|
||||
const QByteArray &publicIdentityKey);
|
||||
static int storeLatestSignedPreKeyId(const QString &service,
|
||||
uint32_t latestSignedPreKeyId);
|
||||
static int storeLatestPreKeyId(const QString &service,
|
||||
uint32_t latestPreKeyId);
|
||||
static int storeDeviceLabel(const QString &service, const QString &label);
|
||||
static int storeKeyId(const QString &service, const QByteArray &keyId);
|
||||
static int storeSession(const QString &service, const QByteArray &session);
|
||||
static int storeUnrespondedSentStanzasCount(const QString &service,
|
||||
int count);
|
||||
static int storeUnrespondedReceivedStanzasCount(const QString &service,
|
||||
int count);
|
||||
static int storeRemovalFromDeviceListDate(const QString &service,
|
||||
const QDateTime &dt);
|
||||
QXmppTask<Result> store(const QString &key, const QByteArray &data) const;
|
||||
QXmppTask<Result> store(const QString &key, const QString &data) const;
|
||||
Store storeCommon() const;
|
||||
|
||||
QXmppTask<Result> storeSession(const QString &ns,
|
||||
const QByteArray &session) const;
|
||||
QXmppTask<Result> storeDeviceLabel(const QString &key,
|
||||
const QString &label) const;
|
||||
QXmppTask<Result> storeKeyId(const QString &key,
|
||||
const QByteArray &keyId) const;
|
||||
QXmppTask<Result> storeOwnKeyId(const QString &key, uint32_t id) const;
|
||||
QXmppTask<Result> storePrivateIdentityKey(const QString &key,
|
||||
const QByteArray &privateIdentityKey) const;
|
||||
QXmppTask<Result> storePublicIdentityKey(const QString &key,
|
||||
const QByteArray &publicIdentityKey) const;
|
||||
QXmppTask<Result> storeLatestSignedPreKeyId(const QString &key,
|
||||
uint32_t latestSignedPreKeyId) const;
|
||||
QXmppTask<Result> storeLatestPreKeyId(const QString &key,
|
||||
uint32_t latestPreKeyId) const;
|
||||
QXmppTask<Result> storeUnrespondedSentStanzasCount(const QString &key,
|
||||
int count) const;
|
||||
QXmppTask<Result> storeUnrespondedReceivedStanzasCount(const QString &key,
|
||||
int count) const;
|
||||
QXmppTask<Result> storeRemovalFromDeviceListDate(const QString &key,
|
||||
const QDateTime &dt) const;
|
||||
|
||||
using TaskBA = QXmppTask<Result> (OmemoDb::*)(const QString &,
|
||||
const QByteArray &) const;
|
||||
using TaskStr = QXmppTask<Result> (OmemoDb::*)(const QString &,
|
||||
const QString &) const;
|
||||
using TaskInt = QXmppTask<Result> (OmemoDb::*)(const QString &, int) const;
|
||||
using TaskUint32 = QXmppTask<Result> (OmemoDb::*)(const QString &,
|
||||
uint32_t) const;
|
||||
using TaskDt = QXmppTask<Result> (OmemoDb::*)(const QString &,
|
||||
const QDateTime &) const;
|
||||
using StoreFn = std::variant<TaskBA, TaskStr, TaskInt, TaskUint32, TaskDt>;
|
||||
using StoreData = std::variant<QByteArray , QString, int, uint32_t, QDateTime>;
|
||||
|
||||
struct StoreArgs
|
||||
{
|
||||
QString key;
|
||||
StoreFn fn;
|
||||
StoreData data;
|
||||
};
|
||||
|
||||
QXmppTask<void> runTask(QXmppPromise<void> &promise,
|
||||
QList<StoreArgs>::const_iterator it,
|
||||
QList<StoreArgs>::const_iterator end);
|
||||
|
||||
template<typename T, typename Q> bool runTask(QXmppPromise<void> &promise,
|
||||
QList<StoreArgs>::const_iterator it,
|
||||
QList<StoreArgs>::const_iterator end);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
32
xxcc.cpp
32
xxcc.cpp
|
@ -6,6 +6,7 @@
|
|||
#include "conversation.h"
|
||||
#include "message.h"
|
||||
#include <QXmppMessage.h>
|
||||
#include <QXmppOmemoElement_p.h>
|
||||
#include <QXmppRosterManager.h>
|
||||
#include <QXmppUtils.h>
|
||||
#include <QKeyEvent>
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include <QScroller>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
xxcc::xxcc(QWidget *const parent) :
|
||||
QWidget(parent),
|
||||
|
@ -194,6 +196,8 @@ void xxcc::addAccount(Client *const c)
|
|||
throw std::runtime_error("Expected non-null QXmppRosterManager");
|
||||
}
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
void xxcc::send(void)
|
||||
{
|
||||
if (!selected)
|
||||
|
@ -201,14 +205,32 @@ void xxcc::send(void)
|
|||
|
||||
const auto from = selected->jidBare(),
|
||||
to = ui.jid->text(), msg = ui.chatinput->toPlainText();
|
||||
const bool enc = ui.omemo->isChecked();
|
||||
static const auto encmsg = "This is an OMEMO-encrypted message.";
|
||||
|
||||
QXmppMessage out(from, to, msg);
|
||||
QXmppMessage out(from, to, enc ? encmsg : msg);
|
||||
|
||||
out.setStamp(QDateTime::currentDateTimeUtc());
|
||||
selected->sendPacket(out);
|
||||
addOutMessage(out);
|
||||
storeMessage(out, Direction::Out);
|
||||
ui.chatinput->clear();
|
||||
selected->sendSensitive(std::move(out)).then(this,
|
||||
[=](const QXmpp::SendResult &&result) mutable
|
||||
{
|
||||
qDebug() << "result.index(): " << result.index();
|
||||
|
||||
if (std::holds_alternative<QXmpp::SendSuccess>(result))
|
||||
{
|
||||
const auto &success = std::get<QXmpp::SendSuccess>(result);
|
||||
qDebug() << "acknowledged: " << success.acknowledged;
|
||||
addOutMessage(out);
|
||||
storeMessage(out, Direction::Out);
|
||||
ui.chatinput->clear();
|
||||
}
|
||||
else if (std::holds_alternative<QXmppError>(result))
|
||||
{
|
||||
const auto &error = std::get<QXmppError>(result);
|
||||
qDebug() << error.description;
|
||||
}
|
||||
});
|
||||
// selected->sendPacket(out);
|
||||
}
|
||||
|
||||
void xxcc::storeMessage(const QXmppMessage &msg, const Direction dir) const
|
||||
|
|
5
xxcc.ui
5
xxcc.ui
|
@ -226,10 +226,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="omemo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
|
Loading…
Reference in New Issue