Page MenuHome GnuPG

No OneTemporary

diff --git a/src/commands/dumpcrlcachecommand.cpp b/src/commands/dumpcrlcachecommand.cpp
index a94c3aab4..268ad6827 100644
--- a/src/commands/dumpcrlcachecommand.cpp
+++ b/src/commands/dumpcrlcachecommand.cpp
@@ -1,351 +1,351 @@
/* -*- mode: c++; c-basic-offset:4 -*-
commands/dumpcrlcachecommand.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "dumpcrlcachecommand.h"
#include "command_p.h"
#include <Libkleo/GnuPG>
#include <KProcess>
#include <KMessageBox>
#include <KLocalizedString>
#include <QPushButton>
#include <KStandardGuiItem>
#include <KConfigGroup>
#include <QString>
#include <QByteArray>
#include <QTimer>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <KSharedConfig>
#include <QFontDatabase>
#include <QTextEdit>
static const int PROCESS_TERMINATE_TIMEOUT = 5000; // milliseconds
namespace
{
class DumpCrlCacheDialog : public QDialog
{
Q_OBJECT
public:
explicit DumpCrlCacheDialog(QWidget *parent = nullptr)
: QDialog(parent), ui(this), mWithRevocations(false)
{
readConfig();
}
~DumpCrlCacheDialog()
{
writeConfig();
}
Q_SIGNALS:
void updateRequested();
public Q_SLOTS:
void append(const QString &line)
{
ui.logTextWidget.append(line);
ui.logTextWidget.ensureCursorVisible();
}
void clear()
{
ui.logTextWidget.clear();
}
public:
void setWithRevocations (bool value) {
mWithRevocations = value;
}
Q_REQUIRED_RESULT bool withRevocations () {
return mWithRevocations;
}
private:
void readConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "DumpCrlCacheDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "DumpCrlCacheDialog");
const QSize size = dialog.readEntry("Size", QSize(600, 400));
if (size.isValid()) {
resize(size);
}
}
void writeConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "DumpCrlCacheDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "DumpCrlCacheDialog");
dialog.writeEntry("Size", size());
dialog.sync();
}
struct Ui {
QTextEdit logTextWidget;
QPushButton updateButton, closeButton, revocationsButton;
QVBoxLayout vlay;
QHBoxLayout hlay;
explicit Ui(DumpCrlCacheDialog *q)
: logTextWidget(q),
updateButton(i18nc("@action:button Update the log text widget", "&Update"), q),
closeButton(q),
vlay(q),
hlay()
{
KGuiItem::assign(&closeButton, KStandardGuiItem::close());
KDAB_SET_OBJECT_NAME(logTextWidget);
KDAB_SET_OBJECT_NAME(updateButton);
KDAB_SET_OBJECT_NAME(closeButton);
KDAB_SET_OBJECT_NAME(vlay);
KDAB_SET_OBJECT_NAME(hlay);
logTextWidget.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
logTextWidget.setReadOnly(true);
vlay.addWidget(&logTextWidget, 1);
vlay.addLayout(&hlay);
revocationsButton.setText(i18n("Show Entries"));
hlay.addWidget(&updateButton);
hlay.addWidget(&revocationsButton);
hlay.addStretch(1);
hlay.addWidget(&closeButton);
connect(&updateButton, &QAbstractButton::clicked,
q, &DumpCrlCacheDialog::updateRequested);
connect(&closeButton, &QAbstractButton::clicked,
q, &QWidget::close);
connect(&revocationsButton, &QAbstractButton::clicked,
q, [q, this] () {
q->mWithRevocations = true;
revocationsButton.setEnabled(false);
q->updateRequested();
});
}
} ui;
bool mWithRevocations;
};
}
using namespace Kleo;
using namespace Kleo::Commands;
static QByteArray chomped(QByteArray ba)
{
while (ba.endsWith('\n') || ba.endsWith('\r')) {
ba.chop(1);
}
return ba;
}
class DumpCrlCacheCommand::Private : Command::Private
{
friend class ::Kleo::Commands::DumpCrlCacheCommand;
DumpCrlCacheCommand *q_func() const
{
return static_cast<DumpCrlCacheCommand *>(q);
}
public:
explicit Private(DumpCrlCacheCommand *qq, KeyListController *c);
~Private();
QString errorString() const
{
return QString::fromLocal8Bit(errorBuffer);
}
private:
void init();
void refreshView();
private:
void slotProcessFinished(int, QProcess::ExitStatus);
void slotProcessReadyReadStandardOutput()
{
static int count;
while (process.canReadLine()) {
if (!dialog) {
break;
}
const QByteArray line = chomped(process.readLine());
if (!line.size()) {
continue;
}
if (!dialog->withRevocations() && line.contains("reasons")) {
count++;
continue;
} else if (count) {
dialog->append (QLatin1Char(' ') +
i18nc("Count of revocations in a CRL",
"Entries:") + QStringLiteral("\t\t%1\n").arg(count));
count = 0;
}
dialog->append(stringFromGpgOutput(line));
}
}
void slotProcessReadyReadStandardError()
{
errorBuffer += process.readAllStandardError();
}
void slotUpdateRequested()
{
if (process.state() == QProcess::NotRunning) {
refreshView();
}
}
void slotDialogDestroyed()
{
dialog = nullptr;
if (process.state() != QProcess::NotRunning) {
q->cancel();
} else {
finished();
}
}
private:
DumpCrlCacheDialog *dialog;
KProcess process;
QByteArray errorBuffer;
bool canceled;
};
DumpCrlCacheCommand::Private *DumpCrlCacheCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const DumpCrlCacheCommand::Private *DumpCrlCacheCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define d d_func()
#define q q_func()
DumpCrlCacheCommand::Private::Private(DumpCrlCacheCommand *qq, KeyListController *c)
: Command::Private(qq, c),
dialog(nullptr),
process(),
errorBuffer(),
canceled(false)
{
process.setOutputChannelMode(KProcess::SeparateChannels);
process.setReadChannel(KProcess::StandardOutput);
process << gpgSmPath() << QStringLiteral("--call-dirmngr") << QStringLiteral("listcrls");
}
DumpCrlCacheCommand::Private::~Private()
{
if (dialog && !dialog->isVisible()) {
delete dialog;
}
}
DumpCrlCacheCommand::DumpCrlCacheCommand(KeyListController *c)
: Command(new Private(this, c))
{
d->init();
}
DumpCrlCacheCommand::DumpCrlCacheCommand(QAbstractItemView *v, KeyListController *c)
: Command(v, new Private(this, c))
{
d->init();
}
void DumpCrlCacheCommand::Private::init()
{
connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)),
q, SLOT(slotProcessFinished(int,QProcess::ExitStatus)));
connect(&process, SIGNAL(readyReadStandardError()),
q, SLOT(slotProcessReadyReadStandardError()));
connect(&process, SIGNAL(readyReadStandardOutput()),
q, SLOT(slotProcessReadyReadStandardOutput()));
}
DumpCrlCacheCommand::~DumpCrlCacheCommand() {}
void DumpCrlCacheCommand::doStart()
{
d->dialog = new DumpCrlCacheDialog;
d->dialog->setAttribute(Qt::WA_DeleteOnClose);
d->dialog->setWindowTitle(i18nc("@title:window", "CRL Cache Dump"));
connect(d->dialog, SIGNAL(updateRequested()),
this, SLOT(slotUpdateRequested()));
connect(d->dialog, SIGNAL(destroyed()),
this, SLOT(slotDialogDestroyed()));
d->refreshView();
}
void DumpCrlCacheCommand::Private::refreshView()
{
dialog->clear();
process.start();
if (process.waitForStarted()) {
dialog->show();
} else {
KMessageBox::error(dialog ? static_cast<QWidget *>(dialog) : parentWidgetOrView(),
i18n("Unable to start process gpgsm. "
"Please check your installation."),
i18n("Dump CRL Cache Error"));
finished();
}
}
void DumpCrlCacheCommand::doCancel()
{
d->canceled = true;
if (d->process.state() != QProcess::NotRunning) {
d->process.terminate();
QTimer::singleShot(PROCESS_TERMINATE_TIMEOUT, &d->process, &QProcess::kill);
}
if (d->dialog) {
d->dialog->close();
}
d->dialog = nullptr;
}
void DumpCrlCacheCommand::Private::slotProcessFinished(int code, QProcess::ExitStatus status)
{
if (!canceled) {
if (status == QProcess::CrashExit)
KMessageBox::error(dialog,
i18n("The GpgSM process that tried to dump the CRL cache "
"ended prematurely because of an unexpected error. "
"Please check the output of gpgsm --call-dirmngr listcrls for details."),
i18n("Dump CRL Cache Error"));
else if (code)
KMessageBox::error(dialog,
i18n("An error occurred while trying to dump the CRL cache. "
"The output from GpgSM was:\n%1", errorString()),
i18n("Dump CRL Cache Error"));
}
}
#undef d
#undef q
#include "moc_dumpcrlcachecommand.cpp"
#include "dumpcrlcachecommand.moc"
diff --git a/src/conf/configuredialog.cpp b/src/conf/configuredialog.cpp
index 63b5bd7aa..1e5a5a2a1 100644
--- a/src/conf/configuredialog.cpp
+++ b/src/conf/configuredialog.cpp
@@ -1,70 +1,70 @@
/*
configuredialog.cpp
This file is part of kleopatra
SPDX-FileCopyrightText: 2000 Espen Sand <espen@kde.org>
SPDX-FileCopyrightText: 2001-2002 Marc Mutz <mutz@kde.org>
SPDX-FileCopyrightText: 2004, 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-only
*/
#include "configuredialog.h"
#include <KConfig>
#include <KLocalizedString>
#include <KConfigGroup>
#include <KSharedConfig>
#if HAVE_KCMUTILS
# include <KCMultiDialog>
#else
# include "kleopageconfigdialog.h"
#endif
ConfigureDialog::ConfigureDialog(QWidget *parent)
#if HAVE_KCMUTILS
: KCMultiDialog(parent)
#else
: KleoPageConfigDialog(parent)
#endif
{
setFaceType(KPageDialog::List);
setWindowTitle(i18nc("@title:window", "Configure"));
addModule(QStringLiteral("kleopatra_config_dirserv"));
addModule(QStringLiteral("kleopatra_config_appear"));
addModule(QStringLiteral("kleopatra_config_cryptooperations"));
addModule(QStringLiteral("kleopatra_config_smimevalidation"));
addModule(QStringLiteral("kleopatra_config_gnupgsystem"));
// We store the minimum size of the dialog on hide, because otherwise
// the KCMultiDialog starts with the size of the first kcm, not
// the largest one. This way at least after the first showing of
// the largest kcm the size is kept.
- const KConfigGroup geometry(KSharedConfig::openConfig(), "Geometry");
+ const KConfigGroup geometry(KSharedConfig::openStateConfig(), "Geometry");
const int width = geometry.readEntry("ConfigureDialogWidth", 0);
const int height = geometry.readEntry("ConfigureDialogHeight", 0);
if (width != 0 && height != 0) {
setMinimumSize(width, height);
}
}
void ConfigureDialog::hideEvent(QHideEvent *e)
{
const QSize minSize = minimumSizeHint();
- KConfigGroup geometry(KSharedConfig::openConfig(), "Geometry");
+ KConfigGroup geometry(KSharedConfig::openStateConfig(), "Geometry");
geometry.writeEntry("ConfigureDialogWidth", minSize.width());
geometry.writeEntry("ConfigureDialogHeight", minSize.height());
#if HAVE_KCMUTILS
KCMultiDialog::hideEvent(e);
#else
KleoPageConfigDialog::hideEvent(e);
#endif
}
ConfigureDialog::~ConfigureDialog()
{
}
diff --git a/src/conf/groupsconfigdialog.cpp b/src/conf/groupsconfigdialog.cpp
index ff8e3698c..cae15fe78 100644
--- a/src/conf/groupsconfigdialog.cpp
+++ b/src/conf/groupsconfigdialog.cpp
@@ -1,113 +1,113 @@
/*
conf/groupsconfigdialog.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 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 "groupsconfigdialog.h"
#include "groupsconfigpage.h"
#include <KConfigGroup>
#include <KGuiItem>
#include <KLocalizedString>
#include <KSharedConfig>
#include <KStandardGuiItem>
#include <QDialogButtonBox>
#include <QPushButton>
class GroupsConfigDialog::Private
{
friend class ::GroupsConfigDialog;
GroupsConfigDialog *const q;
GroupsConfigPage *configPage = nullptr;
bool changed = false;
public:
Private(GroupsConfigDialog *qq)
: q(qq)
, configPage(new GroupsConfigPage(qq))
{
restoreLayout();
}
~Private()
{
saveLayout();
}
private:
void saveLayout()
{
- KConfigGroup configGroup(KSharedConfig::openConfig(), "GroupsConfigDialog");
+ KConfigGroup configGroup(KSharedConfig::openStateConfig(), "GroupsConfigDialog");
configGroup.writeEntry("Size", q->size());
configGroup.sync();
}
void restoreLayout(const QSize &defaultSize = QSize())
{
- const KConfigGroup configGroup(KSharedConfig::openConfig(), "GroupsConfigDialog");
+ const KConfigGroup configGroup(KSharedConfig::openStateConfig(), "GroupsConfigDialog");
const QSize size = configGroup.readEntry("Size", defaultSize);
if (size.isValid()) {
q->resize(size);
}
}
};
GroupsConfigDialog::GroupsConfigDialog(QWidget *parent)
: KConfigDialog(parent, GroupsConfigDialog::dialogName(), /*config=*/ nullptr)
, d(new Private(this))
{
setWindowTitle(i18nc("@title:window", "Configure Groups"));
setFaceType(KPageDialog::Plain);
addPage(d->configPage, i18n("Groups"), /*pixmapName=*/ QString(), /*header=*/ QString(), /*manage=*/ false);
// there are no defaults to restore
buttonBox()->removeButton(buttonBox()->button(QDialogButtonBox::RestoreDefaults));
QPushButton *resetButton = buttonBox()->addButton(QDialogButtonBox::Reset);
KGuiItem::assign(resetButton, KStandardGuiItem::reset());
resetButton->setEnabled(false);
connect(buttonBox()->button(QDialogButtonBox::Reset), &QAbstractButton::clicked,
this, &GroupsConfigDialog::updateWidgets);
connect(d->configPage, &GroupsConfigPage::changed, this, [this] (bool state) {
d->changed = state;
updateButtons();
if (QPushButton *button = buttonBox()->button(QDialogButtonBox::Reset)) {
button->setEnabled(d->changed);
}
});
}
GroupsConfigDialog::~GroupsConfigDialog() = default;
QString GroupsConfigDialog::dialogName()
{
return QStringLiteral("Group Settings");
}
void GroupsConfigDialog::updateSettings()
{
d->configPage->save();
}
void GroupsConfigDialog::updateWidgets()
{
d->configPage->load();
}
bool GroupsConfigDialog::hasChanged()
{
return d->changed;
}
diff --git a/src/crypto/createchecksumscontroller.cpp b/src/crypto/createchecksumscontroller.cpp
index 6df947642..c794415b9 100644
--- a/src/crypto/createchecksumscontroller.cpp
+++ b/src/crypto/createchecksumscontroller.cpp
@@ -1,719 +1,719 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/createchecksumscontroller.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "createchecksumscontroller.h"
#include <utils/input.h>
#include <utils/output.h>
#include <utils/kleo_assert.h>
#include <Libkleo/Stl_Util>
#include <Libkleo/ChecksumDefinition>
#include <Libkleo/Classify>
#include <KLocalizedString>
#include "kleopatra_debug.h"
#include <QTemporaryFile>
#include <KConfigGroup>
#include <KSharedConfig>
#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel>
#include <QListWidget>
#include <QVBoxLayout>
#include <QPointer>
#include <QFileInfo>
#include <QThread>
#include <QMutex>
#include <QProgressDialog>
#include <QDir>
#include <QProcess>
#include <gpg-error.h>
#include <deque>
#include <map>
#include <limits>
#include <functional>
using namespace Kleo;
using namespace Kleo::Crypto;
namespace
{
class ResultDialog : public QDialog
{
Q_OBJECT
public:
ResultDialog(const QStringList &created, const QStringList &errors, QWidget *parent = nullptr, Qt::WindowFlags f = {})
: QDialog(parent, f),
createdLB(created.empty()
? i18nc("@info", "No checksum files have been created.")
: i18nc("@info", "These checksum files have been successfully created:"), this),
createdLW(this),
errorsLB(errors.empty()
? i18nc("@info", "There were no errors.")
: i18nc("@info", "The following errors were encountered:"), this),
errorsLW(this),
buttonBox(QDialogButtonBox::Ok, Qt::Horizontal, this),
vlay(this)
{
KDAB_SET_OBJECT_NAME(createdLB);
KDAB_SET_OBJECT_NAME(createdLW);
KDAB_SET_OBJECT_NAME(errorsLB);
KDAB_SET_OBJECT_NAME(errorsLW);
KDAB_SET_OBJECT_NAME(buttonBox);
KDAB_SET_OBJECT_NAME(vlay);
createdLW.addItems(created);
QRect r;
for (int i = 0; i < created.size(); ++i) {
r = r.united(createdLW.visualRect(createdLW.model()->index(0, i)));
}
createdLW.setMinimumWidth(qMin(1024, r.width() + 4 * createdLW.frameWidth()));
errorsLW.addItems(errors);
vlay.addWidget(&createdLB);
vlay.addWidget(&createdLW, 1);
vlay.addWidget(&errorsLB);
vlay.addWidget(&errorsLW, 1);
vlay.addWidget(&buttonBox);
if (created.empty()) {
createdLW.hide();
}
if (errors.empty()) {
errorsLW.hide();
}
connect(&buttonBox, &QDialogButtonBox::accepted, this, &ResultDialog::accept);
connect(&buttonBox, &QDialogButtonBox::rejected, this, &ResultDialog::reject);
readConfig();
}
~ResultDialog()
{
writeConfig();
}
void readConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "ResultDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "ResultDialog");
const QSize size = dialog.readEntry("Size", QSize(600, 400));
if (size.isValid()) {
resize(size);
}
}
void writeConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "ResultDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "ResultDialog");
dialog.writeEntry("Size", size());
dialog.sync();
}
private:
QLabel createdLB;
QListWidget createdLW;
QLabel errorsLB;
QListWidget errorsLW;
QDialogButtonBox buttonBox;
QVBoxLayout vlay;
};
}
#ifdef Q_OS_UNIX
static const bool HAVE_UNIX = true;
#else
static const bool HAVE_UNIX = false;
#endif
static const Qt::CaseSensitivity fs_cs = HAVE_UNIX ? Qt::CaseSensitive : Qt::CaseInsensitive; // can we use QAbstractFileEngine::caseSensitive()?
static QStringList fs_sort(QStringList l)
{
std::sort(l.begin(), l.end(), [](const QString &lhs, const QString &rhs) {
return QString::compare(lhs, rhs, fs_cs) < 0;
});
return l;
}
static QStringList fs_intersect(QStringList l1, QStringList l2)
{
fs_sort(l1);
fs_sort(l2);
QStringList result;
std::set_intersection(l1.begin(), l1.end(),
l2.begin(), l2.end(),
std::back_inserter(result),
[](const QString &lhs, const QString &rhs) {
return QString::compare(lhs, rhs, fs_cs) < 0;
});
return result;
}
static QList<QRegExp> get_patterns(const std::vector< std::shared_ptr<ChecksumDefinition> > &checksumDefinitions)
{
QList<QRegExp> result;
for (const std::shared_ptr<ChecksumDefinition> &cd : checksumDefinitions)
if (cd) {
const auto patterns = cd->patterns();
for (const QString &pattern : patterns) {
result.push_back(QRegExp(pattern, fs_cs));
}
}
return result;
}
namespace
{
struct matches_any : std::unary_function<QString, bool> {
const QList<QRegExp> m_regexps;
explicit matches_any(const QList<QRegExp> &regexps) : m_regexps(regexps) {}
bool operator()(const QString &s) const
{
return std::any_of(m_regexps.cbegin(), m_regexps.cend(),
[s](const QRegExp &rx) { return rx.exactMatch(s); });
}
};
}
class CreateChecksumsController::Private : public QThread
{
Q_OBJECT
friend class ::Kleo::Crypto::CreateChecksumsController;
CreateChecksumsController *const q;
public:
explicit Private(CreateChecksumsController *qq);
~Private() override;
Q_SIGNALS:
void progress(int, int, const QString &);
private:
void slotOperationFinished()
{
#ifndef QT_NO_PROGRESSDIALOG
if (progressDialog) {
progressDialog->setValue(progressDialog->maximum());
progressDialog->close();
}
#endif // QT_NO_PROGRESSDIALOG
ResultDialog *const dlg = new ResultDialog(created, errors);
dlg->setAttribute(Qt::WA_DeleteOnClose);
q->bringToForeground(dlg);
if (!errors.empty())
q->setLastError(gpg_error(GPG_ERR_GENERAL),
errors.join(QLatin1Char('\n')));
q->emitDoneOrError();
}
void slotProgress(int current, int total, const QString &what)
{
qCDebug(KLEOPATRA_LOG) << "progress: " << current << "/" << total << ": " << qPrintable(what);
#ifndef QT_NO_PROGRESSDIALOG
if (!progressDialog) {
return;
}
progressDialog->setMaximum(total);
progressDialog->setValue(current);
progressDialog->setLabelText(what);
#endif // QT_NO_PROGRESSDIALOG
}
private:
void run() override;
private:
#ifndef QT_NO_PROGRESSDIALOG
QPointer<QProgressDialog> progressDialog;
#endif
mutable QMutex mutex;
const std::vector< std::shared_ptr<ChecksumDefinition> > checksumDefinitions;
std::shared_ptr<ChecksumDefinition> checksumDefinition;
QStringList files;
QStringList errors, created;
bool allowAddition;
volatile bool canceled;
};
CreateChecksumsController::Private::Private(CreateChecksumsController *qq)
: q(qq),
#ifndef QT_NO_PROGRESSDIALOG
progressDialog(),
#endif
mutex(),
checksumDefinitions(ChecksumDefinition::getChecksumDefinitions()),
checksumDefinition(ChecksumDefinition::getDefaultChecksumDefinition(checksumDefinitions)),
files(),
errors(),
created(),
allowAddition(false),
canceled(false)
{
connect(this, SIGNAL(progress(int,int,QString)),
q, SLOT(slotProgress(int,int,QString)));
connect(this, &Private::progress,
q, &Controller::progress);
connect(this, SIGNAL(finished()),
q, SLOT(slotOperationFinished()));
}
CreateChecksumsController::Private::~Private()
{
qCDebug(KLEOPATRA_LOG);
}
CreateChecksumsController::CreateChecksumsController(QObject *p)
: Controller(p), d(new Private(this))
{
}
CreateChecksumsController::CreateChecksumsController(const std::shared_ptr<const ExecutionContext> &ctx, QObject *p)
: Controller(ctx, p), d(new Private(this))
{
}
CreateChecksumsController::~CreateChecksumsController()
{
qCDebug(KLEOPATRA_LOG);
}
void CreateChecksumsController::setFiles(const QStringList &files)
{
kleo_assert(!d->isRunning());
kleo_assert(!files.empty());
const QList<QRegExp> patterns = get_patterns(d->checksumDefinitions);
if (!std::all_of(files.cbegin(), files.cend(), matches_any(patterns)) &&
!std::none_of(files.cbegin(), files.cend(), matches_any(patterns))) {
throw Exception(gpg_error(GPG_ERR_INV_ARG), i18n("Create Checksums: input files must be either all checksum files or all files to be checksummed, not a mixture of both."));
}
const QMutexLocker locker(&d->mutex);
d->files = files;
}
void CreateChecksumsController::setAllowAddition(bool allow)
{
kleo_assert(!d->isRunning());
const QMutexLocker locker(&d->mutex);
d->allowAddition = allow;
}
bool CreateChecksumsController::allowAddition() const
{
const QMutexLocker locker(&d->mutex);
return d->allowAddition;
}
void CreateChecksumsController::start()
{
{
const QMutexLocker locker(&d->mutex);
#ifndef QT_NO_PROGRESSDIALOG
d->progressDialog = new QProgressDialog(i18n("Initializing..."), i18n("Cancel"), 0, 0);
applyWindowID(d->progressDialog);
d->progressDialog->setAttribute(Qt::WA_DeleteOnClose);
d->progressDialog->setMinimumDuration(1000);
d->progressDialog->setWindowTitle(i18nc("@title:window", "Create Checksum Progress"));
connect(d->progressDialog.data(), &QProgressDialog::canceled, this, &CreateChecksumsController::cancel);
#endif // QT_NO_PROGRESSDIALOG
d->canceled = false;
d->errors.clear();
d->created.clear();
}
d->start();
}
void CreateChecksumsController::cancel()
{
qCDebug(KLEOPATRA_LOG);
const QMutexLocker locker(&d->mutex);
d->canceled = true;
}
namespace
{
struct Dir {
QDir dir;
QString sumFile;
QStringList inputFiles;
quint64 totalSize;
std::shared_ptr<ChecksumDefinition> checksumDefinition;
};
}
static QStringList remove_checksum_files(QStringList l, const QList<QRegExp> &rxs)
{
QStringList::iterator end = l.end();
for (const QRegExp &rx : rxs) {
end = std::remove_if(l.begin(), end,
[rx](const QString &str) {
return rx.exactMatch(str);
});
}
l.erase(end, l.end());
return l;
}
namespace
{
struct File {
QString name;
QByteArray checksum;
bool binary;
};
}
static QString decode(const QString &encoded)
{
QString decoded;
decoded.reserve(encoded.size());
bool shift = false;
for (QChar ch : encoded)
if (shift) {
switch (ch.toLatin1()) {
case '\\': decoded += QLatin1Char('\\'); break;
case 'n': decoded += QLatin1Char('\n'); break;
default:
qCDebug(KLEOPATRA_LOG) << "invalid escape sequence" << '\\' << ch << "(interpreted as '" << ch << "')";
decoded += ch;
break;
}
shift = false;
} else {
if (ch == QLatin1Char('\\')) {
shift = true;
} else {
decoded += ch;
}
}
return decoded;
}
static std::vector<File> parse_sum_file(const QString &fileName)
{
std::vector<File> files;
QFile f(fileName);
if (f.open(QIODevice::ReadOnly)) {
QTextStream s(&f);
QRegExp rx(QLatin1String("(\\?)([a-f0-9A-F]+) ([ *])([^\n]+)\n*"));
while (!s.atEnd()) {
const QString line = s.readLine();
if (rx.exactMatch(line)) {
Q_ASSERT(!rx.cap(4).endsWith(QLatin1Char('\n')));
const File file = {
rx.cap(1) == QLatin1String("\\") ? decode(rx.cap(4)) : rx.cap(4),
rx.cap(2).toLatin1(),
rx.cap(3) == QLatin1String("*"),
};
files.push_back(file);
}
}
}
return files;
}
static quint64 aggregate_size(const QDir &dir, const QStringList &files)
{
quint64 n = 0;
for (const QString &file : files) {
n += QFileInfo(dir.absoluteFilePath(file)).size();
}
return n;
}
static std::shared_ptr<ChecksumDefinition> filename2definition(const QString &fileName,
const std::vector< std::shared_ptr<ChecksumDefinition> > &checksumDefinitions)
{
for (const std::shared_ptr<ChecksumDefinition> &cd : checksumDefinitions) {
if (cd) {
const auto patterns = cd->patterns();
for (const QString &pattern : patterns) {
if (QRegExp(pattern, fs_cs).exactMatch(fileName)) {
return cd;
}
}
}
}
return std::shared_ptr<ChecksumDefinition>();
}
static std::vector<Dir> find_dirs_by_sum_files(const QStringList &files, bool allowAddition,
const std::function<void(int)> &progress,
const std::vector< std::shared_ptr<ChecksumDefinition> > &checksumDefinitions)
{
const QList<QRegExp> patterns = get_patterns(checksumDefinitions);
std::vector<Dir> dirs;
dirs.reserve(files.size());
int i = 0;
for (const QString &file : files) {
const QFileInfo fi(file);
const QDir dir = fi.dir();
const QStringList entries = remove_checksum_files(dir.entryList(QDir::Files), patterns);
QStringList inputFiles;
if (allowAddition) {
inputFiles = entries;
} else {
const std::vector<File> parsed = parse_sum_file(fi.absoluteFilePath());
QStringList oldInputFiles;
oldInputFiles.reserve(parsed.size());
std::transform(parsed.cbegin(), parsed.cend(), std::back_inserter(oldInputFiles),
std::mem_fn(&File::name));
inputFiles = fs_intersect(oldInputFiles, entries);
}
const Dir item = {
dir,
fi.fileName(),
inputFiles,
aggregate_size(dir, inputFiles),
filename2definition(fi.fileName(), checksumDefinitions)
};
dirs.push_back(item);
if (progress) {
progress(++i);
}
}
return dirs;
}
namespace
{
struct less_dir : std::binary_function<QDir, QDir, bool> {
bool operator()(const QDir &lhs, const QDir &rhs) const
{
return QString::compare(lhs.absolutePath(), rhs.absolutePath(), fs_cs) < 0;
}
};
}
static std::vector<Dir> find_dirs_by_input_files(const QStringList &files, const std::shared_ptr<ChecksumDefinition> &checksumDefinition, bool allowAddition,
const std::function<void(int)> &progress,
const std::vector< std::shared_ptr<ChecksumDefinition> > &checksumDefinitions)
{
Q_UNUSED(allowAddition)
if (!checksumDefinition) {
return std::vector<Dir>();
}
const QList<QRegExp> patterns = get_patterns(checksumDefinitions);
std::map<QDir, QStringList, less_dir> dirs2files;
// Step 1: sort files by the dir they're contained in:
std::deque<QString> inputs(files.begin(), files.end());
int i = 0;
while (!inputs.empty()) {
const QString file = inputs.front();
inputs.pop_front();
const QFileInfo fi(file);
if (fi.isDir()) {
QDir dir(file);
dirs2files[ dir ] = remove_checksum_files(dir.entryList(QDir::Files), patterns);
const auto entryList = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
std::transform(entryList.cbegin(), entryList.cend(),
std::inserter(inputs, inputs.begin()),
[&dir](const QString &entry) {
return dir.absoluteFilePath(entry);
});
} else {
dirs2files[fi.dir()].push_back(file);
}
if (progress) {
progress(++i);
}
}
// Step 2: convert into vector<Dir>:
std::vector<Dir> dirs;
dirs.reserve(dirs2files.size());
for (std::map<QDir, QStringList, less_dir>::const_iterator it = dirs2files.begin(), end = dirs2files.end(); it != end; ++it) {
const QStringList inputFiles = remove_checksum_files(it->second, patterns);
if (inputFiles.empty()) {
continue;
}
const Dir dir = {
it->first,
checksumDefinition->outputFileName(),
inputFiles,
aggregate_size(it->first, inputFiles),
checksumDefinition
};
dirs.push_back(dir);
if (progress) {
progress(++i);
}
}
return dirs;
}
static QString process(const Dir &dir, bool *fatal)
{
const QString absFilePath = dir.dir.absoluteFilePath(dir.sumFile);
QTemporaryFile out;
QProcess p;
if (!out.open()) {
return QStringLiteral("Failed to open Temporary file.");
}
p.setWorkingDirectory(dir.dir.absolutePath());
p.setStandardOutputFile(out.fileName());
const QString program = dir.checksumDefinition->createCommand();
dir.checksumDefinition->startCreateCommand(&p, dir.inputFiles);
p.waitForFinished();
qCDebug(KLEOPATRA_LOG) << "[" << &p << "] Exit code " << p.exitCode();
if (p.exitStatus() != QProcess::NormalExit || p.exitCode() != 0) {
if (fatal && p.error() == QProcess::FailedToStart) {
*fatal = true;
}
if (p.error() == QProcess::UnknownError)
return i18n("Error while running %1: %2", program,
QString::fromLocal8Bit(p.readAllStandardError().trimmed().constData()));
else {
return i18n("Failed to execute %1: %2", program, p.errorString());
}
}
QFileInfo fi(absFilePath);
if (!(fi.exists() && !QFile::remove(absFilePath)) && QFile::copy(out.fileName(), absFilePath)) {
return QString();
}
return xi18n("Failed to overwrite <filename>%1</filename>.", dir.sumFile);
}
namespace
{
static QDebug operator<<(QDebug s, const Dir &dir)
{
return s << "Dir(" << dir.dir << "->" << dir.sumFile << "<-(" << dir.totalSize << ')' << dir.inputFiles << ")\n";
}
}
void CreateChecksumsController::Private::run()
{
QMutexLocker locker(&mutex);
const QStringList files = this->files;
const std::vector< std::shared_ptr<ChecksumDefinition> > checksumDefinitions = this->checksumDefinitions;
const std::shared_ptr<ChecksumDefinition> checksumDefinition = this->checksumDefinition;
const bool allowAddition = this->allowAddition;
locker.unlock();
QStringList errors;
QStringList created;
if (!checksumDefinition) {
errors.push_back(i18n("No checksum programs defined."));
locker.relock();
this->errors = errors;
return;
} else {
qCDebug(KLEOPATRA_LOG) << "using checksum-definition" << checksumDefinition->id();
}
//
// Step 1: build a list of work to do (no progress):
//
const QString scanning = i18n("Scanning directories...");
Q_EMIT progress(0, 0, scanning);
const bool haveSumFiles = std::all_of(files.cbegin(), files.cend(), matches_any(get_patterns(checksumDefinitions)));
const auto progressCb = [this, &scanning](int c) { Q_EMIT progress(c, 0, scanning); };
const std::vector<Dir> dirs = haveSumFiles
? find_dirs_by_sum_files(files, allowAddition, progressCb, checksumDefinitions)
: find_dirs_by_input_files(files, checksumDefinition, allowAddition, progressCb, checksumDefinitions);
for (const Dir &dir : dirs) {
qCDebug(KLEOPATRA_LOG) << dir;
}
if (!canceled) {
Q_EMIT progress(0, 0, i18n("Calculating total size..."));
const quint64 total = kdtools::accumulate_transform(dirs.cbegin(), dirs.cend(),
std::mem_fn(&Dir::totalSize),
Q_UINT64_C(0));
if (!canceled) {
//
// Step 2: perform work (with progress reporting):
//
// re-scale 'total' to fit into ints (wish QProgressDialog would use quint64...)
const quint64 factor = total / std::numeric_limits<int>::max() + 1;
quint64 done = 0;
for (const Dir &dir : dirs) {
Q_EMIT progress(done / factor, total / factor,
i18n("Checksumming (%2) in %1", dir.checksumDefinition->label(), dir.dir.path()));
bool fatal = false;
const QString error = process(dir, &fatal);
if (!error.isEmpty()) {
errors.push_back(error);
} else {
created.push_back(dir.dir.absoluteFilePath(dir.sumFile));
}
done += dir.totalSize;
if (fatal || canceled) {
break;
}
}
Q_EMIT progress(done / factor, total / factor, i18n("Done."));
}
}
locker.relock();
this->errors = errors;
this->created = created;
// mutex unlocked by QMutexLocker
}
#include "moc_createchecksumscontroller.cpp"
#include "createchecksumscontroller.moc"
diff --git a/src/crypto/gui/decryptverifyfilesdialog.cpp b/src/crypto/gui/decryptverifyfilesdialog.cpp
index 82d45d44b..7ec5553cd 100644
--- a/src/crypto/gui/decryptverifyfilesdialog.cpp
+++ b/src/crypto/gui/decryptverifyfilesdialog.cpp
@@ -1,244 +1,244 @@
/* crypto/gui/decryptverifyfilesdialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "decryptverifyfilesdialog.h"
#include "kleopatra_debug.h"
#include "crypto/taskcollection.h"
#include "crypto/decryptverifytask.h"
#include "crypto/gui/resultpage.h"
#include "crypto/gui/resultlistwidget.h"
#include <Libkleo/FileNameRequester>
#include <QWindow>
#include <QVBoxLayout>
#include <QProgressBar>
#include <QLabel>
#include <QPushButton>
#include <vector>
#include <KLocalizedString>
#include <KMessageBox>
#include <KConfigGroup>
#include <KSharedConfig>
#include <KWindowConfig>
using namespace Kleo;
using namespace Kleo::Crypto;
using namespace Kleo::Crypto::Gui;
DecryptVerifyFilesDialog::DecryptVerifyFilesDialog(const std::shared_ptr<TaskCollection> &coll, QWidget *parent)
: QDialog(parent), m_tasks(coll), m_buttonBox(new QDialogButtonBox)
{
readConfig();
auto vLay = new QVBoxLayout(this);
auto labels = new QWidget;
auto outputLayout = new QHBoxLayout;
m_outputLocationFNR = new FileNameRequester;
auto outLabel = new QLabel(i18n("&Output folder:"));
outLabel->setBuddy(m_outputLocationFNR);
outputLayout->addWidget(outLabel);
outputLayout->addWidget(m_outputLocationFNR);
m_outputLocationFNR->setFilter(QDir::Dirs);
vLay->addLayout(outputLayout);
m_progressLabelLayout = new QVBoxLayout(labels);
vLay->addWidget(labels);
m_progressBar = new QProgressBar;
vLay->addWidget(m_progressBar);
m_resultList = new ResultListWidget;
vLay->addWidget(m_resultList);
m_tasks = coll;
Q_ASSERT(m_tasks);
m_resultList->setTaskCollection(coll);
connect(m_tasks.get(), &TaskCollection::progress, this, &DecryptVerifyFilesDialog::progress);
connect(m_tasks.get(), &TaskCollection::done, this, &DecryptVerifyFilesDialog::allDone);
connect(m_tasks.get(), &TaskCollection::result, this, &DecryptVerifyFilesDialog::result);
connect(m_tasks.get(), &TaskCollection::started, this, &DecryptVerifyFilesDialog::started);
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(m_buttonBox, &QDialogButtonBox::clicked, this, &DecryptVerifyFilesDialog::btnClicked);
layout()->addWidget(m_buttonBox);
bool hasOutputs = false;
for (const auto &t: coll->tasks()) {
if (!qobject_cast<VerifyDetachedTask *>(t.get())) {
hasOutputs = true;
break;
}
}
if (hasOutputs) {
setWindowTitle(i18nc("@title:window", "Decrypt/Verify Files"));
m_saveButton = QDialogButtonBox::SaveAll;
m_buttonBox->addButton(QDialogButtonBox::Discard);
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &DecryptVerifyFilesDialog::checkAccept);
} else {
outLabel->setVisible(false);
m_outputLocationFNR->setVisible(false);
setWindowTitle(i18nc("@title:window", "Verify Files"));
m_buttonBox->addButton(QDialogButtonBox::Close);
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
}
if (m_saveButton) {
m_buttonBox->addButton(m_saveButton);
m_buttonBox->button(m_saveButton)->setEnabled(false);
}
}
DecryptVerifyFilesDialog::~DecryptVerifyFilesDialog()
{
qCDebug(KLEOPATRA_LOG);
writeConfig();
}
void DecryptVerifyFilesDialog::allDone()
{
qCDebug(KLEOPATRA_LOG) << "All done";
Q_ASSERT(m_tasks);
m_progressBar->setRange(0, 100);
m_progressBar->setValue(100);
for (const auto &i: m_progressLabelByTag.keys()) {
if (!i.isEmpty()) {
m_progressLabelByTag.value(i)->setText(i18n("%1: All operations completed.", i));
} else {
m_progressLabelByTag.value(i)->setText(i18n("All operations completed."));
}
}
if (m_tasks->allTasksHaveErrors()) {
return;
}
if (m_saveButton != QDialogButtonBox::NoButton) {
m_buttonBox->button(m_saveButton)->setEnabled(true);
} else {
m_buttonBox->removeButton(m_buttonBox->button(QDialogButtonBox::Close));
m_buttonBox->addButton(QDialogButtonBox::Ok);
}
}
void DecryptVerifyFilesDialog::started(const std::shared_ptr<Task> &task)
{
Q_ASSERT(task);
const auto tag = task->tag();
auto label = labelForTag(tag);
Q_ASSERT(label);
if (tag.isEmpty()) {
label->setText(i18nc("number, operation description", "Operation %1: %2", m_tasks->numberOfCompletedTasks() + 1, task->label()));
} else {
label->setText(i18nc("tag( \"OpenPGP\" or \"CMS\"), operation description", "%1: %2", tag, task->label()));
}
if (m_saveButton != QDialogButtonBox::NoButton) {
m_buttonBox->button(m_saveButton)->setEnabled(false);
} else if (m_buttonBox->button(QDialogButtonBox::Ok)) {
m_buttonBox->removeButton(m_buttonBox->button(QDialogButtonBox::Ok));
m_buttonBox->addButton(QDialogButtonBox::Close);
}
}
QLabel *DecryptVerifyFilesDialog::labelForTag(const QString &tag)
{
if (QLabel *const label = m_progressLabelByTag.value(tag)) {
return label;
}
auto label = new QLabel;
label->setTextFormat(Qt::RichText);
label->setWordWrap(true);
m_progressLabelLayout->addWidget(label);
m_progressLabelByTag.insert(tag, label);
return label;
}
void DecryptVerifyFilesDialog::progress(const QString &msg, int progress, int total)
{
Q_UNUSED(msg)
Q_ASSERT(progress >= 0);
Q_ASSERT(total >= 0);
m_progressBar->setRange(0, total);
m_progressBar->setValue(progress);
}
void DecryptVerifyFilesDialog::setOutputLocation(const QString &dir)
{
m_outputLocationFNR->setFileName(dir);
}
QString DecryptVerifyFilesDialog::outputLocation() const
{
return m_outputLocationFNR->fileName();
}
void DecryptVerifyFilesDialog::btnClicked(QAbstractButton *btn)
{
if (m_buttonBox->buttonRole(btn) == QDialogButtonBox::DestructiveRole) {
close();
}
}
void DecryptVerifyFilesDialog::checkAccept() {
const auto outLoc = outputLocation();
if (outLoc.isEmpty()) {
KMessageBox::information(this, i18n("Please select an output folder."),
i18n("No output folder."));
return;
}
const QFileInfo fi(outLoc);
if (fi.exists() && fi.isDir() && fi.isWritable()) {
accept();
return;
}
if (!fi.exists()) {
qCDebug(KLEOPATRA_LOG) << "Output dir does not exist. Trying to create.";
const QDir dir(outLoc);
if (!dir.mkdir(outLoc)) {
KMessageBox::information(this, i18n("Please select a different output folder."),
i18n("Failed to create output folder."));
return;
} else {
accept();
return;
}
}
KMessageBox::information(this, i18n("Please select a different output folder."),
i18n("Invalid output folder."));
}
void DecryptVerifyFilesDialog::readConfig()
{
winId(); // ensure there's a window created
// set default window size
windowHandle()->resize(640, 480);
// restore size from config file
- KConfigGroup cfgGroup(KSharedConfig::openConfig(), "DecryptVerifyFilesDialog");
+ KConfigGroup cfgGroup(KSharedConfig::openStateConfig(), "DecryptVerifyFilesDialog");
KWindowConfig::restoreWindowSize(windowHandle(), cfgGroup);
// NOTICE: QWindow::setGeometry() does NOT impact the backing QWidget geometry even if the platform
// window was created -> QTBUG-40584. We therefore copy the size here.
// TODO: remove once this was resolved in QWidget QPA
resize(windowHandle()->size());
}
void DecryptVerifyFilesDialog::writeConfig()
{
- KConfigGroup cfgGroup(KSharedConfig::openConfig(), "DecryptVerifyFilesDialog");
+ KConfigGroup cfgGroup(KSharedConfig::openStateConfig(), "DecryptVerifyFilesDialog");
KWindowConfig::saveWindowSize(windowHandle(), cfgGroup);
cfgGroup.sync();
}
diff --git a/src/dialogs/certificatedetailswidget.cpp b/src/dialogs/certificatedetailswidget.cpp
index 97511ce5a..0aca3f4a0 100644
--- a/src/dialogs/certificatedetailswidget.cpp
+++ b/src/dialogs/certificatedetailswidget.cpp
@@ -1,678 +1,678 @@
/* SPDX-FileCopyrightText: 2016 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2017 Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "certificatedetailswidget.h"
#include "ui_certificatedetailswidget.h"
#include "kleopatra_debug.h"
#include "exportdialog.h"
#include "trustchainwidget.h"
#include "subkeyswidget.h"
#include "weboftrustdialog.h"
#include "commands/changepassphrasecommand.h"
#include "commands/changeexpirycommand.h"
#include "commands/certifycertificatecommand.h"
#include "commands/revokecertificationcommand.h"
#include "commands/adduseridcommand.h"
#include "commands/genrevokecommand.h"
#include "commands/detailscommand.h"
#include "commands/dumpcertificatecommand.h"
#include "utils/tags.h"
#include <Libkleo/Formatting>
#include <Libkleo/Dn>
#include <Libkleo/KeyCache>
#include <gpgme++/context.h>
#include <gpgme++/key.h>
#include <gpgme++/keylistresult.h>
#include <gpgme++/tofuinfo.h>
#include <QGpgME/Protocol>
#include <QGpgME/KeyListJob>
#include <QDateTime>
#include <QDialogButtonBox>
#include <QMenu>
#include <KConfigGroup>
#include <KSharedConfig>
#include <QLocale>
#include <gpgme++/gpgmepp_version.h>
#if GPGMEPP_VERSION >= 0x10E00 // 1.14.0
# define GPGME_HAS_REMARKS
#endif
#if GPGMEPP_VERSION >= 0x10F00 // 1.15.0
# define GPGME_HAS_WITH_SECRET
# include <QGpgME/Debug>
#endif
#define HIDE_ROW(row) \
ui.row->setVisible(false); \
ui.row##Lbl->setVisible(false);
Q_DECLARE_METATYPE(GpgME::UserID)
using namespace Kleo;
class CertificateDetailsWidget::Private
{
public:
Private(CertificateDetailsWidget *parent)
: updateInProgress (false), q(parent)
{}
void setupCommonProperties();
void setupPGPProperties();
void setupSMIMEProperties();
void revokeUID(const GpgME::UserID &uid);
void genRevokeCert();
void certifyClicked();
void webOfTrustClicked();
void exportClicked();
void addUserID();
void changePassphrase();
void changeExpiration();
void keysMayHaveChanged();
void showTrustChainDialog();
void showMoreDetails();
void publishCertificate();
void userIDTableContextMenuRequested(const QPoint &p);
QString tofuTooltipString(const GpgME::UserID &uid) const;
void smimeLinkActivated(const QString &link);
void setUpdatedKey(const GpgME::Key &key);
void keyListDone(const GpgME::KeyListResult &,
const std::vector<GpgME::Key> &, const QString &,
const GpgME::Error &);
Ui::CertificateDetailsWidget ui;
GpgME::Key key;
bool updateInProgress;
private:
CertificateDetailsWidget *const q;
};
void CertificateDetailsWidget::Private::setupCommonProperties()
{
// TODO: Enable once implemented
HIDE_ROW(publishing)
const bool hasSecret = key.hasSecret();
const bool isOpenPGP = key.protocol() == GpgME::OpenPGP;
// TODO: Enable once implemented
const bool canRevokeUID = false; // isOpenPGP && hasSecret
ui.changePassphraseBtn->setVisible(hasSecret);
ui.genRevokeBtn->setVisible(isOpenPGP && hasSecret);
ui.certifyBtn->setVisible(isOpenPGP && !hasSecret);
ui.changeExpirationBtn->setVisible(isOpenPGP && hasSecret);
ui.addUserIDBtn->setVisible(hasSecret && isOpenPGP);
ui.webOfTrustBtn->setVisible(isOpenPGP);
ui.hboxLayout_1->addStretch(1);
ui.validFrom->setText(Kleo::Formatting::creationDateString(key));
const QString expiry = Kleo::Formatting::expirationDateString(key);
ui.expires->setText(expiry.isEmpty() ? i18nc("Expires", "never") : expiry);
ui.type->setText(Kleo::Formatting::type(key));
ui.fingerprint->setText(Formatting::prettyID(key.primaryFingerprint()));
if (Kleo::Formatting::complianceMode().isEmpty()) {
HIDE_ROW(compliance)
} else {
ui.complianceLbl->setText(Kleo::Formatting::complianceStringForKey(key));
}
ui.userIDTable->clear();
QStringList headers = { i18n("Email"), i18n("Name"), i18n("Trust Level"), i18n("Tags") };
if (canRevokeUID) {
headers << QString();
}
ui.userIDTable->setColumnCount(headers.count());
ui.userIDTable->setColumnWidth(0, 200);
ui.userIDTable->setColumnWidth(1, 200);
ui.userIDTable->setHeaderLabels(headers);
const auto uids = key.userIDs();
for (unsigned int i = 0; i < uids.size(); ++i) {
const auto &uid = uids[i];
auto item = new QTreeWidgetItem;
const QString toolTip = tofuTooltipString(uid);
item->setData(0, Qt::UserRole, QVariant::fromValue(uid));
auto pMail = Kleo::Formatting::prettyEMail(uid);
auto pName = Kleo::Formatting::prettyName(uid);
if (!isOpenPGP && pMail.isEmpty() && !pName.isEmpty()) {
// S/MIME UserIDs are sometimes split, with one userID
// containing the name another the Mail, we merge these
// UID's into a single item.
if (i + 1 < uids.size()) {
pMail = Kleo::Formatting::prettyEMail(uids[i + 1]);
// skip next uid
++i;
}
}
if (!isOpenPGP && pMail.isEmpty() && pName.isEmpty()) {
// S/MIME certificates sometimes contain urls where both
// name and mail is empty. In that case we print whatever
// the uid is as name.
//
// Can be ugly like (3:uri24:http://ca.intevation.org), but
// this is better then showing an empty entry.
pName = QString::fromLatin1(uid.id());
}
item->setData(0, Qt::DisplayRole, pMail);
item->setData(0, Qt::ToolTipRole, toolTip);
item->setData(1, Qt::DisplayRole, pName);
item->setData(1, Qt::ToolTipRole, toolTip);
QIcon trustIcon;
if (updateInProgress) {
trustIcon = QIcon::fromTheme(QStringLiteral("emblem-question"));
item->setData(2, Qt::DisplayRole, i18n("Updating..."));
} else {
switch (uid.validity()) {
case GpgME::UserID::Unknown:
case GpgME::UserID::Undefined:
trustIcon = QIcon::fromTheme(QStringLiteral("emblem-question"));
break;
case GpgME::UserID::Never:
trustIcon = QIcon::fromTheme(QStringLiteral("emblem-error"));
break;
case GpgME::UserID::Marginal:
trustIcon = QIcon::fromTheme(QStringLiteral("emblem-warning"));
break;
case GpgME::UserID::Full:
case GpgME::UserID::Ultimate:
trustIcon = QIcon::fromTheme(QStringLiteral("emblem-success"));
break;
}
item->setData(2, Qt::DisplayRole, Kleo::Formatting::validityShort(uid));
}
item->setData(2, Qt::DecorationRole, trustIcon);
item->setData(2, Qt::ToolTipRole, toolTip);
GpgME::Error err;
QStringList tagList;
#ifdef GPGME_HAS_REMARKS
for (const auto &tag: uid.remarks(Tags::tagKeys(), err)) {
if (err) {
qCWarning(KLEOPATRA_LOG) << "Getting remarks for user id" << uid.id() << "failed:" << err;
}
tagList << QString::fromStdString(tag);
}
qCDebug(KLEOPATRA_LOG) << "tagList:" << tagList;
#endif
const auto tags = tagList.join(QStringLiteral("; "));
item->setData(3, Qt::DisplayRole, tags);
item->setData(3, Qt::ToolTipRole, toolTip);
ui.userIDTable->addTopLevelItem(item);
if (canRevokeUID) {
auto button = new QPushButton;
button->setIcon(QIcon::fromTheme(QStringLiteral("entry-delete")));
button->setToolTip(i18n("Revoke this User ID"));
button->setMaximumWidth(32);
QObject::connect(button, &QPushButton::clicked,
q, [this, uid]() { revokeUID(uid); });
ui.userIDTable->setItemWidget(item, 4, button);
}
}
if (!Tags::tagsEnabled()) {
ui.userIDTable->hideColumn(3);
}
}
void CertificateDetailsWidget::Private::revokeUID(const GpgME::UserID &uid)
{
Q_UNUSED(uid)
qCWarning(KLEOPATRA_LOG) << "Revoking UserID is not implemented. How did you even get here?!?!";
}
void CertificateDetailsWidget::Private::changeExpiration()
{
auto cmd = new Kleo::Commands::ChangeExpiryCommand(key);
QObject::connect(cmd, &Kleo::Commands::ChangeExpiryCommand::finished,
q, [this]() {
ui.changeExpirationBtn->setEnabled(true);
});
ui.changeExpirationBtn->setEnabled(false);
cmd->start();
}
void CertificateDetailsWidget::Private::changePassphrase()
{
auto cmd = new Kleo::Commands::ChangePassphraseCommand(key);
QObject::connect(cmd, &Kleo::Commands::ChangePassphraseCommand::finished,
q, [this]() {
ui.changePassphraseBtn->setEnabled(true);
});
ui.changePassphraseBtn->setEnabled(false);
cmd->start();
}
void CertificateDetailsWidget::Private::genRevokeCert()
{
auto cmd = new Kleo::Commands::GenRevokeCommand(key);
QObject::connect(cmd, &Kleo::Commands::GenRevokeCommand::finished,
q, [this]() {
ui.genRevokeBtn->setEnabled(true);
});
ui.genRevokeBtn->setEnabled(false);
cmd->start();
}
void CertificateDetailsWidget::Private::certifyClicked()
{
auto cmd = new Kleo::Commands::CertifyCertificateCommand(key);
QObject::connect(cmd, &Kleo::Commands::CertifyCertificateCommand::finished,
q, [this]() {
ui.certifyBtn->setEnabled(true);
});
ui.certifyBtn->setEnabled(false);
cmd->start();
}
void CertificateDetailsWidget::Private::webOfTrustClicked()
{
QScopedPointer<WebOfTrustDialog> dlg(new WebOfTrustDialog(q));
dlg->setKey(key);
dlg->exec();
}
void CertificateDetailsWidget::Private::exportClicked()
{
QScopedPointer<ExportDialog> dlg(new ExportDialog(q));
dlg->setKey(key);
dlg->exec();
}
void CertificateDetailsWidget::Private::addUserID()
{
auto cmd = new Kleo::Commands::AddUserIDCommand(key);
QObject::connect(cmd, &Kleo::Commands::AddUserIDCommand::finished,
q, [this]() {
ui.addUserIDBtn->setEnabled(true);
key.update();
q->setKey(key);
});
ui.addUserIDBtn->setEnabled(false);
cmd->start();
}
void CertificateDetailsWidget::Private::keysMayHaveChanged()
{
auto newKey = Kleo::KeyCache::instance()->findByFingerprint(key.primaryFingerprint());
if (!newKey.isNull()) {
setUpdatedKey(newKey);
}
}
void CertificateDetailsWidget::Private::showTrustChainDialog()
{
QScopedPointer<TrustChainDialog> dlg(new TrustChainDialog(q));
dlg->setKey(key);
dlg->exec();
}
void CertificateDetailsWidget::Private::publishCertificate()
{
qCWarning(KLEOPATRA_LOG) << "publishCertificateis not implemented.";
//TODO
}
void CertificateDetailsWidget::Private::userIDTableContextMenuRequested(const QPoint &p)
{
auto item = ui.userIDTable->itemAt(p);
if (!item) {
return;
}
const auto userID = item->data(0, Qt::UserRole).value<GpgME::UserID>();
QMenu *menu = new QMenu(q);
menu->addAction(QIcon::fromTheme(QStringLiteral("view-certificate-sign")),
i18n("Certify..."),
q, [this, userID]() {
auto cmd = new Kleo::Commands::CertifyCertificateCommand(userID);
ui.userIDTable->setEnabled(false);
connect(cmd, &Kleo::Commands::CertifyCertificateCommand::finished,
q, [this]() {
ui.userIDTable->setEnabled(true);
// Trigger an update when done
q->setKey(key);
});
cmd->start();
});
if (Kleo::Commands::RevokeCertificationCommand::isSupported()) {
menu->addAction(QIcon::fromTheme(QStringLiteral("view-certificate-revoke")),
i18n("Revoke Certification..."),
q, [this, userID]() {
auto cmd = new Kleo::Commands::RevokeCertificationCommand(userID);
ui.userIDTable->setEnabled(false);
connect(cmd, &Kleo::Commands::RevokeCertificationCommand::finished,
q, [this]() {
ui.userIDTable->setEnabled(true);
// Trigger an update when done
q->setKey(key);
});
cmd->start();
});
}
connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater);
menu->popup(ui.userIDTable->viewport()->mapToGlobal(p));
}
void CertificateDetailsWidget::Private::showMoreDetails()
{
ui.moreDetailsBtn->setEnabled(false);
if (key.protocol() == GpgME::CMS) {
auto cmd = new Kleo::Commands::DumpCertificateCommand(key);
connect(cmd, &Kleo::Commands::DumpCertificateCommand::finished,
q, [this]() {
ui.moreDetailsBtn->setEnabled(true);
});
cmd->setUseDialog(true);
cmd->start();
} else {
QScopedPointer<SubKeysDialog> dlg(new SubKeysDialog(q));
dlg->setKey(key);
dlg->exec();
ui.moreDetailsBtn->setEnabled(true);
}
}
QString CertificateDetailsWidget::Private::tofuTooltipString(const GpgME::UserID &uid) const
{
const auto tofu = uid.tofuInfo();
if (tofu.isNull()) {
return QString();
}
QString html = QStringLiteral("<table border=\"0\" cell-padding=\"5\">");
const auto appendRow = [&html](const QString &lbl, const QString &val) {
html += QStringLiteral("<tr>"
"<th style=\"text-align: right; padding-right: 5px; white-space: nowrap;\">%1:</th>"
"<td style=\"white-space: nowrap;\">%2</td>"
"</tr>")
.arg(lbl, val);
};
const auto appendHeader = [this, &html](const QString &hdr) {
html += QStringLiteral("<tr><th colspan=\"2\" style=\"background-color: %1; color: %2\">%3</th></tr>")
.arg(q->palette().highlight().color().name(),
q->palette().highlightedText().color().name(),
hdr);
};
const auto dateTime = [](long ts) {
QLocale l;
return ts == 0 ? i18n("never") : l.toString(QDateTime::fromSecsSinceEpoch(ts), QLocale::ShortFormat);
};
appendHeader(i18n("Signing"));
appendRow(i18n("First message"), dateTime(tofu.signFirst()));
appendRow(i18n("Last message"), dateTime(tofu.signLast()));
appendRow(i18n("Message count"), QString::number(tofu.signCount()));
appendHeader(i18n("Encryption"));
appendRow(i18n("First message"), dateTime(tofu.encrFirst()));
appendRow(i18n("Last message"), dateTime(tofu.encrLast()));
appendRow(i18n("Message count"), QString::number(tofu.encrCount()));
html += QStringLiteral("</table>");
// Make sure the tooltip string is different for each UserID, even if the
// data are the same, otherwise the tooltip is not updated and moved when
// user moves mouse from one row to another.
html += QStringLiteral("<!-- %1 //-->").arg(QString::fromUtf8(uid.id()));
return html;
}
void CertificateDetailsWidget::Private::setupPGPProperties()
{
HIDE_ROW(smimeOwner)
HIDE_ROW(smimeIssuer)
ui.smimeRelatedAddresses->setVisible(false);
ui.trustChainDetailsBtn->setVisible(false);
ui.userIDTable->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui.userIDTable, &QAbstractItemView::customContextMenuRequested,
q, [this](const QPoint &p) { userIDTableContextMenuRequested(p); });
}
static QString formatDNToolTip(const Kleo::DN &dn)
{
QString html = QStringLiteral("<table border=\"0\" cell-spacing=15>");
const auto appendRow = [&html, dn](const QString &lbl, const QString &attr) {
const QString val = dn[attr];
if (!val.isEmpty()) {
html += QStringLiteral(
"<tr><th style=\"text-align: left; white-space: nowrap\">%1:</th>"
"<td style=\"white-space: nowrap\">%2</td>"
"</tr>").arg(lbl, val);
}
};
appendRow(i18n("Common Name"), QStringLiteral("CN"));
appendRow(i18n("Organization"), QStringLiteral("O"));
appendRow(i18n("Street"), QStringLiteral("STREET"));
appendRow(i18n("City"), QStringLiteral("L"));
appendRow(i18n("State"), QStringLiteral("ST"));
appendRow(i18n("Country"), QStringLiteral("C"));
html += QStringLiteral("</table>");
return html;
}
void CertificateDetailsWidget::Private::setupSMIMEProperties()
{
HIDE_ROW(publishing)
const auto ownerId = key.userID(0);
const Kleo::DN dn(ownerId.id());
const QString cn = dn[QStringLiteral("CN")];
const QString o = dn[QStringLiteral("O")];
const QString dnEmail = dn[QStringLiteral("EMAIL")];
const QString name = cn.isEmpty() ? dnEmail : cn;
QString owner;
if (name.isEmpty()) {
owner = dn.dn();
} else if (o.isEmpty()) {
owner = name;
} else {
owner = i18nc("<name> of <company>", "%1 of %2", name, o);
}
ui.smimeOwner->setText(owner);
ui.smimeOwner->setTextInteractionFlags(Qt::TextBrowserInteraction);
const Kleo::DN issuerDN(key.issuerName());
const QString issuerCN = issuerDN[QStringLiteral("CN")];
const QString issuer = issuerCN.isEmpty() ? QString::fromUtf8(key.issuerName()) : issuerCN;
ui.smimeIssuer->setText(QStringLiteral("<a href=\"#issuerDetails\">%1</a>").arg(issuer));
ui.smimeIssuer->setToolTip(formatDNToolTip(issuerDN));
ui.smimeOwner->setToolTip(formatDNToolTip(dn));
}
void CertificateDetailsWidget::Private::smimeLinkActivated(const QString &link)
{
if (link == QLatin1String("#issuerDetails")) {
const auto parentKey = KeyCache::instance()->findIssuers(key, KeyCache::NoOption);
if (!parentKey.size()) {
return;
}
auto cmd = new Kleo::Commands::DetailsCommand(parentKey[0], nullptr);
cmd->setParentWidget(q);
cmd->start();
return;
}
qCWarning(KLEOPATRA_LOG) << "Unknown link activated:" << link;
}
CertificateDetailsWidget::CertificateDetailsWidget(QWidget *parent)
: QWidget(parent)
, d(new Private(this))
{
d->ui.setupUi(this);
connect(d->ui.addUserIDBtn, &QPushButton::clicked,
this, [this]() { d->addUserID(); });
connect(d->ui.changePassphraseBtn, &QPushButton::clicked,
this, [this]() { d->changePassphrase(); });
connect(d->ui.genRevokeBtn, &QPushButton::clicked,
this, [this]() { d->genRevokeCert(); });
connect(d->ui.changeExpirationBtn, &QPushButton::clicked,
this, [this]() { d->changeExpiration(); });
connect(d->ui.smimeOwner, &QLabel::linkActivated,
this, [this](const QString &link) { d->smimeLinkActivated(link); });
connect(d->ui.smimeIssuer, &QLabel::linkActivated,
this, [this](const QString &link) { d->smimeLinkActivated(link); });
connect(d->ui.trustChainDetailsBtn, &QPushButton::pressed,
this, [this]() { d->showTrustChainDialog(); });
connect(d->ui.moreDetailsBtn, &QPushButton::pressed,
this, [this]() { d->showMoreDetails(); });
connect(d->ui.publishing, &QPushButton::pressed,
this, [this]() { d->publishCertificate(); });
connect(d->ui.certifyBtn, &QPushButton::clicked,
this, [this]() { d->certifyClicked(); });
connect(d->ui.webOfTrustBtn, &QPushButton::clicked,
this, [this]() { d->webOfTrustClicked(); });
connect(d->ui.exportBtn, &QPushButton::clicked,
this, [this]() { d->exportClicked(); });
connect(Kleo::KeyCache::instance().get(), &Kleo::KeyCache::keysMayHaveChanged,
this, [this]() { d->keysMayHaveChanged(); });
}
CertificateDetailsWidget::~CertificateDetailsWidget()
{
}
void CertificateDetailsWidget::Private::keyListDone(const GpgME::KeyListResult &,
const std::vector<GpgME::Key> &keys,
const QString &,
const GpgME::Error &) {
updateInProgress = false;
if (keys.size() != 1) {
qCWarning(KLEOPATRA_LOG) << "Invalid keylist result in update.";
return;
}
// As we listen for keysmayhavechanged we get the update
// after updating the keycache.
KeyCache::mutableInstance()->insert(keys);
}
void CertificateDetailsWidget::Private::setUpdatedKey(const GpgME::Key &k)
{
key = k;
setupCommonProperties();
if (key.protocol() == GpgME::OpenPGP) {
setupPGPProperties();
} else {
setupSMIMEProperties();
}
}
void CertificateDetailsWidget::setKey(const GpgME::Key &key)
{
if (key.protocol() == GpgME::CMS) {
// For everything but S/MIME this should be quick
// and we don't need to show another status.
d->updateInProgress = true;
}
d->setUpdatedKey(key);
// Run a keylistjob with full details (TOFU / Validate)
QGpgME::KeyListJob *job = key.protocol() == GpgME::OpenPGP ? QGpgME::openpgp()->keyListJob(false, true, true) :
QGpgME::smime()->keyListJob(false, true, true);
auto ctx = QGpgME::Job::context(job);
ctx->addKeyListMode(GpgME::WithTofu);
ctx->addKeyListMode(GpgME::SignatureNotations);
#ifdef GPGME_HAS_WITH_SECRET
if (key.hasSecret()) {
ctx->addKeyListMode(GpgME::WithSecret);
}
#endif
// Windows QGpgME new style connect problem makes this necessary.
connect(job, SIGNAL(result(GpgME::KeyListResult,std::vector<GpgME::Key>,QString,GpgME::Error)),
this, SLOT(keyListDone(GpgME::KeyListResult,std::vector<GpgME::Key>,QString,GpgME::Error)));
#ifdef GPGME_HAS_WITH_SECRET
job->start(QStringList() << QLatin1String(key.primaryFingerprint()));
#else
job->start(QStringList() << QLatin1String(key.primaryFingerprint()), key.hasSecret());
#endif
}
GpgME::Key CertificateDetailsWidget::key() const
{
return d->key;
}
CertificateDetailsDialog::CertificateDetailsDialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(i18nc("@title:window", "Certificate Details"));
auto l = new QVBoxLayout(this);
l->addWidget(new CertificateDetailsWidget(this));
auto bbox = new QDialogButtonBox(this);
auto btn = bbox->addButton(QDialogButtonBox::Close);
connect(btn, &QPushButton::pressed, this, &QDialog::accept);
l->addWidget(bbox);
readConfig();
}
CertificateDetailsDialog::~CertificateDetailsDialog()
{
writeConfig();
}
void CertificateDetailsDialog::readConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "CertificateDetailsDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "CertificateDetailsDialog");
const QSize size = dialog.readEntry("Size", QSize(730, 280));
if (size.isValid()) {
resize(size);
}
}
void CertificateDetailsDialog::writeConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "CertificateDetailsDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "CertificateDetailsDialog");
dialog.writeEntry("Size", size());
dialog.sync();
}
void CertificateDetailsDialog::setKey(const GpgME::Key &key)
{
auto w = findChild<CertificateDetailsWidget*>();
Q_ASSERT(w);
w->setKey(key);
}
GpgME::Key CertificateDetailsDialog::key() const
{
auto w = findChild<CertificateDetailsWidget*>();
Q_ASSERT(w);
return w->key();
}
#include "moc_certificatedetailswidget.cpp"
diff --git a/src/dialogs/certifycertificatedialog.cpp b/src/dialogs/certifycertificatedialog.cpp
index cbb0d8001..142891109 100644
--- a/src/dialogs/certifycertificatedialog.cpp
+++ b/src/dialogs/certifycertificatedialog.cpp
@@ -1,150 +1,150 @@
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/signcertificatedialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2019 g10code GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "kleopatra_debug.h"
#include "certifycertificatedialog.h"
#include "certifywidget.h"
#include <Libkleo/Formatting>
#include <Libkleo/Stl_Util>
#include <KLocalizedString>
#include <KStandardGuiItem>
#include <KSharedConfig>
#include <KConfigGroup>
#include <KMessageBox>
#include <QVBoxLayout>
#include <QDialogButtonBox>
#include <QPushButton>
#include <gpg-error.h>
using namespace GpgME;
using namespace Kleo;
CertifyCertificateDialog::CertifyCertificateDialog(QWidget *p, Qt::WindowFlags f)
: QDialog(p, f)
{
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
// Setup GUI
auto mainLay = new QVBoxLayout(this);
mCertWidget = new CertifyWidget(this);
mainLay->addWidget(mCertWidget);
QDialogButtonBox *buttonBox = new QDialogButtonBox();
buttonBox->setStandardButtons(QDialogButtonBox::Cancel |
QDialogButtonBox::Ok);
KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("Certify"));
connect(buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked,
this, [this] () {
KConfigGroup conf(KSharedConfig::openConfig(), "CertifySettings");
const auto lastKey = mCertWidget->secKey();
// Do not accept if the keys are the same.
if (!lastKey.isNull() && !mCertWidget->target().isNull() &&
!strcmp(lastKey.primaryFingerprint(),
mCertWidget->target().primaryFingerprint())) {
KMessageBox::error(this, i18n("You cannot certify using the same key."),
i18n("Invalid Selection"), KMessageBox::Notify);
return;
}
if (!lastKey.isNull()) {
conf.writeEntry("LastKey", lastKey.primaryFingerprint());
}
conf.writeEntry("ExportCheckState", mCertWidget->exportableSelected());
conf.writeEntry("PublishCheckState", mCertWidget->publishSelected());
accept();
});
connect(buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked,
this, [this] () {
close();
});
mainLay->addWidget(buttonBox);
- KConfigGroup cfgGroup(KSharedConfig::openConfig(), "CertifyDialog");
+ KConfigGroup cfgGroup(KSharedConfig::openStateConfig(), "CertifyDialog");
const QByteArray geom = cfgGroup.readEntry("geometry", QByteArray());
if (!geom.isEmpty()) {
restoreGeometry(geom);
return;
}
resize(QSize(640, 480));
}
CertifyCertificateDialog::~CertifyCertificateDialog()
{
- KConfigGroup cfgGroup(KSharedConfig::openConfig(), "CertifyDialog");
+ KConfigGroup cfgGroup(KSharedConfig::openStateConfig(), "CertifyDialog");
cfgGroup.writeEntry("geometry", saveGeometry());
cfgGroup.sync();
}
void CertifyCertificateDialog::setCertificateToCertify(const Key &key)
{
setWindowTitle(i18nc("@title:window arg is name, email of certificate holder", "Certify Certificate: %1", Formatting::prettyName(key)));
mCertWidget->setTarget(key);
}
bool CertifyCertificateDialog::exportableCertificationSelected() const
{
return mCertWidget->exportableSelected();
}
bool CertifyCertificateDialog::trustCertificationSelected() const
{
return false;
}
bool CertifyCertificateDialog::nonRevocableCertificationSelected() const
{
return false;
}
Key CertifyCertificateDialog::selectedSecretKey() const
{
return mCertWidget->secKey();
}
bool CertifyCertificateDialog::sendToServer() const
{
return mCertWidget->publishSelected();
}
unsigned int CertifyCertificateDialog::selectedCheckLevel() const
{
//PENDING
#ifdef KLEO_SIGN_KEY_CERTLEVEL_SUPPORT
return d->selectCheckLevelPage->checkLevel();
#endif
return 0;
}
void CertifyCertificateDialog::setSelectedUserIDs(const std::vector<UserID> &uids)
{
mCertWidget->selectUserIDs(uids);
}
std::vector<unsigned int> CertifyCertificateDialog::selectedUserIDs() const
{
return mCertWidget->selectedUserIDs();
}
QString CertifyCertificateDialog::tags() const
{
return mCertWidget->tags();
}
diff --git a/src/dialogs/createcsrforcardkeydialog.cpp b/src/dialogs/createcsrforcardkeydialog.cpp
index 41d7087b7..447b573ce 100644
--- a/src/dialogs/createcsrforcardkeydialog.cpp
+++ b/src/dialogs/createcsrforcardkeydialog.cpp
@@ -1,114 +1,114 @@
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/createcsrforcardkeydialog.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2020 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "createcsrforcardkeydialog.h"
#include "certificatedetailsinputwidget.h"
#include <KConfigGroup>
#include <KSharedConfig>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QVBoxLayout>
using namespace Kleo;
using namespace Kleo::Dialogs;
class CreateCSRForCardKeyDialog::Private
{
friend class ::Kleo::Dialogs::CreateCSRForCardKeyDialog;
CreateCSRForCardKeyDialog *const q;
struct {
CertificateDetailsInputWidget *detailsWidget = nullptr;
QDialogButtonBox *buttonBox = nullptr;
} ui;
public:
Private(CreateCSRForCardKeyDialog *qq)
: q(qq)
{
auto mainLayout = new QVBoxLayout(q);
ui.detailsWidget = new CertificateDetailsInputWidget();
connect(ui.detailsWidget, &CertificateDetailsInputWidget::validityChanged,
q, [this] (bool valid) { onValidityChanged(valid); });
ui.buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(ui.buttonBox, &QDialogButtonBox::accepted, q, &QDialog::accept);
connect(ui.buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject);
mainLayout->addWidget(ui.detailsWidget);
mainLayout->addWidget(ui.buttonBox);
// increase default width by 50 % to get more space for line edits
const QSize sizeHint = q->sizeHint();
const QSize defaultSize = QSize(sizeHint.width() * 15 / 10, sizeHint.height());
restoreGeometry(defaultSize);
}
~Private()
{
saveGeometry();
}
void onValidityChanged(bool valid)
{
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid);
}
private:
void saveGeometry()
{
- KConfigGroup cfgGroup(KSharedConfig::openConfig(), "CreateCSRForCardKeyDialog");
+ KConfigGroup cfgGroup(KSharedConfig::openStateConfig(), "CreateCSRForCardKeyDialog");
cfgGroup.writeEntry("Size", q->size());
cfgGroup.sync();
}
void restoreGeometry(const QSize &defaultSize)
{
- KConfigGroup cfgGroup(KSharedConfig::openConfig(), "CreateCSRForCardKeyDialog");
+ KConfigGroup cfgGroup(KSharedConfig::openStateConfig(), "CreateCSRForCardKeyDialog");
const QSize size = cfgGroup.readEntry("Size", defaultSize);
if (size.isValid()) {
q->resize(size);
}
}
};
CreateCSRForCardKeyDialog::CreateCSRForCardKeyDialog(QWidget *parent)
: QDialog(parent)
, d(new Private(this))
{
}
CreateCSRForCardKeyDialog::~CreateCSRForCardKeyDialog()
{
}
void CreateCSRForCardKeyDialog::setName(const QString &name)
{
d->ui.detailsWidget->setName(name);
}
void CreateCSRForCardKeyDialog::setEmail(const QString &email)
{
d->ui.detailsWidget->setEmail(email);
}
QString CreateCSRForCardKeyDialog::email() const
{
return d->ui.detailsWidget->email();
}
QString CreateCSRForCardKeyDialog::dn() const
{
return d->ui.detailsWidget->dn();
}
diff --git a/src/dialogs/deletecertificatesdialog.cpp b/src/dialogs/deletecertificatesdialog.cpp
index b1752e1de..cb9fb5229 100644
--- a/src/dialogs/deletecertificatesdialog.cpp
+++ b/src/dialogs/deletecertificatesdialog.cpp
@@ -1,232 +1,232 @@
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/deletecertificatesdialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "deletecertificatesdialog.h"
#include <view/keytreeview.h>
#include <Libkleo/KeyListModel>
#include <Libkleo/Stl_Util>
#include <KLocalizedString>
#include <KMessageBox>
#include <KStandardGuiItem>
#include "kleopatra_debug.h"
#include <KConfigGroup>
#include <KSharedConfig>
#include <QLabel>
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QWhatsThis>
#include <QCursor>
#include <QPushButton>
#include <QTreeView>
#include <gpgme++/key.h>
using namespace Kleo;
using namespace Kleo::Dialogs;
using namespace GpgME;
class DeleteCertificatesDialog::Private
{
friend class ::Kleo::Dialogs::DeleteCertificatesDialog;
DeleteCertificatesDialog *const q;
public:
explicit Private(DeleteCertificatesDialog *qq)
: q(qq),
ui(q)
{
}
void slotWhatsThisRequested()
{
qCDebug(KLEOPATRA_LOG);
if (QWidget *const widget = qobject_cast<QWidget *>(q->sender()))
if (!widget->whatsThis().isEmpty()) {
QWhatsThis::showText(QCursor::pos(), widget->whatsThis());
}
}
void readConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "DeleteCertificatesDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "DeleteCertificatesDialog");
ui.selectedKTV.restoreLayout(dialog);
ui.unselectedKTV.restoreLayout(dialog);
const QSize size = dialog.readEntry("Size", QSize(600, 400));
if (size.isValid()) {
q->resize(size);
}
}
void writeConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "DeleteCertificatesDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "DeleteCertificatesDialog");
ui.selectedKTV.saveLayout(dialog);
dialog.writeEntry("Size", q->size());
dialog.sync();
}
private:
struct UI {
QLabel selectedLB;
KeyTreeView selectedKTV;
QLabel unselectedLB;
KeyTreeView unselectedKTV;
QDialogButtonBox buttonBox;
QVBoxLayout vlay;
explicit UI(DeleteCertificatesDialog *qq)
: selectedLB(i18n("These are the certificates you have selected for deletion:"), qq),
selectedKTV(qq),
unselectedLB(i18n("These certificates will be deleted even though you did <b>not</b> "
"explicitly select them (<a href=\"whatsthis://\">Why?</a>):"), qq),
unselectedKTV(qq),
buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel),
vlay(qq)
{
KDAB_SET_OBJECT_NAME(selectedLB);
KDAB_SET_OBJECT_NAME(selectedKTV);
KDAB_SET_OBJECT_NAME(unselectedLB);
KDAB_SET_OBJECT_NAME(unselectedKTV);
KDAB_SET_OBJECT_NAME(buttonBox);
KDAB_SET_OBJECT_NAME(vlay);
vlay.addWidget(&selectedLB);
vlay.addWidget(&selectedKTV, 1);
vlay.addWidget(&unselectedLB);
vlay.addWidget(&unselectedKTV, 1);
vlay.addWidget(&buttonBox);
const QString unselectedWhatsThis
= xi18nc("@info:whatsthis",
"<title>Why do you want to delete more certificates than I selected?</title>"
"<para>When you delete CA certificates (both root CAs and intermediate CAs), "
"the certificates issued by them will also be deleted.</para>"
"<para>This can be nicely seen in <application>Kleopatra</application>'s "
"hierarchical view mode: In this mode, if you delete a certificate that has "
"children, those children will also be deleted. Think of CA certificates as "
"folders containing other certificates: When you delete the folder, you "
"delete its contents, too.</para>");
unselectedLB.setContextMenuPolicy(Qt::NoContextMenu);
unselectedLB.setWhatsThis(unselectedWhatsThis);
unselectedKTV.setWhatsThis(unselectedWhatsThis);
buttonBox.button(QDialogButtonBox::Ok)->setText(i18nc("@action:button", "Delete"));
connect(&unselectedLB, SIGNAL(linkActivated(QString)), qq, SLOT(slotWhatsThisRequested()));
selectedKTV.setFlatModel(AbstractKeyListModel::createFlatKeyListModel(&selectedKTV));
unselectedKTV.setFlatModel(AbstractKeyListModel::createFlatKeyListModel(&unselectedKTV));
selectedKTV.setHierarchicalView(false);
selectedKTV.view()->setSelectionMode(QAbstractItemView::NoSelection);
unselectedKTV.setHierarchicalView(false);
unselectedKTV.view()->setSelectionMode(QAbstractItemView::NoSelection);
connect(&buttonBox, SIGNAL(accepted()), qq, SLOT(accept()));
connect(&buttonBox, &QDialogButtonBox::rejected, qq, &QDialog::reject);
}
} ui;
};
DeleteCertificatesDialog::DeleteCertificatesDialog(QWidget *p)
: QDialog(p), d(new Private(this))
{
d->readConfig();
}
DeleteCertificatesDialog::~DeleteCertificatesDialog()
{
d->writeConfig();
}
void DeleteCertificatesDialog::setSelectedKeys(const std::vector<Key> &keys)
{
d->ui.selectedKTV.setKeys(keys);
}
void DeleteCertificatesDialog::setUnselectedKeys(const std::vector<Key> &keys)
{
d->ui.unselectedLB .setVisible(!keys.empty());
d->ui.unselectedKTV.setVisible(!keys.empty());
d->ui.unselectedKTV.setKeys(keys);
}
std::vector<Key> DeleteCertificatesDialog::keys() const
{
const std::vector<Key> sel = d->ui.selectedKTV.keys();
const std::vector<Key> uns = d->ui.unselectedKTV.keys();
std::vector<Key> result;
result.reserve(sel.size() + uns.size());
result.insert(result.end(), sel.begin(), sel.end());
result.insert(result.end(), uns.begin(), uns.end());
return result;
}
void DeleteCertificatesDialog::accept()
{
const std::vector<Key> sel = d->ui.selectedKTV.keys();
const std::vector<Key> uns = d->ui.unselectedKTV.keys();
const uint secret = std::count_if(sel.cbegin(), sel.cend(), std::mem_fn(&Key::hasSecret))
+ std::count_if(uns.cbegin(), uns.cend(), std::mem_fn(&Key::hasSecret));
const uint total = sel.size() + uns.size();
int ret = KMessageBox::Continue;
if (secret)
ret = KMessageBox::warningContinueCancel(this,
secret == total
? i18np("The certificate to be deleted is your own. "
"It contains private key material, "
"which is needed to decrypt past communication "
"encrypted to the certificate, and should therefore "
"not be deleted.",
"All of the certificates to be deleted "
"are your own. "
"They contain private key material, "
"which is needed to decrypt past communication "
"encrypted to the certificate, and should therefore "
"not be deleted.",
secret)
: i18np("One of the certificates to be deleted "
"is your own. "
"It contains private key material, "
"which is needed to decrypt past communication "
"encrypted to the certificate, and should therefore "
"not be deleted.",
"Some of the certificates to be deleted "
"are your own. "
"They contain private key material, "
"which is needed to decrypt past communication "
"encrypted to the certificate, and should therefore "
"not be deleted.",
secret),
i18n("Secret Key Deletion"),
KStandardGuiItem::guiItem(KStandardGuiItem::Delete),
KStandardGuiItem::cancel(), QString(), KMessageBox::Notify | KMessageBox::Dangerous);
if (ret == KMessageBox::Continue) {
QDialog::accept();
} else {
QDialog::reject();
}
}
#include "moc_deletecertificatesdialog.cpp"
diff --git a/src/dialogs/exportdialog.cpp b/src/dialogs/exportdialog.cpp
index ad82f1e74..f2abd7bc2 100644
--- a/src/dialogs/exportdialog.cpp
+++ b/src/dialogs/exportdialog.cpp
@@ -1,227 +1,227 @@
/* SPDX-FileCopyrightText: 2017 Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "exportdialog.h"
#include "kleopatra_debug.h"
#include "view/waitwidget.h"
#include <QDialogButtonBox>
#include <QPushButton>
#include <QTextEdit>
#include <QVBoxLayout>
#include <gpgme++/key.h>
#include <QGpgME/Protocol>
#include <QGpgME/ExportJob>
#include <KLocalizedString>
#include <KSharedConfig>
#include <KConfigGroup>
#include <Libkleo/Formatting>
#include <gpgme++/gpgmepp_version.h>
#if GPGMEPP_VERSION >= 0x10E00 // 1.14.0
# define GPGME_HAS_EXPORT_FLAGS
#endif
using namespace Kleo;
class ExportWidget::Private
{
public:
Private(ExportWidget *qq)
: q(qq)
{}
void setupUi();
GpgME::Key key;
GpgME::Subkey subkey;
QTextEdit *textEdit;
WaitWidget *waitWidget;
unsigned int flags;
private:
ExportWidget *const q;
};
void ExportWidget::Private::setupUi()
{
auto vlay = new QVBoxLayout(q);
vlay->setContentsMargins(0, 0, 0, 0);
textEdit = new QTextEdit;
textEdit->setVisible(false);
textEdit->setReadOnly(true);
auto fixedFont = QFont(QStringLiteral("Monospace"));
fixedFont.setStyleHint(QFont::TypeWriter);
textEdit->setFont(fixedFont);
textEdit->setReadOnly(true);
vlay->addWidget(textEdit);
waitWidget = new WaitWidget;
waitWidget->setText(i18n("Exporting ..."));
vlay->addWidget(waitWidget);
}
ExportWidget::ExportWidget(QWidget *parent)
: QWidget(parent)
, d(new Private(this))
{
d->setupUi();
}
ExportWidget::~ExportWidget()
{
}
static QString injectComments(const GpgME::Key &key, const QByteArray &data)
{
QString ret = QString::fromUtf8(data);
if (key.protocol() != GpgME::OpenPGP) {
return ret;
}
auto overView = Formatting::toolTip(key, Formatting::Fingerprint |
Formatting::UserIDs |
Formatting::Issuer |
Formatting::Subject |
Formatting::ExpiryDates |
Formatting::CertificateType |
Formatting::CertificateUsage);
// Fixup the HTML coming from the toolTip for our own format.
overView.remove(QLatin1String("<tr><th>"));
overView.replace(QLatin1String("</th><td>"), QLatin1String("\t"));
overView.replace(QLatin1String("</td></tr>"), QLatin1String("\n"));
overView.remove(QLatin1String("<table border=\"0\">"));
overView.remove(QLatin1String("\n</table>"));
overView.replace(QLatin1String("&lt;"), QLatin1String("<"));
overView.replace(QLatin1String("&gt;"), QLatin1String(">"));
auto overViewLines = overView.split(QLatin1Char('\n'));
// Format comments so that they fit for RFC 4880
auto comments = QStringLiteral("Comment: ");
comments += overViewLines.join(QLatin1String("\nComment: ")) + QLatin1Char('\n');
ret.insert(37 /* -----BEGIN PGP PUBLIC KEY BLOCK-----\n */, comments);
return ret;
}
void ExportWidget::exportResult(const GpgME::Error &err, const QByteArray &data)
{
d->waitWidget->setVisible(false);
d->textEdit->setVisible(true);
if (err) {
/* Should not happen. But well,.. */
d->textEdit->setText(i18nc("%1 is error message", "Failed to export: '%1'", QString::fromLatin1(err.asString())));
}
if (!d->flags) {
d->textEdit->setText(injectComments(d->key, data));
} else {
d->textEdit->setText(QString::fromUtf8(data));
}
}
void ExportWidget::setKey(const GpgME::Subkey &key, unsigned int flags)
{
d->waitWidget->setVisible(true);
d->textEdit->setVisible(false);
d->key = key.parent();
d->subkey = key;
d->flags = flags;
auto protocol = d->key.protocol() == GpgME::CMS ?
QGpgME::smime() : QGpgME::openpgp();
auto job = protocol->publicKeyExportJob(true);
connect(job, &QGpgME::ExportJob::result,
this, &ExportWidget::exportResult);
#ifdef GPGME_HAS_EXPORT_FLAGS
job->setExportFlags(flags);
#endif
job->start(QStringList() << QLatin1String(key.fingerprint()) + QLatin1Char('!'));
}
void ExportWidget::setKey(const GpgME::Key &key, unsigned int flags)
{
d->waitWidget->setVisible(true);
d->textEdit->setVisible(false);
d->key = key;
d->flags = flags;
auto protocol = key.protocol() == GpgME::CMS ?
QGpgME::smime() : QGpgME::openpgp();
auto job = protocol->publicKeyExportJob(true);
connect(job, &QGpgME::ExportJob::result,
this, &ExportWidget::exportResult);
#ifdef GPGME_HAS_EXPORT_FLAGS
job->setExportFlags(flags);
#endif
job->start(QStringList() << QLatin1String(key.primaryFingerprint()));
}
GpgME::Key ExportWidget::key() const
{
return d->key;
}
ExportDialog::ExportDialog(QWidget *parent)
: QDialog(parent),
mWidget(new ExportWidget(this))
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "ExportDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "ExportDialog");
const auto size = dialog.readEntry("Size", QSize(600, 800));
if (size.isValid()) {
resize(size);
}
setWindowTitle(i18nc("@title:window", "Export"));
auto l = new QVBoxLayout(this);
l->addWidget(mWidget);
auto bbox = new QDialogButtonBox(this);
auto btn = bbox->addButton(QDialogButtonBox::Close);
connect(btn, &QPushButton::pressed, this, &QDialog::accept);
l->addWidget(bbox);
}
ExportDialog::~ExportDialog()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "ExportDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "ExportDialog");
dialog.writeEntry("Size", size());
dialog.sync();
}
void ExportDialog::setKey(const GpgME::Key &key, unsigned int flags)
{
mWidget->setKey(key, flags);
}
void ExportDialog::setKey(const GpgME::Subkey &key, unsigned int flags)
{
mWidget->setKey(key, flags);
}
GpgME::Key ExportDialog::key() const
{
return mWidget->key();
}
diff --git a/src/dialogs/groupdetailsdialog.cpp b/src/dialogs/groupdetailsdialog.cpp
index a786a4575..d0d3e155b 100644
--- a/src/dialogs/groupdetailsdialog.cpp
+++ b/src/dialogs/groupdetailsdialog.cpp
@@ -1,156 +1,156 @@
/*
dialogs/groupdetailsdialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "groupdetailsdialog.h"
#include "commands/detailscommand.h"
#include "view/keytreeview.h"
#include <Libkleo/KeyGroup>
#include <Libkleo/KeyListModel>
#include <KConfigGroup>
#include <KGuiItem>
#include <KLocalizedString>
#include <KSharedConfig>
#include <KStandardGuiItem>
#include <QDialogButtonBox>
#include <QLabel>
#include <QPushButton>
#include <QTreeView>
#include <QVBoxLayout>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::Dialogs;
Q_DECLARE_METATYPE(GpgME::Key)
class GroupDetailsDialog::Private
{
friend class ::Kleo::Dialogs::GroupDetailsDialog;
GroupDetailsDialog *const q;
struct {
QLabel *groupNameLabel = nullptr;
QLabel *groupCommentLabel = nullptr;
KeyTreeView *treeView = nullptr;
QDialogButtonBox *buttonBox = nullptr;
} ui;
KeyGroup group;
public:
Private(GroupDetailsDialog *qq)
: q(qq)
{
auto mainLayout = new QVBoxLayout(q);
ui.groupNameLabel = new QLabel();
ui.groupNameLabel->setWordWrap(true);
mainLayout->addWidget(ui.groupNameLabel);
ui.groupCommentLabel = new QLabel();
ui.groupCommentLabel->setWordWrap(true);
ui.groupCommentLabel->setVisible(false);
mainLayout->addWidget(ui.groupCommentLabel);
ui.treeView = new KeyTreeView(q);
ui.treeView->view()->setRootIsDecorated(false);
ui.treeView->view()->setSelectionMode(QAbstractItemView::SingleSelection);
ui.treeView->setFlatModel(AbstractKeyListModel::createFlatKeyListModel(ui.treeView));
ui.treeView->setHierarchicalView(false);
connect(ui.treeView->view(), &QAbstractItemView::doubleClicked,
q, [this] (const QModelIndex &index) { showKeyDetails(index); });
mainLayout->addWidget(ui.treeView);
ui.buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
KGuiItem::assign(ui.buttonBox->button(QDialogButtonBox::Close), KStandardGuiItem::close());
connect(ui.buttonBox, &QDialogButtonBox::rejected, q, &QDialog::close);
mainLayout->addWidget(ui.buttonBox);
// calculate default size with enough space for the key list
const auto fm = ui.treeView->fontMetrics();
const QSize sizeHint = q->sizeHint();
const QSize defaultSize = QSize(qMax(sizeHint.width(), 150 * fm.horizontalAdvance(QLatin1Char('x'))),
sizeHint.height() - ui.treeView->sizeHint().height() + 20 * fm.lineSpacing());
restoreLayout(defaultSize);
}
~Private()
{
saveLayout();
}
private:
void saveLayout()
{
- KConfigGroup configGroup(KSharedConfig::openConfig(), "GroupDetailsDialog");
+ KConfigGroup configGroup(KSharedConfig::openStateConfig(), "GroupDetailsDialog");
ui.treeView->saveLayout(configGroup);
configGroup.writeEntry("Size", q->size());
configGroup.sync();
}
void restoreLayout(const QSize &defaultSize)
{
- const KConfigGroup configGroup(KSharedConfig::openConfig(), "GroupDetailsDialog");
+ const KConfigGroup configGroup(KSharedConfig::openStateConfig(), "GroupDetailsDialog");
ui.treeView->restoreLayout(configGroup);
const QSize size = configGroup.readEntry("Size", defaultSize);
if (size.isValid()) {
q->resize(size);
}
}
void showKeyDetails(const QModelIndex &index)
{
const GpgME::Key key = ui.treeView->view()->model()->data(index, KeyList::KeyRole).value<GpgME::Key>();
if (!key.isNull()) {
auto cmd = new DetailsCommand(key, nullptr);
cmd->setParentWidget(q);
cmd->start();
}
}
};
GroupDetailsDialog::GroupDetailsDialog(QWidget *parent)
: QDialog(parent)
, d(new Private(this))
{
setWindowTitle(i18nc("@title:window", "Group Details"));
}
GroupDetailsDialog::~GroupDetailsDialog()
{
}
namespace
{
QString groupComment(const KeyGroup &group)
{
switch (group.source()) {
case KeyGroup::GnuPGConfig:
return i18n("Note: This group is defined in the configuration files of gpg.");
default:
return QString();
}
}
}
void GroupDetailsDialog::setGroup(const KeyGroup &group)
{
d->group = group;
d->ui.groupNameLabel->setText(group.name());
d->ui.groupCommentLabel->setText(groupComment(group));
d->ui.groupCommentLabel->setVisible(!d->ui.groupCommentLabel->text().isEmpty());
const KeyGroup::Keys &keys = group.keys();
d->ui.treeView->setKeys(std::vector<GpgME::Key>(keys.cbegin(), keys.cend()));
}
diff --git a/src/dialogs/revokecertificationdialog.cpp b/src/dialogs/revokecertificationdialog.cpp
index a49e75535..65850b18b 100644
--- a/src/dialogs/revokecertificationdialog.cpp
+++ b/src/dialogs/revokecertificationdialog.cpp
@@ -1,143 +1,143 @@
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/revokecertificationdialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2020 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 "revokecertificationdialog.h"
#include "revokecertificationwidget.h"
#include <Libkleo/Formatting>
#include <KConfigGroup>
#include <KGuiItem>
#include <KLocalizedString>
#include <KSharedConfig>
#include <KStandardGuiItem>
#include <QAbstractButton>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QVBoxLayout>
#include "kleopatra_debug.h"
using namespace GpgME;
using namespace Kleo;
class RevokeCertificationDialog::Private
{
friend class ::Kleo::RevokeCertificationDialog;
RevokeCertificationDialog *const q;
public:
explicit Private(RevokeCertificationDialog *qq);
~Private();
private:
void saveGeometry();
void restoreGeometry(const QSize &defaultSize);
private:
RevokeCertificationWidget *mainWidget = nullptr;
};
RevokeCertificationDialog::Private::Private(RevokeCertificationDialog *qq)
: q(qq)
{
}
RevokeCertificationDialog::Private::~Private()
{
}
void RevokeCertificationDialog::Private::saveGeometry()
{
- KConfigGroup cfgGroup(KSharedConfig::openConfig(), "RevokeCertificationDialog");
+ KConfigGroup cfgGroup(KSharedConfig::openStateConfig(), "RevokeCertificationDialog");
cfgGroup.writeEntry("geometry", q->saveGeometry());
cfgGroup.sync();
}
void RevokeCertificationDialog::Private::restoreGeometry(const QSize &defaultSize)
{
- KConfigGroup cfgGroup(KSharedConfig::openConfig(), "RevokeCertificationDialog");
+ KConfigGroup cfgGroup(KSharedConfig::openStateConfig(), "RevokeCertificationDialog");
const QByteArray geometry = cfgGroup.readEntry("geometry", QByteArray());
if (!geometry.isEmpty()) {
q->restoreGeometry(geometry);
} else {
q->resize(defaultSize);
}
}
RevokeCertificationDialog::RevokeCertificationDialog(QWidget *p, Qt::WindowFlags f)
: QDialog(p, f)
, d(new Private(this))
{
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
auto mainLay = new QVBoxLayout(this);
d->mainWidget = new RevokeCertificationWidget(this);
mainLay->addWidget(d->mainWidget);
QDialogButtonBox *buttonBox = new QDialogButtonBox();
mainLay->addWidget(buttonBox);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel |
QDialogButtonBox::Ok);
KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("Revoke Certification"));
connect(buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked,
this, [this] () {
d->mainWidget->saveConfig();
accept();
});
connect(buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked,
this, [this] () { close(); });
d->restoreGeometry(QSize(640, 480));
}
RevokeCertificationDialog::~RevokeCertificationDialog()
{
d->saveGeometry();
}
void RevokeCertificationDialog::setCertificateToRevoke(const Key &key)
{
setWindowTitle(i18nc("@title:window arg is name, email of certificate holder",
"Revoke Certification: %1", Formatting::prettyName(key)));
d->mainWidget->setTarget(key);
}
void RevokeCertificationDialog::setSelectedUserIDs(const std::vector<UserID> &uids)
{
d->mainWidget->setSelectUserIDs(uids);
}
std::vector<GpgME::UserID> RevokeCertificationDialog::selectedUserIDs() const
{
return d->mainWidget->selectedUserIDs();
}
void Kleo::RevokeCertificationDialog::setSelectedCertificationKey(const GpgME::Key &key)
{
d->mainWidget->setCertificationKey(key);
}
Key RevokeCertificationDialog::selectedCertificationKey() const
{
return d->mainWidget->certificationKey();
}
bool RevokeCertificationDialog::sendToServer() const
{
return d->mainWidget->publishSelected();
}
diff --git a/src/dialogs/subkeyswidget.cpp b/src/dialogs/subkeyswidget.cpp
index b3ecb5baa..9b3e4c183 100644
--- a/src/dialogs/subkeyswidget.cpp
+++ b/src/dialogs/subkeyswidget.cpp
@@ -1,255 +1,255 @@
/* SPDX-FileCopyrightText: 2016 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "subkeyswidget.h"
#include "ui_subkeyswidget.h"
#include "commands/changeexpirycommand.h"
#include "commands/keytocardcommand.h"
#include "commands/importpaperkeycommand.h"
#include "exportdialog.h"
#include <gpgme++/key.h>
#include <gpgme++/context.h>
#include <KConfigGroup>
#include <KSharedConfig>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QTreeWidgetItem>
#include <QMenu>
#include <gpgme++/gpgmepp_version.h>
#if GPGMEPP_VERSION >= 0x10E00 // 1.14.0
# define GPGME_HAS_EXPORT_FLAGS
#endif
#if GPGMEPP_VERSION >= 0x10E01 // 1.14.1
# define CHANGEEXPIRYJOB_SUPPORTS_SUBKEYS
#endif
#include <Libkleo/Formatting>
Q_DECLARE_METATYPE(GpgME::Subkey)
using namespace Kleo;
using namespace Kleo::Commands;
class SubKeysWidget::Private
{
public:
Private(SubKeysWidget *q)
: q(q)
{
ui.setupUi(q);
ui.subkeysTree->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui.subkeysTree, &QAbstractItemView::customContextMenuRequested,
q, [this](const QPoint &p) { tableContextMenuRequested(p); });
}
GpgME::Key key;
Ui::SubKeysWidget ui;
void tableContextMenuRequested(const QPoint &p);
private:
SubKeysWidget *const q;
};
void SubKeysWidget::Private::tableContextMenuRequested(const QPoint &p)
{
auto item = ui.subkeysTree->itemAt(p);
if (!item) {
return;
}
const auto subkey = item->data(0, Qt::UserRole).value<GpgME::Subkey>();
QMenu *menu = new QMenu(q);
connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater);
bool hasActions = false;
#ifdef CHANGEEXPIRYJOB_SUPPORTS_SUBKEYS
if (subkey.parent().protocol() == GpgME::OpenPGP && subkey.parent().hasSecret()) {
hasActions = true;
menu->addAction(i18n("Change Expiry Date..."), q,
[this, subkey]() {
auto cmd = new ChangeExpiryCommand(subkey.parent());
if (subkey.keyID() != key.keyID()) {
// do not set the primary key as subkey
cmd->setSubkey(subkey);
}
ui.subkeysTree->setEnabled(false);
connect(cmd, &ChangeExpiryCommand::finished,
q, [this]() {
ui.subkeysTree->setEnabled(true);
key.update();
q->setKey(key);
});
cmd->setParentWidget(q);
cmd->start();
}
);
}
#endif // CHANGEEXPIRYJOB_SUPPORTS_SUBKEYS
#ifdef GPGME_HAS_EXPORT_FLAGS
if (subkey.parent().protocol() == GpgME::OpenPGP && subkey.canAuthenticate()) {
hasActions = true;
menu->addAction(QIcon::fromTheme(QStringLiteral("view-certificate-export")),
i18n("Export OpenSSH key"),
q, [this, subkey]() {
QScopedPointer<ExportDialog> dlg(new ExportDialog(q));
dlg->setKey(subkey, static_cast<unsigned int> (GpgME::Context::ExportSSH));
dlg->exec();
});
}
#endif // GPGME_HAS_EXPORT_FLAGS
if (!subkey.isSecret()) {
hasActions = true;
menu->addAction(QIcon::fromTheme(QStringLiteral("view-certificate-import")),
i18n("Restore printed backup"),
q, [this, subkey] () {
auto cmd = new ImportPaperKeyCommand(subkey.parent());
ui.subkeysTree->setEnabled(false);
connect(cmd, &ImportPaperKeyCommand::finished,
q, [this]() { ui.subkeysTree->setEnabled(true); });
cmd->setParentWidget(q);
cmd->start();
});
}
if (subkey.isSecret()) {
hasActions = true;
auto action = menu->addAction(QIcon::fromTheme(QStringLiteral("send-to-symbolic")),
i18n("Transfer to smartcard"),
q, [this, subkey]() {
auto cmd = new KeyToCardCommand(subkey);
ui.subkeysTree->setEnabled(false);
connect(cmd, &KeyToCardCommand::finished,
q, [this]() { ui.subkeysTree->setEnabled(true); });
cmd->setParentWidget(q);
cmd->start();
});
action->setEnabled(!KeyToCardCommand::getSuitableCards(subkey).empty());
}
if (hasActions) {
menu->popup(ui.subkeysTree->viewport()->mapToGlobal(p));
} else {
delete menu;
}
}
SubKeysWidget::SubKeysWidget(QWidget *parent)
: QWidget(parent)
, d(new Private(this))
{
}
SubKeysWidget::~SubKeysWidget()
{
}
void SubKeysWidget::setKey(const GpgME::Key &key)
{
d->key = key;
const auto currentItem = d->ui.subkeysTree->currentItem();
const QByteArray selectedKeyFingerprint = currentItem ?
QByteArray(currentItem->data(0, Qt::UserRole).value<GpgME::Subkey>().fingerprint()) : QByteArray();
d->ui.subkeysTree->clear();
for (const auto &subkey : key.subkeys()) {
auto item = new QTreeWidgetItem();
item->setData(0, Qt::DisplayRole, Formatting::prettyID(subkey.keyID()));
item->setData(0, Qt::UserRole, QVariant::fromValue(subkey));
item->setData(1, Qt::DisplayRole, Kleo::Formatting::type(subkey));
item->setData(2, Qt::DisplayRole, Kleo::Formatting::creationDateString(subkey));
item->setData(3, Qt::DisplayRole, Kleo::Formatting::expirationDateString(subkey));
item->setData(4, Qt::DisplayRole, Kleo::Formatting::validityShort(subkey));
switch (subkey.publicKeyAlgorithm()) {
case GpgME::Subkey::AlgoECDSA:
case GpgME::Subkey::AlgoEDDSA:
case GpgME::Subkey::AlgoECDH:
item->setData(5, Qt::DisplayRole, QString::fromStdString(subkey.algoName()));
break;
default:
item->setData(5, Qt::DisplayRole, QString::number(subkey.length()));
}
item->setData(6, Qt::DisplayRole, Kleo::Formatting::usageString(subkey));
item->setData(7, Qt::DisplayRole, subkey.keyID() == key.keyID() ? QStringLiteral("✓") : QString());
d->ui.subkeysTree->addTopLevelItem(item);
if (subkey.fingerprint() == selectedKeyFingerprint) {
d->ui.subkeysTree->setCurrentItem(item);
}
}
const auto subkey = key.subkey(0);
if (const char *card = subkey.cardSerialNumber()) {
d->ui.stored->setText(i18nc("stored...", "on SmartCard with serial no. %1", QString::fromUtf8(card)));
} else {
d->ui.stored->setText(i18nc("stored...", "on this computer"));
}
d->ui.subkeysTree->resizeColumnToContents(0);
}
GpgME::Key SubKeysWidget::key() const
{
return d->key;
}
SubKeysDialog::SubKeysDialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(i18nc("@title:window", "Subkeys Details"));
auto l = new QVBoxLayout(this);
l->addWidget(new SubKeysWidget(this));
auto bbox = new QDialogButtonBox(this);
auto btn = bbox->addButton(QDialogButtonBox::Close);
connect(btn, &QPushButton::clicked, this, &QDialog::accept);
l->addWidget(bbox);
readConfig();
}
SubKeysDialog::~SubKeysDialog()
{
writeConfig();
}
void SubKeysDialog::readConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "SubKeysDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "SubKeysDialog");
const QSize size = dialog.readEntry("Size", QSize(820, 280));
if (size.isValid()) {
resize(size);
}
}
void SubKeysDialog::writeConfig()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "SubKeysDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "SubKeysDialog");
dialog.writeEntry("Size", size());
dialog.sync();
}
void SubKeysDialog::setKey(const GpgME::Key &key)
{
auto w = findChild<SubKeysWidget*>();
Q_ASSERT(w);
w->setKey(key);
}
GpgME::Key SubKeysDialog::key() const
{
auto w = findChild<SubKeysWidget*>();
Q_ASSERT(w);
return w->key();
}
diff --git a/src/dialogs/weboftrustdialog.cpp b/src/dialogs/weboftrustdialog.cpp
index 7adfcdd33..ba777d422 100644
--- a/src/dialogs/weboftrustdialog.cpp
+++ b/src/dialogs/weboftrustdialog.cpp
@@ -1,56 +1,56 @@
/* SPDX-FileCopyrightText: 2017 Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "weboftrustdialog.h"
#include "weboftrustwidget.h"
#include <QDialogButtonBox>
#include <QPushButton>
#include <QVBoxLayout>
#include <gpgme++/key.h>
#include <KLocalizedString>
#include <KSharedConfig>
#include <KConfigGroup>
using namespace Kleo;
WebOfTrustDialog::WebOfTrustDialog(QWidget *parent)
: QDialog(parent)
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "WebOfTrustDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "WebOfTrustDialog");
const QSize size = dialog.readEntry("Size", QSize(900, 400));
if (size.isValid()) {
resize(size);
}
setWindowTitle(i18nc("@title:window", "Certifications"));
mWidget = new WebOfTrustWidget(this);
auto l = new QVBoxLayout(this);
l->addWidget(mWidget);
auto bbox = new QDialogButtonBox(this);
auto btn = bbox->addButton(QDialogButtonBox::Close);
connect(btn, &QPushButton::pressed, this, &QDialog::accept);
l->addWidget(bbox);
}
void WebOfTrustDialog::setKey(const GpgME::Key &key)
{
mWidget->setKey(key);
}
GpgME::Key WebOfTrustDialog::key() const
{
return mWidget->key();
}
WebOfTrustDialog::~WebOfTrustDialog()
{
- KConfigGroup dialog(KSharedConfig::openConfig(), "WebOfTrustDialog");
+ KConfigGroup dialog(KSharedConfig::openStateConfig(), "WebOfTrustDialog");
dialog.writeEntry("Size", size());
dialog.sync();
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 26, 7:03 PM (1 d, 12 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
43/ed/65988c7eb4519f83c625b6a0dcb3

Event Timeline