File indexing completed on 2024-06-23 05:13:53

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     crypto/gui/signingcertificateselectionwidget.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2007, 2009 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "signingcertificateselectionwidget.h"
0013 
0014 #include "ui_signingcertificateselectionwidget.h"
0015 
0016 #include "utils/certificatepair.h"
0017 
0018 #include <Libkleo/Compat>
0019 #include <Libkleo/Formatting>
0020 #include <Libkleo/KeyCache>
0021 #include <Libkleo/Stl_Util>
0022 
0023 #include <QByteArray>
0024 
0025 using namespace Kleo;
0026 using namespace Kleo::Crypto::Gui;
0027 
0028 class SigningCertificateSelectionWidget::Private
0029 {
0030     friend class ::SigningCertificateSelectionWidget;
0031     SigningCertificateSelectionWidget *const q;
0032 
0033 public:
0034     explicit Private(SigningCertificateSelectionWidget *qq);
0035     ~Private();
0036     static std::vector<GpgME::Key> candidates(GpgME::Protocol prot);
0037     static void addCandidates(GpgME::Protocol prot, QComboBox *combo);
0038 
0039 private:
0040     Ui::SigningCertificateSelectionWidget ui;
0041 };
0042 
0043 static GpgME::Key current_cert(const QComboBox &cb)
0044 {
0045     const QByteArray fpr = cb.itemData(cb.currentIndex()).toByteArray();
0046     return KeyCache::instance()->findByFingerprint(fpr.constData());
0047 }
0048 
0049 static void select_cert(QComboBox &cb, const GpgME::Key &key)
0050 {
0051     const QByteArray fpr = key.primaryFingerprint();
0052     if (!fpr.isEmpty()) {
0053         cb.setCurrentIndex(cb.findData(fpr));
0054     }
0055 }
0056 
0057 static void add_cert(QComboBox &cb, const GpgME::Key &key)
0058 {
0059     cb.addItem(Formatting::formatForComboBox(key), QVariant(QByteArray(key.primaryFingerprint())));
0060 }
0061 
0062 SigningCertificateSelectionWidget::Private::Private(SigningCertificateSelectionWidget *qq)
0063     : q(qq)
0064     , ui()
0065 {
0066     ui.setupUi(q);
0067     addCandidates(GpgME::CMS, ui.cmsCombo);
0068     addCandidates(GpgME::OpenPGP, ui.pgpCombo);
0069     ui.rememberCO->setChecked(true);
0070 }
0071 
0072 SigningCertificateSelectionWidget::Private::~Private()
0073 {
0074 }
0075 
0076 SigningCertificateSelectionWidget::SigningCertificateSelectionWidget(QWidget *parent, Qt::WindowFlags f)
0077     : QWidget(parent, f)
0078     , d(new Private(this))
0079 {
0080 }
0081 
0082 SigningCertificateSelectionWidget::~SigningCertificateSelectionWidget()
0083 {
0084 }
0085 
0086 void SigningCertificateSelectionWidget::setSelectedCertificates(const CertificatePair &certificates)
0087 {
0088     setSelectedCertificates(certificates.openpgp, certificates.cms);
0089 }
0090 
0091 void SigningCertificateSelectionWidget::setSelectedCertificates(const GpgME::Key &pgp, const GpgME::Key &cms)
0092 {
0093     select_cert(*d->ui.pgpCombo, pgp);
0094     select_cert(*d->ui.cmsCombo, cms);
0095 }
0096 
0097 std::vector<GpgME::Key> SigningCertificateSelectionWidget::Private::candidates(GpgME::Protocol prot)
0098 {
0099     Q_ASSERT(prot != GpgME::UnknownProtocol);
0100     std::vector<GpgME::Key> keys = KeyCache::instance()->keys();
0101     auto end = keys.end();
0102 
0103     end = std::remove_if(keys.begin(), end, [prot](const GpgME::Key &key) {
0104         return key.protocol() != prot;
0105     });
0106     end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) {
0107         return !key.hasSecret();
0108     });
0109     Q_ASSERT(std::all_of(keys.begin(), end, [](const GpgME::Key &key) {
0110         return key.hasSecret();
0111     }));
0112     end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) {
0113         return !Kleo::keyHasSign(key);
0114     });
0115     end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) {
0116         return key.isExpired();
0117     });
0118     end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) {
0119         return key.isRevoked();
0120     });
0121     keys.erase(end, keys.end());
0122     return keys;
0123 }
0124 
0125 void SigningCertificateSelectionWidget::Private::addCandidates(GpgME::Protocol prot, QComboBox *combo)
0126 {
0127     const std::vector<GpgME::Key> keys = candidates(prot);
0128     for (const GpgME::Key &i : keys) {
0129         add_cert(*combo, i);
0130     }
0131 }
0132 
0133 CertificatePair SigningCertificateSelectionWidget::selectedCertificates() const
0134 {
0135     return {
0136         current_cert(*d->ui.pgpCombo),
0137         current_cert(*d->ui.cmsCombo),
0138     };
0139 }
0140 
0141 bool SigningCertificateSelectionWidget::rememberAsDefault() const
0142 {
0143     return d->ui.rememberCO->isChecked();
0144 }
0145 
0146 void SigningCertificateSelectionWidget::setAllowedProtocols(const std::set<GpgME::Protocol> &allowedProtocols)
0147 {
0148     setAllowedProtocols(allowedProtocols.find(GpgME::OpenPGP) != allowedProtocols.end(), allowedProtocols.find(GpgME::CMS) != allowedProtocols.end());
0149 }
0150 
0151 void SigningCertificateSelectionWidget::setAllowedProtocols(bool pgp, bool cms)
0152 {
0153     d->ui.pgpLabel->setVisible(pgp);
0154     d->ui.pgpCombo->setVisible(pgp);
0155 
0156     d->ui.cmsLabel->setVisible(cms);
0157     d->ui.cmsCombo->setVisible(cms);
0158 }
0159 
0160 #include "moc_signingcertificateselectionwidget.cpp"