Page MenuHome GnuPG

No OneTemporary

diff --git a/src/commands/revokecertificationcommand.cpp b/src/commands/revokecertificationcommand.cpp
index d2eaf8e20..102a92a65 100644
--- a/src/commands/revokecertificationcommand.cpp
+++ b/src/commands/revokecertificationcommand.cpp
@@ -1,239 +1,251 @@
/* -*- mode: c++; c-basic-offset:4 -*-
commands/revokecertificationcommand.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2020 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 "revokecertificationcommand.h"
#include "command_p.h"
#include "exportopenpgpcertstoservercommand.h"
#include "dialogs/revokecertificationdialog.h"
#include <Libkleo/Formatting>
+#include <Libkleo/KeyCache>
#include <QGpgME/Protocol>
#include <QGpgME/QuickJob>
#include <gpgme++/engineinfo.h>
-#include <gpgme++/key.h>
#include <KLocalizedString>
#include "kleopatra_debug.h"
#include <gpgme++/gpgmepp_version.h>
#if GPGMEPP_VERSION >= 0x10E01 // 1.14.1
# define GPGME_HAS_REVSIG
#endif
using namespace Kleo;
using namespace Kleo::Commands;
using namespace GpgME;
using namespace QGpgME;
class RevokeCertificationCommand::Private : public Command::Private
{
friend class ::Kleo::Commands::RevokeCertificationCommand;
RevokeCertificationCommand *q_func() const
{
return static_cast<RevokeCertificationCommand *>(q);
}
public:
explicit Private(RevokeCertificationCommand *qq, KeyListController *c);
~Private();
void init();
private:
void slotDialogAccepted();
void slotDialogRejected();
void slotResult(const Error &err);
private:
void ensureDialogCreated();
void createJob();
private:
+ Key certificationKey;
Key certificationTarget;
std::vector<UserID> uids;
QPointer<RevokeCertificationDialog> dialog;
QPointer<QGpgME::QuickJob> job;
};
RevokeCertificationCommand::Private *RevokeCertificationCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const RevokeCertificationCommand::Private *RevokeCertificationCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define d d_func()
#define q q_func()
RevokeCertificationCommand::Private::Private(RevokeCertificationCommand *qq, KeyListController *c)
: Command::Private(qq, c)
{
}
RevokeCertificationCommand::Private::~Private()
{
}
void RevokeCertificationCommand::Private::init()
{
const std::vector<Key> keys_ = keys();
if (keys_.size() != 1) {
qCWarning(KLEOPATRA_LOG) << "RevokeCertificationCommand::Private::init: Expected exactly one key, but got" << keys_.size();
return;
}
if (keys_.front().protocol() != GpgME::OpenPGP) {
qCWarning(KLEOPATRA_LOG) << "RevokeCertificationCommand::Private::init: Expected OpenPGP key, but got" << keys_.front().protocolAsString();
return;
}
certificationTarget = keys_.front();
}
void RevokeCertificationCommand::Private::slotDialogAccepted()
{
createJob();
#ifdef GPGME_HAS_REVSIG
job->startRevokeSignature(certificationTarget, dialog->selectedCertificationKey(), dialog->selectedUserIDs());
#endif
}
void RevokeCertificationCommand::Private::slotDialogRejected()
{
canceled();
}
void RevokeCertificationCommand::Private::slotResult(const Error &err)
{
if (!err && !err.isCanceled() && dialog && dialog->sendToServer()) {
ExportOpenPGPCertsToServerCommand *const cmd = new ExportOpenPGPCertsToServerCommand(certificationTarget);
cmd->start();
} else if (!err) {
information(i18n("Revocation successful."),
i18n("Revocation Succeeded"));
} else {
error(i18n("<p>An error occurred while trying to revoke the certification of<br/><br/>"
"<b>%1</b>:</p><p>\t%2</p>",
Formatting::formatForComboBox(certificationTarget),
QString::fromUtf8(err.asString())),
i18n("Revocation Error"));
}
finished();
}
void RevokeCertificationCommand::Private::ensureDialogCreated()
{
if (dialog) {
return;
}
dialog = new RevokeCertificationDialog;
applyWindowID(dialog);
dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted()));
connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected()));
}
void RevokeCertificationCommand::Private::createJob()
{
Q_ASSERT(!job);
Q_ASSERT(certificationTarget.protocol() == OpenPGP);
const auto backend = QGpgME::openpgp();
if (!backend) {
return;
}
QuickJob *const j = backend->quickJob();
if (!j) {
return;
}
connect(j, &Job::progress,
q, &Command::progress);
connect(j, SIGNAL(result(GpgME::Error)),
q, SLOT(slotResult(GpgME::Error)));
job = j;
}
RevokeCertificationCommand::RevokeCertificationCommand(QAbstractItemView *v, KeyListController *c)
: Command(v, new Private(this, c))
{
d->init();
}
RevokeCertificationCommand::RevokeCertificationCommand(const GpgME::UserID &uid)
: Command(uid.parent(), new Private(this, nullptr))
{
std::vector<UserID>(1, uid).swap(d->uids);
d->init();
}
+RevokeCertificationCommand::RevokeCertificationCommand(const GpgME::UserID::Signature &signature)
+ : Command(signature.parent().parent(), new Private(this, nullptr))
+{
+ std::vector<UserID>(1, signature.parent()).swap(d->uids);
+ d->certificationKey = KeyCache::instance()->findByKeyIDOrFingerprint(signature.signerKeyID());
+ d->init();
+}
+
RevokeCertificationCommand::~RevokeCertificationCommand()
{
qCDebug(KLEOPATRA_LOG) << "~RevokeCertificationCommand()";
}
// static
bool RevokeCertificationCommand::isSupported()
{
#ifdef GPGME_HAS_REVSIG
return engineInfo(GpgEngine).engineVersion() >= "2.2.24";
#else
return false;
#endif
}
void RevokeCertificationCommand::doStart()
{
if (d->certificationTarget.isNull()) {
d->finished();
return;
}
for (const UserID &uid : qAsConst(d->uids))
if (qstricmp(uid.parent().primaryFingerprint(), d->certificationTarget.primaryFingerprint()) != 0) {
qCWarning(KLEOPATRA_LOG) << "User-ID <-> Key mismatch!";
d->finished();
return;
}
d->ensureDialogCreated();
Q_ASSERT(d->dialog);
d->dialog->setCertificateToRevoke(d->certificationTarget);
if (!d->uids.empty()) {
d->dialog->setSelectedUserIDs(d->uids);
}
+ if (!d->certificationKey.isNull()) {
+ d->dialog->setSelectedCertificationKey(d->certificationKey);
+ }
d->dialog->show();
}
void RevokeCertificationCommand::doCancel()
{
qCDebug(KLEOPATRA_LOG) << "RevokeCertificationCommand::doCancel()";
if (d->job) {
d->job->slotCancel();
}
}
#undef d
#undef q
#include "moc_revokecertificationcommand.cpp"
diff --git a/src/commands/revokecertificationcommand.h b/src/commands/revokecertificationcommand.h
index 8832cc9f1..886fe22f6 100644
--- a/src/commands/revokecertificationcommand.h
+++ b/src/commands/revokecertificationcommand.h
@@ -1,57 +1,55 @@
/* -*- mode: c++; c-basic-offset:4 -*-
commands/revokecertificationcommand.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2020 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __KLEOPATRA_COMMANDS_REVOKECERTIFICATIONCOMMAND_H__
#define __KLEOPATRA_COMMANDS_REVOKECERTIFICATIONCOMMAND_H__
#include <commands/command.h>
-namespace GpgME
-{
-class UserID;
-}
+#include <gpgme++/key.h>
namespace Kleo
{
namespace Commands
{
class RevokeCertificationCommand : public Command
{
Q_OBJECT
public:
explicit RevokeCertificationCommand(QAbstractItemView *view, KeyListController *parent);
explicit RevokeCertificationCommand(const GpgME::UserID &uid);
+ explicit RevokeCertificationCommand(const GpgME::UserID::Signature &signature);
~RevokeCertificationCommand() override;
/* reimp */ static Restrictions restrictions()
{
return OnlyOneKey | MustBeOpenPGP;
}
static bool isSupported();
private:
void doStart() override;
void doCancel() override;
private:
class Private;
inline Private *d_func();
inline const Private *d_func() const;
Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error))
Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted())
Q_PRIVATE_SLOT(d_func(), void slotDialogRejected())
};
} // namespace Commands
} // namespace Kleo
#endif // __KLEOPATRA_COMMANDS_REVOKECERTIFICATIONCOMMAND_H__
diff --git a/src/dialogs/revokecertificationdialog.cpp b/src/dialogs/revokecertificationdialog.cpp
index 24fbff735..a49e75535 100644
--- a/src/dialogs/revokecertificationdialog.cpp
+++ b/src/dialogs/revokecertificationdialog.cpp
@@ -1,138 +1,143 @@
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/revokecertificationdialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2020 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 "revokecertificationdialog.h"
#include "revokecertificationwidget.h"
#include <Libkleo/Formatting>
#include <KConfigGroup>
#include <KGuiItem>
#include <KLocalizedString>
#include <KSharedConfig>
#include <KStandardGuiItem>
#include <QAbstractButton>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QVBoxLayout>
#include "kleopatra_debug.h"
using namespace GpgME;
using namespace Kleo;
class RevokeCertificationDialog::Private
{
friend class ::Kleo::RevokeCertificationDialog;
RevokeCertificationDialog *const q;
public:
explicit Private(RevokeCertificationDialog *qq);
~Private();
private:
void saveGeometry();
void restoreGeometry(const QSize &defaultSize);
private:
RevokeCertificationWidget *mainWidget = nullptr;
};
RevokeCertificationDialog::Private::Private(RevokeCertificationDialog *qq)
: q(qq)
{
}
RevokeCertificationDialog::Private::~Private()
{
}
void RevokeCertificationDialog::Private::saveGeometry()
{
KConfigGroup cfgGroup(KSharedConfig::openConfig(), "RevokeCertificationDialog");
cfgGroup.writeEntry("geometry", q->saveGeometry());
cfgGroup.sync();
}
void RevokeCertificationDialog::Private::restoreGeometry(const QSize &defaultSize)
{
KConfigGroup cfgGroup(KSharedConfig::openConfig(), "RevokeCertificationDialog");
const QByteArray geometry = cfgGroup.readEntry("geometry", QByteArray());
if (!geometry.isEmpty()) {
q->restoreGeometry(geometry);
} else {
q->resize(defaultSize);
}
}
RevokeCertificationDialog::RevokeCertificationDialog(QWidget *p, Qt::WindowFlags f)
: QDialog(p, f)
, d(new Private(this))
{
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
auto mainLay = new QVBoxLayout(this);
d->mainWidget = new RevokeCertificationWidget(this);
mainLay->addWidget(d->mainWidget);
QDialogButtonBox *buttonBox = new QDialogButtonBox();
mainLay->addWidget(buttonBox);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel |
QDialogButtonBox::Ok);
KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("Revoke Certification"));
connect(buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked,
this, [this] () {
d->mainWidget->saveConfig();
accept();
});
connect(buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked,
this, [this] () { close(); });
d->restoreGeometry(QSize(640, 480));
}
RevokeCertificationDialog::~RevokeCertificationDialog()
{
d->saveGeometry();
}
void RevokeCertificationDialog::setCertificateToRevoke(const Key &key)
{
setWindowTitle(i18nc("@title:window arg is name, email of certificate holder",
"Revoke Certification: %1", Formatting::prettyName(key)));
d->mainWidget->setTarget(key);
}
void RevokeCertificationDialog::setSelectedUserIDs(const std::vector<UserID> &uids)
{
d->mainWidget->setSelectUserIDs(uids);
}
std::vector<GpgME::UserID> RevokeCertificationDialog::selectedUserIDs() const
{
return d->mainWidget->selectedUserIDs();
}
+void Kleo::RevokeCertificationDialog::setSelectedCertificationKey(const GpgME::Key &key)
+{
+ d->mainWidget->setCertificationKey(key);
+}
+
Key RevokeCertificationDialog::selectedCertificationKey() const
{
return d->mainWidget->certificationKey();
}
bool RevokeCertificationDialog::sendToServer() const
{
return d->mainWidget->publishSelected();
}
diff --git a/src/dialogs/revokecertificationdialog.h b/src/dialogs/revokecertificationdialog.h
index 1fdf1203f..bf7af90c6 100644
--- a/src/dialogs/revokecertificationdialog.h
+++ b/src/dialogs/revokecertificationdialog.h
@@ -1,49 +1,50 @@
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/revokecertificationdialog.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2020 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __KLEOPATRA_DIALOGS_REVOKECERTIFICATIONDIALOG_H__
#define __KLEOPATRA_DIALOGS_REVOKECERTIFICATIONDIALOG_H__
#include <QDialog>
namespace GpgME
{
class Key;
class UserID;
}
namespace Kleo
{
class RevokeCertificationDialog : public QDialog
{
Q_OBJECT
public:
explicit RevokeCertificationDialog(QWidget *parent = nullptr, Qt::WindowFlags f = {});
~RevokeCertificationDialog() override;
void setCertificateToRevoke(const GpgME::Key &key);
void setSelectedUserIDs(const std::vector<GpgME::UserID> &uids);
std::vector<GpgME::UserID> selectedUserIDs() const;
+ void setSelectedCertificationKey(const GpgME::Key &key);
GpgME::Key selectedCertificationKey() const;
bool sendToServer() const;
private:
class Private;
const std::unique_ptr<Private> d;
};
} // namespace Kleo
#endif /* __KLEOPATRA_DIALOGS_REVOKECERTIFICATIONDIALOG_H__ */
diff --git a/src/dialogs/revokecertificationwidget.cpp b/src/dialogs/revokecertificationwidget.cpp
index 85a1b4af3..5cba2c5f5 100644
--- a/src/dialogs/revokecertificationwidget.cpp
+++ b/src/dialogs/revokecertificationwidget.cpp
@@ -1,265 +1,270 @@
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/revokecertificationwidget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2020 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "revokecertificationwidget.h"
#include <KConfigGroup>
#include <KLocalizedString>
#include <KSharedConfig>
#include <Libkleo/DefaultKeyFilter>
#include <Libkleo/Formatting>
#include <Libkleo/KeySelectionCombo>
#include <QCheckBox>
#include <QFrame>
#include <QHBoxLayout>
#include <QLabel>
#include <QListView>
#include <QStandardItemModel>
#include <QVBoxLayout>
#include <gpgme++/key.h>
#include "kleopatra_debug.h"
#include <gpgme++/gpgmepp_version.h>
#if GPGMEPP_VERSION >= 0x10E00 // 1.14.0
# define GPGME_HAS_UIDHASH
#endif
using namespace Kleo;
namespace {
class CertificationKeyFilter: public DefaultKeyFilter
{
public:
CertificationKeyFilter(const GpgME::Key &certificationTarget);
bool matches(const GpgME::Key &key, Kleo::KeyFilter::MatchContexts contexts) const override;
private:
GpgME::Key mCertificationTarget; // the key to certify or to revoke the certification of
};
CertificationKeyFilter::CertificationKeyFilter(const GpgME::Key &certificationTarget)
: DefaultKeyFilter()
, mCertificationTarget(certificationTarget)
{
setIsOpenPGP(DefaultKeyFilter::Set);
setHasSecret(DefaultKeyFilter::Set);
setCanCertify(DefaultKeyFilter::Set);
setIsBad(DefaultKeyFilter::NotSet);
}
bool CertificationKeyFilter::matches(const GpgME::Key &key, Kleo::KeyFilter::MatchContexts contexts) const
{
if (!(availableMatchContexts() & contexts)) {
return false;
}
// exclude certification target from list of certification keys
if (qstrcmp(key.primaryFingerprint(), mCertificationTarget.primaryFingerprint()) == 0) {
return false;
}
return DefaultKeyFilter::matches(key, contexts);
}
static bool uidsAreEqual(const GpgME::UserID &lhs, const GpgME::UserID &rhs)
{
// use uidhash if available
#ifdef GPGME_HAS_UIDHASH
if (lhs.uidhash() && rhs.uidhash()) {
return strcmp(lhs.uidhash(), rhs.uidhash()) == 0;
}
#endif
// compare actual user ID string and primary key; this is not unique, but it's all we can do if uidhash is missing
return qstrcmp(lhs.id(), rhs.id()) == 0
&& qstrcmp(lhs.parent().primaryFingerprint(), rhs.parent().primaryFingerprint()) == 0;
}
class UserIDModel : public QStandardItemModel
{
Q_OBJECT
public:
explicit UserIDModel(QObject *parent = nullptr) : QStandardItemModel(parent)
{
}
void setKey(const GpgME::Key &key)
{
mKey = key;
clear();
const std::vector<GpgME::UserID> uids = key.userIDs();
for (const auto &uid : uids) {
QStandardItem *const item = new QStandardItem;
item->setText(Formatting::prettyUserID(uid));
item->setCheckable(true);
item->setEditable(false);
item->setCheckState(Qt::Checked);
appendRow(item);
}
}
void setCheckedUserIDs(const std::vector<GpgME::UserID> &checkedUids)
{
const auto keyUids = mKey.userIDs();
Q_ASSERT(rowCount() == static_cast<int>(keyUids.size()));
for (int i = 0; i < rowCount(); ++i) {
const auto &keyUid = keyUids[i];
const bool uidIsChecked = std::find_if(checkedUids.cbegin(), checkedUids.cend(),
[keyUid](const GpgME::UserID &checkedUid) { return uidsAreEqual(keyUid, checkedUid); }) != checkedUids.cend();
item(i)->setCheckState(uidIsChecked ? Qt::Checked : Qt::Unchecked);
}
}
std::vector<GpgME::UserID> checkedUserIDs() const
{
const auto keyUids = mKey.userIDs();
Q_ASSERT(rowCount() == static_cast<int>(keyUids.size()));
std::vector<GpgME::UserID> checkedUids;
for (int i = 0; i < rowCount(); ++i) {
if (item(i)->checkState() == Qt::Checked) {
checkedUids.push_back(keyUids[i]);
}
}
return checkedUids;
}
private:
GpgME::Key mKey;
};
} // unnamed namespace
class RevokeCertificationWidget::Private
{
friend class ::Kleo::RevokeCertificationWidget;
RevokeCertificationWidget *const q;
QLabel *mFprLabel;
KeySelectionCombo *mCertificationKeySelect;
QCheckBox *mPublishCB;
UserIDModel mUserIDModel;
GpgME::Key mTarget;
public:
Private(RevokeCertificationWidget *qq)
: q(qq)
, mFprLabel(new QLabel)
, mCertificationKeySelect(new KeySelectionCombo(/* secretOnly = */ true))
, mPublishCB(new QCheckBox)
{
QVBoxLayout *mainLayout = new QVBoxLayout(q);
mainLayout->addWidget(mFprLabel);
auto certKeyLayout = new QHBoxLayout;
{
auto label = new QLabel(i18n("Certification key:"));
label->setToolTip(i18n("The key whose certifications shall be revoke"));
certKeyLayout->addWidget(label);
}
certKeyLayout->addWidget(mCertificationKeySelect, 1);
mainLayout->addLayout(certKeyLayout);
auto splitLine = new QFrame;
splitLine->setFrameShape(QFrame::HLine);
splitLine->setFrameShadow(QFrame::Sunken);
splitLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
mainLayout->addWidget(splitLine);
auto listView = new QListView;
listView->setModel(&mUserIDModel);
mainLayout->addWidget(listView, 1);
mPublishCB = new QCheckBox(i18n("Publish revocations on keyserver"));
mainLayout->addWidget(mPublishCB);
loadConfig();
}
~Private()
{
}
void saveConfig()
{
KConfigGroup conf(KSharedConfig::openConfig(), "RevokeCertificationSettings");
const auto certificationKey = mCertificationKeySelect->currentKey();
if (!certificationKey.isNull()) {
conf.writeEntry("LastKey", certificationKey.primaryFingerprint());
}
conf.writeEntry("PublishCheckState", mPublishCB->isChecked());
}
void loadConfig()
{
const KConfigGroup conf(KSharedConfig::openConfig(), "RevokeCertificationSettings");
mCertificationKeySelect->setDefaultKey(conf.readEntry("LastKey", QString()));
mPublishCB->setChecked(conf.readEntry("PublishCheckState", false));
}
};
RevokeCertificationWidget::RevokeCertificationWidget(QWidget *parent)
: QWidget(parent)
, d(new Private(this))
{
}
RevokeCertificationWidget::~RevokeCertificationWidget()
{
}
void RevokeCertificationWidget::setTarget(const GpgME::Key &key)
{
d->mTarget = key;
d->mFprLabel->setText(i18n("Fingerprint: <b>%1</b>",
Formatting::prettyID(d->mTarget.primaryFingerprint())) + QStringLiteral("<br/>") +
i18n("<i>Only the fingerprint clearly identifies the key and its owner.</i>"));
d->mCertificationKeySelect->setKeyFilter(std::shared_ptr<KeyFilter>(new CertificationKeyFilter(d->mTarget)));
d->mUserIDModel.setKey(d->mTarget);
}
GpgME::Key RevokeCertificationWidget::target() const
{
return d->mTarget;
}
void RevokeCertificationWidget::setSelectUserIDs(const std::vector<GpgME::UserID> &uids)
{
d->mUserIDModel.setCheckedUserIDs(uids);
}
std::vector<GpgME::UserID> RevokeCertificationWidget::selectedUserIDs() const
{
return d->mUserIDModel.checkedUserIDs();
}
+void RevokeCertificationWidget::setCertificationKey(const GpgME::Key &key)
+{
+ d->mCertificationKeySelect->setDefaultKey(QString::fromLatin1(key.primaryFingerprint()));
+}
+
GpgME::Key RevokeCertificationWidget::certificationKey() const
{
return d->mCertificationKeySelect->currentKey();
}
bool RevokeCertificationWidget::publishSelected() const
{
return d->mPublishCB->isChecked();
}
void Kleo::RevokeCertificationWidget::saveConfig() const
{
d->saveConfig();
}
// for UserIDModel
#include "revokecertificationwidget.moc"
diff --git a/src/dialogs/revokecertificationwidget.h b/src/dialogs/revokecertificationwidget.h
index 0866bfc17..274140bfe 100644
--- a/src/dialogs/revokecertificationwidget.h
+++ b/src/dialogs/revokecertificationwidget.h
@@ -1,61 +1,64 @@
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/revokecertificationwidget.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2020 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __KLEOPATRA_DIALOGS_REVOKECERTIFICATIONWIDGET_H__
#define __KLEOPATRA_DIALOGS_REVOKECERTIFICATIONWIDGET_H__
#include <QWidget>
#include <vector>
namespace GpgME
{
class Key;
class UserID;
}
namespace Kleo
{
/** Widget for revoking OpenPGP certifications. */
class RevokeCertificationWidget : public QWidget
{
Q_OBJECT
public:
explicit RevokeCertificationWidget(QWidget *parent = nullptr);
~RevokeCertificationWidget() override;
/* Set the key to revoke certifications of */
void setTarget(const GpgME::Key &key);
/* Get the key to revoke certifications of */
GpgME::Key target() const;
/* Select specific user ids. Default: all */
void setSelectUserIDs(const std::vector<GpgME::UserID> &uids);
/* The user ids whose certifications shall be revoked */
std::vector<GpgME::UserID> selectedUserIDs() const;
+ /* Set the selected certification key. Default: last used key */
+ void setCertificationKey(const GpgME::Key &key);
+
/* The selected certification key */
GpgME::Key certificationKey() const;
/* Whether the revocations shall be published */
bool publishSelected() const;
void saveConfig() const;
private:
class Private;
const std::unique_ptr<Private> d;
};
} // namespace Kleo
#endif // __KLEOPATRA_DIALOGS_REVOKECERTIFICATIONWIDGET_H__
diff --git a/src/dialogs/weboftrustwidget.cpp b/src/dialogs/weboftrustwidget.cpp
index e63b8ad3f..6f14d27eb 100644
--- a/src/dialogs/weboftrustwidget.cpp
+++ b/src/dialogs/weboftrustwidget.cpp
@@ -1,219 +1,271 @@
-/* SPDX-FileCopyrightText: 2017 Intevation GmbH
+/*
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2017 Intevation GmbH
+ SPDX-FileCopyrightText: 2020 g10 Code GmbH
+ SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "weboftrustwidget.h"
#include "commands/certifycertificatecommand.h"
#include "commands/revokecertificationcommand.h"
#include <QHeaderView>
#include <QVBoxLayout>
#include <QTreeView>
#include <gpgme++/key.h>
#include <gpgme++/keylistresult.h>
#include <QGpgME/Protocol>
#include <QGpgME/KeyListJob>
+#include <Libkleo/KeyCache>
#include <Libkleo/UserIDListModel>
#include "kleopatra_debug.h"
#include "commands/command.h"
#include "utils/remarks.h"
#include <KMessageBox>
#include <KLocalizedString>
#include <QMenu>
using namespace Kleo;
class WebOfTrustWidget::Private
{
friend class ::Kleo::WebOfTrustWidget;
WebOfTrustWidget *const q;
private:
GpgME::Key key;
UserIDListModel certificationsModel;
QGpgME::KeyListJob *keyListJob = nullptr;
QTreeView *certificationsTV = nullptr;
public:
Private(WebOfTrustWidget *qq)
: q(qq)
{
certificationsModel.enableRemarks(Remarks::remarksEnabled());
certificationsTV = new QTreeView;
certificationsTV->setModel(&certificationsModel);
certificationsTV->setAllColumnsShowFocus(true);
certificationsTV->setSelectionMode(QAbstractItemView::ExtendedSelection);
auto vLay = new QVBoxLayout(q);
vLay->setContentsMargins(0, 0, 0, 0);
vLay->addWidget(certificationsTV);
connect(certificationsTV, &QAbstractItemView::doubleClicked,
q, [this] (const QModelIndex &idx) {
certificationDblClicked(idx);
});
certificationsTV->setContextMenuPolicy(Qt::CustomContextMenu);
connect(certificationsTV, &QWidget::customContextMenuRequested,
q, [this] (const QPoint &p) {
contextMenuRequested(p);
});
}
void certificationDblClicked(const QModelIndex &idx)
{
if (!idx.isValid()) {
return;
}
if (!idx.parent().isValid()) {
// No parent -> root item.
return;
}
// grab the keyid
const auto query = certificationsModel.data(idx.sibling(idx.row(), 0)).toString();
// Show details widget or search
auto cmd = Command::commandForQuery(query);
cmd->setParentWId(q->winId());
cmd->start();
}
void addActionsForUserID(QMenu *menu, const GpgME::UserID &userID)
{
menu->addAction(QIcon::fromTheme(QStringLiteral("view-certificate-sign")),
i18n("Certify..."),
q, [this, userID]() {
auto cmd = new Kleo::Commands::CertifyCertificateCommand(userID);
cmd->setParentWidget(q);
certificationsTV->setEnabled(false);
connect(cmd, &Kleo::Commands::CertifyCertificateCommand::finished,
q, [this]() {
certificationsTV->setEnabled(true);
// Trigger an update when done
q->setKey(key);
});
cmd->start();
});
if (Kleo::Commands::RevokeCertificationCommand::isSupported()) {
menu->addAction(QIcon::fromTheme(QStringLiteral("view-certificate-revoke")),
i18n("Revoke Certification..."),
q, [this, userID]() {
auto cmd = new Kleo::Commands::RevokeCertificationCommand(userID);
cmd->setParentWidget(q);
certificationsTV->setEnabled(false);
connect(cmd, &Kleo::Commands::RevokeCertificationCommand::finished,
q, [this]() {
certificationsTV->setEnabled(true);
// Trigger an update when done
q->setKey(key);
});
cmd->start();
});
}
}
+ void addActionsForSignature(QMenu *menu, const GpgME::UserID::Signature &signature)
+ {
+ menu->addAction(QIcon::fromTheme(QStringLiteral("dialog-information")),
+ i18n("Show Certificate Details..."),
+ q, [this, signature]() {
+ auto cmd = Command::commandForQuery(QString::fromUtf8(signature.signerKeyID()));
+ cmd->setParentWId(q->winId());
+ cmd->start();
+ });
+ if (Kleo::Commands::RevokeCertificationCommand::isSupported()) {
+ auto action = menu->addAction(QIcon::fromTheme(QStringLiteral("view-certificate-revoke")),
+ i18n("Revoke Certification..."),
+ q, [this, signature]() {
+ auto cmd = new Kleo::Commands::RevokeCertificationCommand(signature);
+ cmd->setParentWidget(q);
+ certificationsTV->setEnabled(false);
+ connect(cmd, &Kleo::Commands::RevokeCertificationCommand::finished,
+ q, [this]() {
+ certificationsTV->setEnabled(true);
+ // Trigger an update when done
+ q->setKey(key);
+ });
+ cmd->start();
+ });
+ const auto certificationKey = KeyCache::instance()->findByKeyIDOrFingerprint(signature.signerKeyID());
+ const bool isSelfSignature = qstrcmp(signature.parent().parent().keyID(), signature.signerKeyID()) == 0;
+ action->setEnabled(!isSelfSignature && certificationKey.hasSecret() && !signature.isRevokation() && !signature.isExpired() && !signature.isInvalid());
+ if (isSelfSignature) {
+ action->setToolTip(i18n("Revokation of self-certifications is currently not possible."));
+ } else if (!certificationKey.hasSecret()) {
+ action->setToolTip(i18n("You cannot revoke this certification because it wasn't made with one of your keys (or the required secret key is missing)."));
+ } else if (signature.isRevokation()) {
+ action->setToolTip(i18n("You cannot revoke this revokation certification. (But you can re-certify the corresponding user ID.)"));
+ } else if (signature.isExpired()) {
+ action->setToolTip(i18n("You cannot revoke this expired certification."));
+ } else if (signature.isInvalid()) {
+ action->setToolTip(i18n("You cannot revoke this invalid certification."));
+ }
+ if (!action->isEnabled()) {
+ menu->setToolTipsVisible(true);
+ }
+ }
+ }
+
void contextMenuRequested(const QPoint &p)
{
const auto index = certificationsTV->indexAt(p);
const auto userID = certificationsModel.userID(index);
const auto signature = certificationsModel.signature(index);
if (userID.isNull() && signature.isNull()) {
return;
}
QMenu *menu = new QMenu(q);
if (!userID.isNull()) {
addActionsForUserID(menu, userID);
}
+ else if (!signature.isNull()) {
+ addActionsForSignature(menu, signature);
+ }
connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater);
menu->popup(certificationsTV->viewport()->mapToGlobal(p));
}
void startSignatureListing()
{
if (keyListJob) {
return;
}
QGpgME::KeyListJob *const job = QGpgME::openpgp()->keyListJob(/*remote*/false, /*includeSigs*/true, /*validate*/true);
if (!job) {
return;
}
if (Remarks::remarksEnabled()) {
job->addMode(GpgME::SignatureNotations);
}
/* Old style connect here again as QGPGME newstyle connects with
* default arguments don't work on windows. */
connect(job, &QGpgME::KeyListJob::result,
q, &WebOfTrustWidget::signatureListingDone);
connect(job, &QGpgME::KeyListJob::nextKey,
q, &WebOfTrustWidget::signatureListingNextKey);
job->start(QStringList(QString::fromLatin1(key.primaryFingerprint())));
keyListJob = job;
}
};
WebOfTrustWidget::WebOfTrustWidget(QWidget *parent) :
QWidget(parent),
d(new Private(this))
{
}
GpgME::Key WebOfTrustWidget::key() const
{
return d->key;
}
void WebOfTrustWidget::setKey(const GpgME::Key &key)
{
if (key.protocol() != GpgME::OpenPGP) {
qCDebug(KLEOPATRA_LOG) << "Trust chain is only supported for CMS keys";
return;
}
d->key = key;
d->certificationsModel.setKey(key);
d->certificationsTV->expandAll();
d->certificationsTV->header()->resizeSections(QHeaderView::ResizeToContents);
d->startSignatureListing();
}
WebOfTrustWidget::~WebOfTrustWidget()
{
}
void WebOfTrustWidget::signatureListingNextKey(const GpgME::Key &key)
{
GpgME::Key merged = key;
merged.mergeWith(d->key);
setKey(merged);
}
void WebOfTrustWidget::signatureListingDone(const GpgME::KeyListResult &result)
{
if (result.error()) {
KMessageBox::information(this, xi18nc("@info",
"<para>An error occurred while loading the certifications: "
"<message>%1</message></para>",
QString::fromLocal8Bit(result.error().asString())),
i18nc("@title", "Certifications Loading Failed"));
}
d->keyListJob = nullptr;
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Sep 16, 11:58 AM (1 d, 22 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
0b/b0/5533ece8eeeae3ad0b5e4e8e0dff

Event Timeline