File indexing completed on 2024-06-23 05:13:47

0001 /*
0002     cryptooperationsconfigwidget.cpp
0003 
0004     This file is part of kleopatra, the KDE key manager
0005     SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
0008     SPDX-FileContributor: Intevation GmbH
0009 
0010     SPDX-FileCopyrightText: 2022 g10 Code GmbH
0011     SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
0012 
0013     SPDX-License-Identifier: GPL-2.0-or-later
0014  */
0015 
0016 #include <config-kleopatra.h>
0017 
0018 #include "cryptooperationsconfigwidget.h"
0019 #include "kleopatra_debug.h"
0020 
0021 #include "fileoperationspreferences.h"
0022 #include "settings.h"
0023 
0024 #include <Libkleo/ChecksumDefinition>
0025 #include <Libkleo/KeyFilterManager>
0026 #include <libkleo/classifyconfig.h>
0027 
0028 #include <KConfig>
0029 #include <KConfigGroup>
0030 #include <KLocalizedString>
0031 #include <KMessageBox>
0032 #include <KSharedConfig>
0033 
0034 #include <QCheckBox>
0035 #include <QComboBox>
0036 #include <QDir>
0037 #include <QGroupBox>
0038 #include <QHBoxLayout>
0039 #include <QLabel>
0040 #include <QPushButton>
0041 #include <QRegularExpression>
0042 #include <QVBoxLayout>
0043 
0044 #include <memory>
0045 
0046 using namespace Kleo;
0047 using namespace Kleo::Config;
0048 
0049 CryptoOperationsConfigWidget::CryptoOperationsConfigWidget(QWidget *p, Qt::WindowFlags f)
0050     : QWidget{p, f}
0051 {
0052     setupGui();
0053 }
0054 
0055 void CryptoOperationsConfigWidget::setupGui()
0056 {
0057     auto baseLay = new QVBoxLayout(this);
0058 
0059     mPGPFileExtCB = new QCheckBox(i18n(R"(Create OpenPGP encrypted files with ".pgp" file extensions instead of ".gpg")"));
0060     mASCIIArmorCB = new QCheckBox(i18n("Create signed or encrypted files as text files."));
0061     mASCIIArmorCB->setToolTip(i18nc("@info",
0062                                     "Set this option to encode encrypted or signed files as base64 encoded text. "
0063                                     "So that they can be opened with an editor or sent in a mail body. "
0064                                     "This will increase file size by one third."));
0065     mTreatP7mEmailCB = new QCheckBox(i18nc("@option:check", "Treat .p7m files without extensions as mails."));
0066     mAutoDecryptVerifyCB = new QCheckBox(i18n("Automatically start operation based on input detection for decrypt/verify."));
0067     mAutoExtractArchivesCB = new QCheckBox(i18n("Automatically extract file archives after decryption"));
0068     mTmpDirCB = new QCheckBox(i18n("Create temporary decrypted files in the folder of the encrypted file."));
0069     mTmpDirCB->setToolTip(i18nc("@info", "Set this option to avoid using the users temporary directory."));
0070     mSymmetricOnlyCB = new QCheckBox(i18n("Use symmetric encryption only."));
0071     mSymmetricOnlyCB->setToolTip(i18nc("@info", "Set this option to disable public key encryption."));
0072 
0073     baseLay->addWidget(mPGPFileExtCB);
0074     baseLay->addWidget(mTreatP7mEmailCB);
0075     baseLay->addWidget(mAutoDecryptVerifyCB);
0076     baseLay->addWidget(mAutoExtractArchivesCB);
0077     baseLay->addWidget(mASCIIArmorCB);
0078     baseLay->addWidget(mTmpDirCB);
0079     baseLay->addWidget(mSymmetricOnlyCB);
0080 
0081     auto comboLay = new QGridLayout;
0082 
0083     mChecksumDefinitionCB.createWidgets(this);
0084     mChecksumDefinitionCB.label()->setText(i18n("Checksum program to use when creating checksum files:"));
0085     comboLay->addWidget(mChecksumDefinitionCB.label(), 0, 0);
0086     comboLay->addWidget(mChecksumDefinitionCB.widget(), 0, 1);
0087 
0088     mArchiveDefinitionCB.createWidgets(this);
0089     mArchiveDefinitionCB.label()->setText(i18n("Archive command to use when archiving files:"));
0090     comboLay->addWidget(mArchiveDefinitionCB.label(), 1, 0);
0091     comboLay->addWidget(mArchiveDefinitionCB.widget(), 1, 1);
0092 
0093     baseLay->addLayout(comboLay);
0094     baseLay->addStretch(1);
0095 
0096     for (auto cb : findChildren<QCheckBox *>()) {
0097         connect(cb, &QCheckBox::toggled, this, &CryptoOperationsConfigWidget::changed);
0098     }
0099     for (auto combo : findChildren<QComboBox *>()) {
0100         connect(combo, &QComboBox::currentIndexChanged, this, &CryptoOperationsConfigWidget::changed);
0101     }
0102 }
0103 
0104 CryptoOperationsConfigWidget::~CryptoOperationsConfigWidget()
0105 {
0106 }
0107 
0108 void CryptoOperationsConfigWidget::defaults()
0109 {
0110     FileOperationsPreferences filePrefs;
0111     filePrefs.setUsePGPFileExt(filePrefs.findItem(QStringLiteral("UsePGPFileExt"))->getDefault().toBool());
0112     filePrefs.setAutoDecryptVerify(filePrefs.findItem(QStringLiteral("AutoDecryptVerify"))->getDefault().toBool());
0113     filePrefs.setAutoExtractArchives(filePrefs.findItem(QStringLiteral("AutoExtractArchives"))->getDefault().toBool());
0114     filePrefs.setAddASCIIArmor(filePrefs.findItem(QStringLiteral("AddASCIIArmor"))->getDefault().toBool());
0115     filePrefs.setDontUseTmpDir(filePrefs.findItem(QStringLiteral("DontUseTmpDir"))->getDefault().toBool());
0116     filePrefs.setSymmetricEncryptionOnly(filePrefs.findItem(QStringLiteral("SymmetricEncryptionOnly"))->getDefault().toBool());
0117     filePrefs.setArchiveCommand(filePrefs.findItem(QStringLiteral("ArchiveCommand"))->getDefault().toString());
0118 
0119     ClassifyConfig classifyConfig;
0120     classifyConfig.setP7mWithoutExtensionAreEmail(classifyConfig.defaultP7mWithoutExtensionAreEmailValue());
0121 
0122     Settings settings;
0123     settings.setChecksumDefinitionId(settings.findItem(QStringLiteral("ChecksumDefinitionId"))->getDefault().toString());
0124 
0125     load(filePrefs, settings, classifyConfig);
0126 }
0127 
0128 void CryptoOperationsConfigWidget::load(const Kleo::FileOperationsPreferences &filePrefs,
0129                                         const Kleo::Settings &settings,
0130                                         const Kleo::ClassifyConfig &classifyConfig)
0131 {
0132     mPGPFileExtCB->setChecked(filePrefs.usePGPFileExt());
0133     mPGPFileExtCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("UsePGPFileExt")));
0134     mAutoDecryptVerifyCB->setChecked(filePrefs.autoDecryptVerify());
0135     mAutoDecryptVerifyCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("AutoDecryptVerify")));
0136     mAutoExtractArchivesCB->setChecked(filePrefs.autoExtractArchives());
0137     mAutoExtractArchivesCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("AutoExtractArchives")));
0138     mASCIIArmorCB->setChecked(filePrefs.addASCIIArmor());
0139     mASCIIArmorCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("AddASCIIArmor")));
0140     mTmpDirCB->setChecked(filePrefs.dontUseTmpDir());
0141     mTmpDirCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("DontUseTmpDir")));
0142     mSymmetricOnlyCB->setChecked(filePrefs.symmetricEncryptionOnly());
0143     mSymmetricOnlyCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("SymmetricEncryptionOnly")));
0144     mTreatP7mEmailCB->setEnabled(!classifyConfig.isP7mWithoutExtensionAreEmailImmutable());
0145 
0146     const auto defaultChecksumDefinitionId = settings.checksumDefinitionId();
0147     {
0148         const auto index = mChecksumDefinitionCB.widget()->findData(defaultChecksumDefinitionId);
0149         if (index >= 0) {
0150             mChecksumDefinitionCB.widget()->setCurrentIndex(index);
0151         } else {
0152             qCWarning(KLEOPATRA_LOG) << "No checksum definition found with id" << defaultChecksumDefinitionId;
0153         }
0154     }
0155     mChecksumDefinitionCB.setEnabled(!settings.isImmutable(QStringLiteral("ChecksumDefinitionId")));
0156 
0157     const auto ad_default_id = filePrefs.archiveCommand();
0158     {
0159         const auto index = mArchiveDefinitionCB.widget()->findData(ad_default_id);
0160         if (index >= 0) {
0161             mArchiveDefinitionCB.widget()->setCurrentIndex(index);
0162         } else {
0163             qCWarning(KLEOPATRA_LOG) << "No archive definition found with id" << ad_default_id;
0164         }
0165     }
0166     mArchiveDefinitionCB.setEnabled(!filePrefs.isImmutable(QStringLiteral("ArchiveCommand")));
0167 }
0168 
0169 void CryptoOperationsConfigWidget::load()
0170 {
0171     mChecksumDefinitionCB.widget()->clear();
0172     const auto cds = ChecksumDefinition::getChecksumDefinitions();
0173     for (const std::shared_ptr<ChecksumDefinition> &cd : cds) {
0174         mChecksumDefinitionCB.widget()->addItem(cd->label(), QVariant{cd->id()});
0175     }
0176 
0177     // This is a weird hack but because we are a KCM we can't link
0178     // against ArchiveDefinition which pulls in loads of other classes.
0179     // So we do the parsing which archive definitions exist here ourself.
0180     mArchiveDefinitionCB.widget()->clear();
0181     if (KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("libkleopatrarc"))) {
0182         const QStringList groups = config->groupList().filter(QRegularExpression(QStringLiteral("^Archive Definition #")));
0183         for (const QString &group : groups) {
0184             const KConfigGroup cGroup(config, group);
0185             const QString id = cGroup.readEntryUntranslated(QStringLiteral("id"));
0186             const QString name = cGroup.readEntry("Name");
0187             mArchiveDefinitionCB.widget()->addItem(name, QVariant(id));
0188         }
0189     }
0190 
0191     load(FileOperationsPreferences{}, Settings{}, ClassifyConfig{});
0192 }
0193 
0194 void CryptoOperationsConfigWidget::save()
0195 {
0196     FileOperationsPreferences filePrefs;
0197     filePrefs.setUsePGPFileExt(mPGPFileExtCB->isChecked());
0198     filePrefs.setAutoDecryptVerify(mAutoDecryptVerifyCB->isChecked());
0199     filePrefs.setAutoExtractArchives(mAutoExtractArchivesCB->isChecked());
0200     filePrefs.setAddASCIIArmor(mASCIIArmorCB->isChecked());
0201     filePrefs.setDontUseTmpDir(mTmpDirCB->isChecked());
0202     filePrefs.setSymmetricEncryptionOnly(mSymmetricOnlyCB->isChecked());
0203 
0204     Settings settings;
0205     const int idx = mChecksumDefinitionCB.widget()->currentIndex();
0206     if (idx >= 0) {
0207         const auto id = mChecksumDefinitionCB.widget()->itemData(idx).toString();
0208         settings.setChecksumDefinitionId(id);
0209     }
0210     settings.save();
0211 
0212     const int aidx = mArchiveDefinitionCB.widget()->currentIndex();
0213     if (aidx >= 0) {
0214         const QString id = mArchiveDefinitionCB.widget()->itemData(aidx).toString();
0215         filePrefs.setArchiveCommand(id);
0216     }
0217     filePrefs.save();
0218 
0219     ClassifyConfig classifyConfig;
0220     classifyConfig.setP7mWithoutExtensionAreEmail(mTreatP7mEmailCB->isChecked());
0221     classifyConfig.save();
0222 }
0223 
0224 #include "moc_cryptooperationsconfigwidget.cpp"