File indexing completed on 2024-05-12 16:06:47

0001 /*
0002     SPDX-FileCopyrightText: 2019 Bubli <Katarina.Behrens@cib.de>
0003     SPDX-FileCopyrightText: 2020 Albert Astals Cid <albert.astals.cid@kdab.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "pdfsettingswidget.h"
0009 
0010 #include "pdfsettings.h"
0011 #include "pdfsignatureutils.h"
0012 
0013 #include <KLocalizedString>
0014 #include <KUrlRequester>
0015 
0016 #include <QEvent>
0017 #include <QHBoxLayout>
0018 #include <QMessageBox>
0019 #include <QTreeWidget>
0020 #include <QTreeWidgetItem>
0021 
0022 #if POPPLER_VERSION_MACRO >= QT_VERSION_CHECK(23, 06, 0)
0023 QString PDFSettingsWidget::popplerEnumToSettingString(Poppler::CryptoSignBackend backend)
0024 {
0025     switch (backend) {
0026     case Poppler::CryptoSignBackend::NSS:
0027         return QStringLiteral("NSS");
0028     case Poppler::CryptoSignBackend::GPG:
0029         return QStringLiteral("GPG");
0030     }
0031     return {};
0032 }
0033 
0034 static QString popplerEnumToUserString(Poppler::CryptoSignBackend backend)
0035 {
0036     // I'm unsure if we want these translatable, but if so
0037     // we sholud do something here rather than forward directly to the
0038     // technical popplerEnumToSettingString
0039     return PDFSettingsWidget::popplerEnumToSettingString(backend);
0040 }
0041 
0042 std::optional<Poppler::CryptoSignBackend> PDFSettingsWidget::settingStringToPopplerEnum(QStringView backend)
0043 {
0044     if (backend == QStringLiteral("NSS")) {
0045         return Poppler::CryptoSignBackend::NSS;
0046     }
0047     if (backend == QStringLiteral("GPG")) {
0048         return Poppler::CryptoSignBackend::GPG;
0049     }
0050     return std::nullopt;
0051 }
0052 #endif
0053 
0054 PDFSettingsWidget::PDFSettingsWidget(QWidget *parent)
0055     : QWidget(parent)
0056 {
0057     m_pdfsw.setupUi(this);
0058 
0059 #if POPPLER_VERSION_MACRO < QT_VERSION_CHECK(23, 07, 0)
0060     m_pdfsw.kcfg_OverprintPreviewEnabled->hide();
0061 #endif
0062 
0063 #if POPPLER_VERSION_MACRO >= QT_VERSION_CHECK(23, 06, 0)
0064     auto backends = Poppler::availableCryptoSignBackends();
0065     if (!backends.empty()) {
0066         // Let's try get the currently stored backend:
0067         auto currentBackend = settingStringToPopplerEnum(PDFSettings::self()->signatureBackend());
0068         if (!currentBackend) {
0069             currentBackend = Poppler::activeCryptoSignBackend();
0070         }
0071         if (currentBackend != Poppler::activeCryptoSignBackend() && currentBackend) {
0072             if (!Poppler::setActiveCryptoSignBackend(currentBackend.value())) {
0073                 // erm. This must be a case of having either modified
0074                 // the config file manually to something not available
0075                 // in the poppler installed here or have reconfigured
0076                 // their poppler to not have the previously selected one
0077                 // available any longer.
0078                 // Probably the safest bet is to take whatever is active
0079                 currentBackend = Poppler::activeCryptoSignBackend();
0080             }
0081         }
0082         int selected = -1;
0083         for (auto backend : backends) {
0084             if (backend == currentBackend) {
0085                 selected = m_pdfsw.kcfg_SignatureBackend->count();
0086             }
0087             m_pdfsw.kcfg_SignatureBackend->addItem(popplerEnumToUserString(backend), QVariant(popplerEnumToSettingString(backend)));
0088         }
0089         m_pdfsw.kcfg_SignatureBackend->setProperty("kcfg_property", QByteArray("currentData"));
0090 
0091         m_pdfsw.kcfg_SignatureBackend->setCurrentIndex(selected);
0092         connect(m_pdfsw.kcfg_SignatureBackend, &QComboBox::currentTextChanged, this, [this](const QString &text) {
0093             auto backendEnum = settingStringToPopplerEnum(text);
0094             if (!backendEnum) {
0095                 return;
0096             }
0097             Poppler::setActiveCryptoSignBackend(backendEnum.value());
0098             m_pdfsw.certDBGroupBox->setVisible(backendEnum == Poppler::CryptoSignBackend::NSS);
0099             m_certificatesAsked = false;
0100             if (m_tree) {
0101                 m_tree->clear();
0102             }
0103             update();
0104         });
0105 
0106         m_pdfsw.certDBGroupBox->setVisible(currentBackend == Poppler::CryptoSignBackend::NSS);
0107 #else
0108     if (Poppler::hasNSSSupport()) {
0109         // Better hide the signature backend selection; we have not really any
0110         // need for that.
0111         m_pdfsw.signatureBackendContainer->hide();
0112 #endif
0113 
0114         m_pdfsw.loadSignaturesButton->hide();
0115 
0116         KUrlRequester *pDlg = new KUrlRequester();
0117         pDlg->setObjectName(QStringLiteral("kcfg_DBCertificatePath"));
0118         pDlg->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly);
0119         pDlg->setEnabled(false);
0120         m_pdfsw.formLayout->setWidget(1, QFormLayout::FieldRole, pDlg);
0121 
0122         connect(m_pdfsw.customRadioButton, &QRadioButton::toggled, pDlg, &KUrlRequester::setEnabled);
0123 
0124         if (!PDFSettings::useDefaultCertDB()) {
0125             m_pdfsw.customRadioButton->setChecked(true);
0126             m_pdfsw.defaultLabel->setVisible(false);
0127         }
0128 
0129         m_tree = new QTreeWidget(this);
0130         m_tree->setHeaderLabels({i18nc("Name of the person to whom the cerficate was issued", "Issued to"), i18n("E-mail"), i18nc("Certificate expiration date", "Expiration date")});
0131         m_tree->setRootIsDecorated(false);
0132 
0133         m_pdfsw.certificatesPlaceholder->addWidget(m_tree);
0134 
0135         connect(PDFSettings::self(), &PDFSettings::useDefaultDBChanged, this, &PDFSettingsWidget::warnRestartNeeded);
0136         connect(PDFSettings::self(), &PDFSettings::dBCertificatePathChanged, this, [this] {
0137             if (!PDFSettings::useDefaultCertDB()) {
0138                 warnRestartNeeded();
0139             }
0140         });
0141         connect(m_pdfsw.loadSignaturesButton, &QPushButton::clicked, this, [this] {
0142             m_certificatesAsked = false;
0143             update();
0144         });
0145     } else {
0146         QHBoxLayout *lay = new QHBoxLayout(this);
0147         QLabel *l = new QLabel(i18n("You are using a Poppler library built without NSS support.\nAdding Digital Signatures isn't available for that reason"));
0148         l->setWordWrap(true);
0149         lay->addWidget(l);
0150     }
0151 }
0152 
0153 bool PDFSettingsWidget::event(QEvent *e)
0154 {
0155     if (m_tree && e->type() == QEvent::Paint && !m_certificatesAsked) {
0156         m_certificatesAsked = true;
0157 
0158         PopplerCertificateStore st;
0159         bool userCancelled;
0160         const QList<Okular::CertificateInfo> certs = st.signingCertificates(&userCancelled);
0161 
0162         m_pdfsw.loadSignaturesButton->setVisible(userCancelled);
0163 
0164         for (const auto &cert : certs) {
0165             new QTreeWidgetItem(m_tree,
0166                                 {cert.subjectInfo(Okular::CertificateInfo::EntityInfoKey::CommonName, Okular::CertificateInfo::EmptyString::TranslatedNotAvailable),
0167                                  cert.subjectInfo(Okular::CertificateInfo::EntityInfoKey::EmailAddress, Okular::CertificateInfo::EmptyString::TranslatedNotAvailable),
0168                                  cert.validityEnd().toString(QStringLiteral("yyyy-MM-dd"))});
0169         }
0170 
0171         m_pdfsw.defaultLabel->setText(Poppler::getNSSDir());
0172 
0173         m_tree->resizeColumnToContents(1);
0174         m_tree->resizeColumnToContents(0);
0175     }
0176     return QWidget::event(e);
0177 }
0178 
0179 void PDFSettingsWidget::warnRestartNeeded()
0180 {
0181     if (!m_warnedAboutRestart) {
0182 #if POPPLER_VERSION_MACRO >= QT_VERSION_CHECK(23, 06, 0)
0183         if (PDFSettings::self()->signatureBackend() != QStringLiteral("NSS")) {
0184             return;
0185         }
0186 #endif
0187         m_warnedAboutRestart = true;
0188         QMessageBox::information(this, i18n("Restart needed"), i18n("You need to restart Okular after changing the NSS directory settings"));
0189     }
0190 }