File indexing completed on 2023-12-03 09:19:03

0001 /*
0002     SPDX-FileCopyrightText: 2008, 2010, 2012 Rolf Eike Beer <kde@opensource.sf-tec.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "kgpgfirstassistant.h"
0008 
0009 #include "gpgproc.h"
0010 #include "kgpginterface.h"
0011 #include "core/kgpgkey.h"
0012 
0013 #include <KLocalizedString>
0014 #include <KMessageBox>
0015 #include <KUrlRequester>
0016 #include <kio_version.h>
0017 
0018 #include <QCheckBox>
0019 #include <QComboBox>
0020 #include <QGridLayout>
0021 #include <QHBoxLayout>
0022 #include <QLabel>
0023 #include <QSpacerItem>
0024 #include <QStandardPaths>
0025 #include <QTextStream>
0026 #include <QWidget>
0027 #include <QUrl>
0028 
0029 using namespace KgpgCore;
0030 
0031 KGpgFirstAssistant::KGpgFirstAssistant(QWidget *parent)
0032         : KAssistantDialog(parent)
0033 {
0034     setWindowTitle(i18n("KGpg Assistant"));
0035 
0036     QWidget *page = new QWidget(this);
0037     QGridLayout *gridLayout = new QGridLayout(page);
0038     gridLayout->setSpacing(6);
0039     gridLayout->setContentsMargins(0, 0, 0, 0);
0040 
0041     QLabel *label = new QLabel(page);
0042     QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
0043     sizePolicy.setHorizontalStretch(0);
0044     sizePolicy.setVerticalStretch(0);
0045     sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth());
0046     label->setSizePolicy(sizePolicy);
0047     label->setFrameShape(QFrame::NoFrame);
0048     label->setFrameShadow(QFrame::Plain);
0049     label->setScaledContents(false);
0050     label->setAlignment(Qt::AlignTop);
0051     label->setWordWrap(false);
0052 
0053     gridLayout->addWidget(label, 0, 0, 3, 1);
0054 
0055     label = new QLabel(page);
0056     label->setAlignment(Qt::AlignTop);
0057     label->setWordWrap(true);
0058     label->setText(i18n("This assistant will first setup some basic configuration options required for KGpg to work properly. Next, it will allow you to create your own key pair, enabling you to encrypt your files and emails."));
0059 
0060     gridLayout->addWidget(label, 0, 1, 1, 1);
0061 
0062     QSpacerItem *spacerItem = new QSpacerItem(20, 41, QSizePolicy::Minimum, QSizePolicy::Expanding);
0063 
0064     gridLayout->addItem(spacerItem, 1, 1, 1, 1);
0065 
0066     page_welcome = addPage(page, i18n("Welcome to the KGpg Assistant"));
0067 
0068     page = new QWidget(this);
0069 
0070     gridLayout = new QGridLayout(page);
0071     gridLayout->setSpacing(6);
0072     gridLayout->setContentsMargins(0, 0, 0, 0);
0073 
0074     label = new QLabel(page);
0075     label->setAlignment(Qt::AlignTop);
0076     label->setWordWrap(true);
0077     label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
0078     label->setText(i18n("KGpg needs to know which GnuPG binary to use."));
0079 
0080     gridLayout->addWidget(label, 0, 1, 1, 1);
0081 
0082     label = new QLabel(page);
0083     label->setAlignment(Qt::AlignTop);
0084     label->setWordWrap(true);
0085     label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
0086     label->setText(i18n("Unless you want to try some unusual settings, just click on the \"next\" button."));
0087 
0088     gridLayout->addWidget(label, 1, 1, 1, 1);
0089 
0090     spacerItem = new QSpacerItem(20, 60, QSizePolicy::Minimum, QSizePolicy::Expanding);
0091 
0092     gridLayout->addItem(spacerItem, 4, 1, 1, 1);
0093 
0094     txtGpgVersion = new QLabel(page);
0095     txtGpgVersion->setWordWrap(true);
0096 
0097     gridLayout->addWidget(txtGpgVersion, 3, 1, 1, 1);
0098 
0099     binURL = new KUrlRequester(page);
0100 #if KIO_VERSION >= QT_VERSION_CHECK(5, 108, 0)
0101     binURL->setNameFilters({
0102         i18nc("search filter name for gpg binary", "GnuPG binary") + QLatin1String(" (gpg)"),
0103         i18n("All files") + QLatin1String(" (*)"),
0104     });
0105 #else
0106     binURL->setFilter(QLatin1String("gpg|") + i18nc("search filter name for gpg binary", "GnuPG binary") + QLatin1String("\n*|")+ i18n("All files"));
0107 #endif
0108     QString gpgBin = QStandardPaths::findExecutable(QLatin1String("gpg2"));
0109     if (gpgBin.isEmpty())
0110         gpgBin = QStandardPaths::findExecutable(QLatin1String("gpg"));
0111     if (gpgBin.isEmpty())
0112         gpgBin = QLatin1String("gpg");
0113     binURL->setUrl(QUrl::fromLocalFile(gpgBin));
0114 
0115     connect(binURL, &KUrlRequester::textChanged, this, &KGpgFirstAssistant::slotBinaryChanged);
0116     slotBinaryChanged(gpgBin);
0117 
0118     gridLayout->addWidget(binURL, 2, 1, 1, 1);
0119 
0120     page_binary = addPage(page, i18n("GnuPG Binary"));
0121 
0122     page = new QWidget(this);
0123 
0124     gridLayout = new QGridLayout(page);
0125     gridLayout->setSpacing(6);
0126     gridLayout->setContentsMargins(0, 0, 0, 0);
0127     text_optionsfound = new QLabel(page);
0128     text_optionsfound->setAlignment(Qt::AlignTop);
0129     text_optionsfound->setWordWrap(true);
0130     text_optionsfound->setText(i18n("Unless you want to try some unusual settings, just click on the \"next\" button."));
0131 
0132     gridLayout->addWidget(text_optionsfound, 1, 1, 1, 1);
0133 
0134     label = new QLabel(page);
0135     label->setAlignment(Qt::AlignTop);
0136     label->setWordWrap(true);
0137     label->setText(i18n("KGpg needs to know where your GnuPG configuration file is stored."));
0138 
0139     gridLayout->addWidget(label, 0, 1, 1, 1);
0140 
0141     spacerItem = new QSpacerItem(20, 60, QSizePolicy::Minimum, QSizePolicy::Expanding);
0142 
0143     gridLayout->addItem(spacerItem, 4, 1, 1, 1);
0144 
0145     pathURL = new KUrlRequester(page);
0146 
0147     gridLayout->addWidget(pathURL, 3, 1, 1, 1);
0148 
0149     label = new QLabel(page);
0150     label->setAlignment(Qt::AlignVCenter);
0151     label->setWordWrap(true);
0152     label->setText(i18n("Path to your GnuPG configuration file:"));
0153 
0154     gridLayout->addWidget(label, 2, 1, 1, 1);
0155 
0156     label = new QLabel(page);
0157     sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth());
0158     label->setSizePolicy(sizePolicy);
0159     label->setFrameShape(QFrame::NoFrame);
0160     label->setFrameShadow(QFrame::Plain);
0161     label->setScaledContents(false);
0162     label->setAlignment(Qt::AlignTop);
0163     label->setWordWrap(false);
0164 
0165     gridLayout->addWidget(label, 0, 0, 5, 1);
0166     page_config = addPage(page, i18n("Configuration File"));
0167 
0168     page = new QWidget(this);
0169     gridLayout = new QGridLayout(page);
0170     gridLayout->setSpacing(6);
0171     gridLayout->setContentsMargins(0, 0, 0, 0);
0172 
0173     QHBoxLayout *hboxLayout = new QHBoxLayout();
0174     hboxLayout->setSpacing(6);
0175     label = new QLabel(page);
0176     label->setText(i18n("Your default key:"));
0177 
0178     hboxLayout->addWidget(label);
0179 
0180     CBdefault = new QComboBox(page);
0181     QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Fixed);
0182     sizePolicy1.setHorizontalStretch(0);
0183     sizePolicy1.setVerticalStretch(0);
0184     sizePolicy1.setHeightForWidth(CBdefault->sizePolicy().hasHeightForWidth());
0185     CBdefault->setSizePolicy(sizePolicy1);
0186 
0187     hboxLayout->addWidget(CBdefault);
0188 
0189     gridLayout->addLayout(hboxLayout, 0, 1, 1, 1);
0190 
0191     spacerItem = new QSpacerItem(20, 30, QSizePolicy::Minimum, QSizePolicy::Expanding);
0192 
0193     gridLayout->addItem(spacerItem, 1, 1, 1, 1);
0194 
0195     page_defaultkey = addPage(page, i18n("Default Key"));
0196 
0197     page = new QWidget(this);
0198 
0199     gridLayout = new QGridLayout(page);
0200     gridLayout->setSpacing(6);
0201     gridLayout->setContentsMargins(0, 0, 0, 0);
0202 
0203     binlabel = new QLabel(page);
0204 
0205     gridLayout->addWidget(binlabel, 0, 1, 1, 1);
0206 
0207     versionLabel = new QLabel(page);
0208 
0209     gridLayout->addWidget(versionLabel, 1, 1, 1, 1);
0210 
0211     defaultkeylabel = new QLabel(page);
0212 
0213     gridLayout->addWidget(defaultkeylabel, 2, 1, 1, 1);
0214 
0215     generateCB = new QCheckBox(page);
0216     generateCB->setText(i18n("Generate new key"));
0217 
0218     gridLayout->addWidget(generateCB, 3, 1, 1, 1);
0219 
0220     spacerItem = new QSpacerItem(20, 30, QSizePolicy::Minimum, QSizePolicy::Expanding);
0221 
0222     gridLayout->addItem(spacerItem, 4, 1, 1, 1);
0223 
0224     autostartCB = new QCheckBox(page);
0225     autostartCB->setChecked(true);
0226     autostartCB->setText(i18n("Start KGpg automatically at KDE startup."));
0227 
0228     gridLayout->addWidget(autostartCB, 5, 1, 1, 1);
0229 
0230     page_done = addPage(page, i18n("Done"));
0231 }
0232 
0233 void
0234 KGpgFirstAssistant::findConfigPath(const QString &gpgBinary)
0235 {
0236     const QString gpgHome = GPGProc::getGpgHome(gpgBinary);
0237     QString confPath = gpgHome + QLatin1String( "gpg.conf" );
0238 
0239     if (!QFile(confPath).exists()) {
0240         const QString confPathOpt = gpgHome + QLatin1String("options");
0241         if (QFile(confPathOpt).exists()) {
0242             confPath = confPathOpt;
0243         } else {
0244                         if (KMessageBox::questionYesNo(nullptr, i18n("<qt><b>The GnuPG configuration file was not found</b>. Should KGpg try to create a config file ?</qt>"), QString(), KGuiItem(i18n("Create Config")), KGuiItem(i18n("Do Not Create"))) == KMessageBox::Yes) {
0245                 QFile file(confPath);
0246                 if (file.open(QIODevice::WriteOnly)) {
0247                     QTextStream stream(&file);
0248                     stream << "# GnuPG config file created by KGpg\n";
0249                     file.close();
0250                 }
0251             } else {
0252                 text_optionsfound->setText(i18n("<qt><b>The GnuPG configuration file was not found</b>.</qt>"));
0253                 confPath.clear();
0254             }
0255         }
0256     }
0257 
0258     pathURL->setUrl(QUrl::fromLocalFile(confPath));
0259 
0260     const QStringList secids = KgpgInterface::readSecretKeys();
0261 
0262     bool noSecKeys = secids.isEmpty();
0263     generateCB->setChecked(noSecKeys);
0264     setAppropriate(page_defaultkey, !noSecKeys);
0265 
0266     if (noSecKeys) {
0267         defaultkeylabel->setVisible(false);
0268         return;
0269     }
0270 
0271     const KgpgKeyList publiclist = KgpgInterface::readPublicKeys(secids);
0272 
0273     CBdefault->clear();
0274 
0275     for (const KgpgKey &k : publiclist) {
0276         QString s;
0277 
0278         if (k.email().isEmpty())
0279             s = i18nc("Name: ID", "%1: %2", k.name(), k.id());
0280         else
0281             s = i18nc("Name (Email): ID", "%1 (%2): %3", k.name(), k.email(), k.id());
0282 
0283         CBdefault->addItem(s, k.fingerprint());
0284     }
0285 
0286     CBdefault->setCurrentIndex(0);
0287 }
0288 
0289 void
0290 KGpgFirstAssistant::next()
0291 {
0292     if (currentPage() == page_binary) {
0293         const QString &gpgbin = binURL->url().path();
0294         binlabel->setText(i18n("Your GnuPG binary is: %1", gpgbin));
0295         findConfigPath(gpgbin);
0296     } else if (currentPage() == page_config) {
0297         m_confPath = pathURL->url().path();
0298 
0299         const QString defaultID = KgpgInterface::getGpgSetting(QLatin1String( "default-key" ), m_confPath);
0300 
0301         if (!defaultID.isEmpty()) {
0302             for (int i = 0; i < CBdefault->count(); i++) {
0303 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0304                 if (CBdefault->itemData(i).toString().rightRef(defaultID.length()).compare(defaultID) == 0) {
0305 #else
0306                 if (QStringView(CBdefault->itemData(i).toString()).right(defaultID.length()).compare(defaultID) == 0) {
0307 #endif
0308                     CBdefault->setCurrentIndex(i);
0309                     break;
0310                 }
0311             }
0312         }
0313         versionLabel->setText(i18n("You have GnuPG version: %1", m_gpgVersion));
0314     } else if (currentPage() == page_defaultkey) {
0315         defaultkeylabel->setVisible(true);
0316         defaultkeylabel->setText(i18n("Your default key is: %1", CBdefault->currentText()));
0317         int i = CBdefault->currentIndex();
0318         if (i >= 0) {
0319             defaultkeylabel->setToolTip(CBdefault->itemData(i).toString());
0320         }
0321     }
0322     KAssistantDialog::next();
0323 }
0324 
0325 bool
0326 KGpgFirstAssistant::runKeyGenerate() const
0327 {
0328     return generateCB->isChecked();
0329 }
0330 
0331 QString
0332 KGpgFirstAssistant::getConfigPath() const
0333 {
0334     return m_confPath;
0335 }
0336 
0337 QString
0338 KGpgFirstAssistant::getDefaultKey() const
0339 {
0340     int i = CBdefault->currentIndex();
0341     if (i < 0)
0342         return QString();
0343     else
0344         return CBdefault->itemData(i).toString();
0345 }
0346 
0347 bool
0348 KGpgFirstAssistant::getAutoStart() const
0349 {
0350     return autostartCB->isChecked();
0351 }
0352 
0353 void
0354 KGpgFirstAssistant::slotBinaryChanged(const QString &binary)
0355 {
0356     if (binary.isEmpty()) {
0357         setValid(page_binary, false);
0358         return;
0359     }
0360 
0361     m_gpgVersion = GPGProc::gpgVersionString(binary);
0362     setValid(page_binary, !m_gpgVersion.isEmpty());
0363     if (!m_gpgVersion.isEmpty()) {
0364         const int gpgver = GPGProc::gpgVersion(m_gpgVersion);
0365 
0366         if (gpgver < 0x10400) {
0367             txtGpgVersion->setText(i18n("Your GnuPG version (%1) seems to be too old.<br />Compatibility with versions before 1.4.0 is no longer guaranteed.", m_gpgVersion));
0368         } else {
0369             txtGpgVersion->setText(i18n("You have GnuPG version: %1", m_gpgVersion));
0370         }
0371     }
0372 }