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

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2004 George Staikos <staikos@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 
0008 #include "kwalletwizard.h"
0009 
0010 #include "ui_kwalletwizardpageexplanation.h"
0011 #include "ui_kwalletwizardpageintro.h"
0012 #include "ui_kwalletwizardpageoptions.h"
0013 #include "ui_kwalletwizardpagepassword.h"
0014 #ifdef HAVE_GPGMEPP
0015 #include "ui_kwalletwizardpagegpgkey.h"
0016 #include "ui_kwalletwizardpagepasswordgpg.h"
0017 #endif
0018 
0019 #include <KLocalizedString>
0020 #include <QButtonGroup>
0021 #include <QDebug>
0022 #include <QIcon>
0023 
0024 #ifdef HAVE_GPGMEPP
0025 #include <KMessageBox>
0026 #include <QComboBox>
0027 #include <gpgme++/context.h>
0028 #include <gpgme++/key.h>
0029 #include <gpgme++/keylistresult.h>
0030 #endif
0031 
0032 class PageIntro : public QWizardPage
0033 {
0034 public:
0035     explicit PageIntro(QWidget *parent)
0036         : QWizardPage(parent)
0037     {
0038         ui.setupUi(this);
0039 
0040         ui.ktitlewidget->setText("<h1>" + i18n("KWallet") + "</h1>");
0041         ui.ktitlewidget->setIcon(QIcon::fromTheme(QStringLiteral("kwalletmanager")));
0042 
0043         bg = new QButtonGroup(this);
0044         bg->setExclusive(true);
0045         bg->addButton(ui._basic, 0);
0046         bg->addButton(ui._advanced, 1);
0047 
0048         // force the "basic" button to be selected
0049         ui._basic->setChecked(true);
0050     }
0051 
0052     QButtonGroup *bg;
0053 
0054 private:
0055     Ui::KWalletWizardPageIntro ui;
0056 };
0057 
0058 class PagePassword : public QWizardPage
0059 {
0060 public:
0061     explicit PagePassword(KWalletWizard *parent)
0062         : QWizardPage(parent)
0063     {
0064         ui.setupUi(this);
0065 
0066         registerField(QStringLiteral("useWallet"), ui._useWallet);
0067         registerField(QStringLiteral("pass1"), ui._pass1);
0068         registerField(QStringLiteral("pass2"), ui._pass2);
0069 #ifdef HAVE_GPGMEPP
0070         registerField(QStringLiteral("useGPG"), ui._radioGpg);
0071         registerField(QStringLiteral("useBlowfish"), ui._radioBlowfish);
0072         connect(ui._radioBlowfish, &QRadioButton::toggled, parent, &KWalletWizard::passwordPageUpdate);
0073 #endif
0074 
0075         connect(ui._useWallet, &QCheckBox::clicked, parent, &KWalletWizard::passwordPageUpdate);
0076         connect(ui._pass1, &QLineEdit::textChanged, parent, &KWalletWizard::passwordPageUpdate);
0077         connect(ui._pass2, &QLineEdit::textChanged, parent, &KWalletWizard::passwordPageUpdate);
0078         ui._useWallet->setChecked(true);
0079     }
0080 
0081     int nextId() const override
0082     {
0083 #ifdef HAVE_GPGMEPP
0084         int nextId = -1;
0085         if (field(QStringLiteral("useWallet")).toBool()) {
0086             if (field(QStringLiteral("useBlowfish")).toBool()) {
0087                 nextId = static_cast<KWalletWizard *>(wizard())->wizardType() == KWalletWizard::Basic
0088                     ? -1
0089                     : KWalletWizard::PageOptionsId; // same as non GPGMEPP case
0090             } else {
0091                 nextId = KWalletWizard::PageGpgKeyId;
0092             }
0093         }
0094 
0095         return nextId;
0096 #else
0097         return static_cast<KWalletWizard *>(wizard())->wizardType() == KWalletWizard::Basic ? -1 : KWalletWizard::PageOptionsId;
0098 #endif
0099     }
0100 
0101     void setMatchLabelText(const QString &text)
0102     {
0103         ui._matchLabel->setText(text);
0104     }
0105 
0106 private:
0107 #ifdef HAVE_GPGMEPP
0108     Ui::KWalletWizardPagePasswordGpg ui;
0109 #else
0110     Ui::KWalletWizardPagePassword ui;
0111 #endif
0112 };
0113 
0114 #ifdef HAVE_GPGMEPP
0115 typedef std::vector<GpgME::Key> KeysVector;
0116 Q_DECLARE_METATYPE(GpgME::Key)
0117 
0118 struct AddKeyToCombo {
0119     QComboBox *_list;
0120     AddKeyToCombo(QComboBox *list)
0121         : _list(list)
0122     {
0123     }
0124     void operator()(const GpgME::Key &k)
0125     {
0126         QString text = QStringLiteral("%1 (%2)").arg(k.shortKeyID(), k.userID(0).email());
0127         QVariant varKey;
0128         varKey.setValue(k);
0129         _list->addItem(text, varKey);
0130     }
0131 };
0132 
0133 class PageGpgKey : public QWizardPage
0134 {
0135 public:
0136     explicit PageGpgKey(QWidget *parent)
0137         : QWizardPage(parent)
0138         , userHasGpgKeys(false)
0139     {
0140         ui.setupUi(this);
0141 
0142         registerField(QStringLiteral("gpgKey"), ui._gpgKey);
0143 
0144         KeysVector keys;
0145         GpgME::initializeLibrary();
0146         GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
0147         if (err) {
0148             qDebug() << "OpenPGP not supported on your system!";
0149             KMessageBox::error(
0150                 this,
0151                 i18n("The GpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
0152         } else {
0153             std::shared_ptr<GpgME::Context> ctx(GpgME::Context::createForProtocol(GpgME::OpenPGP));
0154             if (nullptr == ctx) {
0155                 KMessageBox::error(
0156                     this,
0157                     i18n("The GpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
0158             } else {
0159                 ctx->setKeyListMode(GpgME::KeyListMode::Local);
0160                 err = ctx->startKeyListing();
0161                 while (!err) {
0162                     GpgME::Key k = ctx->nextKey(err);
0163                     if (err) {
0164                         break;
0165                     }
0166                     if (!k.isInvalid() && k.canEncrypt() && (k.ownerTrust() == GpgME::Key::Ultimate)) {
0167                         keys.push_back(k);
0168                     }
0169                 }
0170                 ctx->endKeyListing();
0171             }
0172         }
0173         std::for_each(keys.begin(), keys.end(), AddKeyToCombo(ui._gpgKey));
0174 
0175         userHasGpgKeys = keys.size() > 0;
0176         if (userHasGpgKeys) {
0177             ui.stackedWidget->setCurrentWidget(ui._pageWhenHasKeys);
0178         } else {
0179             ui.stackedWidget->setCurrentWidget(ui._pageNoKeys);
0180             setFinalPage(true);
0181         }
0182         Q_EMIT completeChanged();
0183     }
0184 
0185     int nextId() const override
0186     {
0187         return static_cast<KWalletWizard *>(wizard())->wizardType() == KWalletWizard::Basic ? -1 : KWalletWizard::PageOptionsId;
0188     }
0189 
0190     bool isComplete() const override
0191     {
0192         return userHasGpgKeys;
0193     }
0194 
0195     bool hasGpgKeys() const
0196     {
0197         return userHasGpgKeys;
0198     }
0199 
0200     GpgME::Key gpgKey() const
0201     {
0202         QVariant varKey = ui._gpgKey->itemData(field(QStringLiteral("gpgKey")).toInt());
0203         return varKey.value<GpgME::Key>();
0204     }
0205 
0206 private:
0207     Ui::KWalletWizardPageGpgKey ui;
0208     bool userHasGpgKeys;
0209 };
0210 #endif
0211 
0212 class PageOptions : public QWizardPage
0213 {
0214 public:
0215     explicit PageOptions(QWidget *parent)
0216         : QWizardPage(parent)
0217     {
0218         ui.setupUi(this);
0219 
0220         registerField(QStringLiteral("closeWhenIdle"), ui._closeIdle);
0221         registerField(QStringLiteral("networkWallet"), ui._networkWallet);
0222     }
0223 
0224 private:
0225     Ui::KWalletWizardPageOptions ui;
0226 };
0227 
0228 class PageExplanation : public QWizardPage
0229 {
0230 public:
0231     PageExplanation(QWidget *parent)
0232         : QWizardPage(parent)
0233     {
0234         ui.setupUi(this);
0235         setFinalPage(true);
0236     }
0237 
0238 private:
0239     Ui::KWalletWizardPageExplanation ui;
0240 };
0241 
0242 KWalletWizard::KWalletWizard(QWidget *parent)
0243     : QWizard(parent)
0244 {
0245     setOption(HaveFinishButtonOnEarlyPages);
0246 
0247     m_pageIntro = new PageIntro(this);
0248     setPage(PageIntroId, m_pageIntro);
0249     m_pagePasswd = new PagePassword(this);
0250     setPage(PagePasswordId, m_pagePasswd);
0251 #ifdef HAVE_GPGMEPP
0252     m_pageGpgKey = new PageGpgKey(this);
0253     setPage(PageGpgKeyId, m_pageGpgKey);
0254 #endif
0255     setPage(PageOptionsId, new PageOptions(this));
0256     setPage(PageExplanationId, new PageExplanation(this));
0257 
0258     resize(500, 420);
0259 }
0260 
0261 void KWalletWizard::passwordPageUpdate()
0262 {
0263     bool complete = true;
0264     if (field(QStringLiteral("useWallet")).toBool()) {
0265 #ifdef HAVE_GPGMEPP
0266         if (field(QStringLiteral("useBlowfish")).toBool()) {
0267             m_pagePasswd->setFinalPage(wizardType() == Basic);
0268             button(NextButton)->setVisible(wizardType() != Basic);
0269 #endif
0270             if (field(QStringLiteral("pass1")).toString() == field(QStringLiteral("pass2")).toString()) {
0271                 if (field(QStringLiteral("pass1")).toString().isEmpty()) {
0272                     m_pagePasswd->setMatchLabelText(i18n("<qt>Password is empty.  <b>(WARNING: Insecure)</b></qt>"));
0273                 } else {
0274                     m_pagePasswd->setMatchLabelText(i18n("Passwords match."));
0275                 }
0276             } else {
0277                 m_pagePasswd->setMatchLabelText(i18n("Passwords do not match."));
0278                 complete = false;
0279             }
0280 #ifdef HAVE_GPGMEPP
0281         } else {
0282             m_pagePasswd->setFinalPage(false);
0283             button(NextButton)->setEnabled(true);
0284             return;
0285         }
0286 #endif
0287     } else {
0288         m_pagePasswd->setMatchLabelText(QString());
0289     }
0290     button(wizardType() == Basic ? FinishButton : NextButton)->setEnabled(complete);
0291 }
0292 
0293 KWalletWizard::WizardType KWalletWizard::wizardType() const
0294 {
0295     return (KWalletWizard::WizardType)m_pageIntro->bg->checkedId();
0296 }
0297 
0298 void KWalletWizard::initializePage(int id)
0299 {
0300     switch (id) {
0301     case PagePasswordId: {
0302         bool islast = m_pageIntro->bg->checkedId() == 0;
0303         m_pagePasswd->setFinalPage(islast);
0304         button(NextButton)->setVisible(!islast);
0305         break;
0306     }
0307     }
0308 }
0309 
0310 #ifdef HAVE_GPGMEPP
0311 GpgME::Key KWalletWizard::gpgKey() const
0312 {
0313     return m_pageGpgKey->gpgKey();
0314 }
0315 #endif
0316 
0317 #include "moc_kwalletwizard.cpp"