diff --git a/src/dialogs/weboftrustdialog.cpp b/src/dialogs/weboftrustdialog.cpp index ba777d422..e80a59cde 100644 --- a/src/dialogs/weboftrustdialog.cpp +++ b/src/dialogs/weboftrustdialog.cpp @@ -1,56 +1,135 @@ -/* SPDX-FileCopyrightText: 2017 Intevation GmbH +/* -*- mode: c++; c-basic-offset:4 -*- + dialogs/weboftrustdialog.cpp + + This file is part of Kleopatra, the KDE keymanager + SPDX-FileCopyrightText: 2017 Intevation GmbH + SPDX-FileCopyrightText: 2022 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ +#include + #include "weboftrustdialog.h" + #include "weboftrustwidget.h" +#include "commands/importcertificatefromkeyservercommand.h" + +#include + #include #include #include #include #include #include #include +#include +#include + using namespace Kleo; WebOfTrustDialog::WebOfTrustDialog(QWidget *parent) : QDialog(parent) { KConfigGroup dialog(KSharedConfig::openStateConfig(), "WebOfTrustDialog"); const QSize size = dialog.readEntry("Size", QSize(900, 400)); if (size.isValid()) { resize(size); } setWindowTitle(i18nc("@title:window", "Certifications")); mWidget = new WebOfTrustWidget(this); auto l = new QVBoxLayout(this); l->addWidget(mWidget); auto bbox = new QDialogButtonBox(this); + auto btn = bbox->addButton(QDialogButtonBox::Close); connect(btn, &QPushButton::pressed, this, &QDialog::accept); + + mFetchKeysBtn = bbox->addButton(i18nc("@action:button", "Fetch Missing Keys"), + QDialogButtonBox::ActionRole); + mFetchKeysBtn->setToolTip(i18nc("@info:tooltip", "Look up and import all keys that were used to certify the user ids of this key")); + connect(mFetchKeysBtn, &QPushButton::pressed, this, &WebOfTrustDialog::fetchMissingKeys); +#ifndef QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID + mFetchKeysBtn->setVisible(false); +#endif + l->addWidget(bbox); } void WebOfTrustDialog::setKey(const GpgME::Key &key) { mWidget->setKey(key); + mFetchKeysBtn->setEnabled(!key.isBad()); } GpgME::Key WebOfTrustDialog::key() const { return mWidget->key(); } WebOfTrustDialog::~WebOfTrustDialog() { KConfigGroup dialog(KSharedConfig::openStateConfig(), "WebOfTrustDialog"); dialog.writeEntry("Size", size()); dialog.sync(); } + +namespace +{ +auto accumulateMissingSignerKeys(const std::vector &signatures) +{ + return std::accumulate( + std::begin(signatures), std::end(signatures), + std::set{}, + [] (auto &keyIds, const auto &signature) { + if (signature.status() == GpgME::UserID::Signature::NoPublicKey) { + keyIds.insert(QLatin1String{signature.signerKeyID()}); + } + return keyIds; + } + ); +} + +auto accumulateMissingSignerKeys(const std::vector &userIds) +{ + return std::accumulate( + std::begin(userIds), std::end(userIds), + std::set(), + [] (auto &keyIds, const auto &userID) { + if (!userID.isBad()) { + const auto newKeyIds = accumulateMissingSignerKeys(userID.signatures()); + std::copy(std::begin(newKeyIds), std::end(newKeyIds), + std::inserter(keyIds, std::end(keyIds))); + } + return keyIds; + } + ); +} +} + +void WebOfTrustDialog::fetchMissingKeys() +{ + if (key().isNull()) { + return; + } + const auto missingSignerKeys = accumulateMissingSignerKeys(key().userIDs()); + + auto cmd = new Kleo::ImportCertificateFromKeyserverCommand{QStringList{std::begin(missingSignerKeys), std::end(missingSignerKeys)}}; + cmd->setParentWidget(this); + setEnabled(false); + connect(cmd, &Kleo::ImportCertificateFromKeyserverCommand::finished, + this, [this]() { + // Trigger an update when done + setKey(key()); + setEnabled(true); + }); + cmd->start(); +} diff --git a/src/dialogs/weboftrustdialog.h b/src/dialogs/weboftrustdialog.h index 0eb046ffa..d9582e299 100644 --- a/src/dialogs/weboftrustdialog.h +++ b/src/dialogs/weboftrustdialog.h @@ -1,33 +1,43 @@ -/* SPDX-FileCopyrightText: 2017 Intevation GmbH +/* -*- mode: c++; c-basic-offset:4 -*- + dialogs/weboftrustdialog.h + + This file is part of Kleopatra, the KDE keymanager + SPDX-FileCopyrightText: 2017 Intevation GmbH + SPDX-FileCopyrightText: 2022 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include namespace GpgME { class Key; } namespace Kleo { class WebOfTrustWidget; class WebOfTrustDialog : public QDialog { Q_OBJECT public: explicit WebOfTrustDialog(QWidget *parent = nullptr); ~WebOfTrustDialog() override; void setKey(const GpgME::Key &key); GpgME::Key key() const; private: - WebOfTrustWidget *mWidget; + void fetchMissingKeys(); + +private: + QPushButton *mFetchKeysBtn = nullptr; + WebOfTrustWidget *mWidget = nullptr; }; } // namespace Kleo