Page MenuHome GnuPG

No OneTemporary

diff --git a/src/commands/deletecertificatescommand.cpp b/src/commands/deletecertificatescommand.cpp
index d6fbd0b3a..8c0336df2 100644
--- a/src/commands/deletecertificatescommand.cpp
+++ b/src/commands/deletecertificatescommand.cpp
@@ -1,426 +1,426 @@
/*
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "deletecertificatescommand.h"
#include "command_p.h"
#include <dialogs/deletecertificatesdialog.h>
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <Libkleo/Predicates>
#include <Libkleo/Stl_Util>
#include <QGpgME/DeleteJob>
#include <QGpgME/MultiDeleteJob>
#include <QGpgME/Protocol>
#include <qgpgme/qgpgme_version.h>
#include <gpgme++/key.h>
#include <KLocalizedString>
#include <QAbstractItemView>
#include <QPointer>
#include <KLazyLocalizedString>
#include <algorithm>
#include <vector>
using namespace GpgME;
using namespace Kleo;
using namespace Kleo::Dialogs;
using namespace QGpgME;
class DeleteCertificatesCommand::Private : public Command::Private
{
friend class ::Kleo::DeleteCertificatesCommand;
DeleteCertificatesCommand *q_func() const
{
return static_cast<DeleteCertificatesCommand *>(q);
}
public:
explicit Private(DeleteCertificatesCommand *qq, KeyListController *c);
~Private() override;
void startDeleteJob(GpgME::Protocol protocol);
void cancelJobs();
void pgpDeleteResult(const GpgME::Error &);
void cmsDeleteResult(const GpgME::Error &);
void showErrorsAndFinish();
bool canDelete(GpgME::Protocol proto) const
{
if (const auto cbp = (proto == GpgME::OpenPGP ? QGpgME::openpgp() : QGpgME::smime()))
if (DeleteJob *const job = cbp->deleteJob()) {
job->slotCancel();
return true;
}
return false;
}
void ensureDialogCreated()
{
if (dialog) {
return;
}
dialog = new DeleteCertificatesDialog;
applyWindowID(dialog);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setWindowTitle(i18nc("@title:window", "Delete Certificates"));
connect(dialog, &QDialog::accepted, q_func(), [this]() {
slotDialogAccepted();
});
connect(dialog, &QDialog::rejected, q_func(), [this]() {
slotDialogRejected();
});
}
void ensureDialogShown()
{
if (dialog) {
dialog->show();
}
}
void slotDialogAccepted();
void slotDialogRejected()
{
canceled();
}
private:
QPointer<DeleteCertificatesDialog> dialog;
QPointer<MultiDeleteJob> cmsJob, pgpJob;
GpgME::Error cmsError, pgpError;
std::vector<Key> cmsKeys, pgpKeys;
std::shared_ptr<KeyCacheAutoRefreshSuspension> keyCacheAutoRefreshSuspension;
};
DeleteCertificatesCommand::Private *DeleteCertificatesCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const DeleteCertificatesCommand::Private *DeleteCertificatesCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define d d_func()
#define q q_func()
DeleteCertificatesCommand::Private::Private(DeleteCertificatesCommand *qq, KeyListController *c)
: Command::Private(qq, c)
{
}
DeleteCertificatesCommand::Private::~Private()
{
}
DeleteCertificatesCommand::DeleteCertificatesCommand(KeyListController *p)
: Command(new Private(this, p))
{
}
DeleteCertificatesCommand::DeleteCertificatesCommand(QAbstractItemView *v, KeyListController *p)
: Command(v, new Private(this, p))
{
}
DeleteCertificatesCommand::~DeleteCertificatesCommand()
{
}
namespace
{
enum Action {
Nothing = 0,
Failure = 1,
ClearCMS = 2,
ClearPGP = 4
};
// const unsigned int errorCase =
// openpgp.empty() << 3U | d->canDelete( OpenPGP ) << 2U |
// cms.empty() << 1U | d->canDelete( CMS ) << 0U ;
static const struct {
const KLazyLocalizedString text;
Action actions;
} deletionErrorCases[16] = {
// if havePGP
// if cantPGP
// if haveCMS
{kli18n("Neither the OpenPGP nor the CMS "
"backends support certificate deletion.\n"
"Check your installation."),
Failure}, // cantCMS
{kli18n("The OpenPGP backend does not support "
"certificate deletion.\n"
"Check your installation.\n"
"Only the selected CMS certificates "
"will be deleted."),
ClearPGP}, // canCMS
// if !haveCMS
{kli18n("The OpenPGP backend does not support "
"certificate deletion.\n"
"Check your installation."),
Failure},
{kli18n("The OpenPGP backend does not support "
"certificate deletion.\n"
"Check your installation."),
Failure},
// if canPGP
// if haveCMS
{kli18n("The CMS backend does not support "
"certificate deletion.\n"
"Check your installation.\n"
"Only the selected OpenPGP certificates "
"will be deleted."),
ClearCMS}, // cantCMS
{KLazyLocalizedString(), Nothing}, // canCMS
// if !haveCMS
{KLazyLocalizedString(), Nothing}, // cantCMS
{KLazyLocalizedString(), Nothing}, // canCMS
// if !havePGP
// if cantPGP
// if haveCMS
{kli18n("The CMS backend does not support "
"certificate deletion.\n"
"Check your installation."),
Failure}, // cantCMS
{KLazyLocalizedString(), Nothing}, // canCMS
// if !haveCMS
{KLazyLocalizedString(), Nothing}, // cantCMS
{KLazyLocalizedString(), Nothing}, // canCMS
// if canPGP
// if haveCMS
{kli18n("The CMS backend does not support "
"certificate deletion.\n"
"Check your installation."),
Failure}, // cantCMS
{KLazyLocalizedString(), Nothing}, // canCMS
// if !haveCMS
{KLazyLocalizedString(), Nothing}, // cantCMS
{KLazyLocalizedString(), Nothing}, // canCMS
};
} // anon namespace
void DeleteCertificatesCommand::doStart()
{
std::vector<Key> selected = d->keys();
if (selected.empty()) {
d->finished();
return;
}
std::sort(selected.begin(), selected.end(), _detail::ByFingerprint<std::less>());
// Calculate the closure of the selected keys (those that need to
// be deleted with them, though not selected themselves):
std::vector<Key> toBeDeleted = KeyCache::instance()->findSubjects(selected);
std::sort(toBeDeleted.begin(), toBeDeleted.end(), _detail::ByFingerprint<std::less>());
std::vector<Key> unselected;
unselected.reserve(toBeDeleted.size());
std::set_difference(toBeDeleted.begin(),
toBeDeleted.end(),
selected.begin(),
selected.end(),
std::back_inserter(unselected),
_detail::ByFingerprint<std::less>());
d->ensureDialogCreated();
d->dialog->setSelectedKeys(selected);
d->dialog->setUnselectedKeys(unselected);
d->ensureDialogShown();
}
void DeleteCertificatesCommand::Private::slotDialogAccepted()
{
std::vector<Key> keys = dialog->keys();
Q_ASSERT(!keys.empty());
auto pgpBegin = keys.begin();
auto pgpEnd = std::stable_partition(pgpBegin, keys.end(), [](const GpgME::Key &key) {
return key.protocol() != GpgME::CMS;
});
auto cmsBegin = pgpEnd;
auto cmsEnd = keys.end();
std::vector<Key> openpgp(pgpBegin, pgpEnd);
std::vector<Key> cms(cmsBegin, cmsEnd);
const unsigned int errorCase = //
openpgp.empty() << 3U //
| canDelete(OpenPGP) << 2U //
| cms.empty() << 1U //
| canDelete(CMS) << 0U;
if (const unsigned int actions = deletionErrorCases[errorCase].actions) {
information(KLocalizedString(deletionErrorCases[errorCase].text).toString(),
(actions & Failure) ? i18n("Certificate Deletion Failed") : i18n("Certificate Deletion Problem"));
if (actions & ClearCMS) {
cms.clear();
}
if (actions & ClearPGP) {
openpgp.clear();
}
if (actions & Failure) {
canceled();
return;
}
}
Q_ASSERT(!openpgp.empty() || !cms.empty());
pgpKeys.swap(openpgp);
cmsKeys.swap(cms);
keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh();
if (!pgpKeys.empty()) {
startDeleteJob(GpgME::OpenPGP);
}
if (!cmsKeys.empty()) {
startDeleteJob(GpgME::CMS);
}
if ((pgpKeys.empty() || pgpError.code()) && (cmsKeys.empty() || cmsError.code())) {
showErrorsAndFinish();
}
}
void DeleteCertificatesCommand::Private::startDeleteJob(GpgME::Protocol protocol)
{
Q_ASSERT(protocol != GpgME::UnknownProtocol);
const std::vector<Key> &keys = protocol == CMS ? cmsKeys : pgpKeys;
const auto backend = (protocol == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime();
Q_ASSERT(backend);
std::unique_ptr<MultiDeleteJob> job(new MultiDeleteJob(backend));
connect(job.get(), &QGpgME::MultiDeleteJob::result, q_func(), [this, protocol](const GpgME::Error &result) {
if (protocol == CMS) {
cmsDeleteResult(result);
} else {
pgpDeleteResult(result);
}
});
connect(job.get(), &QGpgME::Job::jobProgress, q, &Command::progress);
#if QGPGME_VERSION >= QT_VERSION_CHECK(2, 0, 1)
- if (const Error err = job->start(keys, GpgME::DeletionFlags::AllowSecret | GpgME::DeletionFlags::Force)) {
+ if (const Error err = job->start(keys, GpgME::DeletionFlag::AllowSecret | GpgME::DeletionFlag::Force)) {
#else
if (const Error err = job->start(keys, true /* allowSecretKeyDeletion */)) {
#endif
(protocol == CMS ? cmsError : pgpError) = err;
} else {
(protocol == CMS ? cmsJob : pgpJob) = job.release();
}
}
void DeleteCertificatesCommand::Private::showErrorsAndFinish()
{
Q_ASSERT(!pgpJob);
Q_ASSERT(!cmsJob);
// on success, we know which keys were removed
#if QGPGME_VERSION >= QT_VERSION_CHECK(2, 0, 0)
if (!pgpKeys.empty() && pgpError.isSuccess()) {
#else
if (!pgpKeys.empty() && !pgpError && !pgpError.isCanceled()) {
#endif
KeyCache::mutableInstance()->remove(pgpKeys);
}
#if QGPGME_VERSION >= QT_VERSION_CHECK(2, 0, 0)
if (!cmsKeys.empty() && cmsError.isSuccess()) {
#else
if (!cmsKeys.empty() && !cmsError && !cmsError.isCanceled()) {
#endif
KeyCache::mutableInstance()->remove(cmsKeys);
}
// force a keylisting in any case because the deleted keys might have certified other keys
const GpgME::Protocol protocolToUpdate = (!pgpKeys.empty() //
? (!cmsKeys.empty() //
? GpgME::Protocol::UnknownProtocol
: GpgME::Protocol::OpenPGP)
: GpgME::Protocol::CMS);
KeyCache::mutableInstance()->reload(protocolToUpdate, KeyCache::ForceReload);
if (pgpError || cmsError) {
QString pgpErrorString;
if (pgpError) {
pgpErrorString = i18n("OpenPGP backend: %1", Formatting::errorAsString(pgpError));
}
QString cmsErrorString;
if (cmsError) {
cmsErrorString = i18n("CMS backend: %1", Formatting::errorAsString(cmsError));
}
const QString msg = i18n(
"<qt><p>An error occurred while trying to delete "
"the certificate:</p>"
"<p><b>%1</b></p></qt>",
pgpError ? cmsError ? pgpErrorString + QLatin1StringView("</br>") + cmsErrorString : pgpErrorString : cmsErrorString);
error(msg, i18n("Certificate Deletion Failed"));
}
finished();
}
void DeleteCertificatesCommand::doCancel()
{
d->cancelJobs();
}
void DeleteCertificatesCommand::Private::pgpDeleteResult(const Error &err)
{
pgpError = err;
pgpJob = nullptr;
if (!cmsJob) {
showErrorsAndFinish();
}
}
void DeleteCertificatesCommand::Private::cmsDeleteResult(const Error &err)
{
cmsError = err;
cmsJob = nullptr;
if (!pgpJob) {
showErrorsAndFinish();
}
}
void DeleteCertificatesCommand::Private::cancelJobs()
{
if (cmsJob) {
cmsJob->slotCancel();
}
if (pgpJob) {
pgpJob->slotCancel();
}
}
#undef d
#undef q
#include "moc_deletecertificatescommand.cpp"

File Metadata

Mime Type
text/x-diff
Expires
Sun, Dec 14, 3:02 PM (1 d, 17 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
d0/53/592719f3b4b1d056b984cb321c21

Event Timeline