diff --git a/.gitmodules b/.gitmodules index bbe5364..098973a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "external/qxmpp"] path = external/qxmpp url = https://github.com/qxmpp-project/qxmpp.git +[submodule "external/storage"] + path = external/storage + url = https://git.macaw.me/blue/storage diff --git a/CMakeLists.txt b/CMakeLists.txt index af1e7f3..3f5bd96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,7 +147,13 @@ else () endif () ## LMDB -find_package(LMDB REQUIRED) +#find_package(LMDB REQUIRED) + + +#TODO conditioning! +add_subdirectory(external/storage) +target_include_directories(squawk PRIVATE external/storage) +target_link_libraries(squawk PRIVATE storage) # Linking target_link_libraries(squawk diff --git a/core/handlers/omemohandler.cpp b/core/handlers/omemohandler.cpp index ef2f5ea..c1dc7ef 100644 --- a/core/handlers/omemohandler.cpp +++ b/core/handlers/omemohandler.cpp @@ -14,4 +14,148 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include #include "omemohandler.h" +#include "core/account.h" + +Core::OmemoHandler::OmemoHandler(Account* account) : + QXmppOmemoStorage(), + acc(account), + ownDevice(std::nullopt), + db("omemo"), + meta(db.addCache("meta")), + devices(db.addCache>("devices")), + preKeyPairs(db.addCache("preKeyPairs")), + signedPreKeyPairs(db.addCache("signedPreKeyPairs")) +{ + db.open(); + try { + QVariant own = meta->getRecord("ownDevice"); + ownDevice.value() = own.value(); + qDebug() << "Successfully found own device omemo data for account" << acc->getName(); + } catch (const DataBase::NotFound& e) { + qDebug() << "No device omemo data was found for account" << acc->getName(); + } +} + +Core::OmemoHandler::~OmemoHandler() { + db.close(); +} + +QFuture Core::OmemoHandler::emptyVoidFuture() { + QFutureInterface result(QFutureInterfaceBase::Started); + result.reportFinished(); + return result.future(); +} + +QFuture Core::OmemoHandler::allData() { + OmemoData data; + data.ownDevice = ownDevice; + + std::map pkeys = preKeyPairs->readAll(); + for (const std::pair& pair : pkeys) { + data.preKeyPairs.insert(pair.first, pair.second); + } + + std::map spre = signedPreKeyPairs->readAll(); + for (const std::pair& pair : spre) { + data.signedPreKeyPairs.insert(pair.first, pair.second); + } + + std::map> devs = devices->readAll(); + for (const std::pair>& pair : devs) { + data.devices.insert(pair.first, pair.second); + } + + QFutureInterface result(QFutureInterfaceBase::Started); + result.reportResult(std::move(data)); + result.reportFinished(); + return result.future(); +} + +QFuture Core::OmemoHandler::addDevice(const QString& jid, uint32_t deviceId, const QXmppOmemoStorage::Device& device) { + QHash devs; + bool had = true; + try { + devs = devices->getRecord(jid); + } catch (const DataBase::NotFound& error) { + had = false; + } + + devs.insert(deviceId, device); + if (had) { + devices->changeRecord(jid, devs); + } else { + devices->addRecord(jid, devs); + } + + return emptyVoidFuture(); +} + +QFuture Core::OmemoHandler::addPreKeyPairs(const QHash& keyPairs) { + for (QHash::const_iterator itr = keyPairs.begin(), end = keyPairs.end(); itr != end; ++itr) { + preKeyPairs->forceRecord(itr.key(), itr.value()); + } + + return emptyVoidFuture(); +} + +QFuture Core::OmemoHandler::addSignedPreKeyPair(uint32_t keyId, const QXmppOmemoStorage::SignedPreKeyPair& keyPair) { + signedPreKeyPairs->addRecord(keyId, keyPair); + return emptyVoidFuture(); +} + +QFuture Core::OmemoHandler::removeDevice(const QString& jid, uint32_t deviceId) { + QHash devs = devices->getRecord(jid); + devs.remove(deviceId); + if (devs.isEmpty()) { + devices->removeRecord(jid); + } else { + devices->changeRecord(jid, devs); + } + return emptyVoidFuture(); +} + +QFuture Core::OmemoHandler::removeDevices(const QString& jid) { + devices->removeRecord(jid); + return emptyVoidFuture(); +} + +QFuture Core::OmemoHandler::removePreKeyPair(uint32_t keyId) { + preKeyPairs->removeRecord(keyId); + return emptyVoidFuture(); +} + +QFuture Core::OmemoHandler::removeSignedPreKeyPair(uint32_t keyId) { + signedPreKeyPairs->removeRecord(keyId); + return emptyVoidFuture(); +} + +QFuture Core::OmemoHandler::setOwnDevice(const std::optional& device) { + bool had = ownDevice.has_value(); + ownDevice = device; + if (ownDevice.has_value()) { + if (had) { + meta->changeRecord("ownDevice", QVariant::fromValue(ownDevice.value())); + } else { + meta->addRecord("ownDevice", QVariant::fromValue(ownDevice.value())); + } + } else { + if (had) { + meta->removeRecord("ownDevice"); + } + } + return emptyVoidFuture(); +} + +QFuture Core::OmemoHandler::resetAll() { + ownDevice = std::nullopt; + db.drop(); + + return emptyVoidFuture(); +} + + + + + diff --git a/core/handlers/omemohandler.h b/core/handlers/omemohandler.h index 2759a21..8f3ac9c 100644 --- a/core/handlers/omemohandler.h +++ b/core/handlers/omemohandler.h @@ -18,14 +18,17 @@ #define CORE_OMEMOHANDLER_H #include -#include +#include + +Q_DECLARE_METATYPE(QXmppOmemoStorage::OwnDevice); namespace Core { +class Account; class OmemoHandler : public QXmppOmemoStorage { public: - OmemoHandler(); + OmemoHandler(Account* account); ~OmemoHandler() override; QFuture allData() override; @@ -45,13 +48,24 @@ public: QFuture resetAll() override; private: + static QFuture emptyVoidFuture(); + +private: + Account* acc; std::optional ownDevice; - Cache> devices; - Cache preKeyPairs; - Cache signedPreKeyPairs; - - + DataBase db; + DataBase::Cache* meta; + DataBase::Cache>* devices; + DataBase::Cache* preKeyPairs; + DataBase::Cache* signedPreKeyPairs; }; } + +QDataStream& operator << (QDataStream &out, const QXmppOmemoStorage::Device& device); +QDataStream& operator >> (QDataStream &out, QXmppOmemoStorage::Device device); + +QDataStream& operator << (QDataStream &out, const QXmppOmemoStorage::SignedPreKeyPair& device); +QDataStream& operator >> (QDataStream &out, QXmppOmemoStorage::SignedPreKeyPair device); + #endif // CORE_OMEMOHANDLER_H diff --git a/external/qxmpp b/external/qxmpp index fe83e9c..f6e7591 160000 --- a/external/qxmpp +++ b/external/qxmpp @@ -1 +1 @@ -Subproject commit fe83e9c3d42c3becf682e2b5ecfc9d77b24c614f +Subproject commit f6e7591e21b4c55319918ac296b2341b2e9f1988 diff --git a/external/storage b/external/storage new file mode 160000 index 0000000..08daad4 --- /dev/null +++ b/external/storage @@ -0,0 +1 @@ +Subproject commit 08daad48ad36d9f12dc6485a085190e31e4cf49e diff --git a/main/main.cpp b/main/main.cpp index 086dbc0..58063e0 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -33,6 +33,10 @@ #include #include +#ifdef WITH_OMEMO +#include +#endif + int main(int argc, char *argv[]) { qRegisterMetaType("Shared::Message"); @@ -40,12 +44,15 @@ int main(int argc, char *argv[]) qRegisterMetaType("Shared::VCard"); qRegisterMetaType>("std::list"); qRegisterMetaType>("std::list"); - qRegisterMetaType>("std::list"); - qRegisterMetaType>("std::set"); - qRegisterMetaType>("std::list"); + qRegisterMetaType>("std::list"); + qRegisterMetaType>("std::set"); + qRegisterMetaType>("std::list"); qRegisterMetaType>("QSet"); qRegisterMetaType("Shared::ConnectionState"); qRegisterMetaType("Shared::Availability"); +#ifdef WITH_OMEMO + qRegisterMetaType("QXmppOmemoStorage::OwnDevice"); +#endif QApplication app(argc, argv); SignalCatcher sc(&app);