1 /*
2     This file is part of the KDE project
3     SPDX-FileCopyrightText: 2013 Valentin Rusu <kde@rusu.info>
4 
5     SPDX-License-Identifier: LGPL-2.0-only
6 */
7 
8 #include "knewwalletdialog.h"
9 #include "kwalletd_debug.h"
10 #include <KLocalizedString>
11 #include <KMessageBox>
12 #include <QTableWidget>
13 #include <QTableWidgetItem>
14 #include <gpgme++/context.h>
15 #include <gpgme++/key.h>
16 #include <gpgme++/keylistresult.h>
17 
18 Q_DECLARE_METATYPE(GpgME::Key)
19 
20 namespace KWallet
21 {
KNewWalletDialog(const QString & appName,const QString & walletName,QWidget * parent)22 KNewWalletDialog::KNewWalletDialog(const QString &appName, const QString &walletName, QWidget *parent)
23     : QWizard(parent)
24 {
25     setOption(HaveFinishButtonOnEarlyPages);
26     _intro = new KNewWalletDialogIntro(appName, walletName, this);
27     _introId = addPage(_intro);
28 
29     _gpg = new KNewWalletDialogGpg(appName, walletName, this);
30     _gpgId = addPage(_gpg);
31 }
32 
isBlowfish() const33 bool KNewWalletDialog::isBlowfish() const
34 {
35     return _intro->isBlowfish();
36 }
37 
gpgKey() const38 GpgME::Key KNewWalletDialog::gpgKey() const
39 {
40     QVariant varKey = field(QStringLiteral("key"));
41     return varKey.value<GpgME::Key>();
42 }
43 
KNewWalletDialogIntro(const QString & appName,const QString & walletName,QWidget * parent)44 KNewWalletDialogIntro::KNewWalletDialogIntro(const QString &appName, const QString &walletName, QWidget *parent)
45     : QWizardPage(parent)
46 {
47     _ui.setupUi(this);
48     if (appName.isEmpty()) {
49         _ui.labelIntro->setText(
50             i18n("<qt>KDE has requested to create a new wallet named '<b>%1</b>'. This is used to store sensitive data in a secure fashion. Please choose the "
51                  "new wallet's type below or click cancel to deny the application's request.</qt>",
52                  walletName.toHtmlEscaped()));
53     } else {
54         _ui.labelIntro->setText(
55             i18n("<qt>The application '<b>%1</b>' has requested to create a new wallet named '<b>%2</b>'. This is used to store sensitive data in a secure "
56                  "fashion. Please choose the new wallet's type below or click cancel to deny the application's request.</qt>",
57                  appName.toHtmlEscaped(),
58                  walletName.toHtmlEscaped()));
59     }
60 }
61 
onBlowfishToggled(bool blowfish)62 void KNewWalletDialogIntro::onBlowfishToggled(bool blowfish)
63 {
64     setFinalPage(blowfish);
65 }
66 
isBlowfish() const67 bool KNewWalletDialogIntro::isBlowfish() const
68 {
69     return _ui.radioBlowfish->isChecked();
70 }
71 
nextId() const72 int KNewWalletDialogIntro::nextId() const
73 {
74     if (isBlowfish()) {
75         return -1;
76     } else {
77         return qobject_cast<const KNewWalletDialog *>(wizard())->gpgId();
78     }
79 }
80 
KNewWalletDialogGpg(const QString & appName,const QString & walletName,QWidget * parent)81 KNewWalletDialogGpg::KNewWalletDialogGpg(const QString &appName, const QString &walletName, QWidget *parent)
82     : QWizardPage(parent)
83     , _alreadyInitialized(false)
84     , _complete(false)
85 {
86     _ui.setupUi(this);
87 }
88 
89 struct AddKeyToList {
90     QTableWidget *_list;
91     int _row;
AddKeyToListKWallet::AddKeyToList92     AddKeyToList(QTableWidget *list)
93         : _list(list)
94         , _row(0)
95     {
96     }
operator ()KWallet::AddKeyToList97     void operator()(const GpgME::Key &k)
98     {
99         GpgME::UserID uid = k.userID(0);
100         QString name(uid.name());
101         if (uid.comment()) {
102             name = QStringLiteral("%1 (%2)").arg(name, uid.comment());
103         }
104         _list->setItem(_row, 0, new QTableWidgetItem(name));
105         _list->setItem(_row, 1, new QTableWidgetItem(uid.email()));
106         _list->setItem(_row, 2, new QTableWidgetItem(k.shortKeyID()));
107         QVariant varKey;
108         varKey.setValue(k);
109         _list->item(_row, 0)->setData(Qt::UserRole, varKey);
110         ++_row;
111     }
112 };
113 
initializePage()114 void KNewWalletDialogGpg::initializePage()
115 {
116     if (_alreadyInitialized) {
117         return;
118     }
119 
120     registerField(QStringLiteral("key"), this);
121 
122     GpgME::initializeLibrary();
123     GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
124     if (err) {
125         qCDebug(KWALLETD_LOG) << "OpenPGP not supported on your system!";
126         KMessageBox::error(this,
127                            i18n("The GpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
128         Q_EMIT completeChanged();
129         return;
130     }
131     std::shared_ptr<GpgME::Context> _ctx(GpgME::Context::createForProtocol(GpgME::OpenPGP));
132     if (!_ctx) {
133         KMessageBox::error(this,
134                            i18n("The GpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
135         Q_EMIT completeChanged();
136         return;
137     }
138     _ctx->setKeyListMode(GpgME::Local);
139 
140     std::vector<GpgME::Key> keys;
141     err = _ctx->startKeyListing();
142     while (!err) {
143         GpgME::Key k = _ctx->nextKey(err);
144         if (err) {
145             break;
146         }
147         if (!k.isInvalid() && k.canEncrypt() && (k.ownerTrust() == GpgME::Key::Ultimate)) {
148             keys.push_back(k);
149         }
150     }
151     _ctx->endKeyListing();
152 
153     if (keys.size() == 0) {
154         KMessageBox::error(this,
155                            i18n("Seems that your system has no keys suitable for encryption. Please set-up at least one encryption key, then try again."));
156         Q_EMIT completeChanged();
157         return;
158     }
159 
160     _ui.listCertificates->setRowCount(keys.size());
161     std::for_each(keys.begin(), keys.end(), AddKeyToList(_ui.listCertificates));
162     _ui.listCertificates->resizeColumnsToContents();
163     _ui.listCertificates->setCurrentCell(0, 0);
164 
165     _alreadyInitialized = true;
166 }
167 
onItemSelectionChanged()168 void KNewWalletDialogGpg::onItemSelectionChanged()
169 {
170     _complete = _ui.listCertificates->currentRow() >= 0;
171     QVariant varKey = _ui.listCertificates->item(_ui.listCertificates->currentRow(), 0)->data(Qt::UserRole);
172     setField(QStringLiteral("key"), varKey);
173     Q_EMIT completeChanged();
174 }
175 
isComplete() const176 bool KNewWalletDialogGpg::isComplete() const
177 {
178     return _complete;
179 }
180 
validateCurrentPage()181 bool KNewWalletDialogGpg::validateCurrentPage()
182 {
183     return false;
184 }
185 
186 } // namespace
187 #include "moc_knewwalletdialog.cpp"
188