qt: Allow specifying user IDs to use when refreshing keys via WKD
* lang/qt/src/wkdrefreshjob.h, lang/qt/src/wkdrefreshjob.cpp (WKDRefreshJob::start): New overload. * lang/qt/src/wkdrefreshjob_p.h (WKDRefreshJobPrivate): Add field m_userIds. * lang/qt/src/qgpgmewkdrefreshjob.cpp (toEmailAddresses): New. (locate_external_keys): Change return type and arguments. (refresh_keys): Remove. (QGpgMEWKDRefreshJobPrivate::startIt): Get emails from keys or user IDs. Remove duplicates. Call locate_external_keys instead of refresh_keys. * lang/qt/tests/run-wkdrefreshjob.cpp (CommandLineOptions, parseCommandLine): New. (main): Support new option --all-userids. -- The new start() overload allows to specify the user IDs to use for the WKD lookup explicitly. This allows updating user IDs via WKD which were originally not retrieved via WKD. GnuPG-bug-id: 6672
This commit is contained in:
parent
aee18a2ab2
commit
3f297387bf
@ -88,6 +88,21 @@ static QStringList toEmailAddressesOriginatingFromWKD(const std::vector<GpgME::K
|
||||
return emails;
|
||||
}
|
||||
|
||||
static QStringList toEmailAddresses(const std::vector<GpgME::UserID> &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<Key> &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<Key> &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<Key> &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 {};
|
||||
|
@ -54,4 +54,11 @@ GpgME::Error WKDRefreshJob::start(const std::vector<GpgME::Key> &keys)
|
||||
return d->startIt();
|
||||
}
|
||||
|
||||
GpgME::Error WKDRefreshJob::start(const std::vector<GpgME::UserID> &userIDs)
|
||||
{
|
||||
auto d = jobPrivate<WKDRefreshJobPrivate>(this);
|
||||
d->m_userIds = userIDs;
|
||||
return d->startIt();
|
||||
}
|
||||
|
||||
#include "wkdrefreshjob.moc"
|
||||
|
@ -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<GpgME::Key> &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<GpgME::UserID> &userIDs);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ namespace QGpgME
|
||||
struct WKDRefreshJobPrivate : public JobPrivate
|
||||
{
|
||||
std::vector<GpgME::Key> m_keys;
|
||||
std::vector<GpgME::UserID> m_userIds;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <protocol.h>
|
||||
#include <wkdrefreshjob.h>
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user