File indexing completed on 2024-11-24 03:41:05

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2013 Valentin Rusu <kde@rusu.info>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 #include "knewwalletdialog.h"
0009 #include "kwalletd_debug.h"
0010 #include <KLocalizedString>
0011 #include <KMessageBox>
0012 #include <QTableWidget>
0013 #include <QTableWidgetItem>
0014 #include <gpgme++/context.h>
0015 #include <gpgme++/key.h>
0016 #include <gpgme++/keylistresult.h>
0017 
0018 Q_DECLARE_METATYPE(GpgME::Key)
0019 
0020 namespace KWallet
0021 {
0022 KNewWalletDialog::KNewWalletDialog(const QString &appName, const QString &walletName, QWidget *parent)
0023     : QWizard(parent)
0024 {
0025     setOption(HaveFinishButtonOnEarlyPages);
0026     _intro = new KNewWalletDialogIntro(appName, walletName, this);
0027     _introId = addPage(_intro);
0028 
0029     _gpg = new KNewWalletDialogGpg(this);
0030     _gpgId = addPage(_gpg);
0031 }
0032 
0033 bool KNewWalletDialog::isBlowfish() const
0034 {
0035     return _intro->isBlowfish();
0036 }
0037 
0038 GpgME::Key KNewWalletDialog::gpgKey() const
0039 {
0040     QVariant varKey = field(QStringLiteral("key"));
0041     return varKey.value<GpgME::Key>();
0042 }
0043 
0044 KNewWalletDialogIntro::KNewWalletDialogIntro(const QString &appName, const QString &walletName, QWidget *parent)
0045     : QWizardPage(parent)
0046 {
0047     _ui.setupUi(this);
0048     if (appName.isEmpty()) {
0049         _ui.labelIntro->setText(
0050             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 "
0051                  "new wallet's type below or click cancel to deny the application's request.</qt>",
0052                  walletName.toHtmlEscaped()));
0053     } else {
0054         _ui.labelIntro->setText(
0055             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 "
0056                  "fashion. Please choose the new wallet's type below or click cancel to deny the application's request.</qt>",
0057                  appName.toHtmlEscaped(),
0058                  walletName.toHtmlEscaped()));
0059     }
0060 }
0061 
0062 void KNewWalletDialogIntro::onBlowfishToggled(bool blowfish)
0063 {
0064     setFinalPage(blowfish);
0065 }
0066 
0067 bool KNewWalletDialogIntro::isBlowfish() const
0068 {
0069     return _ui.radioBlowfish->isChecked();
0070 }
0071 
0072 int KNewWalletDialogIntro::nextId() const
0073 {
0074     if (isBlowfish()) {
0075         return -1;
0076     } else {
0077         return qobject_cast<const KNewWalletDialog *>(wizard())->gpgId();
0078     }
0079 }
0080 
0081 KNewWalletDialogGpg::KNewWalletDialogGpg(QWidget *parent)
0082     : QWizardPage(parent)
0083 {
0084     _ui.setupUi(this);
0085 }
0086 
0087 struct AddKeyToList {
0088     QTableWidget *_list;
0089     int _row;
0090     AddKeyToList(QTableWidget *list)
0091         : _list(list)
0092         , _row(0)
0093     {
0094     }
0095     void operator()(const GpgME::Key &k)
0096     {
0097         GpgME::UserID uid = k.userID(0);
0098         QString name(uid.name());
0099         if (uid.comment()) {
0100             name = QStringLiteral("%1 (%2)").arg(name, uid.comment());
0101         }
0102         _list->setItem(_row, 0, new QTableWidgetItem(name));
0103         _list->setItem(_row, 1, new QTableWidgetItem(uid.email()));
0104         _list->setItem(_row, 2, new QTableWidgetItem(k.shortKeyID()));
0105         QVariant varKey;
0106         varKey.setValue(k);
0107         _list->item(_row, 0)->setData(Qt::UserRole, varKey);
0108         ++_row;
0109     }
0110 };
0111 
0112 void KNewWalletDialogGpg::initializePage()
0113 {
0114     if (_alreadyInitialized) {
0115         return;
0116     }
0117 
0118     registerField(QStringLiteral("key"), this);
0119 
0120     GpgME::initializeLibrary();
0121     GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
0122     if (err) {
0123         qCDebug(KWALLETD_LOG) << "OpenPGP not supported on your system!";
0124         KMessageBox::error(this,
0125                            i18n("The GpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
0126         Q_EMIT completeChanged();
0127         return;
0128     }
0129     std::shared_ptr<GpgME::Context> _ctx(GpgME::Context::createForProtocol(GpgME::OpenPGP));
0130     if (!_ctx) {
0131         KMessageBox::error(this,
0132                            i18n("The GpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
0133         Q_EMIT completeChanged();
0134         return;
0135     }
0136     _ctx->setKeyListMode(GpgME::Local);
0137 
0138     std::vector<GpgME::Key> keys;
0139     err = _ctx->startKeyListing();
0140     while (!err) {
0141         GpgME::Key k = _ctx->nextKey(err);
0142         if (err) {
0143             break;
0144         }
0145         if (!k.isInvalid() && k.canEncrypt() && (k.ownerTrust() == GpgME::Key::Ultimate)) {
0146             keys.push_back(k);
0147         }
0148     }
0149     _ctx->endKeyListing();
0150 
0151     if (keys.size() == 0) {
0152         KMessageBox::error(this,
0153                            i18n("Seems that your system has no keys suitable for encryption. Please set-up at least one encryption key, then try again."));
0154         Q_EMIT completeChanged();
0155         return;
0156     }
0157 
0158     _ui.listCertificates->setRowCount(keys.size());
0159     std::for_each(keys.begin(), keys.end(), AddKeyToList(_ui.listCertificates));
0160     _ui.listCertificates->resizeColumnsToContents();
0161     _ui.listCertificates->setCurrentCell(0, 0);
0162 
0163     _alreadyInitialized = true;
0164 }
0165 
0166 void KNewWalletDialogGpg::onItemSelectionChanged()
0167 {
0168     _complete = _ui.listCertificates->currentRow() >= 0;
0169     QVariant varKey = _ui.listCertificates->item(_ui.listCertificates->currentRow(), 0)->data(Qt::UserRole);
0170     setField(QStringLiteral("key"), varKey);
0171     Q_EMIT completeChanged();
0172 }
0173 
0174 bool KNewWalletDialogGpg::isComplete() const
0175 {
0176     return _complete;
0177 }
0178 
0179 bool KNewWalletDialogGpg::validateCurrentPage()
0180 {
0181     return false;
0182 }
0183 
0184 } // namespace
0185 #include "moc_knewwalletdialog.cpp"