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;
|
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)
|
QGpgMEWKDRefreshJob::QGpgMEWKDRefreshJob(Context *context)
|
||||||
@ -99,12 +114,11 @@ QGpgMEWKDRefreshJob::QGpgMEWKDRefreshJob(Context *context)
|
|||||||
|
|
||||||
QGpgMEWKDRefreshJob::~QGpgMEWKDRefreshJob() = default;
|
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;
|
qCDebug(QGPGME_LOG) << __func__ << "locating external keys for" << emails;
|
||||||
if (emails.empty()) {
|
if (emails.empty()) {
|
||||||
return ImportResult{};
|
return std::make_tuple(ImportResult{}, QString{}, Error{});
|
||||||
}
|
}
|
||||||
|
|
||||||
Context::KeyListModeSaver saver{ctx};
|
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();
|
qCDebug(QGPGME_LOG) << __func__ << "result:" << toLogString(result).c_str();
|
||||||
job.release();
|
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{});
|
return std::make_tuple(result, QString{}, Error{});
|
||||||
}
|
}
|
||||||
|
|
||||||
GpgME::Error QGpgMEWKDRefreshJobPrivate::startIt()
|
GpgME::Error QGpgMEWKDRefreshJobPrivate::startIt()
|
||||||
{
|
{
|
||||||
if (m_keys.empty()) {
|
QStringList emails;
|
||||||
return Error::fromCode(GPG_ERR_INV_VALUE);
|
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) {
|
q->run([emails](Context *ctx) {
|
||||||
return refresh_keys(ctx, m_keys);
|
return locate_external_keys(ctx, emails);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -54,4 +54,11 @@ GpgME::Error WKDRefreshJob::start(const std::vector<GpgME::Key> &keys)
|
|||||||
return d->startIt();
|
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"
|
#include "wkdrefreshjob.moc"
|
||||||
|
@ -43,14 +43,14 @@ namespace GpgME
|
|||||||
{
|
{
|
||||||
class Error;
|
class Error;
|
||||||
class Key;
|
class Key;
|
||||||
|
class UserID;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace QGpgME
|
namespace QGpgME
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This job refreshes OpenPGP keys via WKD. Only user IDs that have WKD set as
|
* This job refreshes OpenPGP keys via WKD.
|
||||||
* origin are used for the WKD lookup. Revoked user IDs are ignored.
|
|
||||||
*/
|
*/
|
||||||
class QGPGME_EXPORT WKDRefreshJob : public AbstractImportJob
|
class QGPGME_EXPORT WKDRefreshJob : public AbstractImportJob
|
||||||
{
|
{
|
||||||
@ -61,9 +61,18 @@ public:
|
|||||||
~WKDRefreshJob() override;
|
~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);
|
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
|
struct WKDRefreshJobPrivate : public JobPrivate
|
||||||
{
|
{
|
||||||
std::vector<GpgME::Key> m_keys;
|
std::vector<GpgME::Key> m_keys;
|
||||||
|
std::vector<GpgME::UserID> m_userIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include <protocol.h>
|
#include <protocol.h>
|
||||||
#include <wkdrefreshjob.h>
|
#include <wkdrefreshjob.h>
|
||||||
|
|
||||||
|
#include <QCommandLineParser>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
@ -53,6 +54,36 @@ std::ostream &operator<<(std::ostream &os, const QString &s)
|
|||||||
return os << s.toLocal8Bit().constData();
|
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 getOpenPGPKey(const QString &keyId, Error &err)
|
||||||
{
|
{
|
||||||
Key key;
|
Key key;
|
||||||
@ -74,22 +105,19 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
GpgME::initializeLibrary();
|
GpgME::initializeLibrary();
|
||||||
|
|
||||||
if (argc != 2) {
|
|
||||||
std::cerr << "Usage: " << argv[0] << " KEYID" << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QCoreApplication app{argc, argv};
|
QCoreApplication app{argc, argv};
|
||||||
const auto keyId = qApp->arguments().last();
|
app.setApplicationName("run-wkdrefreshjob");
|
||||||
|
|
||||||
|
const auto options = parseCommandLine(app.arguments());
|
||||||
|
|
||||||
Error err;
|
Error err;
|
||||||
const auto key = getOpenPGPKey(keyId, err);
|
const auto key = getOpenPGPKey(options.keyId, err);
|
||||||
if (err.code() == GPG_ERR_AMBIGUOUS_NAME) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
if (key.isNull()) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -111,7 +139,11 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
qApp->quit();
|
qApp->quit();
|
||||||
});
|
});
|
||||||
err = job->start({key});
|
if (options.allUserIds) {
|
||||||
|
err = job->start(key.userIDs());
|
||||||
|
} else {
|
||||||
|
err = job->start({key});
|
||||||
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
std::cerr << "Error: " << err.asString() << std::endl;
|
std::cerr << "Error: " << err.asString() << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user