diff --git a/src/commands/importcertificatefromfilecommand.cpp b/src/commands/importcertificatefromfilecommand.cpp
index 0e238f0ae..53ebe9f9e 100644
--- a/src/commands/importcertificatefromfilecommand.cpp
+++ b/src/commands/importcertificatefromfilecommand.cpp
@@ -1,169 +1,174 @@
/* -*- mode: c++; c-basic-offset:4 -*-
importcertificatefromfilecommand.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include
#include "importcertificatefromfilecommand.h"
#include "importcertificatescommand_p.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace GpgME;
using namespace Kleo;
using namespace QGpgME;
class ImportCertificateFromFileCommand::Private : public ImportCertificatesCommand::Private
{
friend class ::ImportCertificateFromFileCommand;
ImportCertificateFromFileCommand *q_func() const
{
return static_cast(q);
}
public:
explicit Private(ImportCertificateFromFileCommand *qq, KeyListController *c);
~Private() override;
bool ensureHaveFile();
private:
QStringList files;
};
ImportCertificateFromFileCommand::Private *ImportCertificateFromFileCommand::d_func()
{
return static_cast(d.get());
}
const ImportCertificateFromFileCommand::Private *ImportCertificateFromFileCommand::d_func() const
{
return static_cast(d.get());
}
ImportCertificateFromFileCommand::Private::Private(ImportCertificateFromFileCommand *qq, KeyListController *c)
: ImportCertificatesCommand::Private(qq, c),
files()
{
}
ImportCertificateFromFileCommand::Private::~Private() {}
#define d d_func()
#define q q_func()
ImportCertificateFromFileCommand::ImportCertificateFromFileCommand()
: ImportCertificatesCommand(new Private(this, nullptr))
{
}
ImportCertificateFromFileCommand::ImportCertificateFromFileCommand(KeyListController *p)
: ImportCertificatesCommand(new Private(this, p))
{
}
ImportCertificateFromFileCommand::ImportCertificateFromFileCommand(QAbstractItemView *v, KeyListController *p)
: ImportCertificatesCommand(v, new Private(this, p))
{
}
ImportCertificateFromFileCommand::ImportCertificateFromFileCommand(const QStringList &files, KeyListController *p)
: ImportCertificatesCommand(new Private(this, p))
{
d->files = files;
}
ImportCertificateFromFileCommand::ImportCertificateFromFileCommand(const QStringList &files, QAbstractItemView *v, KeyListController *p)
: ImportCertificatesCommand(v, new Private(this, p))
{
d->files = files;
}
ImportCertificateFromFileCommand::~ImportCertificateFromFileCommand() {}
void ImportCertificateFromFileCommand::setFiles(const QStringList &files)
{
d->files = files;
}
void ImportCertificateFromFileCommand::doStart()
{
if (!d->ensureHaveFile()) {
Q_EMIT canceled();
d->finished();
return;
}
+ d->setProgressWindowTitle(i18nc("@title:window", "Importing Certificates"));
+ d->setProgressLabelText(i18np("Importing certificates from 1 file...",
+ "Importing certificates from %1 files...",
+ d->files.size()));
+
//TODO: use KIO here
d->setWaitForMoreJobs(true);
for (const QString &fn : std::as_const(d->files)) {
QFile in(fn);
if (!in.open(QIODevice::ReadOnly)) {
d->error(i18n("Could not open file %1 for reading: %2", in.fileName(), in.errorString()), i18n("Certificate Import Failed"));
d->importResult({fn, GpgME::UnknownProtocol, ImportType::Local, ImportResult{}});
continue;
}
const auto data = in.readAll();
d->startImport(GpgME::OpenPGP, data, fn);
d->startImport(GpgME::CMS, data, fn);
d->importGroupsFromFile(fn);
}
d->setWaitForMoreJobs(false);
}
static QStringList get_file_name(QWidget *parent)
{
const QString certificateFilter = i18n("Certificates") + QLatin1String(" (*.asc *.cer *.cert *.crt *.der *.pem *.gpg *.p7c *.p12 *.pfx *.pgp *.kgrp)");
const QString anyFilesFilter = i18n("Any files") + QLatin1String(" (*)");
QString previousDir;
if (const KSharedConfig::Ptr config = KSharedConfig::openConfig()) {
const KConfigGroup group(config, "Import Certificate");
previousDir = group.readPathEntry("last-open-file-directory", QDir::homePath());
}
const QStringList files = QFileDialog::getOpenFileNames(parent, i18n("Select Certificate File"), previousDir, certificateFilter + QLatin1String(";;") + anyFilesFilter);
if (!files.empty())
if (const KSharedConfig::Ptr config = KSharedConfig::openConfig()) {
KConfigGroup group(config, "Import Certificate");
group.writePathEntry("last-open-file-directory", QFileInfo(files.front()).path());
}
return files;
}
bool ImportCertificateFromFileCommand::Private::ensureHaveFile()
{
if (files.empty()) {
files = get_file_name(parentWidgetOrView());
}
return !files.empty();
}
#undef d
#undef q
diff --git a/src/commands/importcertificatefromkeyservercommand.cpp b/src/commands/importcertificatefromkeyservercommand.cpp
index a25265a7e..bb4937489 100644
--- a/src/commands/importcertificatefromkeyservercommand.cpp
+++ b/src/commands/importcertificatefromkeyservercommand.cpp
@@ -1,100 +1,92 @@
/* commands/importcertificatefromkeyservercommand.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include
#include "importcertificatefromkeyservercommand.h"
#include "importcertificatescommand_p.h"
#include
-#include
-
#include "kleopatra_debug.h"
using namespace Kleo;
class ImportCertificateFromKeyserverCommand::Private : public ImportCertificatesCommand::Private
{
friend class ::ImportCertificateFromKeyserverCommand;
ImportCertificateFromKeyserverCommand *q_func() const
{
return static_cast(q);
}
public:
explicit Private(ImportCertificateFromKeyserverCommand *qq,
const QStringList &keyIds, const QString &id);
~Private() override;
private:
void start();
private:
QStringList mKeyIds;
QString mId;
};
ImportCertificateFromKeyserverCommand::Private *ImportCertificateFromKeyserverCommand::d_func()
{
return static_cast(d.get());
}
const ImportCertificateFromKeyserverCommand::Private *ImportCertificateFromKeyserverCommand::d_func() const
{
return static_cast(d.get());
}
#define q q_func()
#define d d_func()
ImportCertificateFromKeyserverCommand::Private::Private(ImportCertificateFromKeyserverCommand *qq,
const QStringList &keyIds, const QString &id)
: ImportCertificatesCommand::Private{qq, nullptr}
, mKeyIds{keyIds}
, mId{id}
{
}
ImportCertificateFromKeyserverCommand::Private::~Private() = default;
void ImportCertificateFromKeyserverCommand::Private::start()
{
- const auto progressDialog = new QProgressDialog{parentWidgetOrView()};
- progressDialog->setAttribute(Qt::WA_DeleteOnClose);
- progressDialog->setModal(true);
- progressDialog->setRange(0, 0);
- progressDialog->setWindowTitle(i18nc("@title:window", "Fetching Keys"));
- progressDialog->setLabelText(i18np("Fetching 1 key... (this can take a while)", "Fetching %1 keys... (this can take a while)", mKeyIds.size()));
- connect(progressDialog, &QProgressDialog::canceled, q, &Command::cancel);
- connect(q, &Command::finished, progressDialog, [progressDialog]() { progressDialog->accept(); });
+ setProgressWindowTitle(i18nc("@title:window", "Fetching Keys"));
+ setProgressLabelText(i18np("Fetching 1 key... (this can take a while)",
+ "Fetching %1 keys... (this can take a while)",
+ mKeyIds.size()));
setWaitForMoreJobs(true);
// start one import per key id to allow canceling the key retrieval without
// losing already retrieved keys
for (const auto &keyId : mKeyIds) {
startImport(GpgME::OpenPGP, {keyId}, mId);
}
setWaitForMoreJobs(false);
-
- progressDialog->show();
}
ImportCertificateFromKeyserverCommand::ImportCertificateFromKeyserverCommand(const QStringList &keyIds, const QString &id)
: ImportCertificatesCommand{new Private{this, keyIds, id}}
{
}
ImportCertificateFromKeyserverCommand::~ImportCertificateFromKeyserverCommand() = default;
void ImportCertificateFromKeyserverCommand::doStart()
{
d->start();
}
#undef q_func
#undef d_func
diff --git a/src/commands/importcertificatescommand.cpp b/src/commands/importcertificatescommand.cpp
index 8a45bec89..1115c3585 100644
--- a/src/commands/importcertificatescommand.cpp
+++ b/src/commands/importcertificatescommand.cpp
@@ -1,864 +1,936 @@
/* -*- mode: c++; c-basic-offset:4 -*-
commands/importcertificatescommand.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007, 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2021, 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include
#include "importcertificatescommand.h"
#include "importcertificatescommand_p.h"
#include "certifycertificatecommand.h"
#include "kleopatra_debug.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include
#include // for Qt::escape
#include
#include
#include
"};
}
report += QLatin1String{""};
return report;
}
// Returns false on error, true if please certify was shown.
bool ImportCertificatesCommand::Private::showPleaseCertify(const GpgME::Import &imp)
{
const char *fpr = imp.fingerprint();
if (!fpr) {
// WTF
qCWarning(KLEOPATRA_LOG) << "Import without fingerprint";
return false;
}
// Exactly one public key imported. Let's see if it is openpgp. We are async here so
// we can just fetch it.
auto ctx = GpgME::Context::createForProtocol(GpgME::OpenPGP);
if (!ctx) {
// WTF
qCWarning(KLEOPATRA_LOG) << "Failed to create OpenPGP proto";
return false;
}
GpgME::Error err;
auto key = ctx->key(fpr, err, false);
delete ctx;
if (key.isNull() || err) {
// No such key most likely not OpenPGP
return false;
}
for (const auto &uid: key.userIDs()) {
if (uid.validity() >= GpgME::UserID::Marginal) {
// Already marginal so don't bug the user
return false;
}
}
const QStringList suggestions = QStringList() << i18n("A phone call to the person.")
<< i18n("Using a business card.")
<< i18n("Confirming it on a trusted website.");
auto sel = KMessageBox::questionYesNo(parentWidgetOrView(),
i18n("In order to mark the certificate as valid (green) it needs to be certified.") + QStringLiteral("
") +
i18n("Certifying means that you check the Fingerprint.") + QStringLiteral("
") +
i18n("Some suggestions to do this are:") +
QStringLiteral("%1").arg(suggestions.join(QStringLiteral("
") +
i18n("Do you wish to start this process now?"),
i18nc("@title", "You have imported a new certificate (public key)"),
KStandardGuiItem::yes(), KStandardGuiItem::no(), QStringLiteral("CertifyQuestion"));
if (sel == KMessageBox::Yes) {
QEventLoop loop;
auto cmd = new Commands::CertifyCertificateCommand(key);
cmd->setParentWidget(parentWidgetOrView());
loop.connect(cmd, SIGNAL(finished()), SLOT(quit()));
QMetaObject::invokeMethod(cmd, &Commands::CertifyCertificateCommand::start, Qt::QueuedConnection);
loop.exec();
}
return true;
}
void ImportCertificatesCommand::Private::showDetails(const std::vector &res,
const std::vector &groups)
{
if (res.size() == 1 && res[0].result.numImported() == 1 && res[0].result.imports().size() == 1) {
if (showPleaseCertify(res[0].result.imports()[0])) {
return;
}
}
setImportResultProxyModel(res);
information(make_message_report(res, groups),
i18n("Certificate Import Result"));
}
static QString make_error_message(const Error &err, const QString &id)
{
Q_ASSERT(err);
Q_ASSERT(!err.isCanceled());
return id.isEmpty()
? i18n("An error occurred while trying "
"to import the certificate:
"
"%1
",
QString::fromLocal8Bit(err.asString()))
: i18n("An error occurred while trying "
"to import the certificate %1:
"
"%2
",
id, QString::fromLocal8Bit(err.asString()));
}
void ImportCertificatesCommand::Private::showError(QWidget *parent, const Error &err, const QString &id)
{
if (parent) {
KMessageBox::error(parent, make_error_message(err, id), i18n("Certificate Import Failed"));
} else {
showError(err, id);
}
}
void ImportCertificatesCommand::Private::showError(const Error &err, const QString &id)
{
error(make_error_message(err, id), i18n("Certificate Import Failed"));
}
void ImportCertificatesCommand::Private::setWaitForMoreJobs(bool wait)
{
if (wait == waitForMoreJobs) {
return;
}
waitForMoreJobs = wait;
if (!waitForMoreJobs) {
tryToFinish();
}
}
void ImportCertificatesCommand::Private::importResult(const ImportResult &result, QGpgME::Job *finishedJob)
{
if (!finishedJob) {
finishedJob = qobject_cast(q->sender());
}
Q_ASSERT(finishedJob);
auto it = std::find_if(std::cbegin(jobs), std::cend(jobs),
[finishedJob](const auto &job) { return job.job == finishedJob; });
Q_ASSERT(it != std::cend(jobs));
if (it == std::cend(jobs)) {
qCWarning(KLEOPATRA_LOG) << __func__ << "Error: Finished job not found";
return;
}
const auto job = *it;
jobs.erase(std::remove(std::begin(jobs), std::end(jobs), job), std::end(jobs));
+ increaseProgressValue();
importResult({job.id, job.protocol, job.type, result});
}
void ImportCertificatesCommand::Private::importResult(const ImportResultData &result)
{
qCDebug(KLEOPATRA_LOG) << __func__ << result.id;
results.push_back(result);
tryToFinish();
}
static void handleOwnerTrust(const std::vector &results)
{
//iterate over all imported certificates
for (const auto &r: results) {
//when a new certificate got a secret key
if (r.result.numSecretKeysImported() >= 1) {
const char *fingerPr = r.result.imports()[0].fingerprint();
GpgME::Error err;
QScopedPointer
ctx(Context::createForProtocol(GpgME::Protocol::OpenPGP));
if (!ctx){
qCWarning(KLEOPATRA_LOG) << "Failed to get context";
continue;
}
const Key toTrustOwner = ctx->key(fingerPr, err , false);
if (toTrustOwner.isNull()) {
return;
}
QStringList uids;
const auto toTrustOwnerUserIDs{toTrustOwner.userIDs()};
uids.reserve(toTrustOwnerUserIDs.size());
for (const UserID &uid : toTrustOwnerUserIDs) {
uids << Formatting::prettyNameAndEMail(uid);
}
const QString str = xi18nc("@info",
"You have imported a Secret Key."
"The key has the fingerprint:"
"%1"
""
"And claims the User IDs:"
"- %2
"
""
"Is this your own key? (Set trust level to ultimate)",
QString::fromUtf8(fingerPr),
uids.join(QLatin1String("- ")));
int k = KMessageBox::questionYesNo(nullptr, str, i18nc("@title:window",
"Secret key imported"));
if (k == KMessageBox::Yes) {
//To use the ChangeOwnerTrustJob over
//the CryptoBackendFactory
const QGpgME::Protocol *const backend = QGpgME::openpgp();
if (!backend){
qCWarning(KLEOPATRA_LOG) << "Failed to get CryptoBackend";
return;
}
ChangeOwnerTrustJob *const j = backend->changeOwnerTrustJob();
j->start(toTrustOwner, Key::Ultimate);
}
}
}
}
static void validateImportedCertificate(const GpgME::Import &import)
{
if (const auto fpr = import.fingerprint()) {
auto key = KeyCache::instance()->findByFingerprint(fpr);
if (!key.isNull()) {
// this triggers a keylisting with validation for this certificate
key.update();
} else {
qCWarning(KLEOPATRA_LOG) << __func__ << "Certificate with fingerprint" << fpr << "not found";
}
}
}
static void handleExternalCMSImports(const std::vector &results)
{
// For external CMS Imports we have to manually do a keylist
// with validation to get the intermediate and root ca imported
// automatically if trusted-certs and extra-certs are used.
for (const auto &r : results) {
if (r.protocol == GpgME::CMS && r.type == ImportType::External
&& !importFailed(r) && !importWasCanceled(r)) {
const auto imports = r.result.imports();
std::for_each(std::begin(imports), std::end(imports), &validateImportedCertificate);
}
}
}
void ImportCertificatesCommand::Private::processResults()
{
+ importGroups();
+
handleExternalCMSImports(results);
- handleOwnerTrust(results);
+ // ensure that the progress dialog is closed before we show any other dialogs
+ setProgressToMaximum();
- importGroups();
+ handleOwnerTrust(results);
showDetails(results, importedGroups);
auto tv = dynamic_cast (view());
if (!tv) {
qCDebug(KLEOPATRA_LOG) << "Failed to find treeview";
} else {
tv->expandAll();
}
finished();
}
void ImportCertificatesCommand::Private::tryToFinish()
{
if (waitForMoreJobs || !jobs.empty()) {
return;
}
auto keyCache = KeyCache::mutableInstance();
keyListConnection = connect(keyCache.get(), &KeyCache::keyListingDone,
q, [this]() { keyCacheUpdated(); });
keyCache->startKeyListing();
}
void ImportCertificatesCommand::Private::keyCacheUpdated()
{
disconnect(keyListConnection);
keyCacheAutoRefreshSuspension.reset();
const auto allIds = std::accumulate(std::cbegin(results), std::cend(results),
std::set{},
[](auto &allIds, const auto &r) {
allIds.insert(r.id);
return allIds;
});
const auto canceledIds = std::accumulate(std::cbegin(results), std::cend(results),
std::set{},
[](auto &canceledIds, const auto &r) {
if (importWasCanceled(r)) {
canceledIds.insert(r.id);
}
return canceledIds;
});
const auto totalConsidered = std::accumulate(std::cbegin(results), std::cend(results),
0,
[](auto totalConsidered, const auto &r) {
return totalConsidered + r.result.numConsidered();
});
if (totalConsidered == 0 && canceledIds.size() == allIds.size()) {
// nothing was considered for import and at least one import per id was
// canceled => treat the command as canceled
canceled();
return;
}
if (std::any_of(std::cbegin(results), std::cend(results), &importFailed)) {
+ // ensure that the progress dialog is closed before we show any other dialogs
+ setProgressToMaximum();
setImportResultProxyModel(results);
for (const auto &r : results) {
if (importFailed(r)) {
showError(r.result.error(), r.id);
}
}
finished();
return;
}
processResults();
}
static ImportedGroup storeGroup(const KeyGroup &group, const QString &id)
{
const auto status = KeyCache::instance()->group(group.id()).isNull() ?
ImportedGroup::Status::New :
ImportedGroup::Status::Updated;
if (status == ImportedGroup::Status::New) {
KeyCache::mutableInstance()->insert(group);
} else {
KeyCache::mutableInstance()->update(group);
}
return {id, group, status};
}
void ImportCertificatesCommand::Private::importGroups()
{
for (const auto &path : filesToImportGroupsFrom) {
const bool certificateImportSucceeded =
std::any_of(std::cbegin(results), std::cend(results),
[path](const auto &r) {
return r.id == path && !importFailed(r) && !importWasCanceled(r);
});
if (certificateImportSucceeded) {
qCDebug(KLEOPATRA_LOG) << __func__ << "Importing groups from file" << path;
const auto groups = readKeyGroups(path);
std::transform(std::begin(groups), std::end(groups),
std::back_inserter(importedGroups),
[path](const auto &group) {
return storeGroup(group, path);
});
}
+ increaseProgressValue();
}
}
static std::unique_ptr get_import_job(GpgME::Protocol protocol)
{
Q_ASSERT(protocol != UnknownProtocol);
if (const auto backend = (protocol == GpgME::OpenPGP ? QGpgME::openpgp() : QGpgME::smime())) {
return std::unique_ptr(backend->importJob());
} else {
return std::unique_ptr();
}
}
void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, const QByteArray &data, const QString &id, const ImportOptions &options)
{
Q_ASSERT(protocol != UnknownProtocol);
if (std::find(nonWorkingProtocols.cbegin(), nonWorkingProtocols.cend(), protocol) != nonWorkingProtocols.cend()) {
return;
}
std::unique_ptr job = get_import_job(protocol);
if (!job.get()) {
nonWorkingProtocols.push_back(protocol);
error(i18n("The type of this certificate (%1) is not supported by this Kleopatra installation.",
Formatting::displayName(protocol)),
i18n("Certificate Import Failed"));
importResult({id, protocol, ImportType::Local, ImportResult{}});
return;
}
keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh();
std::vector connections = {
connect(job.get(), SIGNAL(result(GpgME::ImportResult)),
q, SLOT(importResult(GpgME::ImportResult))),
connect(job.get(), &Job::progress,
q, &Command::progress)
};
#ifdef QGPGME_SUPPORTS_IMPORT_WITH_FILTER
job->setImportFilter(options.importFilter);
#endif
#ifdef QGPGME_SUPPORTS_IMPORT_WITH_KEY_ORIGIN
job->setKeyOrigin(options.keyOrigin, options.keyOriginUrl);
#endif
const GpgME::Error err = job->start(data);
if (err.code()) {
importResult({id, protocol, ImportType::Local, ImportResult{err}});
} else {
+ increaseProgressMaximum();
jobs.push_back({id, protocol, ImportType::Local, job.release(), connections});
}
}
static std::unique_ptr get_import_from_keyserver_job(GpgME::Protocol protocol)
{
Q_ASSERT(protocol != UnknownProtocol);
if (const auto backend = (protocol == GpgME::OpenPGP ? QGpgME::openpgp() : QGpgME::smime())) {
return std::unique_ptr(backend->importFromKeyserverJob());
} else {
return std::unique_ptr();
}
}
void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, const std::vector &keys, const QString &id)
{
Q_ASSERT(protocol != UnknownProtocol);
if (std::find(nonWorkingProtocols.cbegin(), nonWorkingProtocols.cend(), protocol) != nonWorkingProtocols.cend()) {
return;
}
std::unique_ptr job = get_import_from_keyserver_job(protocol);
if (!job.get()) {
nonWorkingProtocols.push_back(protocol);
error(i18n("The type of this certificate (%1) is not supported by this Kleopatra installation.",
Formatting::displayName(protocol)),
i18n("Certificate Import Failed"));
importResult({id, protocol, ImportType::External, ImportResult{}});
return;
}
keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh();
std::vector connections = {
connect(job.get(), SIGNAL(result(GpgME::ImportResult)),
q, SLOT(importResult(GpgME::ImportResult))),
connect(job.get(), &Job::progress,
q, &Command::progress)
};
const GpgME::Error err = job->start(keys);
if (err.code()) {
importResult({id, protocol, ImportType::External, ImportResult{err}});
} else {
+ increaseProgressMaximum();
jobs.push_back({id, protocol, ImportType::External, job.release(), connections});
}
}
static auto get_receive_keys_job(GpgME::Protocol protocol)
{
Q_ASSERT(protocol != UnknownProtocol);
#ifdef QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID
std::unique_ptr job{};
if (const auto backend = (protocol == GpgME::OpenPGP ? QGpgME::openpgp() : QGpgME::smime())) {
job.reset(backend->receiveKeysJob());
}
return job;
#else
return std::unique_ptr{};
#endif
}
void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, const QStringList &keyIds, const QString &id)
{
Q_ASSERT(protocol != UnknownProtocol);
auto job = get_receive_keys_job(protocol);
if (!job.get()) {
qCWarning(KLEOPATRA_LOG) << "Failed to get ReceiveKeysJob for protocol" << Formatting::displayName(protocol);
importResult({id, protocol, ImportType::External, ImportResult{}});
return;
}
#ifdef QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID
keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh();
std::vector connections = {
connect(job.get(), SIGNAL(result(GpgME::ImportResult)),
q, SLOT(importResult(GpgME::ImportResult))),
connect(job.get(), &Job::progress,
q, &Command::progress)
};
const GpgME::Error err = job->start(keyIds);
if (err.code()) {
importResult({id, protocol, ImportType::External, ImportResult{err}});
} else {
+ increaseProgressMaximum();
jobs.push_back({id, protocol, ImportType::External, job.release(), connections});
}
#endif
}
void ImportCertificatesCommand::Private::importGroupsFromFile(const QString &filename)
{
+ increaseProgressMaximum();
filesToImportGroupsFrom.push_back(filename);
}
+void ImportCertificatesCommand::Private::setUpProgressDialog()
+{
+ if (progressDialog) {
+ return;
+ }
+ progressDialog = new QProgressDialog{parentWidgetOrView()};
+ progressDialog->setModal(true);
+ progressDialog->setWindowTitle(progressWindowTitle);
+ progressDialog->setLabelText(progressLabelText);
+ progressDialog->setMinimumDuration(1000);
+ progressDialog->setMaximum(1);
+ progressDialog->setValue(0);
+ connect(progressDialog, &QProgressDialog::canceled, q, &Command::cancel);
+ connect(q, &Command::finished, progressDialog, [this]() { progressDialog->accept(); });
+}
+
+void ImportCertificatesCommand::Private::setProgressWindowTitle(const QString &title)
+{
+ if (progressDialog) {
+ progressDialog->setWindowTitle(title);
+ } else {
+ progressWindowTitle = title;
+ }
+}
+
+void ImportCertificatesCommand::Private::setProgressLabelText(const QString &text)
+{
+ if (progressDialog) {
+ progressDialog->setLabelText(text);
+ } else {
+ progressLabelText = text;
+ }
+}
+
+void ImportCertificatesCommand::Private::increaseProgressMaximum()
+{
+ setUpProgressDialog();
+ progressDialog->setMaximum(progressDialog->maximum() + 1);
+ qCDebug(KLEOPATRA_LOG) << __func__ << "progress:" << progressDialog->value() << "/" << progressDialog->maximum();
+}
+
+void ImportCertificatesCommand::Private::increaseProgressValue()
+{
+ progressDialog->setValue(progressDialog->value() + 1);
+ qCDebug(KLEOPATRA_LOG) << __func__ << "progress:" << progressDialog->value() << "/" << progressDialog->maximum();
+}
+
+void ImportCertificatesCommand::Private::setProgressToMaximum()
+{
+ qCDebug(KLEOPATRA_LOG) << __func__;
+ progressDialog->setValue(progressDialog->maximum());
+}
+
void ImportCertificatesCommand::doCancel()
{
const auto jobsToCancel = d->jobs;
std::for_each(std::begin(jobsToCancel), std::end(jobsToCancel),
[this](const auto &job) {
std::for_each(std::cbegin(job.connections), std::cend(job.connections),
[this](const auto &connection) { QObject::disconnect(connection); });
job.job->slotCancel();
d->importResult(ImportResult{Error::fromCode(GPG_ERR_CANCELED)}, job.job);
});
}
#undef d
#undef q
#include "moc_importcertificatescommand.cpp"
#include "importcertificatescommand.moc"
diff --git a/src/commands/importcertificatescommand_p.h b/src/commands/importcertificatescommand_p.h
index 0e8eb5a9d..56fd9ca4f 100644
--- a/src/commands/importcertificatescommand_p.h
+++ b/src/commands/importcertificatescommand_p.h
@@ -1,152 +1,164 @@
/* -*- mode: c++; c-basic-offset:4 -*-
commands/importcertificatescommand_p.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007, 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2021, 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "command_p.h"
#include "importcertificatescommand.h"
#include
#include
#include
#include
#include