1 /* -*- mode: c++; c-basic-offset:4 -*-
2     crypto/gui/signingcertificateselectionwidget.cpp
3 
4     This file is part of Kleopatra, the KDE keymanager
5     SPDX-FileCopyrightText: 2007, 2009 Klarälvdalens Datakonsult AB
6 
7     SPDX-License-Identifier: GPL-2.0-or-later
8 */
9 
10 #include <config-kleopatra.h>
11 
12 #include "signingcertificateselectionwidget.h"
13 
14 #include "ui_signingcertificateselectionwidget.h"
15 
16 #include <Libkleo/KeyCache>
17 #include <Libkleo/Formatting>
18 #include <Libkleo/Stl_Util>
19 
20 #include <QByteArray>
21 #include <QMap>
22 
23 
24 using namespace Kleo;
25 using namespace Kleo::Crypto::Gui;
26 
27 class SigningCertificateSelectionWidget::Private
28 {
29     friend class ::SigningCertificateSelectionWidget;
30     SigningCertificateSelectionWidget *const q;
31 public:
32     explicit Private(SigningCertificateSelectionWidget *qq);
33     ~Private();
34     static std::vector<GpgME::Key> candidates(GpgME::Protocol prot);
35     static void addCandidates(GpgME::Protocol prot, QComboBox *combo);
36 
37 private:
38     Ui::SigningCertificateSelectionWidget ui;
39 };
40 
current_cert(const QComboBox & cb)41 static GpgME::Key current_cert(const QComboBox &cb)
42 {
43     const QByteArray fpr = cb.itemData(cb.currentIndex()).toByteArray();
44     return KeyCache::instance()->findByFingerprint(fpr.constData());
45 }
46 
select_cert(QComboBox & cb,const GpgME::Key & key)47 static void select_cert(QComboBox &cb, const GpgME::Key &key)
48 {
49     const QByteArray fpr = key.primaryFingerprint();
50     if (!fpr.isEmpty()) {
51         cb.setCurrentIndex(cb.findData(fpr));
52     }
53 }
54 
add_cert(QComboBox & cb,const GpgME::Key & key)55 static void add_cert(QComboBox &cb, const GpgME::Key &key)
56 {
57     cb.addItem(Formatting::formatForComboBox(key),
58                QVariant(QByteArray(key.primaryFingerprint())));
59 
60 }
61 
Private(SigningCertificateSelectionWidget * qq)62 SigningCertificateSelectionWidget::Private::Private(SigningCertificateSelectionWidget *qq)
63     : q(qq), ui()
64 {
65     ui.setupUi(q);
66     addCandidates(GpgME::CMS, ui.cmsCombo);
67     addCandidates(GpgME::OpenPGP, ui.pgpCombo);
68     ui.rememberCO->setChecked(true);
69 }
70 
~Private()71 SigningCertificateSelectionWidget::Private::~Private() {}
72 
SigningCertificateSelectionWidget(QWidget * parent,Qt::WindowFlags f)73 SigningCertificateSelectionWidget::SigningCertificateSelectionWidget(QWidget *parent, Qt::WindowFlags f)
74     : QWidget(parent, f), d(new Private(this))
75 {
76 
77 }
78 
~SigningCertificateSelectionWidget()79 SigningCertificateSelectionWidget::~SigningCertificateSelectionWidget() {}
80 
setSelectedCertificates(const QMap<GpgME::Protocol,GpgME::Key> & certificates)81 void SigningCertificateSelectionWidget::setSelectedCertificates(const QMap<GpgME::Protocol, GpgME::Key> &certificates)
82 {
83     setSelectedCertificates(certificates[GpgME::OpenPGP], certificates[GpgME::CMS]);
84 }
85 
setSelectedCertificates(const GpgME::Key & pgp,const GpgME::Key & cms)86 void SigningCertificateSelectionWidget::setSelectedCertificates(const GpgME::Key &pgp, const GpgME::Key &cms)
87 {
88     select_cert(*d->ui.pgpCombo, pgp);
89     select_cert(*d->ui.cmsCombo, cms);
90 }
91 
candidates(GpgME::Protocol prot)92 std::vector<GpgME::Key> SigningCertificateSelectionWidget::Private::candidates(GpgME::Protocol prot)
93 {
94     Q_ASSERT(prot != GpgME::UnknownProtocol);
95     std::vector<GpgME::Key> keys = KeyCache::instance()->keys();
96     auto end = keys.end();
97 
98     end = std::remove_if(keys.begin(), end, [prot](const GpgME::Key &key) { return key.protocol() != prot; });
99     end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) { return !key.hasSecret(); });
100     Q_ASSERT(std::all_of(keys.begin(), end, [](const GpgME::Key &key) { return key.hasSecret(); }));
101     end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) { return !key.canReallySign(); });
102     end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) { return key.isExpired(); });
103     end = std::remove_if(keys.begin(), end, [](const GpgME::Key &key) { return key.isRevoked(); });
104     keys.erase(end, keys.end());
105     return keys;
106 }
107 
addCandidates(GpgME::Protocol prot,QComboBox * combo)108 void SigningCertificateSelectionWidget::Private::addCandidates(GpgME::Protocol prot, QComboBox *combo)
109 {
110     const std::vector<GpgME::Key> keys = candidates(prot);
111     for (const GpgME::Key &i : keys) {
112         add_cert(*combo, i);
113     }
114 }
115 
selectedCertificates() const116 QMap<GpgME::Protocol, GpgME::Key> SigningCertificateSelectionWidget::selectedCertificates() const
117 {
118     QMap<GpgME::Protocol, GpgME::Key> res;
119 
120     res.insert(GpgME::OpenPGP, current_cert(*d->ui.pgpCombo));
121     res.insert(GpgME::CMS,     current_cert(*d->ui.cmsCombo));
122 
123     return res;
124 }
125 
rememberAsDefault() const126 bool SigningCertificateSelectionWidget::rememberAsDefault() const
127 {
128     return d->ui.rememberCO->isChecked();
129 }
130 
setAllowedProtocols(const std::set<GpgME::Protocol> & allowedProtocols)131 void SigningCertificateSelectionWidget::setAllowedProtocols(const std::set<GpgME::Protocol> &allowedProtocols)
132 {
133     setAllowedProtocols(allowedProtocols.find(GpgME::OpenPGP) != allowedProtocols.end(),
134                         allowedProtocols.find(GpgME::CMS) != allowedProtocols.end());
135 }
136 
setAllowedProtocols(bool pgp,bool cms)137 void SigningCertificateSelectionWidget::setAllowedProtocols(bool pgp, bool cms)
138 {
139     d->ui.pgpLabel->setVisible(pgp);
140     d->ui.pgpCombo->setVisible(pgp);
141 
142     d->ui.cmsLabel->setVisible(cms);
143     d->ui.cmsCombo->setVisible(cms);
144 }
145 
146