#include "credentials.h" #include #include #include #include static const QString service = "xxcc", sep = ";"; QXmppTask Credentials::load( Credentials::PairList &pairs, QStringList::const_iterator &it, QStringList::const_iterator end) { if (it == end) return QXmpp::Private::makeReadyTask( PairListResult(pairs)); QXmppPromise promise; 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(); } QXmppTask Credentials::load() { QXmppPromise promise; 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(); } QXmppTask Credentials::store(Client *c) { QXmppPromise promise; const QXmppConfiguration &cfg = c->configuration(); const QString user = cfg.jidBare(); store(user, cfg.password()).then(this, [=] (StoreResult &&result) mutable { store(user).then(this, [=] (StoreResult &&result) mutable { promise.finish(result); }); }); return promise.task(); } QXmppTask Credentials::store(const QString &user) { 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(); } QXmppTask Credentials::storedUsersList() { QXmppPromise promise; load("users").then(this, [=] (LoadResult &&result) mutable { promise.finish(result); }); return promise.task(); } QXmppTask Credentials::load(const QString &key) { QXmppPromise promise; auto job = new QKeychain::ReadPasswordJob(service); job->setKey(key); job->connect(job, &QKeychain::Job::finished, this, [=] (QKeychain::Job *const job) mutable { auto readjob = dynamic_cast(job); if (readjob->error()) { const auto error = "Failed to load " + key + ": " + readjob->errorString(); std::cerr << qPrintable(error) << std::endl; promise.finish(Error{error}); } else { auto users = readjob->textData(); promise.finish(QString(users)); } }); job->start(); return promise.task(); } QXmppTask Credentials::store(const QString &key, const QString &value) { 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(); }