Page MenuHome GnuPG

No OneTemporary

diff --git a/src/conf/cryptooperationsconfigwidget.cpp b/src/conf/cryptooperationsconfigwidget.cpp
index f5f36d7b3..605b6f685 100644
--- a/src/conf/cryptooperationsconfigwidget.cpp
+++ b/src/conf/cryptooperationsconfigwidget.cpp
@@ -1,225 +1,244 @@
/*
cryptooperationsconfigwidget.cpp
This file is part of kleopatra, the KDE key manager
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "cryptooperationsconfigwidget.h"
#include "kleopatra_debug.h"
#include "fileoperationspreferences.h"
#include "settings.h"
#include <Libkleo/ChecksumDefinition>
#include <Libkleo/KeyFilterManager>
#include <libkleo/classifyconfig.h>
#include <KConfig>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KMessageBox>
#include <KSharedConfig>
#include <QCheckBox>
#include <QComboBox>
#include <QDir>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QRegularExpression>
#include <QVBoxLayout>
#include <memory>
using namespace Kleo;
using namespace Kleo::Config;
CryptoOperationsConfigWidget::CryptoOperationsConfigWidget(QWidget *p, Qt::WindowFlags f)
: QWidget{p, f}
{
setupGui();
}
void CryptoOperationsConfigWidget::setupGui()
{
auto baseLay = new QVBoxLayout(this);
mPGPFileExtCB = new QCheckBox(i18n(R"(Create OpenPGP encrypted files with ".pgp" file extensions instead of ".gpg")"));
mASCIIArmorCB = new QCheckBox(i18n("Create signed or encrypted files as text files."));
mASCIIArmorCB->setToolTip(i18nc("@info",
"Set this option to encode encrypted or signed files as base64 encoded text. "
"So that they can be opened with an editor or sent in a mail body. "
"This will increase file size by one third."));
mTreatP7mEmailCB = new QCheckBox(i18nc("@option:check", "Treat .p7m files without extensions as mails."));
mAutoDecryptVerifyCB = new QCheckBox(i18n("Automatically start operation based on input detection for decrypt/verify."));
mAutoExtractArchivesCB = new QCheckBox(i18n("Automatically extract file archives after decryption"));
mTmpDirCB = new QCheckBox(i18n("Create temporary decrypted files in the folder of the encrypted file."));
mTmpDirCB->setToolTip(i18nc("@info", "Set this option to avoid using the users temporary directory."));
mSymmetricOnlyCB = new QCheckBox(i18n("Use symmetric encryption only."));
mSymmetricOnlyCB->setToolTip(i18nc("@info", "Set this option to disable public key encryption."));
+ mAsymmetricOnlyCB = new QCheckBox(i18n("Use public-key encryption only."));
+ mAsymmetricOnlyCB->setToolTip(i18nc("@info", "Set this option to disable password-based encryption."));
+
+ connect(mSymmetricOnlyCB, &QCheckBox::toggled, this, [this]() {
+ if (mSymmetricOnlyCB->isChecked()) {
+ mAsymmetricOnlyCB->setChecked(false);
+ }
+ });
+
+ connect(mAsymmetricOnlyCB, &QCheckBox::toggled, this, [this]() {
+ if (mAsymmetricOnlyCB->isChecked()) {
+ mSymmetricOnlyCB->setChecked(false);
+ }
+ });
baseLay->addWidget(mPGPFileExtCB);
baseLay->addWidget(mTreatP7mEmailCB);
baseLay->addWidget(mAutoDecryptVerifyCB);
baseLay->addWidget(mAutoExtractArchivesCB);
baseLay->addWidget(mASCIIArmorCB);
baseLay->addWidget(mTmpDirCB);
baseLay->addWidget(mSymmetricOnlyCB);
+ baseLay->addWidget(mAsymmetricOnlyCB);
auto comboLay = new QGridLayout;
mChecksumDefinitionCB.createWidgets(this);
mChecksumDefinitionCB.label()->setText(i18n("Checksum program to use when creating checksum files:"));
comboLay->addWidget(mChecksumDefinitionCB.label(), 0, 0);
comboLay->addWidget(mChecksumDefinitionCB.widget(), 0, 1);
mArchiveDefinitionCB.createWidgets(this);
mArchiveDefinitionCB.label()->setText(i18n("Archive command to use when archiving files:"));
comboLay->addWidget(mArchiveDefinitionCB.label(), 1, 0);
comboLay->addWidget(mArchiveDefinitionCB.widget(), 1, 1);
baseLay->addLayout(comboLay);
baseLay->addStretch(1);
for (auto cb : findChildren<QCheckBox *>()) {
connect(cb, &QCheckBox::toggled, this, &CryptoOperationsConfigWidget::changed);
}
for (auto combo : findChildren<QComboBox *>()) {
connect(combo, &QComboBox::currentIndexChanged, this, &CryptoOperationsConfigWidget::changed);
}
}
CryptoOperationsConfigWidget::~CryptoOperationsConfigWidget()
{
}
void CryptoOperationsConfigWidget::defaults()
{
FileOperationsPreferences filePrefs;
filePrefs.setUsePGPFileExt(filePrefs.findItem(QStringLiteral("UsePGPFileExt"))->getDefault().toBool());
filePrefs.setAutoDecryptVerify(filePrefs.findItem(QStringLiteral("AutoDecryptVerify"))->getDefault().toBool());
filePrefs.setAutoExtractArchives(filePrefs.findItem(QStringLiteral("AutoExtractArchives"))->getDefault().toBool());
filePrefs.setAddASCIIArmor(filePrefs.findItem(QStringLiteral("AddASCIIArmor"))->getDefault().toBool());
filePrefs.setDontUseTmpDir(filePrefs.findItem(QStringLiteral("DontUseTmpDir"))->getDefault().toBool());
filePrefs.setSymmetricEncryptionOnly(filePrefs.findItem(QStringLiteral("SymmetricEncryptionOnly"))->getDefault().toBool());
+ filePrefs.setAsymmetricEncryptionOnly(filePrefs.findItem(QStringLiteral("AsymmetricEncryptionOnly"))->getDefault().toBool());
filePrefs.setArchiveCommand(filePrefs.findItem(QStringLiteral("ArchiveCommand"))->getDefault().toString());
ClassifyConfig classifyConfig;
classifyConfig.setP7mWithoutExtensionAreEmail(classifyConfig.defaultP7mWithoutExtensionAreEmailValue());
Settings settings;
settings.setChecksumDefinitionId(settings.findItem(QStringLiteral("ChecksumDefinitionId"))->getDefault().toString());
load(filePrefs, settings, classifyConfig);
}
void CryptoOperationsConfigWidget::load(const Kleo::FileOperationsPreferences &filePrefs,
const Kleo::Settings &settings,
const Kleo::ClassifyConfig &classifyConfig)
{
mPGPFileExtCB->setChecked(filePrefs.usePGPFileExt());
mPGPFileExtCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("UsePGPFileExt")));
mAutoDecryptVerifyCB->setChecked(filePrefs.autoDecryptVerify());
mAutoDecryptVerifyCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("AutoDecryptVerify")));
mAutoExtractArchivesCB->setChecked(filePrefs.autoExtractArchives());
mAutoExtractArchivesCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("AutoExtractArchives")));
mASCIIArmorCB->setChecked(filePrefs.addASCIIArmor());
mASCIIArmorCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("AddASCIIArmor")));
mTmpDirCB->setChecked(filePrefs.dontUseTmpDir());
mTmpDirCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("DontUseTmpDir")));
mSymmetricOnlyCB->setChecked(filePrefs.symmetricEncryptionOnly());
mSymmetricOnlyCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("SymmetricEncryptionOnly")));
+ mAsymmetricOnlyCB->setChecked(filePrefs.asymmetricEncryptionOnly());
+ mAsymmetricOnlyCB->setEnabled(!filePrefs.isAsymmetricEncryptionOnlyImmutable());
mTreatP7mEmailCB->setChecked(classifyConfig.p7mWithoutExtensionAreEmail());
mTreatP7mEmailCB->setEnabled(!classifyConfig.isP7mWithoutExtensionAreEmailImmutable());
const auto defaultChecksumDefinitionId = settings.checksumDefinitionId();
{
const auto index = mChecksumDefinitionCB.widget()->findData(defaultChecksumDefinitionId);
if (index >= 0) {
mChecksumDefinitionCB.widget()->setCurrentIndex(index);
} else {
qCWarning(KLEOPATRA_LOG) << "No checksum definition found with id" << defaultChecksumDefinitionId;
}
}
mChecksumDefinitionCB.setEnabled(!settings.isImmutable(QStringLiteral("ChecksumDefinitionId")));
const auto ad_default_id = filePrefs.archiveCommand();
{
const auto index = mArchiveDefinitionCB.widget()->findData(ad_default_id);
if (index >= 0) {
mArchiveDefinitionCB.widget()->setCurrentIndex(index);
} else {
qCWarning(KLEOPATRA_LOG) << "No archive definition found with id" << ad_default_id;
}
}
mArchiveDefinitionCB.setEnabled(!filePrefs.isImmutable(QStringLiteral("ArchiveCommand")));
}
void CryptoOperationsConfigWidget::load()
{
mChecksumDefinitionCB.widget()->clear();
const auto cds = ChecksumDefinition::getChecksumDefinitions();
for (const std::shared_ptr<ChecksumDefinition> &cd : cds) {
mChecksumDefinitionCB.widget()->addItem(cd->label(), QVariant{cd->id()});
}
// This is a weird hack but because we are a KCM we can't link
// against ArchiveDefinition which pulls in loads of other classes.
// So we do the parsing which archive definitions exist here ourself.
mArchiveDefinitionCB.widget()->clear();
if (KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("libkleopatrarc"))) {
const QStringList groups = config->groupList().filter(QRegularExpression(QStringLiteral("^Archive Definition #")));
for (const QString &group : groups) {
const KConfigGroup cGroup(config, group);
const QString id = cGroup.readEntryUntranslated(QStringLiteral("id"));
const QString name = cGroup.readEntry("Name");
mArchiveDefinitionCB.widget()->addItem(name, QVariant(id));
}
}
load(FileOperationsPreferences{}, Settings{}, ClassifyConfig{});
}
void CryptoOperationsConfigWidget::save()
{
FileOperationsPreferences filePrefs;
filePrefs.setUsePGPFileExt(mPGPFileExtCB->isChecked());
filePrefs.setAutoDecryptVerify(mAutoDecryptVerifyCB->isChecked());
filePrefs.setAutoExtractArchives(mAutoExtractArchivesCB->isChecked());
filePrefs.setAddASCIIArmor(mASCIIArmorCB->isChecked());
filePrefs.setDontUseTmpDir(mTmpDirCB->isChecked());
filePrefs.setSymmetricEncryptionOnly(mSymmetricOnlyCB->isChecked());
+ filePrefs.setAsymmetricEncryptionOnly(mAsymmetricOnlyCB->isChecked());
Settings settings;
const int idx = mChecksumDefinitionCB.widget()->currentIndex();
if (idx >= 0) {
const auto id = mChecksumDefinitionCB.widget()->itemData(idx).toString();
settings.setChecksumDefinitionId(id);
}
settings.save();
const int aidx = mArchiveDefinitionCB.widget()->currentIndex();
if (aidx >= 0) {
const QString id = mArchiveDefinitionCB.widget()->itemData(aidx).toString();
filePrefs.setArchiveCommand(id);
}
filePrefs.save();
ClassifyConfig classifyConfig;
classifyConfig.setP7mWithoutExtensionAreEmail(mTreatP7mEmailCB->isChecked());
classifyConfig.save();
}
#include "moc_cryptooperationsconfigwidget.cpp"
diff --git a/src/conf/cryptooperationsconfigwidget.h b/src/conf/cryptooperationsconfigwidget.h
index a40557432..246343927 100644
--- a/src/conf/cryptooperationsconfigwidget.h
+++ b/src/conf/cryptooperationsconfigwidget.h
@@ -1,63 +1,64 @@
/*
cryptooperationsconfigwidget.h
This file is part of kleopatra, the KDE key manager
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "labelledwidget.h"
#include <QWidget>
class QCheckBox;
class QComboBox;
class QBoxLayout;
class QPushButton;
namespace Kleo
{
class FileOperationsPreferences;
class Settings;
class ClassifyConfig;
namespace Config
{
class CryptoOperationsConfigWidget : public QWidget
{
Q_OBJECT
public:
explicit CryptoOperationsConfigWidget(QWidget *parent = nullptr, Qt::WindowFlags f = {});
~CryptoOperationsConfigWidget() override;
void load();
void save();
void defaults();
Q_SIGNALS:
void changed();
private:
void setupGui();
void load(const Kleo::FileOperationsPreferences &filePrefs, const Kleo::Settings &settings, const Kleo::ClassifyConfig &classifyConfig);
private:
QCheckBox *mPGPFileExtCB = nullptr;
QCheckBox *mTreatP7mEmailCB = nullptr;
QCheckBox *mAutoDecryptVerifyCB = nullptr;
QCheckBox *mAutoExtractArchivesCB = nullptr;
QCheckBox *mASCIIArmorCB = nullptr;
QCheckBox *mTmpDirCB = nullptr;
QCheckBox *mSymmetricOnlyCB = nullptr;
+ QCheckBox *mAsymmetricOnlyCB = nullptr;
Kleo::LabelledWidget<QComboBox> mChecksumDefinitionCB;
Kleo::LabelledWidget<QComboBox> mArchiveDefinitionCB;
QPushButton *mApplyBtn = nullptr;
};
}
}
diff --git a/src/crypto/gui/signencryptwidget.cpp b/src/crypto/gui/signencryptwidget.cpp
index 892eaec5b..c8e79f6fe 100644
--- a/src/crypto/gui/signencryptwidget.cpp
+++ b/src/crypto/gui/signencryptwidget.cpp
@@ -1,895 +1,898 @@
/* crypto/gui/signencryptwidget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "signencryptwidget.h"
#include "kleopatra_debug.h"
#include "certificatelineedit.h"
#include "fileoperationspreferences.h"
#include "kleopatraapplication.h"
#include "settings.h"
#include "unknownrecipientwidget.h"
#include "dialogs/certificateselectiondialog.h"
#include "utils/gui-helper.h"
#include <QCheckBox>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QScrollArea>
#include <QScrollBar>
#include <QVBoxLayout>
#include <Libkleo/Algorithm>
#include <Libkleo/Compliance>
#include <Libkleo/DefaultKeyFilter>
#include <Libkleo/ExpiryChecker>
#include <Libkleo/ExpiryCheckerConfig>
#include <Libkleo/ExpiryCheckerSettings>
#include <Libkleo/KeyCache>
#include <Libkleo/KeyHelpers>
#include <Libkleo/KeyListModel>
#include <Libkleo/KeyListSortFilterProxyModel>
#include <Libkleo/UserIDSelectionCombo>
#include <Libkleo/GnuPG>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KMessageBox>
#include <KMessageWidget>
#include <KSharedConfig>
using namespace Kleo;
using namespace Kleo::Dialogs;
using namespace GpgME;
namespace
{
class SignCertificateFilter : public DefaultKeyFilter
{
public:
SignCertificateFilter(GpgME::Protocol proto)
: DefaultKeyFilter()
{
setIsBad(DefaultKeyFilter::NotSet);
setHasSecret(DefaultKeyFilter::Set);
setCanSign(DefaultKeyFilter::Set);
setValidIfSMIME(DefaultKeyFilter::Set);
if (proto == GpgME::OpenPGP) {
setIsOpenPGP(DefaultKeyFilter::Set);
} else if (proto == GpgME::CMS) {
setIsOpenPGP(DefaultKeyFilter::NotSet);
}
}
};
class EncryptCertificateFilter : public DefaultKeyFilter
{
public:
EncryptCertificateFilter(GpgME::Protocol proto)
: DefaultKeyFilter()
{
setIsBad(DefaultKeyFilter::NotSet);
setCanEncrypt(DefaultKeyFilter::Set);
setValidIfSMIME(DefaultKeyFilter::Set);
if (proto == GpgME::OpenPGP) {
setIsOpenPGP(DefaultKeyFilter::Set);
} else if (proto == GpgME::CMS) {
setIsOpenPGP(DefaultKeyFilter::NotSet);
}
}
};
class EncryptSelfCertificateFilter : public EncryptCertificateFilter
{
public:
EncryptSelfCertificateFilter(GpgME::Protocol proto)
: EncryptCertificateFilter(proto)
{
setRevoked(DefaultKeyFilter::NotSet);
setExpired(DefaultKeyFilter::NotSet);
setCanEncrypt(DefaultKeyFilter::Set);
setHasSecret(DefaultKeyFilter::Set);
setValidIfSMIME(DefaultKeyFilter::Set);
}
};
}
class SignEncryptWidget::Private
{
SignEncryptWidget *const q;
public:
struct RecipientWidgets {
CertificateLineEdit *edit;
KMessageWidget *expiryMessage;
};
explicit Private(SignEncryptWidget *qq, bool sigEncExclusive)
: q{qq}
, mModel{AbstractKeyListModel::createFlatKeyListModel(qq)}
, mIsExclusive{sigEncExclusive}
{
}
CertificateLineEdit *addRecipientWidget();
/* Inserts a new recipient widget after widget @p after or at the end
* if @p after is null. */
CertificateLineEdit *insertRecipientWidget(CertificateLineEdit *after);
void recpRemovalRequested(const RecipientWidgets &recipient);
void onProtocolChanged();
void updateCheckBoxes();
ExpiryChecker *expiryChecker();
void updateExpiryMessages(KMessageWidget *w, const GpgME::Key &key, ExpiryChecker::CheckFlags flags);
void updateAllExpiryMessages();
public:
UserIDSelectionCombo *mSigSelect = nullptr;
KMessageWidget *mSignKeyExpiryMessage = nullptr;
UserIDSelectionCombo *mSelfSelect = nullptr;
KMessageWidget *mEncryptToSelfKeyExpiryMessage = nullptr;
std::vector<RecipientWidgets> mRecpWidgets;
QList<UnknownRecipientWidget *> mUnknownWidgets;
QList<GpgME::Key> mAddedKeys;
QList<KeyGroup> mAddedGroups;
QVBoxLayout *mRecpLayout = nullptr;
Operations mOp;
AbstractKeyListModel *mModel = nullptr;
QCheckBox *mSymmetric = nullptr;
QCheckBox *mSigChk = nullptr;
QCheckBox *mEncOtherChk = nullptr;
QCheckBox *mEncSelfChk = nullptr;
GpgME::Protocol mCurrentProto = GpgME::UnknownProtocol;
const bool mIsExclusive;
std::unique_ptr<ExpiryChecker> mExpiryChecker;
};
SignEncryptWidget::SignEncryptWidget(QWidget *parent, bool sigEncExclusive)
: QWidget{parent}
, d{new Private{this, sigEncExclusive}}
{
auto lay = new QVBoxLayout(this);
lay->setContentsMargins(0, 0, 0, 0);
d->mModel->useKeyCache(true, KeyList::IncludeGroups);
const bool haveSecretKeys = !KeyCache::instance()->secretKeys().empty();
const bool havePublicKeys = !KeyCache::instance()->keys().empty();
const bool symmetricOnly = FileOperationsPreferences().symmetricEncryptionOnly();
+ const bool asymmetricOnly = FileOperationsPreferences().asymmetricEncryptionOnly();
/* The signature selection */
{
auto sigGrp = new QGroupBox{i18nc("@title:group", "Prove authenticity (sign)"), this};
d->mSigChk = new QCheckBox{i18n("Sign as:"), this};
d->mSigChk->setEnabled(haveSecretKeys);
d->mSigChk->setChecked(haveSecretKeys);
d->mSigSelect = new UserIDSelectionCombo{KeyUsage::Sign, this};
d->mSigSelect->setEnabled(d->mSigChk->isChecked());
d->mSignKeyExpiryMessage = new KMessageWidget{this};
d->mSignKeyExpiryMessage->setVisible(false);
auto groupLayout = new QGridLayout{sigGrp};
groupLayout->setColumnStretch(1, 1);
groupLayout->addWidget(d->mSigChk, 0, 0);
groupLayout->addWidget(d->mSigSelect, 0, 1);
groupLayout->addWidget(d->mSignKeyExpiryMessage, 1, 1);
lay->addWidget(sigGrp);
connect(d->mSigChk, &QCheckBox::toggled, this, [this](bool checked) {
d->mSigSelect->setEnabled(checked);
updateOp();
d->updateExpiryMessages(d->mSignKeyExpiryMessage, signKey(), ExpiryChecker::OwnSigningKey);
});
connect(d->mSigSelect, &UserIDSelectionCombo::currentKeyChanged, this, [this]() {
updateOp();
d->updateExpiryMessages(d->mSignKeyExpiryMessage, signKey(), ExpiryChecker::OwnSigningKey);
});
}
// Recipient selection
{
auto encBox = new QGroupBox{i18nc("@title:group", "Encrypt"), this};
auto encBoxLay = new QVBoxLayout{encBox};
auto recipientGrid = new QGridLayout;
int row = 0;
// Own key
d->mEncSelfChk = new QCheckBox{i18n("Encrypt for me:"), this};
d->mEncSelfChk->setEnabled(haveSecretKeys && !symmetricOnly);
d->mEncSelfChk->setChecked(haveSecretKeys && !symmetricOnly);
d->mSelfSelect = new UserIDSelectionCombo{KeyUsage::Encrypt, this};
d->mSelfSelect->setEnabled(d->mEncSelfChk->isChecked());
d->mEncryptToSelfKeyExpiryMessage = new KMessageWidget{this};
d->mEncryptToSelfKeyExpiryMessage->setVisible(false);
recipientGrid->addWidget(d->mEncSelfChk, row, 0);
recipientGrid->addWidget(d->mSelfSelect, row, 1);
row++;
recipientGrid->addWidget(d->mEncryptToSelfKeyExpiryMessage, row, 1);
// Checkbox for other keys
row++;
d->mEncOtherChk = new QCheckBox{i18n("Encrypt for others:"), this};
d->mEncOtherChk->setEnabled(havePublicKeys && !symmetricOnly);
d->mEncOtherChk->setChecked(havePublicKeys && !symmetricOnly);
recipientGrid->addWidget(d->mEncOtherChk, row, 0, Qt::AlignTop);
connect(d->mEncOtherChk, &QCheckBox::toggled, this, [this](bool checked) {
for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
recipient.edit->setEnabled(checked);
d->updateExpiryMessages(recipient.expiryMessage, checked ? recipient.edit->key() : Key{}, ExpiryChecker::EncryptionKey);
}
updateOp();
});
d->mRecpLayout = new QVBoxLayout;
recipientGrid->addLayout(d->mRecpLayout, row, 1);
recipientGrid->setRowStretch(row + 1, 1);
// Scroll area for other keys
auto recipientWidget = new QWidget;
auto recipientScroll = new QScrollArea;
recipientWidget->setLayout(recipientGrid);
recipientScroll->setWidget(recipientWidget);
recipientScroll->setWidgetResizable(true);
recipientScroll->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
recipientScroll->setFrameStyle(QFrame::NoFrame);
recipientScroll->setFocusPolicy(Qt::NoFocus);
recipientGrid->setContentsMargins(0, 0, 0, 0);
encBoxLay->addWidget(recipientScroll, 1);
auto bar = recipientScroll->verticalScrollBar();
connect(bar, &QScrollBar::rangeChanged, this, [bar](int, int max) {
bar->setValue(max);
});
d->addRecipientWidget();
// Checkbox for password
d->mSymmetric = new QCheckBox(i18n("Encrypt with password. Anyone you share the password with can read the data."));
d->mSymmetric->setToolTip(i18nc("Tooltip information for symmetric encryption",
"Additionally to the keys of the recipients you can encrypt your data with a password. "
"Anyone who has the password can read the data without any secret key. "
"Using a password is <b>less secure</b> then public key cryptography. Even if you pick a very strong password."));
- d->mSymmetric->setChecked(symmetricOnly || !havePublicKeys);
+ d->mSymmetric->setChecked((symmetricOnly || !havePublicKeys) && !asymmetricOnly);
+ d->mSymmetric->setEnabled(!asymmetricOnly);
encBoxLay->addWidget(d->mSymmetric);
// Connect it
connect(d->mEncSelfChk, &QCheckBox::toggled, this, [this](bool checked) {
d->mSelfSelect->setEnabled(checked);
updateOp();
d->updateExpiryMessages(d->mEncryptToSelfKeyExpiryMessage, selfKey(), ExpiryChecker::OwnEncryptionKey);
});
connect(d->mSelfSelect, &UserIDSelectionCombo::currentKeyChanged, this, [this]() {
updateOp();
d->updateExpiryMessages(d->mEncryptToSelfKeyExpiryMessage, selfKey(), ExpiryChecker::OwnEncryptionKey);
});
connect(d->mSymmetric, &QCheckBox::toggled, this, &SignEncryptWidget::updateOp);
if (d->mIsExclusive) {
connect(d->mEncOtherChk, &QCheckBox::toggled, this, [this](bool value) {
if (d->mCurrentProto != GpgME::CMS) {
return;
}
if (value) {
d->mSigChk->setChecked(false);
}
});
connect(d->mEncSelfChk, &QCheckBox::toggled, this, [this](bool value) {
if (d->mCurrentProto != GpgME::CMS) {
return;
}
if (value) {
d->mSigChk->setChecked(false);
}
});
connect(d->mSigChk, &QCheckBox::toggled, this, [this](bool value) {
if (d->mCurrentProto != GpgME::CMS) {
return;
}
if (value) {
d->mEncSelfChk->setChecked(false);
d->mEncOtherChk->setChecked(false);
}
});
}
// Ensure that the d->mSigChk is aligned together with the encryption check boxes.
d->mSigChk->setMinimumWidth(qMax(d->mEncOtherChk->width(), d->mEncSelfChk->width()));
lay->addWidget(encBox);
}
connect(KeyCache::instance().get(), &Kleo::KeyCache::keysMayHaveChanged, this, [this]() {
d->updateCheckBoxes();
d->updateAllExpiryMessages();
});
connect(KleopatraApplication::instance(), &KleopatraApplication::configurationChanged, this, [this]() {
d->updateCheckBoxes();
d->mExpiryChecker.reset();
d->updateAllExpiryMessages();
});
loadKeys();
d->onProtocolChanged();
updateOp();
}
SignEncryptWidget::~SignEncryptWidget() = default;
void SignEncryptWidget::setSignAsText(const QString &text)
{
d->mSigChk->setText(text);
}
void SignEncryptWidget::setEncryptForMeText(const QString &text)
{
d->mEncSelfChk->setText(text);
}
void SignEncryptWidget::setEncryptForOthersText(const QString &text)
{
d->mEncOtherChk->setText(text);
}
void SignEncryptWidget::setEncryptWithPasswordText(const QString &text)
{
d->mSymmetric->setText(text);
}
CertificateLineEdit *SignEncryptWidget::Private::addRecipientWidget()
{
return insertRecipientWidget(nullptr);
}
CertificateLineEdit *SignEncryptWidget::Private::insertRecipientWidget(CertificateLineEdit *after)
{
Q_ASSERT(!after || mRecpLayout->indexOf(after) != -1);
const auto index = after ? mRecpLayout->indexOf(after) + 2 : mRecpLayout->count();
const RecipientWidgets recipient{new CertificateLineEdit{mModel, KeyUsage::Encrypt, new EncryptCertificateFilter{mCurrentProto}, q}, new KMessageWidget{q}};
recipient.edit->setAccessibleNameOfLineEdit(i18nc("text for screen readers", "recipient key"));
recipient.edit->setEnabled(mEncOtherChk->isChecked());
recipient.expiryMessage->setVisible(false);
if (static_cast<unsigned>(index / 2) < mRecpWidgets.size()) {
mRecpWidgets.insert(mRecpWidgets.begin() + index / 2, recipient);
} else {
mRecpWidgets.push_back(recipient);
}
if (mRecpLayout->count() > 0) {
auto prevWidget = after ? after : mRecpLayout->itemAt(mRecpLayout->count() - 1)->widget();
Kleo::forceSetTabOrder(prevWidget, recipient.edit);
Kleo::forceSetTabOrder(recipient.edit, recipient.expiryMessage);
}
mRecpLayout->insertWidget(index, recipient.edit);
mRecpLayout->insertWidget(index + 1, recipient.expiryMessage);
connect(recipient.edit, &CertificateLineEdit::keyChanged, q, &SignEncryptWidget::recipientsChanged);
connect(recipient.edit, &CertificateLineEdit::editingStarted, q, &SignEncryptWidget::recipientsChanged);
connect(recipient.edit, &CertificateLineEdit::cleared, q, &SignEncryptWidget::recipientsChanged);
connect(recipient.edit, &CertificateLineEdit::certificateSelectionRequested, q, [this, recipient]() {
q->certificateSelectionRequested(recipient.edit);
});
return recipient.edit;
}
void SignEncryptWidget::addRecipient(const Key &key)
{
CertificateLineEdit *certSel = d->addRecipientWidget();
if (!key.isNull()) {
certSel->setKey(key);
d->mAddedKeys << key;
}
}
void SignEncryptWidget::addRecipient(const KeyGroup &group)
{
CertificateLineEdit *certSel = d->addRecipientWidget();
if (!group.isNull()) {
certSel->setGroup(group);
d->mAddedGroups << group;
}
}
void SignEncryptWidget::certificateSelectionRequested(CertificateLineEdit *certificateLineEdit)
{
CertificateSelectionDialog dlg{this};
dlg.setOptions(CertificateSelectionDialog::Options( //
CertificateSelectionDialog::MultiSelection | //
CertificateSelectionDialog::EncryptOnly | //
CertificateSelectionDialog::optionsFromProtocol(d->mCurrentProto) | //
CertificateSelectionDialog::IncludeGroups));
if (!certificateLineEdit->key().isNull()) {
const auto key = certificateLineEdit->key();
const auto name = QString::fromUtf8(key.userID(0).name());
const auto email = QString::fromUtf8(key.userID(0).email());
dlg.setStringFilter(!name.isEmpty() ? name : email);
} else if (!certificateLineEdit->group().isNull()) {
dlg.setStringFilter(certificateLineEdit->group().name());
} else if (!certificateLineEdit->userID().isNull()) {
const auto userID = certificateLineEdit->userID();
const auto name = QString::fromUtf8(userID.name());
const auto email = QString::fromUtf8(userID.email());
dlg.setStringFilter(!name.isEmpty() ? name : email);
} else {
dlg.setStringFilter(certificateLineEdit->text());
}
if (dlg.exec()) {
const std::vector<UserID> userIds = dlg.selectedUserIDs();
const std::vector<KeyGroup> groups = dlg.selectedGroups();
if (userIds.size() == 0 && groups.size() == 0) {
return;
}
CertificateLineEdit *certWidget = nullptr;
for (const auto &userId : userIds) {
if (!certWidget) {
certWidget = certificateLineEdit;
} else {
certWidget = d->insertRecipientWidget(certWidget);
}
certWidget->setUserID(userId);
}
for (const KeyGroup &group : groups) {
if (!certWidget) {
certWidget = certificateLineEdit;
} else {
certWidget = d->insertRecipientWidget(certWidget);
}
certWidget->setGroup(group);
}
}
recipientsChanged();
}
void SignEncryptWidget::clearAddedRecipients()
{
for (auto w : std::as_const(d->mUnknownWidgets)) {
d->mRecpLayout->removeWidget(w);
delete w;
}
for (auto &key : std::as_const(d->mAddedKeys)) {
removeRecipient(key);
}
for (auto &group : std::as_const(d->mAddedGroups)) {
removeRecipient(group);
}
}
void SignEncryptWidget::addUnknownRecipient(const char *keyID)
{
auto unknownWidget = new UnknownRecipientWidget(keyID);
d->mUnknownWidgets << unknownWidget;
if (d->mRecpLayout->count() > 0) {
auto lastWidget = d->mRecpLayout->itemAt(d->mRecpLayout->count() - 1)->widget();
setTabOrder(lastWidget, unknownWidget);
}
d->mRecpLayout->addWidget(unknownWidget);
connect(KeyCache::instance().get(), &Kleo::KeyCache::keysMayHaveChanged, this, [this]() {
// Check if any unknown recipient can now be found.
for (auto w : d->mUnknownWidgets) {
auto key = KeyCache::instance()->findByKeyIDOrFingerprint(w->keyID().toLatin1().constData());
if (key.isNull()) {
std::vector<std::string> subids;
subids.push_back(std::string(w->keyID().toLatin1().constData()));
for (const auto &subkey : KeyCache::instance()->findSubkeysByKeyID(subids)) {
key = subkey.parent();
}
}
if (key.isNull()) {
continue;
}
// Key is now available replace by line edit.
qCDebug(KLEOPATRA_LOG) << "Removing widget for keyid: " << w->keyID();
d->mRecpLayout->removeWidget(w);
d->mUnknownWidgets.removeAll(w);
delete w;
addRecipient(key);
}
});
}
void SignEncryptWidget::recipientsChanged()
{
const bool hasEmptyRecpWidget = std::any_of(std::cbegin(d->mRecpWidgets), std::cend(d->mRecpWidgets), [](auto w) {
return w.edit->isEmpty();
});
if (!hasEmptyRecpWidget) {
d->addRecipientWidget();
}
updateOp();
for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
if (!recipient.edit->isEditingInProgress() || recipient.edit->isEmpty()) {
d->updateExpiryMessages(recipient.expiryMessage, d->mEncOtherChk->isChecked() ? recipient.edit->key() : Key{}, ExpiryChecker::EncryptionKey);
}
}
}
Key SignEncryptWidget::signKey() const
{
if (d->mSigSelect->isEnabled()) {
return d->mSigSelect->currentKey();
}
return Key();
}
Key SignEncryptWidget::selfKey() const
{
if (d->mSelfSelect->isEnabled()) {
return d->mSelfSelect->currentKey();
}
return Key();
}
std::vector<Key> SignEncryptWidget::recipients() const
{
std::vector<Key> ret;
for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
const auto *const w = recipient.edit;
if (!w->isEnabled()) {
// If one is disabled, all are disabled.
break;
}
const Key k = w->key();
const KeyGroup g = w->group();
const UserID u = w->userID();
if (!k.isNull()) {
ret.push_back(k);
} else if (!g.isNull()) {
const auto keys = g.keys();
std::copy(keys.begin(), keys.end(), std::back_inserter(ret));
} else if (!u.isNull()) {
ret.push_back(u.parent());
}
}
const Key k = selfKey();
if (!k.isNull()) {
ret.push_back(k);
}
return ret;
}
bool SignEncryptWidget::isDeVsAndValid() const
{
if (!signKey().isNull() && !DeVSCompliance::keyIsCompliant(signKey())) {
return false;
}
if (!selfKey().isNull() && !DeVSCompliance::keyIsCompliant(selfKey())) {
return false;
}
for (const auto &key : recipients()) {
if (!DeVSCompliance::keyIsCompliant(key)) {
return false;
}
}
return true;
}
static QString expiryMessage(const ExpiryChecker::Result &result)
{
if (result.expiration.certificate.isNull()) {
return {};
}
switch (result.expiration.status) {
case ExpiryChecker::Expired:
return i18nc("@info", "This certificate is expired.");
case ExpiryChecker::ExpiresSoon: {
if (result.expiration.duration.count() == 0) {
return i18nc("@info", "This certificate expires today.");
} else {
return i18ncp("@info", "This certificate expires tomorrow.", "This certificate expires in %1 days.", result.expiration.duration.count());
}
}
case ExpiryChecker::NoSuitableSubkey:
if (result.checkFlags & ExpiryChecker::EncryptionKey) {
return i18nc("@info", "This certificate cannot be used for encryption.");
} else {
return i18nc("@info", "This certificate cannot be used for signing.");
}
case ExpiryChecker::InvalidKey:
case ExpiryChecker::InvalidCheckFlags:
break; // wrong usage of ExpiryChecker; can be ignored
case ExpiryChecker::NotNearExpiry:;
}
return {};
}
void SignEncryptWidget::updateOp()
{
const Key sigKey = signKey();
const std::vector<Key> recp = recipients();
Operations op = NoOperation;
if (!sigKey.isNull()) {
op |= Sign;
}
if (!recp.empty() || encryptSymmetric()) {
op |= Encrypt;
}
d->mOp = op;
Q_EMIT operationChanged(d->mOp);
Q_EMIT keysChanged();
}
SignEncryptWidget::Operations SignEncryptWidget::currentOp() const
{
return d->mOp;
}
namespace
{
bool recipientWidgetHasFocus(QWidget *w)
{
// check if w (or its focus proxy) or a child widget of w has focus
return w->hasFocus() || w->isAncestorOf(qApp->focusWidget());
}
}
void SignEncryptWidget::Private::recpRemovalRequested(const RecipientWidgets &recipient)
{
if (!recipient.edit) {
return;
}
const int emptyEdits = std::count_if(std::cbegin(mRecpWidgets), std::cend(mRecpWidgets), [](const auto &r) {
return r.edit->isEmpty();
});
if (emptyEdits > 1) {
if (recipientWidgetHasFocus(recipient.edit) || recipientWidgetHasFocus(recipient.expiryMessage)) {
const int index = mRecpLayout->indexOf(recipient.edit);
const auto focusWidget = (index < mRecpLayout->count() - 2) ? //
mRecpLayout->itemAt(index + 2)->widget()
: mRecpLayout->itemAt(mRecpLayout->count() - 3)->widget();
focusWidget->setFocus();
}
mRecpLayout->removeWidget(recipient.expiryMessage);
mRecpLayout->removeWidget(recipient.edit);
const auto it = std::find_if(std::begin(mRecpWidgets), std::end(mRecpWidgets), [recipient](const auto &r) {
return r.edit == recipient.edit;
});
mRecpWidgets.erase(it);
recipient.expiryMessage->deleteLater();
recipient.edit->deleteLater();
}
}
void SignEncryptWidget::removeRecipient(const GpgME::Key &key)
{
for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
const auto editKey = recipient.edit->key();
if (key.isNull() && editKey.isNull()) {
d->recpRemovalRequested(recipient);
return;
}
if (editKey.primaryFingerprint() && key.primaryFingerprint() && !strcmp(editKey.primaryFingerprint(), key.primaryFingerprint())) {
d->recpRemovalRequested(recipient);
return;
}
}
}
void SignEncryptWidget::removeRecipient(const KeyGroup &group)
{
for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
const auto editGroup = recipient.edit->group();
if (group.isNull() && editGroup.isNull()) {
d->recpRemovalRequested(recipient);
return;
}
if (editGroup.name() == group.name()) {
d->recpRemovalRequested(recipient);
return;
}
}
}
bool SignEncryptWidget::encryptSymmetric() const
{
return d->mSymmetric->isChecked();
}
void SignEncryptWidget::loadKeys()
{
KConfigGroup keys(KSharedConfig::openConfig(), QStringLiteral("SignEncryptKeys"));
auto cache = KeyCache::instance();
d->mSigSelect->setDefaultKey(keys.readEntry("SigningKey", QString()));
d->mSelfSelect->setDefaultKey(keys.readEntry("EncryptKey", QString()));
}
void SignEncryptWidget::saveOwnKeys() const
{
KConfigGroup keys(KSharedConfig::openConfig(), QStringLiteral("SignEncryptKeys"));
auto sigKey = d->mSigSelect->currentKey();
auto encKey = d->mSelfSelect->currentKey();
if (!sigKey.isNull()) {
keys.writeEntry("SigningKey", sigKey.primaryFingerprint());
}
if (!encKey.isNull()) {
keys.writeEntry("EncryptKey", encKey.primaryFingerprint());
}
}
void SignEncryptWidget::setSigningChecked(bool value)
{
d->mSigChk->setChecked(value && !KeyCache::instance()->secretKeys().empty());
}
void SignEncryptWidget::setEncryptionChecked(bool checked)
{
if (checked) {
const bool haveSecretKeys = !KeyCache::instance()->secretKeys().empty();
const bool havePublicKeys = !KeyCache::instance()->keys().empty();
const bool symmetricOnly = FileOperationsPreferences().symmetricEncryptionOnly();
+ const bool asymmetricOnly = FileOperationsPreferences().asymmetricEncryptionOnly();
d->mEncSelfChk->setChecked(haveSecretKeys && !symmetricOnly);
d->mEncOtherChk->setChecked(havePublicKeys && !symmetricOnly);
- d->mSymmetric->setChecked(symmetricOnly || !havePublicKeys);
+ d->mSymmetric->setChecked((symmetricOnly || !havePublicKeys) && !asymmetricOnly);
} else {
d->mEncSelfChk->setChecked(false);
d->mEncOtherChk->setChecked(false);
d->mSymmetric->setChecked(false);
}
}
void SignEncryptWidget::setProtocol(GpgME::Protocol proto)
{
if (d->mCurrentProto == proto) {
return;
}
d->mCurrentProto = proto;
d->onProtocolChanged();
}
void Kleo::SignEncryptWidget::Private::onProtocolChanged()
{
mSigSelect->setKeyFilter(std::shared_ptr<KeyFilter>(new SignCertificateFilter(mCurrentProto)));
mSelfSelect->setKeyFilter(std::shared_ptr<KeyFilter>(new EncryptSelfCertificateFilter(mCurrentProto)));
const auto encFilter = std::shared_ptr<KeyFilter>(new EncryptCertificateFilter(mCurrentProto));
for (const auto &recipient : std::as_const(mRecpWidgets)) {
recipient.edit->setKeyFilter(encFilter);
}
if (mIsExclusive) {
mSymmetric->setDisabled(mCurrentProto == GpgME::CMS);
if (mSymmetric->isChecked() && mCurrentProto == GpgME::CMS) {
mSymmetric->setChecked(false);
}
if (mSigChk->isChecked() && mCurrentProto == GpgME::CMS && (mEncSelfChk->isChecked() || mEncOtherChk->isChecked())) {
mSigChk->setChecked(false);
}
}
}
static bool recipientIsOkay(const CertificateLineEdit *edit)
{
if (!edit->isEnabled() || edit->isEmpty()) {
return true;
}
if (!edit->hasAcceptableInput()) {
return false;
}
if (const auto userID = edit->userID(); !userID.isNull()) {
return Kleo::canBeUsedForEncryption(userID.parent()) && !userID.isBad();
}
if (const auto key = edit->key(); !key.isNull()) {
return Kleo::canBeUsedForEncryption(key);
}
if (const auto group = edit->group(); !group.isNull()) {
return std::ranges::all_of(group.keys(), Kleo::canBeUsedForEncryption);
}
// we should never reach this point
return false;
}
bool SignEncryptWidget::isComplete() const
{
if (currentOp() == NoOperation) {
return false;
}
if ((currentOp() & SignEncryptWidget::Sign) && !Kleo::canBeUsedForSigning(signKey())) {
return false;
}
if (currentOp() & SignEncryptWidget::Encrypt) {
if (!selfKey().isNull() && !Kleo::canBeUsedForEncryption(selfKey())) {
return false;
}
const bool allOtherRecipientsAreOkay = std::ranges::all_of(d->mRecpWidgets, [](const auto &r) {
return recipientIsOkay(r.edit);
});
if (!allOtherRecipientsAreOkay) {
return false;
}
}
return true;
}
bool SignEncryptWidget::validate()
{
CertificateLineEdit *firstUnresolvedRecipient = nullptr;
QStringList unresolvedRecipients;
for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
if (recipient.edit->isEnabled() && !recipient.edit->hasAcceptableInput()) {
if (!firstUnresolvedRecipient) {
firstUnresolvedRecipient = recipient.edit;
}
unresolvedRecipients.push_back(recipient.edit->text().toHtmlEscaped());
}
}
if (!unresolvedRecipients.isEmpty()) {
KMessageBox::errorList(this,
i18n("Could not find a key for the following recipients:"),
unresolvedRecipients,
i18nc("@title:window", "Failed to find some keys"));
}
if (firstUnresolvedRecipient) {
firstUnresolvedRecipient->setFocus();
}
return unresolvedRecipients.isEmpty();
}
void SignEncryptWidget::Private::updateCheckBoxes()
{
const bool haveSecretKeys = !KeyCache::instance()->secretKeys().empty();
const bool havePublicKeys = !KeyCache::instance()->keys().empty();
const bool symmetricOnly = FileOperationsPreferences().symmetricEncryptionOnly();
mSigChk->setEnabled(haveSecretKeys);
mEncSelfChk->setEnabled(haveSecretKeys && !symmetricOnly);
mEncOtherChk->setEnabled(havePublicKeys && !symmetricOnly);
if (symmetricOnly) {
mEncSelfChk->setChecked(false);
mEncOtherChk->setChecked(false);
mSymmetric->setChecked(true);
}
}
ExpiryChecker *Kleo::SignEncryptWidget::Private::expiryChecker()
{
if (!mExpiryChecker) {
mExpiryChecker.reset(new ExpiryChecker{ExpiryCheckerConfig{}.settings()});
}
return mExpiryChecker.get();
}
void SignEncryptWidget::Private::updateExpiryMessages(KMessageWidget *messageWidget, const GpgME::Key &key, ExpiryChecker::CheckFlags flags)
{
messageWidget->setCloseButtonVisible(false);
if (!Settings{}.showExpiryNotifications() || key.isNull()) {
messageWidget->setVisible(false);
} else {
const auto result = expiryChecker()->checkKey(key, flags);
const auto message = expiryMessage(result);
messageWidget->setText(message);
messageWidget->setVisible(!message.isEmpty());
}
}
void SignEncryptWidget::Private::updateAllExpiryMessages()
{
updateExpiryMessages(mSignKeyExpiryMessage, q->signKey(), ExpiryChecker::OwnSigningKey);
updateExpiryMessages(mEncryptToSelfKeyExpiryMessage, q->selfKey(), ExpiryChecker::OwnEncryptionKey);
for (const auto &recipient : std::as_const(mRecpWidgets)) {
if (recipient.edit->isEnabled()) {
updateExpiryMessages(recipient.expiryMessage, recipient.edit->key(), ExpiryChecker::EncryptionKey);
}
}
}
#include "moc_signencryptwidget.cpp"
diff --git a/src/kcfg/fileoperationspreferences.kcfg b/src/kcfg/fileoperationspreferences.kcfg
index b2d4f9672..0c4d72ef6 100644
--- a/src/kcfg/fileoperationspreferences.kcfg
+++ b/src/kcfg/fileoperationspreferences.kcfg
@@ -1,45 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name="kleopatrarc" />
<group name="FileOperations">
<entry name="UsePGPFileExt" key="file-extension-pgp" type="Bool">
<label>Use pgp as the default extension for generated OpenPGP files</label>
<whatsthis>Set this to make kleopatra default to pgp file extensions for OpenPGP files.</whatsthis>
<default>false</default>
</entry>
<entry name="AutoDecryptVerify" key="auto-decrypt-verify" type="Bool">
<label>Automatically start operation based on input detection for decrypt/verify.</label>
<whatsthis>With this option set Kleopatra no longer asks you what you want to do with input files but instead automatically starts the operations it detects as applicable to the input.</whatsthis>
<default>true</default>
</entry>
<entry name="AutoExtractArchives" key="auto-extract-archives" type="Bool">
<label>Automatically extract archives after decryption.</label>
<whatsthis>If this option is set, then Kleopatra automatically extracts file archives after decryption.</whatsthis>
<default>true</default>
</entry>
<entry name="ArchiveCommand" key="default-archive-cmd" type="String">
<label>Use this command to create file archives.</label>
<whatsthis>When encrypting multiple files or a folder Kleopatra creates an encrypted archive with this command.</whatsthis>
<default>tar</default>
</entry>
<entry name="AddASCIIArmor" key="ascii-armor" type="Bool">
<label>Create signed or encrypted files as text files.</label>
<whatsthis>Set this option to encode encrypted or signed files as base64 encoded text. So that they can be opened with an editor or sent in a mail body. This will increase file size by one third.</whatsthis>
<default>false</default>
</entry>
<entry name="DontUseTmpDir" key="dont-use-tmp-dir" type="Bool">
<label>Create temporary decrypted files in the folder of the encrypted file.</label>
<whatsthis>Set this option to avoid using the users temporary directory.</whatsthis>
<default>false</default>
</entry>
<entry name="SymmetricEncryptionOnly" key="symmetric-encryption-only" type="Bool">
<label>Use symmetric encryption only.</label>
<whatsthis>Set this option to disable public key encryption.</whatsthis>
<default>false</default>
</entry>
+ <entry name="AsymmetricEncryptionOnly" key="asymmetric-encryption-only" type="Bool">
+ <label>Use asymmetric encryption only.</label>
+ <whatsthis>Set this option to disable password-based encryption.</whatsthis>
+ <default>false</default>
+ </entry>
</group>
</kcfg>

File Metadata

Mime Type
text/x-diff
Expires
Tue, Dec 30, 5:41 PM (1 d, 18 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
35/b3/0f363ca77dae78d4344d74a69312

Event Timeline