From 5bbe04c9ca091a0626f34afe5e3ba2141e2963de Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Mon, 28 Aug 2023 00:20:54 +0200 Subject: WIP OMEMO TrustDb/JidDb --- credentials.cpp | 251 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 183 insertions(+), 68 deletions(-) (limited to 'credentials.cpp') diff --git a/credentials.cpp b/credentials.cpp index 8d6a01b..5cd6e6f 100644 --- a/credentials.cpp +++ b/credentials.cpp @@ -1,103 +1,218 @@ #include "credentials.h" -#include #include +#include #include #include static const QString service = "xxcc", sep = ";"; -QList Credentials::load() +QXmppTask Credentials::load( + Credentials::PairList &pairs, + QStringList::const_iterator &it, + QStringList::const_iterator end) { - const QStringList users = storedUsers(); - QList ret; + if (it == end) + return QXmpp::Private::makeReadyTask( + PairListResult(pairs)); - for (const auto &user : users) - { - QKeychain::ReadPasswordJob job(service); - QEventLoop loop; - - job.setKey(user); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); + QXmppPromise promise; - const QString pwd = job.textData(); + load(*it).then(this, + [=] (LoadResult &&result) mutable + { + if (std::holds_alternative(result)) + { + pairs << Pair(*it, std::get(result)); + + load(pairs, ++it, end).then(this, + [=] (PairListResult &&result) mutable + { + promise.finish(result); + }); + } + else if (std::holds_alternative(result)) + promise.finish(Error{std::get(result)}); + }); + + return promise.task(); +} - if (job.error()) - std::cerr << "Failed to retrieve password for " << qPrintable(user) - << ": " << qPrintable(job.errorString()) << std::endl; - else - ret.append(Pair(user, pwd)); - } +QXmppTask Credentials::load() +{ + QXmppPromise promise; - return ret; + storedUsers().then(this, + [=] (Users &&result) mutable + { + if (std::holds_alternative(result)) + { + PairList pairs; + auto list = new QStringList(std::get(result)); + auto begin = list->cbegin(); + const auto end = list->cend(); + + load(pairs, begin, end).then(this, + [=] (PairListResult &&result) mutable + { + delete list; + promise.finish(result); + }); + } + else if (std::holds_alternative(result)) + promise.finish(Error{std::get(result)}); + }); + + return promise.task(); } -void Credentials::store(Client *c) +QXmppTask Credentials::store(Client *c) { - QKeychain::WritePasswordJob job(service); + QXmppPromise promise; const QXmppConfiguration &cfg = c->configuration(); const QString user = cfg.jidBare(); - QEventLoop loop; - - job.setKey(user); - job.setTextData(cfg.password()); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); - - if (job.error()) - std::cerr << "Failed to store password: " - << qPrintable(job.errorString()) << std::endl; - else - storeUser(user); + + store(user, cfg.password()).then(this, + [=] (StoreResult &&result) mutable + { + store(user).then(this, + [=] (StoreResult &&result) mutable + { + promise.finish(result); + }); + }); + + return promise.task(); } -void Credentials::storeUser(const QString &user) +QXmppTask Credentials::store(const QString &user) { - QString list = storedUsersList(); - QKeychain::WritePasswordJob job(service); - QEventLoop loop; + QXmppPromise promise; + + storedUsersList().then(this, + [=] (LoadResult &&result) mutable + { + if (std::holds_alternative(result)) + { + auto &list = std::get(result); + + if (!list.isEmpty()) + list += sep; + + list += user; + store("users", list).then(this, + [=] (StoreResult &&result) mutable + { + promise.finish(result); + }); + } + else if (std::holds_alternative(result)) + { + store("users", user).then(this, + [=] (StoreResult &&result) mutable + { + promise.finish(result); + }); + } + }); + + return promise.task(); +} - if (!list.isEmpty()) - list += sep; +QXmppTask Credentials::storedUsersList() +{ + QXmppPromise promise; - list += user; + load("users").then(this, + [=] (LoadResult &&result) mutable + { + promise.finish(result); + }); - job.setKey("users"); - job.setTextData(list); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); + return promise.task(); - if (job.error()) - std::cerr << "Failed to store user: " - << qPrintable(job.errorString()) << std::endl; } -QString Credentials::storedUsersList() +QXmppTask Credentials::load(const QString &key) { - QKeychain::ReadPasswordJob job(service); - QString ret; - QEventLoop loop; + QXmppPromise promise; + auto job = new QKeychain::ReadPasswordJob(service); - job.setKey("users"); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); + job->setKey(key); + job->connect(job, &QKeychain::Job::finished, this, + [=] (QKeychain::Job *const job) mutable + { + auto readjob = dynamic_cast(job); - const QString users = job.textData(); + if (readjob->error()) + { + const auto error = "Failed to load " + key + ": " + + readjob->errorString(); - if (job.error()) - std::cerr << "Failed to retrieve users: " - << qPrintable(job.errorString()) << std::endl; - else - ret = users; + std::cerr << qPrintable(error) << std::endl; + promise.finish(Error{error}); + } + else + { + auto users = readjob->textData(); - return ret; + promise.finish(QString(users)); + } + }); + + job->start(); + return promise.task(); } -QStringList Credentials::storedUsers() +QXmppTask Credentials::store(const QString &key, + const QString &value) { - return storedUsersList().split(sep); + QXmppPromise promise; + auto job = new QKeychain::WritePasswordJob(service); + + job->setKey(key); + job->setTextData(value); + job->connect(job, &QKeychain::Job::finished, this, + [=] (QKeychain::Job *const job) mutable + { + if (job->error()) + { + StoreResult sr; + + const auto error = "Failed to store " + key + ": " + + job->errorString(); + + std::cerr << qPrintable(error) << std::endl; + sr = Error{error}; + promise.finish(StoreResult(sr)); + } + else + promise.finish(Success{}); + }); + + job->start(); + return promise.task(); +} + +QXmppTask Credentials::storedUsers() +{ + QXmppPromise promise; + + storedUsersList().then(this, + [=] (LoadResult &&result) mutable + { + if (std::holds_alternative(result)) + { + const auto &value = std::get(result); + + promise.finish(QStringList(value.split(sep))); + } + else if (std::holds_alternative(result)) + { + const auto &error = std::get(result); + + promise.finish(Error{error.description}); + } + }); + + return promise.task(); } -- cgit v1.2.3