Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18825189
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
9 KB
Subscribers
None
View Options
diff --git a/src/commands/refreshcertificatecommand.cpp b/src/commands/refreshcertificatecommand.cpp
index aa6b1ee12..c7686b8f0 100644
--- a/src/commands/refreshcertificatecommand.cpp
+++ b/src/commands/refreshcertificatecommand.cpp
@@ -1,193 +1,293 @@
/* -*- mode: c++; c-basic-offset:4 -*-
commands/refreshcertificatecommand.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "refreshcertificatecommand.h"
#include "command_p.h"
#include <KLocalizedString>
#include <KMessageBox>
#include <QGpgME/Protocol>
#ifdef QGPGME_SUPPORTS_KEY_REFRESH
#include <QGpgME/RefreshKeysJob>
+#include <QGpgME/RefreshOpenPGPKeysJob>
#endif
+#include <gpgme++/importresult.h>
+
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace GpgME;
class RefreshCertificateCommand::Private : public Command::Private
{
friend class ::RefreshCertificateCommand;
RefreshCertificateCommand *q_func() const
{
return static_cast<RefreshCertificateCommand *>(q);
}
public:
explicit Private(RefreshCertificateCommand *qq);
~Private() override;
void start();
void cancel();
#ifdef QGPGME_SUPPORTS_KEY_REFRESH
- std::unique_ptr<QGpgME::RefreshKeysJob> startJob();
+ std::unique_ptr<QGpgME::RefreshOpenPGPKeysJob> startOpenPGPJob();
+ std::unique_ptr<QGpgME::RefreshKeysJob> startSMIMEJob();
#endif
- void onJobResult(const Error &err);
+ void onOpenPGPJobResult(const ImportResult &result);
+ void onSMIMEJobResult(const Error &err);
void showError(const Error &err);
private:
Key key;
#ifdef QGPGME_SUPPORTS_KEY_REFRESH
- QPointer<QGpgME::RefreshKeysJob> job;
+ QPointer<QGpgME::Job> job;
#endif
};
RefreshCertificateCommand::Private *RefreshCertificateCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const RefreshCertificateCommand::Private *RefreshCertificateCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define d d_func()
#define q q_func()
RefreshCertificateCommand::Private::Private(RefreshCertificateCommand *qq)
: Command::Private{qq}
{
}
RefreshCertificateCommand::Private::~Private() = default;
namespace
{
Key getKey(const std::vector<Key> &keys)
{
if (keys.size() != 1) {
qCWarning(KLEOPATRA_LOG) << "Expected exactly one key, but got" << keys.size();
return {};
}
const Key key = keys.front();
if (key.protocol() == GpgME::UnknownProtocol) {
qCWarning(KLEOPATRA_LOG) << "Key has unknown protocol";
return {};
}
return key;
}
}
void RefreshCertificateCommand::Private::start()
{
key = getKey(keys());
if (key.isNull()) {
finished();
return;
}
#ifdef QGPGME_SUPPORTS_KEY_REFRESH
- auto refreshJob = startJob();
+ std::unique_ptr<QGpgME::Job> refreshJob;
+ switch (key.protocol()) {
+ case GpgME::OpenPGP:
+ refreshJob = startOpenPGPJob();
+ break;
+ case GpgME::CMS:
+ refreshJob = startSMIMEJob();
+ break;
+ default:
+ ; // cannot happen ;-)
+ }
if (!refreshJob) {
finished();
return;
}
job = refreshJob.release();
#else
KMessageBox::error(parentWidgetOrView(), i18n("The backend does not support refreshing individual certificates."));
finished();
#endif
}
void RefreshCertificateCommand::Private::cancel()
{
#ifdef QGPGME_SUPPORTS_KEY_REFRESH
if (job) {
job->slotCancel();
}
job.clear();
#endif
}
#ifdef QGPGME_SUPPORTS_KEY_REFRESH
-std::unique_ptr<QGpgME::RefreshKeysJob> RefreshCertificateCommand::Private::startJob()
+std::unique_ptr<QGpgME::RefreshOpenPGPKeysJob> RefreshCertificateCommand::Private::startOpenPGPJob()
+{
+ std::unique_ptr<QGpgME::RefreshOpenPGPKeysJob> refreshJob{QGpgME::openpgp()->refreshOpenPGPKeysJob()};
+ Q_ASSERT(refreshJob);
+
+ connect(refreshJob.get(), &QGpgME::RefreshOpenPGPKeysJob::result,
+ q, [this](const GpgME::ImportResult &result) {
+ onOpenPGPJobResult(result);
+ });
+ connect(refreshJob.get(), &QGpgME::Job::progress,
+ q, &Command::progress);
+
+ const GpgME::Error err = refreshJob->start({key});
+ if (err) {
+ showError(err);
+ return {};
+ }
+ Q_EMIT q->info(i18nc("@info:status", "Refreshing key..."));
+
+ return refreshJob;
+}
+
+std::unique_ptr<QGpgME::RefreshKeysJob> RefreshCertificateCommand::Private::startSMIMEJob()
{
- auto jobFactory = key.protocol() == GpgME::OpenPGP ? QGpgME::openpgp() : QGpgME::smime();
- Q_ASSERT(jobFactory);
- std::unique_ptr<QGpgME::RefreshKeysJob> refreshJob{jobFactory->refreshKeysJob()};
+ std::unique_ptr<QGpgME::RefreshKeysJob> refreshJob{QGpgME::smime()->refreshKeysJob()};
Q_ASSERT(refreshJob);
connect(refreshJob.get(), &QGpgME::RefreshKeysJob::result,
q, [this](const GpgME::Error &err) {
- onJobResult(err);
+ onSMIMEJobResult(err);
});
connect(refreshJob.get(), &QGpgME::Job::progress,
q, &Command::progress);
const GpgME::Error err = refreshJob->start({key});
if (err) {
showError(err);
return {};
}
Q_EMIT q->info(i18nc("@info:status", "Refreshing key..."));
return refreshJob;
}
#endif
-void RefreshCertificateCommand::Private::onJobResult(const Error &err)
+namespace
+{
+static auto informationOnChanges(const ImportResult &result)
+{
+ QString text;
+
+ // if additional keys have been retrieved via WKD, then most of the below
+ // details are just a guess and may concern the additional keys instead of
+ // the refresh keys; this could only be clarified by a thorough comparison of
+ // unrefreshed and refreshed key
+
+ if (result.numUnchanged() == result.numConsidered()) {
+ // if numUnchanged < numConsidered, then it is not clear whether the refreshed key
+ // hasn't changed or whether another key retrieved via WKD hasn't changed
+ text = i18n("The key hasn't changed.");
+ } else if (result.newRevocations() > 0) {
+ // it is possible that a revoked key has been newly imported via WKD,
+ // but it is much more likely that the refreshed key was revoked
+ text = i18n("The key has been revoked.");
+ } else {
+ // it doesn't make much sense to list below details if the key has been revoked
+ text = i18n("The key has been updated.");
+
+ QStringList details;
+ if (result.newUserIDs() > 0) {
+ details.push_back(i18n("New user IDs: %1", result.newUserIDs()));
+ }
+ if (result.newSubkeys() > 0) {
+ details.push_back(i18n("New subkeys: %1", result.newSubkeys()));
+ }
+ if (result.newSignatures() > 0) {
+ details.push_back(i18n("New signatures: %1", result.newSignatures()));
+ }
+ if (!details.empty()) {
+ text += QLatin1String{"<br><br>"} + details.join(QLatin1String{"<br>"});
+ }
+ }
+
+ text = QLatin1String{"<p>"} + text + QLatin1String{"</p>"};
+ if (result.numImported() > 0) {
+ text += QLatin1String{"<p>"} + i18np("Additionally, one new key has been retrieved.",
+ "Additionally, %1 new keys have been retrieved.",
+ result.numImported()) + QLatin1String{"</p>"};
+ }
+
+ return text;
+}
+
+}
+
+void RefreshCertificateCommand::Private::onOpenPGPJobResult(const ImportResult &result)
+{
+ if (result.error()) {
+ showError(result.error());
+ finished();
+ return;
+ }
+
+ if (!result.error().isCanceled()) {
+ information(informationOnChanges(result),
+ i18nc("@title:window", "Key Refreshed"));
+ }
+ finished();
+}
+
+void RefreshCertificateCommand::Private::onSMIMEJobResult(const Error &err)
{
if (err) {
showError(err);
finished();
return;
}
if (!err.isCanceled()) {
information(i18nc("@info", "The key was refreshed successfully."),
i18nc("@title:window", "Key Refreshed"));
}
finished();
}
void RefreshCertificateCommand::Private::showError(const Error &err)
{
error(xi18nc("@info",
"<para>An error occurred while refreshing the key:</para>"
"<para><message>%1</message></para>",
QString::fromLocal8Bit(err.asString())),
i18nc("@title:window", "Refreshing Failed"));
}
RefreshCertificateCommand::RefreshCertificateCommand(const GpgME::Key &key)
: Command{key, new Private{this}}
{
}
RefreshCertificateCommand::~RefreshCertificateCommand() = default;
void RefreshCertificateCommand::doStart()
{
d->start();
}
void RefreshCertificateCommand::doCancel()
{
d->cancel();
}
#undef d
#undef q
#include "moc_refreshcertificatecommand.cpp"
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Dec 23, 2:09 PM (16 h, 33 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
1e/19/779b3810a0add91f18873dbbe436
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment