diff --git a/src/crypto/gui/signerresolvepage.cpp b/src/crypto/gui/signerresolvepage.cpp index 9d59a0d89..1982d3751 100644 --- a/src/crypto/gui/signerresolvepage.cpp +++ b/src/crypto/gui/signerresolvepage.cpp @@ -1,668 +1,668 @@ /* -*- mode: c++; c-basic-offset:4 -*- crypto/gui/signerresolvepage.cpp 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 #include "signerresolvepage.h" #include "signerresolvepage_p.h" #include "signingcertificateselectiondialog.h" -#include +#include "crypto/certificateresolver.h" +#include "utils/keys.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace GpgME; using namespace Kleo; using namespace Kleo::Crypto; using namespace Kleo::Crypto::Gui; namespace { static SignerResolvePage::Operation operationFromFlags(bool sign, bool encrypt) { if (!encrypt && sign) { return SignerResolvePage::SignOnly; } if (!sign && encrypt) { return SignerResolvePage::EncryptOnly; } return SignerResolvePage::SignAndEncrypt; } static QString formatLabel(Protocol p, const Key &key) { return i18nc("%1=protocol (S/Mime, OpenPGP), %2=certificate", "Sign using %1: %2", Formatting::displayName(p), !key.isNull() ? Formatting::formatForComboBox(key) : i18n("No certificate selected")); } static std::vector supportedProtocols() { std::vector protocols; protocols.push_back(OpenPGP); protocols.push_back(CMS); return protocols; } } AbstractSigningProtocolSelectionWidget::AbstractSigningProtocolSelectionWidget(QWidget *p, Qt::WindowFlags f) : QWidget(p, f) { } ReadOnlyProtocolSelectionWidget::ReadOnlyProtocolSelectionWidget(QWidget *p, Qt::WindowFlags f) : AbstractSigningProtocolSelectionWidget(p, f) { auto const layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); const auto supportedProtocolsLst = supportedProtocols(); for (const Protocol i: supportedProtocolsLst) { auto const l = new QLabel; l->setText(formatLabel(i, Key())); layout->addWidget(l); m_labels[i] = l; } } void ReadOnlyProtocolSelectionWidget::setProtocolChecked(Protocol protocol, bool checked) { QLabel *const l = label(protocol); Q_ASSERT(l); l->setVisible(checked); } bool ReadOnlyProtocolSelectionWidget::isProtocolChecked(Protocol protocol) const { QLabel *const l = label(protocol); Q_ASSERT(l); return l->isVisible(); } std::set ReadOnlyProtocolSelectionWidget::checkedProtocols() const { std::set res; for (const Protocol i : supportedProtocols()) { if (isProtocolChecked(i)) { res.insert(i); } } return res; } SigningProtocolSelectionWidget::SigningProtocolSelectionWidget(QWidget *parent, Qt::WindowFlags f) : AbstractSigningProtocolSelectionWidget(parent, f) { m_buttonGroup = new QButtonGroup(this); connect(m_buttonGroup, &QButtonGroup::idClicked, this, &SigningProtocolSelectionWidget::userSelectionChanged); auto const layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); for (const Protocol i : supportedProtocols()) { auto const b = new QCheckBox; b->setText(formatLabel(i, Key())); m_buttons[i] = b; layout->addWidget(b); m_buttonGroup->addButton(b); } setExclusive(true); } void SigningProtocolSelectionWidget::setProtocolChecked(Protocol p, bool checked) { Q_ASSERT(p != UnknownProtocol); QCheckBox *const b = button(p); Q_ASSERT(b); b->setChecked(checked); } bool SigningProtocolSelectionWidget::isProtocolChecked(Protocol p) const { Q_ASSERT(p != UnknownProtocol); const QAbstractButton *const b = button(p); Q_ASSERT(b); return b->isChecked(); } std::set SigningProtocolSelectionWidget::checkedProtocols() const { std::set res; for (auto it = m_buttons.begin(), end = m_buttons.end(); it != end; ++it) if (it->second->isChecked()) { res.insert(it->first); } return res; } void SigningProtocolSelectionWidget::setExclusive(bool exclusive) { if (exclusive == isExclusive()) { return; } m_buttonGroup->setExclusive(exclusive); Q_EMIT userSelectionChanged(); } QCheckBox *SigningProtocolSelectionWidget::button(Protocol p) const { const auto it = m_buttons.find(p); return it == m_buttons.end() ? nullptr : it->second; } QLabel *ReadOnlyProtocolSelectionWidget::label(Protocol p) const { const auto it = m_labels.find(p); return it == m_labels.end() ? nullptr : it->second; } bool SigningProtocolSelectionWidget::isExclusive() const { return m_buttonGroup->exclusive(); } void SigningProtocolSelectionWidget::setCertificate(Protocol prot, const Key &key) { QAbstractButton *const b = button(prot); Q_ASSERT(b); b->setText(formatLabel(prot, key)); } void ReadOnlyProtocolSelectionWidget::setCertificate(Protocol prot, const Key &key) { QLabel *const l = label(prot); l->setText(formatLabel(prot, key)); } namespace { class ValidatorImpl : public SignerResolvePage::Validator { public: QString explanation() const override { return QString(); } bool isComplete() const override { return true; } QString customWindowTitle() const override { return QString(); } }; } class SignerResolvePage::Private { friend class ::Kleo::Crypto::Gui::SignerResolvePage; SignerResolvePage *const q; public: explicit Private(SignerResolvePage *qq); ~Private(); void setOperation(Operation operation); void operationButtonClicked(int operation); void selectCertificates(); - void setCertificates(const QMap &certs); + void setCertificates(const CertificatePair &certs); void updateModeSelectionWidgets(); void updateUi(); bool protocolSelected(Protocol p) const; bool protocolSelectionActuallyUserMutable() const; private: QButtonGroup *signEncryptGroup; QRadioButton *signAndEncryptRB; QRadioButton *encryptOnlyRB; QRadioButton *signOnlyRB; QGroupBox *signingCertificateBox; QLabel *signerLabelLabel; QLabel *signerLabel; QGroupBox *encryptBox; QCheckBox *textArmorCO; QPushButton *selectCertificatesButton; SigningProtocolSelectionWidget *signingProtocolSelectionWidget; ReadOnlyProtocolSelectionWidget *readOnlyProtocolSelectionWidget; std::vector presetProtocols; bool signingMutable; bool encryptionMutable; bool signingSelected; bool encryptionSelected; bool multipleProtocolsAllowed; bool protocolSelectionUserMutable; - QMap certificates; + CertificatePair certificates; std::shared_ptr validator; std::shared_ptr signingPreferences; }; bool SignerResolvePage::Private::protocolSelectionActuallyUserMutable() const { return (q->protocolSelectionUserMutable() || presetProtocols.empty()) && q->operation() == SignOnly; } SignerResolvePage::Private::Private(SignerResolvePage *qq) : q(qq) , presetProtocols() , signingMutable(true) , encryptionMutable(true) , signingSelected(false) , encryptionSelected(false) , multipleProtocolsAllowed(false) , protocolSelectionUserMutable(true) , validator(new ValidatorImpl) { auto layout = new QVBoxLayout(q); signEncryptGroup = new QButtonGroup(q); q->connect(signEncryptGroup, SIGNAL(buttonClicked(int)), q, SLOT(operationButtonClicked(int))); signAndEncryptRB = new QRadioButton; signAndEncryptRB->setText(i18n("Sign and encrypt (OpenPGP only)")); signAndEncryptRB->setChecked(true); signEncryptGroup->addButton(signAndEncryptRB, SignAndEncrypt); layout->addWidget(signAndEncryptRB); encryptOnlyRB = new QRadioButton; encryptOnlyRB->setText(i18n("Encrypt only")); signEncryptGroup->addButton(encryptOnlyRB, EncryptOnly); layout->addWidget(encryptOnlyRB); signOnlyRB = new QRadioButton; signOnlyRB->setText(i18n("Sign only")); signEncryptGroup->addButton(signOnlyRB, SignOnly); layout->addWidget(signOnlyRB); encryptBox = new QGroupBox; encryptBox->setTitle(i18n("Encryption Options")); QBoxLayout *const encryptLayout = new QVBoxLayout(encryptBox); textArmorCO = new QCheckBox; textArmorCO->setText(i18n("Text output (ASCII armor)")); encryptLayout->addWidget(textArmorCO); layout->addWidget(encryptBox); signingCertificateBox = new QGroupBox; signingCertificateBox->setTitle(i18n("Signing Options")); auto signerLayout = new QGridLayout(signingCertificateBox); signerLayout->setColumnStretch(1, 1); signerLabelLabel = new QLabel; signerLabelLabel->setText(i18n("Signer:")); signerLayout->addWidget(signerLabelLabel, 1, 0); signerLabel = new QLabel; signerLayout->addWidget(signerLabel, 1, 1); signerLabelLabel->setVisible(false); signerLabel->setVisible(false); signingProtocolSelectionWidget = new SigningProtocolSelectionWidget; connect(signingProtocolSelectionWidget, SIGNAL(userSelectionChanged()), q, SLOT(updateUi())); signerLayout->addWidget(signingProtocolSelectionWidget, 2, 0, 1, -1); readOnlyProtocolSelectionWidget = new ReadOnlyProtocolSelectionWidget; signerLayout->addWidget(readOnlyProtocolSelectionWidget, 3, 0, 1, -1); selectCertificatesButton = new QPushButton; selectCertificatesButton->setText(i18n("Change Signing Certificates...")); selectCertificatesButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); signerLayout->addWidget(selectCertificatesButton, 4, 0, 1, -1, Qt::AlignLeft); q->connect(selectCertificatesButton, SIGNAL(clicked()), q, SLOT(selectCertificates())); layout->addWidget(signingCertificateBox); layout->addStretch(); } void SignerResolvePage::setValidator(const std::shared_ptr &validator) { Q_ASSERT(validator); d->validator = validator; d->updateUi(); } std::shared_ptr SignerResolvePage::validator() const { return d->validator; } SignerResolvePage::Private::~Private() {} bool SignerResolvePage::Private::protocolSelected(Protocol p) const { Q_ASSERT(p != UnknownProtocol); return signingProtocolSelectionWidget->isProtocolChecked(p); } -void SignerResolvePage::Private::setCertificates(const QMap &certs) +void SignerResolvePage::Private::setCertificates(const CertificatePair &certs) { certificates = certs; - for (auto it = certs.cbegin(), endIt = certs.cend(); it != endIt; ++it) { - const Protocol proto = it.key(); - const Key &key = it.value(); - readOnlyProtocolSelectionWidget->setCertificate(proto, key); - signingProtocolSelectionWidget->setCertificate(proto, key); - } + readOnlyProtocolSelectionWidget->setCertificate(GpgME::OpenPGP, certs.openpgp); + signingProtocolSelectionWidget->setCertificate(GpgME::OpenPGP, certs.openpgp); + readOnlyProtocolSelectionWidget->setCertificate(GpgME::CMS, certs.cms); + signingProtocolSelectionWidget->setCertificate(GpgME::CMS, certs.cms); updateUi(); } void SignerResolvePage::Private::updateUi() { const bool ismutable = protocolSelectionActuallyUserMutable(); readOnlyProtocolSelectionWidget->setVisible(!ismutable); signingProtocolSelectionWidget->setVisible(ismutable); q->setExplanation(validator->explanation()); Q_EMIT q->completeChanged(); const QString customTitle = validator->customWindowTitle(); if (!customTitle.isEmpty()) { Q_EMIT q->windowTitleChanged(customTitle); } selectCertificatesButton->setEnabled(signingProtocolSelectionWidget->checkedProtocols().size() > 0); } void SignerResolvePage::setProtocolSelectionUserMutable(bool ismutable) { if (d->protocolSelectionUserMutable == ismutable) { return; } d->protocolSelectionUserMutable = ismutable; d->updateModeSelectionWidgets(); } bool SignerResolvePage::protocolSelectionUserMutable() const { return d->protocolSelectionUserMutable; } void SignerResolvePage::setMultipleProtocolsAllowed(bool allowed) { if (d->multipleProtocolsAllowed == allowed) { return; } d->multipleProtocolsAllowed = allowed; d->updateModeSelectionWidgets(); } bool SignerResolvePage::multipleProtocolsAllowed() const { return d->multipleProtocolsAllowed; } void SignerResolvePage::Private::updateModeSelectionWidgets() { const bool bothMutable = signingMutable && encryptionMutable; const bool noSigningPossible = !signingSelected && !signingMutable; const bool noEncryptionPossible = !encryptionSelected && !encryptionMutable; signAndEncryptRB->setChecked(signingSelected && encryptionSelected); signOnlyRB->setChecked(signingSelected && !encryptionSelected); encryptOnlyRB->setChecked(encryptionSelected && !signingSelected); const bool canSignAndEncrypt = !noSigningPossible && !noEncryptionPossible && bothMutable && presetProtocols != std::vector(1, CMS); const bool canSignOnly = !encryptionSelected || encryptionMutable; const bool canEncryptOnly = !signingSelected || signingMutable; signAndEncryptRB->setEnabled(canSignAndEncrypt); signOnlyRB->setEnabled(canSignOnly); encryptOnlyRB->setEnabled(canEncryptOnly); const bool buttonsVisible = signingMutable || encryptionMutable; signOnlyRB->setVisible(buttonsVisible); encryptOnlyRB->setVisible(buttonsVisible); signAndEncryptRB->setVisible(buttonsVisible); signingProtocolSelectionWidget->setExclusive(!multipleProtocolsAllowed); signingCertificateBox->setVisible(!noSigningPossible); encryptBox->setVisible(!noEncryptionPossible); updateUi(); } void SignerResolvePage::Private::selectCertificates() { QPointer dlg = new SigningCertificateSelectionDialog(q); dlg->setAllowedProtocols(signingProtocolSelectionWidget->checkedProtocols()); if (dlg->exec() == QDialog::Accepted && dlg) { - const QMap certs = dlg->selectedCertificates(); + const auto certs = dlg->selectedCertificates(); setCertificates(certs); if (signingPreferences && dlg->rememberAsDefault()) { - signingPreferences->setPreferredCertificate(OpenPGP, certs.value(OpenPGP)); - signingPreferences->setPreferredCertificate(CMS, certs.value(CMS)); + signingPreferences->setPreferredCertificate(OpenPGP, certs.openpgp); + signingPreferences->setPreferredCertificate(CMS, certs.cms); } } delete dlg; updateUi(); } void SignerResolvePage::Private::operationButtonClicked(int mode_) { const auto op = static_cast(mode_); signingCertificateBox->setEnabled(op != EncryptOnly); encryptBox->setEnabled(op != SignOnly); if (op == SignAndEncrypt) { signingProtocolSelectionWidget->setProtocolChecked(CMS, false); readOnlyProtocolSelectionWidget->setProtocolChecked(CMS, false); signingProtocolSelectionWidget->setProtocolChecked(OpenPGP, true); readOnlyProtocolSelectionWidget->setProtocolChecked(OpenPGP, true); } updateUi(); } void SignerResolvePage::Private::setOperation(Operation op) { switch (op) { case SignOnly: signOnlyRB->click(); break; case EncryptOnly: encryptOnlyRB->click(); break; case SignAndEncrypt: signAndEncryptRB->click(); break; } } SignerResolvePage::Operation SignerResolvePage::operation() const { return operationFromFlags(signingSelected(), encryptionSelected()); } SignerResolvePage::SignerResolvePage(QWidget *parent, Qt::WindowFlags f) : WizardPage(parent, f), d(new Private(this)) { setTitle(i18n("Choose Operation to be Performed")); // setSubTitle( i18n( "TODO" ) ); setPresetProtocol(UnknownProtocol); - d->setCertificates(QMap()); + d->setCertificates({}); d->updateModeSelectionWidgets(); d->operationButtonClicked(EncryptOnly); } SignerResolvePage::~SignerResolvePage() {} void SignerResolvePage::setSignersAndCandidates(const std::vector &signers, const std::vector< std::vector > &keys) { kleo_assert(signers.empty() || signers.size() == keys.size()); switch (signers.size()) { case 0: d->signerLabelLabel->setVisible(false); d->signerLabel->setVisible(false); // TODO: use default identity? break; case 1: d->signerLabelLabel->setVisible(true); d->signerLabel->setVisible(true); // TODO: use default identity? d->signerLabel->setText(signers.front().prettyAddress()); break; default: // > 1 kleo_assert(!"Resolving multiple signers not implemented"); } d->updateUi(); } void SignerResolvePage::setPresetProtocol(Protocol protocol) { std::vector protocols; if (protocol != CMS) { protocols.push_back(OpenPGP); } if (protocol != OpenPGP) { protocols.push_back(CMS); } setPresetProtocols(protocols); d->updateUi(); } void SignerResolvePage::setPresetProtocols(const std::vector &protocols) { d->presetProtocols = protocols; for (const Protocol i : supportedProtocols()) { const bool checked = std::find(protocols.begin(), protocols.end(), i) != protocols.end(); d->signingProtocolSelectionWidget->setProtocolChecked(i, checked); d->readOnlyProtocolSelectionWidget->setProtocolChecked(i, checked); } d->updateModeSelectionWidgets(); } std::set SignerResolvePage::selectedProtocols() const { return d->signingProtocolSelectionWidget->checkedProtocols(); } std::vector SignerResolvePage::signingCertificates(Protocol protocol) const { std::vector result; - if (protocol != CMS && d->signingProtocolSelectionWidget->isProtocolChecked(OpenPGP) && !d->certificates[OpenPGP].isNull()) { - result.push_back(d->certificates[OpenPGP]); + if (protocol != CMS && d->signingProtocolSelectionWidget->isProtocolChecked(OpenPGP) && !d->certificates.openpgp.isNull()) { + result.push_back(d->certificates.openpgp); } - if (protocol != OpenPGP && d->signingProtocolSelectionWidget->isProtocolChecked(CMS) && !d->certificates[CMS].isNull()) { - result.push_back(d->certificates[CMS]); + if (protocol != OpenPGP && d->signingProtocolSelectionWidget->isProtocolChecked(CMS) && !d->certificates.cms.isNull()) { + result.push_back(d->certificates.cms); } return result; } std::vector SignerResolvePage::resolvedSigners() const { std::vector result = signingCertificates(CMS); const std::vector pgp = signingCertificates(OpenPGP); result.insert(result.end(), pgp.begin(), pgp.end()); return result; } bool SignerResolvePage::isComplete() const { Q_ASSERT(d->validator); return d->validator->isComplete(); } bool SignerResolvePage::encryptionSelected() const { return !d->signOnlyRB->isChecked(); } void SignerResolvePage::setEncryptionSelected(bool selected) { d->encryptionSelected = selected; d->updateModeSelectionWidgets(); d->setOperation(operationFromFlags(d->signingSelected, d->encryptionSelected)); } bool SignerResolvePage::signingSelected() const { return !d->encryptOnlyRB->isChecked(); } void SignerResolvePage::setSigningSelected(bool selected) { d->signingSelected = selected; d->updateModeSelectionWidgets(); d->setOperation(operationFromFlags(d->signingSelected, d->encryptionSelected)); } bool SignerResolvePage::isEncryptionUserMutable() const { return d->encryptionMutable; } bool SignerResolvePage::isSigningUserMutable() const { return d->signingMutable; } void SignerResolvePage::setEncryptionUserMutable(bool ismutable) { d->encryptionMutable = ismutable; d->updateModeSelectionWidgets(); } void SignerResolvePage::setSigningUserMutable(bool ismutable) { d->signingMutable = ismutable; d->updateModeSelectionWidgets(); } std::set SignerResolvePage::selectedProtocolsWithoutSigningCertificate() const { std::set res; for (const Protocol i : selectedProtocols()) { if (signingCertificates(i).empty()) { res.insert(i); } } return res; } bool SignerResolvePage::isAsciiArmorEnabled() const { return d->textArmorCO->isChecked(); } void SignerResolvePage::setAsciiArmorEnabled(bool enabled) { d->textArmorCO->setChecked(enabled); } void SignerResolvePage::setSigningPreferences(const std::shared_ptr &prefs) { d->signingPreferences = prefs; - QMap map; - map[OpenPGP] = prefs ? prefs->preferredCertificate(OpenPGP) : Key(); - map[CMS] = prefs ? prefs->preferredCertificate(CMS) : Key(); - d->setCertificates(map); + const CertificatePair certs = { + prefs ? prefs->preferredCertificate(OpenPGP) : Key(), + prefs ? prefs->preferredCertificate(CMS) : Key() + }; + d->setCertificates(certs); } std::shared_ptr SignerResolvePage::signingPreferences() const { return d->signingPreferences; } void SignerResolvePage::onNext() { } #include "moc_signerresolvepage.cpp" #include "moc_signerresolvepage_p.cpp" diff --git a/src/crypto/gui/signingcertificateselectiondialog.cpp b/src/crypto/gui/signingcertificateselectiondialog.cpp index 98bcd4e09..252ada2a5 100644 --- a/src/crypto/gui/signingcertificateselectiondialog.cpp +++ b/src/crypto/gui/signingcertificateselectiondialog.cpp @@ -1,62 +1,65 @@ /* -*- mode: c++; c-basic-offset:4 -*- crypto/gui/signingcertificateselectiondialog.cpp 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 #include "signingcertificateselectiondialog.h" + #include "signingcertificateselectionwidget.h" +#include "utils/keys.h" + #include #include #include #include #include using namespace Kleo; using namespace Kleo::Crypto::Gui; SigningCertificateSelectionDialog::SigningCertificateSelectionDialog(QWidget *parent) : QDialog(parent), widget(new SigningCertificateSelectionWidget(this)) { setWindowTitle(i18nc("@title:window", "Select Signing Certificates")); auto mainLayout = new QVBoxLayout(this); mainLayout->addWidget(widget); auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, this, &SigningCertificateSelectionDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &SigningCertificateSelectionDialog::reject); mainLayout->addWidget(buttonBox); } SigningCertificateSelectionDialog::~SigningCertificateSelectionDialog() {} -void SigningCertificateSelectionDialog::setSelectedCertificates(const QMap &certificates) +void SigningCertificateSelectionDialog::setSelectedCertificates(const CertificatePair &certificates) { widget->setSelectedCertificates(certificates); } -QMap SigningCertificateSelectionDialog::selectedCertificates() const +CertificatePair SigningCertificateSelectionDialog::selectedCertificates() const { return widget->selectedCertificates(); } bool SigningCertificateSelectionDialog::rememberAsDefault() const { return widget->rememberAsDefault(); } void SigningCertificateSelectionDialog::setAllowedProtocols(const std::set &allowedProtocols) { widget->setAllowedProtocols(allowedProtocols); } diff --git a/src/crypto/gui/signingcertificateselectiondialog.h b/src/crypto/gui/signingcertificateselectiondialog.h index c89c2d04d..eb1ebfac8 100644 --- a/src/crypto/gui/signingcertificateselectiondialog.h +++ b/src/crypto/gui/signingcertificateselectiondialog.h @@ -1,51 +1,53 @@ /* -*- mode: c++; c-basic-offset:4 -*- crypto/gui/signingcertificateselectiondialog.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include #include #include template class QMap; namespace Kleo { +class CertificatePair; + namespace Crypto { namespace Gui { class SigningCertificateSelectionWidget; class SigningCertificateSelectionDialog : public QDialog { Q_OBJECT public: explicit SigningCertificateSelectionDialog(QWidget *parent = nullptr); ~SigningCertificateSelectionDialog() override; void setAllowedProtocols(const std::set &allowedProtocols); - void setSelectedCertificates(const QMap &certificates); - Q_REQUIRED_RESULT QMap selectedCertificates() const; + void setSelectedCertificates(const CertificatePair &certificates); + Q_REQUIRED_RESULT CertificatePair selectedCertificates() const; Q_REQUIRED_RESULT bool rememberAsDefault() const; private: SigningCertificateSelectionWidget *const widget; }; } } } diff --git a/src/crypto/gui/signingcertificateselectionwidget.cpp b/src/crypto/gui/signingcertificateselectionwidget.cpp index bd50e308a..9e3b442cd 100644 --- a/src/crypto/gui/signingcertificateselectionwidget.cpp +++ b/src/crypto/gui/signingcertificateselectionwidget.cpp @@ -1,145 +1,145 @@ /* -*- mode: c++; c-basic-offset:4 -*- crypto/gui/signingcertificateselectionwidget.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007, 2009 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "signingcertificateselectionwidget.h" #include "ui_signingcertificateselectionwidget.h" +#include "utils/keys.h" + #include #include #include #include #include using namespace Kleo; using namespace Kleo::Crypto::Gui; class SigningCertificateSelectionWidget::Private { friend class ::SigningCertificateSelectionWidget; SigningCertificateSelectionWidget *const q; public: explicit Private(SigningCertificateSelectionWidget *qq); ~Private(); static std::vector candidates(GpgME::Protocol prot); static void addCandidates(GpgME::Protocol prot, QComboBox *combo); private: Ui::SigningCertificateSelectionWidget ui; }; static GpgME::Key current_cert(const QComboBox &cb) { const QByteArray fpr = cb.itemData(cb.currentIndex()).toByteArray(); return KeyCache::instance()->findByFingerprint(fpr.constData()); } static void select_cert(QComboBox &cb, const GpgME::Key &key) { const QByteArray fpr = key.primaryFingerprint(); if (!fpr.isEmpty()) { cb.setCurrentIndex(cb.findData(fpr)); } } static void add_cert(QComboBox &cb, const GpgME::Key &key) { cb.addItem(Formatting::formatForComboBox(key), QVariant(QByteArray(key.primaryFingerprint()))); } SigningCertificateSelectionWidget::Private::Private(SigningCertificateSelectionWidget *qq) : q(qq), ui() { ui.setupUi(q); addCandidates(GpgME::CMS, ui.cmsCombo); addCandidates(GpgME::OpenPGP, ui.pgpCombo); ui.rememberCO->setChecked(true); } SigningCertificateSelectionWidget::Private::~Private() {} SigningCertificateSelectionWidget::SigningCertificateSelectionWidget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f), d(new Private(this)) { } SigningCertificateSelectionWidget::~SigningCertificateSelectionWidget() {} -void SigningCertificateSelectionWidget::setSelectedCertificates(const QMap &certificates) +void SigningCertificateSelectionWidget::setSelectedCertificates(const CertificatePair &certificates) { - setSelectedCertificates(certificates[GpgME::OpenPGP], certificates[GpgME::CMS]); + setSelectedCertificates(certificates.openpgp, certificates.cms); } void SigningCertificateSelectionWidget::setSelectedCertificates(const GpgME::Key &pgp, const GpgME::Key &cms) { select_cert(*d->ui.pgpCombo, pgp); select_cert(*d->ui.cmsCombo, cms); } std::vector SigningCertificateSelectionWidget::Private::candidates(GpgME::Protocol prot) { Q_ASSERT(prot != GpgME::UnknownProtocol); std::vector keys = KeyCache::instance()->keys(); auto end = keys.end(); end = std::remove_if(keys.begin(), end, [prot](const GpgME::Key &key) { return key.protocol() != prot; }); end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) { return !key.hasSecret(); }); Q_ASSERT(std::all_of(keys.begin(), end, [](const GpgME::Key &key) { return key.hasSecret(); })); end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) { return !key.canReallySign(); }); end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) { return key.isExpired(); }); end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) { return key.isRevoked(); }); keys.erase(end, keys.end()); return keys; } void SigningCertificateSelectionWidget::Private::addCandidates(GpgME::Protocol prot, QComboBox *combo) { const std::vector keys = candidates(prot); for (const GpgME::Key &i : keys) { add_cert(*combo, i); } } -QMap SigningCertificateSelectionWidget::selectedCertificates() const +CertificatePair SigningCertificateSelectionWidget::selectedCertificates() const { - QMap res; - - res.insert(GpgME::OpenPGP, current_cert(*d->ui.pgpCombo)); - res.insert(GpgME::CMS, current_cert(*d->ui.cmsCombo)); - - return res; + return { + current_cert(*d->ui.pgpCombo), + current_cert(*d->ui.cmsCombo), + }; } bool SigningCertificateSelectionWidget::rememberAsDefault() const { return d->ui.rememberCO->isChecked(); } void SigningCertificateSelectionWidget::setAllowedProtocols(const std::set &allowedProtocols) { setAllowedProtocols(allowedProtocols.find(GpgME::OpenPGP) != allowedProtocols.end(), allowedProtocols.find(GpgME::CMS) != allowedProtocols.end()); } void SigningCertificateSelectionWidget::setAllowedProtocols(bool pgp, bool cms) { d->ui.pgpLabel->setVisible(pgp); d->ui.pgpCombo->setVisible(pgp); d->ui.cmsLabel->setVisible(cms); d->ui.cmsCombo->setVisible(cms); } diff --git a/src/crypto/gui/signingcertificateselectionwidget.h b/src/crypto/gui/signingcertificateselectionwidget.h index f82536f1b..114599f1a 100644 --- a/src/crypto/gui/signingcertificateselectionwidget.h +++ b/src/crypto/gui/signingcertificateselectionwidget.h @@ -1,57 +1,59 @@ /* -*- mode: c++; c-basic-offset:4 -*- crypto/gui/signingcertificateselectionwidget.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007, 2009 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include #include #include template class QMap; namespace GpgME { class Key; } namespace Kleo { +class CertificatePair; + namespace Crypto { namespace Gui { class SigningCertificateSelectionWidget : public QWidget { Q_OBJECT public: explicit SigningCertificateSelectionWidget(QWidget *parent = nullptr, Qt::WindowFlags f = {}); ~SigningCertificateSelectionWidget() override; void setAllowedProtocols(const std::set &allowedProtocols); void setAllowedProtocols(bool pgp, bool cms); - void setSelectedCertificates(const QMap &certificates); + void setSelectedCertificates(const CertificatePair &certificates); void setSelectedCertificates(const GpgME::Key &pgp, const GpgME::Key &cms); - QMap selectedCertificates() const; + CertificatePair selectedCertificates() const; bool rememberAsDefault() const; private: class Private; kdtools::pimpl_ptr d; }; } } } diff --git a/src/utils/keys.h b/src/utils/keys.h index 1d8d7058e..0e142a7b4 100644 --- a/src/utils/keys.h +++ b/src/utils/keys.h @@ -1,35 +1,42 @@ /* -*- mode: c++; c-basic-offset:4 -*- utils/keys.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2022 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace Kleo { + +struct CertificatePair { + GpgME::Key openpgp; + GpgME::Key cms; +}; + /** Returns true if \p signature is a self-signature. */ bool isSelfSignature(const GpgME::UserID::Signature &signature); /** * Returns true if the most recent self-signature of \p userId is a revocation * signature or if it has expired. */ bool isRevokedOrExpired(const GpgME::UserID &userId); /** * Returns true if \p key can be used to certify user IDs, i.e. if the key * has the required capability and if the secret key of the (primary) * certification subkey is available in the keyring or on a smart card. * * \note Key::hasSecret() also returns true if a secret key stub, e.g. of an * offline key, is available in the keyring. */ bool canCreateCertifications(const GpgME::Key &key); + }