diff --git a/lang/qt/src/qgpgmewkdrefreshjob.cpp b/lang/qt/src/qgpgmewkdrefreshjob.cpp index 8bad1ef1..f590ed4b 100644 --- a/lang/qt/src/qgpgmewkdrefreshjob.cpp +++ b/lang/qt/src/qgpgmewkdrefreshjob.cpp @@ -88,6 +88,21 @@ static QStringList toEmailAddressesOriginatingFromWKD(const std::vector &userIds) +{ + const QStringList emails = std::accumulate( + std::begin(userIds), + std::end(userIds), + QStringList{}, + [](QStringList &emails, const UserID &userId) { + if (!userId.isRevoked() && !userId.addrSpec().empty()) { + emails.push_back(QString::fromStdString(userId.addrSpec())); + } + return emails; + }); + return emails; +} + } QGpgMEWKDRefreshJob::QGpgMEWKDRefreshJob(Context *context) @@ -99,12 +114,11 @@ QGpgMEWKDRefreshJob::QGpgMEWKDRefreshJob(Context *context) QGpgMEWKDRefreshJob::~QGpgMEWKDRefreshJob() = default; -static ImportResult locate_external_keys(Context *ctx, const std::vector &keys) +static QGpgMEWKDRefreshJob::result_type locate_external_keys(Context *ctx, const QStringList &emails) { - const auto emails = toEmailAddressesOriginatingFromWKD(keys); qCDebug(QGPGME_LOG) << __func__ << "locating external keys for" << emails; if (emails.empty()) { - return ImportResult{}; + return std::make_tuple(ImportResult{}, QString{}, Error{}); } Context::KeyListModeSaver saver{ctx}; @@ -121,24 +135,22 @@ static ImportResult locate_external_keys(Context *ctx, const std::vector &k qCDebug(QGPGME_LOG) << __func__ << "result:" << toLogString(result).c_str(); job.release(); - return result; -} - -static QGpgMEWKDRefreshJob::result_type refresh_keys(Context *ctx, const std::vector &keys) -{ - const auto result = locate_external_keys(ctx, keys); - return std::make_tuple(result, QString{}, Error{}); } GpgME::Error QGpgMEWKDRefreshJobPrivate::startIt() { - if (m_keys.empty()) { - return Error::fromCode(GPG_ERR_INV_VALUE); + QStringList emails; + if (!m_keys.empty()) { + emails = toEmailAddressesOriginatingFromWKD(m_keys); + } else { + emails = toEmailAddresses(m_userIds); } + std::sort(emails.begin(), emails.end()); + emails.erase(std::unique(emails.begin(), emails.end()), emails.end()); - q->run([=](Context *ctx) { - return refresh_keys(ctx, m_keys); + q->run([emails](Context *ctx) { + return locate_external_keys(ctx, emails); }); return {}; diff --git a/lang/qt/src/wkdrefreshjob.cpp b/lang/qt/src/wkdrefreshjob.cpp index 37b990c8..f79df2c5 100644 --- a/lang/qt/src/wkdrefreshjob.cpp +++ b/lang/qt/src/wkdrefreshjob.cpp @@ -54,4 +54,11 @@ GpgME::Error WKDRefreshJob::start(const std::vector &keys) return d->startIt(); } +GpgME::Error WKDRefreshJob::start(const std::vector &userIDs) +{ + auto d = jobPrivate(this); + d->m_userIds = userIDs; + return d->startIt(); +} + #include "wkdrefreshjob.moc" diff --git a/lang/qt/src/wkdrefreshjob.h b/lang/qt/src/wkdrefreshjob.h index c3aec65f..cbaaf6b0 100644 --- a/lang/qt/src/wkdrefreshjob.h +++ b/lang/qt/src/wkdrefreshjob.h @@ -43,14 +43,14 @@ namespace GpgME { class Error; class Key; +class UserID; } namespace QGpgME { /** - * This job refreshes OpenPGP keys via WKD. Only user IDs that have WKD set as - * origin are used for the WKD lookup. Revoked user IDs are ignored. + * This job refreshes OpenPGP keys via WKD. */ class QGPGME_EXPORT WKDRefreshJob : public AbstractImportJob { @@ -61,9 +61,18 @@ public: ~WKDRefreshJob() override; /** - * Starts a refresh of the \a keys. + * Starts a refresh of the \a keys. Only user IDs that have WKD set as + * origin are used for the WKD lookup. Revoked user IDs are ignored. + * + * Use the other start overload to use all user IDs for the WKD lookup. */ GpgME::Error start(const std::vector &keys); + + /** + * Starts a refresh of the keys belonging to the user IDs \a userIDs. + * All user IDs are used for the WKD lookup. Revoked user IDs are ignored. + */ + GpgME::Error start(const std::vector &userIDs); }; } diff --git a/lang/qt/src/wkdrefreshjob_p.h b/lang/qt/src/wkdrefreshjob_p.h index 377350f3..60fdfedd 100644 --- a/lang/qt/src/wkdrefreshjob_p.h +++ b/lang/qt/src/wkdrefreshjob_p.h @@ -44,6 +44,7 @@ namespace QGpgME struct WKDRefreshJobPrivate : public JobPrivate { std::vector m_keys; + std::vector m_userIds; }; } diff --git a/lang/qt/tests/run-wkdrefreshjob.cpp b/lang/qt/tests/run-wkdrefreshjob.cpp index 757ee899..c75718e6 100644 --- a/lang/qt/tests/run-wkdrefreshjob.cpp +++ b/lang/qt/tests/run-wkdrefreshjob.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -53,6 +54,36 @@ std::ostream &operator<<(std::ostream &os, const QString &s) return os << s.toLocal8Bit().constData(); } +struct CommandLineOptions { + bool allUserIds; + QString keyId; +}; + +CommandLineOptions parseCommandLine(const QStringList &arguments) +{ + CommandLineOptions options; + + QCommandLineParser parser; + parser.setApplicationDescription("Test program for WKDRefreshJob"); + parser.addHelpOption(); + parser.addOptions({ + {"all-userids", "Query WKD for all user IDs."}, + }); + parser.addPositionalArgument("key ID", "Key to refresh"); + + parser.process(arguments); + + const auto args = parser.positionalArguments(); + if (args.size() != 1) { + parser.showHelp(1); + } + + options.allUserIds = parser.isSet("all-userids"); + options.keyId = args[0]; + + return options; +} + Key getOpenPGPKey(const QString &keyId, Error &err) { Key key; @@ -74,22 +105,19 @@ int main(int argc, char **argv) { GpgME::initializeLibrary(); - if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " KEYID" << std::endl; - return 1; - } - QCoreApplication app{argc, argv}; - const auto keyId = qApp->arguments().last(); + app.setApplicationName("run-wkdrefreshjob"); + + const auto options = parseCommandLine(app.arguments()); Error err; - const auto key = getOpenPGPKey(keyId, err); + const auto key = getOpenPGPKey(options.keyId, err); if (err.code() == GPG_ERR_AMBIGUOUS_NAME) { - std::cerr << "Error: Multiple OpenPGP keys matching '" << keyId << "' found" << std::endl; + std::cerr << "Error: Multiple OpenPGP keys matching '" << options.keyId << "' found" << std::endl; return 1; } if (key.isNull()) { - std::cerr << "Error: No OpenPGP key matching '" << keyId << "' found" << std::endl; + std::cerr << "Error: No OpenPGP key matching '" << options.keyId << "' found" << std::endl; return 1; } if (err) { @@ -111,7 +139,11 @@ int main(int argc, char **argv) } qApp->quit(); }); - err = job->start({key}); + if (options.allUserIds) { + err = job->start(key.userIDs()); + } else { + err = job->start({key}); + } if (err) { std::cerr << "Error: " << err.asString() << std::endl; return 1;