summaryrefslogtreecommitdiff
path: root/jiddb.cpp
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2026-02-03 15:59:29 +0100
committerXavier Del Campo Romero <xavi92@disroot.org>2026-02-03 16:26:52 +0100
commitfdb64c59865e4db76addfb8222f6421443e25240 (patch)
tree0de2bad9f758c69b7fb9ba2670653c8515a3a70d /jiddb.cpp
parent207176de48d5e44c8d3e6318b526db5d772dd008 (diff)
downloadyachat6-fdb64c59865e4db76addfb8222f6421443e25240.tar.gz
Import files from xxcc
Diffstat (limited to 'jiddb.cpp')
-rw-r--r--jiddb.cpp912
1 files changed, 912 insertions, 0 deletions
diff --git a/jiddb.cpp b/jiddb.cpp
new file mode 100644
index 0000000..53d77e0
--- /dev/null
+++ b/jiddb.cpp
@@ -0,0 +1,912 @@
+#include "jiddb.h"
+#include <QDir>
+#include <QSqlQuery>
+#include <QSqlError>
+#include <QStandardPaths>
+#include <QTimeZone>
+#include <QVariant>
+#include <iostream>
+#include <stdexcept>
+
+JidDb::JidDb(const QString &jid) :
+ jid(jid),
+ db(QSqlDatabase::addDatabase("QSQLITE"))
+{
+ const auto path = QStandardPaths::writableLocation(
+ QStandardPaths::AppDataLocation);
+ const QDir dir;
+
+ if (!dir.exists(path) && !dir.mkdir(path))
+ throw std::runtime_error("Failed to create app dir");
+
+ const auto abspath = path + "/" + jid + ".db";
+
+ db.setDatabaseName(abspath);
+
+ if (!db.open())
+ throw std::runtime_error(qPrintable("database" + abspath
+ + "could not be created"));
+
+ QSqlQuery q(db);
+
+ if (!q.exec("create table if not exists roster "
+ "(jid TEXT unique) strict;"))
+ std::cerr << "JidDb::JidDb: query exec failed" << std::endl;
+}
+
+int JidDb::addToRoster(const QString &jid)
+{
+ QSqlQuery q(db);
+
+ if (!q.exec("insert or ignore into roster (jid) values ('" + jid + "');"))
+ {
+ std::cerr << "JidDb::addToRoster: query exec failed" << std::endl;
+ return -1;
+ }
+
+ Q_EMIT addedToRoster(jid);
+ return 0;
+}
+
+int JidDb::addToRoster(const QStringList &roster)
+{
+ for (const auto &r : roster)
+ if (addToRoster(r))
+ return -1;
+
+ return 0;
+}
+
+QStringList JidDb::roster() const
+{
+ QStringList ret;
+ QSqlQuery q(db);
+
+ if (!q.exec("select jid from roster;"))
+ std::cerr << "query exec failed" << std::endl;
+ else
+ while (q.next())
+ ret.append(q.value("jid").toString());
+
+ return ret;
+}
+
+int JidDb::ensureContactTable(const QString &jid) const
+{
+ QSqlQuery q(db);
+
+ if (!q.exec("create table if not exists '" + jid +
+ "' (direction TEXT, time INTEGER, body TEXT) strict;"))
+ {
+ std::cerr << "JidDb::storeMessage: query exec failed" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+static QString securityPolicyTableName(const QString &encryption)
+{
+ return "securityPolicy/" + encryption;
+}
+
+int JidDb::ensureSecurityPolicyTable(const QString &encryption,
+ QString &table) const
+{
+ QSqlQuery q(db);
+
+ table = securityPolicyTableName(encryption);
+
+ if (!q.exec("create table if not exists '" + table
+ + "' (policy TEXT unique) strict;"))
+ {
+ std::cerr << "JidDb::ensureSecurityPolicyTable: query exec failed"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+static QString keysTableName(const QString &encryption)
+{
+ return "keys/" + encryption;
+}
+
+int JidDb::ensureKeysTable(const QString &encryption, QString &table) const
+{
+ QSqlQuery q(db);
+
+ table = keysTableName(encryption);
+
+ if (!q.exec("create table if not exists '" + table
+ + "' (owner TEXT, trustlevel TEXT, key TEXT) strict;"))
+ {
+ std::cerr << "JidDb::ensureKeysTable: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+QList<JidDb::Message> JidDb::messages(const QString &jid,
+ const int tail) const
+{
+ QSqlQuery q(db);
+
+ if (ensureContactTable(jid))
+ return QList<Message>();
+ else if (tail < 0)
+ {
+ if (!q.exec("select * from '" + jid + "' order by time;"))
+ {
+ std::cerr << "JidDb::messages: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return QList<Message>();
+ }
+ }
+ else if (!q.exec("select * from '" + jid + "' order by time desc limit "
+ + QString::number(tail) + ";"))
+ {
+ std::cerr << "JidDb::messages: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return QList<Message>();
+ }
+
+ QList<Message> ret;
+
+ while (q.next())
+ {
+ Message m;
+ bool ok;
+ qlonglong t = q.value("time").toLongLong(&ok);
+
+ if (!ok)
+ {
+ std::cerr << "JidDb::messages: invalid time" << std::endl;
+ // Attempt to read other messages.
+ continue;
+ }
+
+ m.body = q.value("body").toString();
+ m.dt = QDateTime::fromSecsSinceEpoch(t, QTimeZone::systemTimeZone());
+
+ const auto dirstr = q.value("direction").toString();
+
+ if (dirstr == "in")
+ m.direction = Direction::In;
+ else if (dirstr == "out")
+ m.direction = Direction::Out;
+ else
+ {
+ std::cerr << "JidDb::messages: invalid direction" << std::endl;
+ // Attempt to read other messages.
+ continue;
+ }
+
+ ret << m;
+ }
+
+ return ret;
+}
+
+int JidDb::store(const JidDb::Message &msg) const
+{
+ QSqlQuery q(db);
+ QString dir;
+
+ switch (msg.direction)
+ {
+ case Direction::In:
+ dir = "in";
+ break;
+
+ case Direction::Out:
+ dir = "out";
+ break;
+ }
+
+ ensureContactTable(msg.contact);
+
+ if (!q.exec("insert into '" + msg.contact
+ + "' (direction, time, body) values "
+ "('" + dir + "', "
+ + QString::number(msg.dt.toSecsSinceEpoch()) + ", "
+ "'" + msg.body + "')"))
+ {
+ std::cerr << "JidDb::storeMessage: query exec 2 failed" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+QStringList JidDb::tables() const
+{
+ QSqlQuery q(db);
+
+ if (!q.exec("select name from sqlite_schema where "
+ "type = 'table' and name not like 'sqlite_%'"))
+ {
+ std::cerr << "JidDb::conversations: query failed" << std::endl;
+ return QStringList();
+ }
+
+ QStringList ret;
+
+ while (q.next())
+ ret << q.value("name").toString();
+
+ return ret;
+}
+
+QList<JidDb::Conversation> JidDb::conversations() const
+{
+ const auto conversations = tables();
+ QList<Conversation> ret;
+
+ for (const auto &jid : conversations)
+ if (jid.contains('@'))
+ {
+ const auto msgs = messages(jid, 1);
+
+ if (!msgs.isEmpty())
+ {
+ const auto &m = msgs.first();
+
+ ret << Conversation(jid, m.body, m.dt);
+ }
+ }
+
+ return ret;
+}
+
+QString JidDb::securityPolicy(const QString &encryption) const
+{
+ const auto tb = tables();
+ const auto name = securityPolicyTableName(encryption);
+
+ for (const auto &t : tb)
+ {
+ if (t == name)
+ {
+ QStringList ret;
+ QSqlQuery q(db);
+
+ if (!q.exec("select policy from '" + name + "';"))
+ std::cerr << "query exec failed" << std::endl;
+ else
+ while (q.next())
+ return q.value("policy").toString();
+
+ break;
+ }
+ }
+
+ return QString();
+}
+
+std::optional<QXmppOmemoStorage::OwnDevice> JidDb::omemoOwnDevice() const
+{
+ return std::optional<QXmppOmemoStorage::OwnDevice>();
+}
+
+int JidDb::store(const QString &encryption, const QString &policy) const
+{
+ QString table;
+
+ if (ensureSecurityPolicyTable(encryption, table))
+ return -1;
+
+ QSqlQuery q(db);
+
+ if (!q.exec("insert or ignore into '" + table
+ + "' (policy) values ('" + policy + "');"))
+ {
+ std::cerr << "JidDb::store: query exec failed"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+QList<JidDb::Keys> JidDb::keys(const QString &encryption) const
+{
+ QList<Keys> ret;
+ QString table;
+
+ if (ensureKeysTable(encryption, table))
+ {
+ std::cerr << "JidDb::keys: ensureKeysTable failed" << std::endl;
+ return QList<Keys>();
+ }
+
+ QSqlQuery q(db);
+
+ if (!q.exec("select owner, trustlevel, key from '" + table + "';"))
+ std::cerr << "JidDb::keys: query exec failed" << std::endl;
+ else
+ while (q.next())
+ {
+ const auto owner = q.value("owner").toString();
+ const auto trust_level = q.value("trustlevel").toString();
+ const auto key_b64 = q.value("key").toString();
+ const auto key = QByteArray::fromBase64(key_b64.toLatin1());
+ bool found = false;
+
+ for (auto &k : ret)
+ if (k.owner == owner)
+ {
+ k.keys.append(key);
+ found = true;
+ break;
+ }
+
+ if (!found)
+ {
+ Keys keys;
+
+ keys.owner = owner;
+ keys.trust_level = trust_level;
+ keys.keys.append(key);
+ ret.append(keys);
+ }
+ }
+
+ return ret;
+}
+
+int JidDb::store(const QString &encryption, const JidDb::Keys &keys) const
+{
+ QString table;
+
+ if (ensureKeysTable(encryption, table))
+ {
+ std::cerr << "JidDb::store: ensureKeysTable failed" << std::endl;
+ return -1;
+ }
+
+ for (const auto &k : keys.keys)
+ {
+ QSqlQuery q(db);
+
+ const auto kstr = k.isEmpty() ? "\"\""
+ : "'" + QString::fromLatin1(k.toBase64()) + "'";
+
+ if (!q.exec("insert or replace into '" + table
+ + "' (owner, trustlevel, key) values ("
+ "'" + keys.owner + "', "
+ "'" + keys.trust_level + "',"
+ + kstr
+ + ");"))
+ {
+ std::cerr << "JidDb::store: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int JidDb::ensureOmemoDeviceTable() const
+{
+ QSqlQuery q(db);
+
+ if (!q.exec("create table if not exists 'omemo/devices' "
+ "(jid TEXT, deviceID INTEGER, keyID TEXT, session TEXT, "
+ "unresp_sent INTEGER, unresp_recv INTEGER, removal INTEGER) "
+ "strict;"))
+ {
+ std::cerr << "JidDb::ensureOmemoTable: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int JidDb::store(const QString &jid, const uint32_t id,
+ const QXmppOmemoStorage::Device &d) const
+{
+ if (ensureOmemoDeviceTable())
+ {
+ std::cerr << "JidDb::store: ensureOmemoTable failed" << std::endl;
+ return -1;
+ }
+
+ QSqlQuery q(db);
+ const auto keyId = d.keyId.isEmpty() ? "\"\""
+ : "'" + QString::fromLatin1(d.keyId.toBase64()) + "'",
+ session = d.session.isEmpty() ? "\"\""
+ : "'" + QString::fromLatin1(d.session.toBase64()) + "'",
+ query = "insert or replace into 'omemo/devices' "
+ "(jid, deviceID, keyID, session, "
+ "unresp_sent, unresp_recv , removal) values ("
+ "'" + jid + "', "
+ + QString::number(id) + ", "
+ + keyId + ", "
+ + session + ", "
+ + QString::number(d.unrespondedSentStanzasCount) + ", "
+ + QString::number(d.unrespondedReceivedStanzasCount) + ", "
+ + QString::number(d.removalFromDeviceListDate.toSecsSinceEpoch())
+ + ");";
+
+ if (!q.exec(query))
+ {
+ std::cerr << "JidDb::store(id, jid, d): query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int JidDb::ensureOmemoSignedPreKeyTable() const
+{
+ QSqlQuery q(db);
+
+ if (!q.exec("create table if not exists 'omemo/signedprekeys' "
+ "(id INTEGER, creation INTEGER, data TEXT) strict;"))
+ {
+ std::cerr << "JidDb::ensureOmemoSignedPreKeyTable: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int JidDb::store(uint32_t id, const QXmppOmemoStorage::SignedPreKeyPair &spk)
+ const
+{
+ if (ensureOmemoSignedPreKeyTable())
+ {
+ std::cerr << "JidDb::store: ensureOmemoSignedPreKeyTable failed"
+ << std::endl;
+ return -1;
+ }
+
+ QSqlQuery q(db);
+ const auto data = spk.data.isEmpty() ? "\"\""
+ : "'" + QString::fromLatin1(spk.data.toBase64()) + "'",
+ query = "insert or replace into 'omemo/signedprekeys' "
+ "(id, creation, data) values ("
+ + QString::number(id) + ", "
+ + QString::number(spk.creationDate.toSecsSinceEpoch()) + ", "
+ + data
+ + ");";
+
+ if (!q.exec(query))
+ {
+ std::cerr << "JidDb::store(spk): query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int JidDb::ensureOmemoPreKeyTable() const
+{
+ QSqlQuery q(db);
+
+ if (!q.exec("create table if not exists 'omemo/prekeys' "
+ "(id INTEGER, data TEXT) strict;"))
+ {
+ std::cerr << "JidDb::ensureOmemoPreKeyTable: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int JidDb::store(const QHash<uint32_t, QByteArray> &pairs) const
+{
+ if (ensureOmemoPreKeyTable())
+ {
+ std::cerr << "JidDb::store: ensureOmemoPreKeyTable failed"
+ << std::endl;
+ return -1;
+ }
+
+ for (const auto id : pairs.keys())
+ {
+ const auto data = pairs.value(id);
+ const auto datastr = data.isEmpty() ? "\"\""
+ : "'" + QString::fromLatin1(data.toBase64()) + "'",
+ query = "insert or replace into 'omemo/prekeys' "
+ "(id, data) values ("
+ + QString::number(id) + ", "
+ + datastr
+ + ");";
+
+ QSqlQuery q(db);
+
+ if (!q.exec(query))
+ {
+ std::cerr << "JidDb::store(pairs): query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int JidDb::ensureOmemoOwnDeviceTable() const
+{
+ QSqlQuery q(db);
+
+ if (!q.exec("create table if not exists 'omemo/owndevice' "
+ "(id INTEGER, label TEXT, privkey TEXT, pubkey TEXT, "
+ "latestSignedPreKeyId INTEGER, latestPreKeyId INTEGER) strict;"))
+ {
+ std::cerr << "JidDb::ensureOmemoOwnDeviceTable: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int JidDb::store(const QXmppOmemoStorage::OwnDevice &own) const
+{
+ if (ensureOmemoOwnDeviceTable())
+ {
+ std::cerr << "JidDb::store: ensureOmemoOwnDeviceTable failed"
+ << std::endl;
+ return -1;
+ }
+
+ QSqlQuery q(db);
+ const auto privkey = own.privateIdentityKey.isEmpty() ? "\"\""
+ : "'" + QString::fromLatin1(own.privateIdentityKey.toBase64()) + "'",
+ pubkey = own.publicIdentityKey.isEmpty() ? "\"\""
+ : "'" + QString::fromLatin1(own.publicIdentityKey.toBase64()) + "'",
+ query = "insert or replace into 'omemo/owndevice' "
+ "(id, label, privkey, pubkey, latestSignedPreKeyId, "
+ "latestPreKeyId) values ("
+ + QString::number(own.id) + ", "
+ "'" + own.label + "', "
+ + privkey + ", "
+ + pubkey + ", "
+ + QString::number(own.latestSignedPreKeyId) + ", "
+ + QString::number(own.latestPreKeyId)
+ + ");";
+
+ if (!q.exec(query))
+ {
+ std::cerr << "JidDb::store(own): query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ std::cerr << "Query was: " << qPrintable(query) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+QList<JidDb::OmemoDevice> JidDb::omemoDevices() const
+{
+ QList<OmemoDevice> ret;
+ QSqlQuery q(db);
+
+ if (!q.exec("select * from 'omemo/devices';"))
+ {
+ std::cerr << "JidDb::omemoDevices: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return QList<OmemoDevice>();
+ }
+
+ while (q.next())
+ {
+ QXmppOmemoStorage::Device device;
+ bool ok;
+ const uint32_t deviceId = q.value("deviceID").toULongLong(&ok);
+
+ if (!ok)
+ {
+ std::cerr << "JidDb::messages: invalid deviceID" << std::endl;
+ // Attempt to read other messages.
+ continue;
+ }
+
+ device.unrespondedReceivedStanzasCount =
+ q.value("unresp_recv").toInt(&ok);
+
+ if (!ok)
+ {
+ std::cerr << "JidDb::messages: invalid unresp_recv" << std::endl;
+ // Attempt to read other messages.
+ continue;
+ }
+
+ device.unrespondedSentStanzasCount = q.value("unresp_sent").toInt(&ok);
+
+ if (!ok)
+ {
+ std::cerr << "JidDb::messages: invalid unresp_sent" << std::endl;
+ // Attempt to read other messages.
+ continue;
+ }
+
+ const QByteArray keyId = q.value("keyID").toByteArray(),
+ session = q.value("session").toByteArray();
+ const auto jid = q.value("jid").toString();
+ bool found = false;
+
+ for (auto &r : ret)
+ if (jid == r.jid)
+ {
+ r.devices.insert(deviceId, device);
+ break;
+ }
+
+ if (!found)
+ {
+ OmemoDevice d;
+
+ d.jid = jid;
+ d.devices.insert(deviceId, device);
+ ret << d;
+ }
+ }
+
+ return ret;
+}
+
+QHash<uint32_t, QXmppOmemoStorage::SignedPreKeyPair> JidDb::signedPreKeyPairs()
+ const
+{
+ QHash<uint32_t, QXmppOmemoStorage::SignedPreKeyPair> ret;
+
+ QSqlQuery q(db);
+
+ if (!q.exec("select * from 'omemo/signedprekeys';"))
+ {
+ std::cerr << "JidDb::signedPreKeyPairs: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return QHash<uint32_t, QXmppOmemoStorage::SignedPreKeyPair>();
+ }
+
+ while (q.next())
+ {
+ QXmppOmemoStorage::SignedPreKeyPair spk;
+ bool ok;
+ const uint32_t id = q.value("id").toULongLong(&ok);
+
+ if (!ok)
+ {
+ std::cerr << "JidDb::messages: invalid id" << std::endl;
+ // Attempt to read other entries.
+ continue;
+ }
+
+ const auto creation = q.value("creation").toInt(&ok);
+
+ if (!ok)
+ {
+ std::cerr << "JidDb::messages: invalid creation date" << std::endl;
+ // Attempt to read other entries.
+ continue;
+ }
+
+ spk.creationDate = QDateTime::fromSecsSinceEpoch(creation);
+ spk.data = q.value("data").toString().toLatin1().toBase64();
+ ret.insert(id, spk);
+ }
+
+ return ret;
+}
+
+QHash<uint32_t, QByteArray> JidDb::preKeyPairs() const
+{
+ QHash<uint32_t, QByteArray> ret;
+
+ QSqlQuery q(db);
+
+ if (!q.exec("select * from 'omemo/signedprekeys';"))
+ {
+ std::cerr << "JidDb::signedPreKeyPairs: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return QHash<uint32_t, QByteArray>();
+ }
+
+ while (q.next())
+ {
+ bool ok;
+ const uint32_t id = q.value("id").toULongLong(&ok);
+
+ if (!ok)
+ {
+ std::cerr << "JidDb::messages: invalid id" << std::endl;
+ // Attempt to read other entries.
+ continue;
+ }
+
+ const auto data = q.value("data").toString().toLatin1().toBase64();
+ ret.insert(id, data);
+ }
+
+ return ret;
+}
+
+void JidDb::removeKeys(const QString &encryption) const
+{
+ QString table;
+
+ if (ensureKeysTable(encryption, table))
+ std::cerr << "JidDb::removeKeys: ensureKeysTable failed" << std::endl;
+ else
+ {
+ QSqlQuery q(db);
+
+ if (!q.exec("delete from '" + table + "'"))
+ std::cerr << "JidDb::removeKeys: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ }
+}
+
+void JidDb::removeOmemoDevice(const QString &jid, const uint32_t id) const
+{
+ if (ensureOmemoDeviceTable())
+ std::cerr << "JidDb::removeOmemoDevice: ensureOmemoDeviceTable failed"
+ << std::endl;
+ else
+ {
+ QSqlQuery q(db);
+ const auto idstr = QString::number(id);
+
+ if (!q.exec("delete from 'omemo/devices' "
+ "where (jid = '" + jid + "' "
+ "and id = " + idstr + ")"))
+ std::cerr << "JidDb::removeOmemoDevice: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ }
+}
+
+void JidDb::removeOmemoDevices(const QString &jid) const
+{
+ if (ensureOmemoDeviceTable())
+ std::cerr << "JidDb::removeOmemoDevices: ensureOmemoDeviceTable failed"
+ << std::endl;
+ else
+ {
+ QSqlQuery q(db);
+
+ if (!q.exec("delete from 'omemo/devices' "
+ "where jid = '" + jid + "'"))
+ std::cerr << "JidDb::removeOmemoDevices: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ }
+}
+
+int JidDb::ensureOwnIdTable(const QString &encryption, QString &table)
+ const
+{
+ QSqlQuery q(db);
+
+ table = encryption + "/ownID";
+
+ if (!q.exec("create table if not exists '" + table + "' "
+ "(ID TEXT) strict;"))
+ {
+ std::cerr << "JidDb::ensureOwnIdTable: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+QByteArray JidDb::ownKeyId(const QString &encryption) const
+{
+ QString table;
+
+ if (ensureOwnIdTable(encryption, table))
+ {
+ std::cerr << "JidDb::store: ensureOwnIdTable failed" << std::endl;
+ return QByteArray();
+ }
+
+ QSqlQuery q(db);
+
+ if (!q.exec("select * from '" + table + "';"))
+ {
+ std::cerr << "JidDb::ownKeyId: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ return QByteArray();
+ }
+
+ while (q.next())
+ {
+ const auto id = q.value("id").toString();
+
+ return QByteArray::fromBase64(id.toLatin1());
+ }
+
+ return QByteArray();
+}
+
+int JidDb::store(const QString &encryption, const QByteArray &ownId) const
+{
+ QString table;
+
+ if (ensureOwnIdTable(encryption, table))
+ {
+ std::cerr << "JidDb::store: ensureOmemoOwnDeviceTable failed"
+ << std::endl;
+ return -1;
+ }
+
+ QSqlQuery q(db);
+ const auto id = ownId.isEmpty() ? "\"\""
+ : "'" + QString::fromLatin1(ownId.toBase64()) + "'",
+ query = "insert or replace into '" + table + "' "
+ "(id) values ("
+ + id
+ + ");";
+
+ return 0;
+}
+
+void JidDb::removeSignedPreKeyPair(const uint32_t id) const
+{
+ if (ensureOmemoSignedPreKeyTable())
+ std::cerr << "JidDb::removeSignedPreKeyPair: "
+ "ensureOmemoSignedPreKeyTable failed" << std::endl;
+ else
+ {
+ QSqlQuery q(db);
+ const auto idstr = QString::number(id);
+
+ if (!q.exec("delete from 'omemo/signedprekeys' where id = " + idstr))
+ std::cerr << "JidDb::removeSignedPreKeyPair: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ }
+}
+
+void JidDb::removePreKeyPair(const uint32_t id) const
+{
+ if (ensureOmemoPreKeyTable())
+ std::cerr << "JidDb::removePreKeyPair: "
+ "ensureOmemoPreKeyTable failed" << std::endl;
+ else
+ {
+ QSqlQuery q(db);
+ const auto idstr = QString::number(id);
+
+ if (!q.exec("delete from 'omemo/prekeys' where id = " + idstr))
+ std::cerr << "JidDb::removePreKeyPair: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ }
+}
+
+void JidDb::removeOmemo() const
+{
+ if (ensureOmemoSignedPreKeyTable())
+ std::cerr << "JidDb::removeOmemo: "
+ "ensureOmemoSignedPreKeyTable failed" << std::endl;
+ else if (ensureOmemoPreKeyTable())
+ std::cerr << "JidDb::removeOmemo: "
+ "ensureOmemoPreKeyTable failed" << std::endl;
+ else
+ {
+ QSqlQuery q(db);
+
+ if (!q.exec("delete from 'omemo/signedprekeys'"))
+ std::cerr << "JidDb::removeOmemo: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ else
+ {
+ QSqlQuery q(db);
+
+ if (!q.exec("delete from 'omemo/prekeys'"))
+ std::cerr << "JidDb::removeOmemo: query exec failed: "
+ << qPrintable(q.lastError().text()) << std::endl;
+ }
+ }
+}