Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34166299
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
29 KB
Subscribers
None
View Options
diff --git a/src/crypto/autodecryptverifyfilescontroller.cpp b/src/crypto/autodecryptverifyfilescontroller.cpp
index 4b79c1571..ef89983c0 100644
--- a/src/crypto/autodecryptverifyfilescontroller.cpp
+++ b/src/crypto/autodecryptverifyfilescontroller.cpp
@@ -1,664 +1,666 @@
/* -*- mode: c++; c-basic-offset:4 -*-
autodecryptverifyfilescontroller.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 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-or-later
*/
#include <config-kleopatra.h>
#include "autodecryptverifyfilescontroller.h"
#include "fileoperationspreferences.h"
#include <crypto/decryptverifytask.h>
#include <crypto/gui/decryptverifyfilesdialog.h>
#include <crypto/gui/decryptverifyoperationwidget.h>
#include <crypto/taskcollection.h>
#include "commands/decryptverifyfilescommand.h"
-#include <Libkleo/GnuPG>
#include <utils/archivedefinition.h>
#include <utils/input.h>
#include <utils/kleo_assert.h>
#include <utils/output.h>
+#include <utils/overwritedialog.h>
#include <utils/path-helper.h>
+#include <Libkleo/Algorithm>
#include <Libkleo/Classify>
+#include <Libkleo/GnuPG>
#ifndef Q_OS_WIN
#include <KIO/CopyJob>
#include <KIO/Global>
#endif
#include "kleopatra_debug.h"
#include <KLocalizedString>
#include <KMessageBox>
#include <QGpgME/DecryptVerifyArchiveJob>
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QTemporaryDir>
#include <QTimer>
#include <gpgme++/decryptionresult.h>
using namespace GpgME;
using namespace Kleo;
using namespace Kleo::Crypto;
using namespace Kleo::Crypto::Gui;
class AutoDecryptVerifyFilesController::Private
{
AutoDecryptVerifyFilesController *const q;
public:
explicit Private(AutoDecryptVerifyFilesController *qq);
void schedule();
QString getEmbeddedFileName(const QString &fileName) const;
void exec();
std::vector<std::shared_ptr<Task>> buildTasks(const QStringList &, QStringList &);
struct CryptoFile {
QString baseName;
QString fileName;
GpgME::Protocol protocol = GpgME::UnknownProtocol;
int classification = 0;
std::shared_ptr<Output> output;
};
QVector<CryptoFile> classifyAndSortFiles(const QStringList &files);
void reportError(int err, const QString &details)
{
q->setLastError(err, details);
q->emitDoneOrError();
}
void cancelAllTasks();
QStringList m_passedFiles, m_filesAfterPreparation;
std::vector<std::shared_ptr<const DecryptVerifyResult>> m_results;
std::vector<std::shared_ptr<Task>> m_runnableTasks, m_completedTasks;
std::shared_ptr<Task> m_runningTask;
bool m_errorDetected = false;
DecryptVerifyOperation m_operation = DecryptVerify;
QPointer<DecryptVerifyFilesDialog> m_dialog;
std::unique_ptr<QTemporaryDir> m_workDir;
};
AutoDecryptVerifyFilesController::Private::Private(AutoDecryptVerifyFilesController *qq)
: q(qq)
{
qRegisterMetaType<VerificationResult>();
}
void AutoDecryptVerifyFilesController::Private::schedule()
{
if (!m_runningTask && !m_runnableTasks.empty()) {
const std::shared_ptr<Task> t = m_runnableTasks.back();
m_runnableTasks.pop_back();
t->start();
m_runningTask = t;
}
if (!m_runningTask) {
kleo_assert(m_runnableTasks.empty());
for (const std::shared_ptr<const DecryptVerifyResult> &i : std::as_const(m_results)) {
Q_EMIT q->verificationResult(i->verificationResult());
}
}
}
QString AutoDecryptVerifyFilesController::Private::getEmbeddedFileName(const QString &fileName) const
{
auto it = std::find_if(m_results.cbegin(), m_results.cend(), [fileName](const auto &r) {
return r->fileName() == fileName;
});
if (it != m_results.cend()) {
const auto embeddedFilePath = QString::fromUtf8((*it)->decryptionResult().fileName());
if (embeddedFilePath.contains(QLatin1Char{'\\'})) {
// ignore embedded file names containing '\'
return {};
}
// strip the path from the embedded file name
return QFileInfo{embeddedFilePath}.fileName();
} else {
return {};
}
}
void AutoDecryptVerifyFilesController::Private::exec()
{
Q_ASSERT(!m_dialog);
QStringList undetected;
std::vector<std::shared_ptr<Task>> tasks = buildTasks(m_passedFiles, undetected);
if (!undetected.isEmpty()) {
// Since GpgME 1.7.0 Classification is supposed to be reliable
// so we really can't do anything with this data.
reportError(makeGnuPGError(GPG_ERR_GENERAL),
xi18n("Failed to find encrypted or signed data in one or more files.<nl/>"
"You can manually select what to do with the files now.<nl/>"
"If they contain signed or encrypted data please report a bug (see Help->Report Bug)."));
auto cmd = new Commands::DecryptVerifyFilesCommand(undetected, nullptr, true);
cmd->start();
}
if (tasks.empty()) {
q->emitDoneOrError();
return;
}
Q_ASSERT(m_runnableTasks.empty());
m_runnableTasks.swap(tasks);
std::shared_ptr<TaskCollection> coll(new TaskCollection);
for (const std::shared_ptr<Task> &i : std::as_const(m_runnableTasks)) {
q->connectTask(i);
}
coll->setTasks(m_runnableTasks);
DecryptVerifyFilesDialog dialog{coll};
m_dialog = &dialog;
m_dialog->setOutputLocation(heuristicBaseDirectory(m_passedFiles));
QTimer::singleShot(0, q, SLOT(schedule()));
const auto result = m_dialog->exec();
if (result == QDialog::Rejected) {
q->cancel();
} else if (result == QDialog::Accepted && m_workDir) {
// Without workdir there is nothing to move.
const QDir workdir(m_workDir->path());
const QDir outDir(m_dialog->outputLocation());
- bool overWriteAll = false;
qCDebug(KLEOPATRA_LOG) << workdir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
- for (const QFileInfo &fi : workdir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot)) {
+ const auto filesAndFoldersToMove = workdir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
+ const auto fileCount = Kleo::count_if(filesAndFoldersToMove, [](const auto &fi) {
+ return !fi.isDir();
+ });
+ OverwritePolicy overwritePolicy{m_dialog, fileCount > 1 ? OverwritePolicy::MultipleFiles : OverwritePolicy::Options{}};
+ for (const QFileInfo &fi : filesAndFoldersToMove) {
const auto inpath = fi.absoluteFilePath();
if (fi.isDir()) {
// A directory. Assume that the input was an archive
// and avoid directory merges by trying to find a non
// existing directory.
auto candidate = fi.fileName();
if (candidate.startsWith(QLatin1Char('-'))) {
// Bug in GpgTar Extracts stdout passed archives to a dir named -
candidate = QFileInfo(m_passedFiles.first()).baseName();
}
QString suffix;
QFileInfo ofi;
int i = 0;
do {
ofi = QFileInfo(outDir.absoluteFilePath(candidate + suffix));
if (!ofi.exists()) {
break;
}
suffix = QStringLiteral("_%1").arg(++i);
} while (i < 1000);
const auto destPath = ofi.absoluteFilePath();
#ifndef Q_OS_WIN
auto job = KIO::moveAs(QUrl::fromLocalFile(inpath), QUrl::fromLocalFile(destPath));
qCDebug(KLEOPATRA_LOG) << "Moving" << job->srcUrls().front().toLocalFile() << "to" << job->destUrl().toLocalFile();
if (!job->exec()) {
if (job->error() == KIO::ERR_USER_CANCELED) {
break;
}
reportError(makeGnuPGError(GPG_ERR_GENERAL),
xi18nc("@info",
"<para>Failed to move <filename>%1</filename> to <filename>%2</filename>.</para>"
"<para><message>%3</message></para>",
inpath,
destPath,
job->errorString()));
}
#else
// On Windows, KIO::move does not work for folders when crossing partition boundaries
if (!moveDir(inpath, destPath)) {
reportError(makeGnuPGError(GPG_ERR_GENERAL),
xi18nc("@info", "<para>Failed to move <filename>%1</filename> to <filename>%2</filename>.</para>", inpath, destPath));
}
#endif
continue;
}
const auto embeddedFileName = getEmbeddedFileName(inpath);
QString outFileName = fi.fileName();
if (!embeddedFileName.isEmpty() && embeddedFileName != fi.fileName()) {
// we switch "Yes" and "No" because Yes is default, but saving with embedded file name could be dangerous
const auto answer = KMessageBox::questionTwoActionsCancel(
m_dialog,
xi18n("Shall the file be saved with the original file name <filename>%1</filename>?", embeddedFileName),
i18n("Use Original File Name?"),
KGuiItem(xi18n("No, Save As <filename>%1</filename>", fi.fileName())),
KGuiItem(xi18n("Yes, Save As <filename>%1</filename>", embeddedFileName)));
if (answer == KMessageBox::Cancel) {
qCDebug(KLEOPATRA_LOG) << "Saving canceled for:" << inpath;
continue;
} else if (answer == KMessageBox::ButtonCode::SecondaryAction) {
outFileName = embeddedFileName;
}
}
- const auto outpath = outDir.absoluteFilePath(outFileName);
+ auto outpath = outDir.absoluteFilePath(outFileName);
qCDebug(KLEOPATRA_LOG) << "Moving " << inpath << " to " << outpath;
const QFileInfo ofi(outpath);
if (ofi.exists()) {
- int sel = KMessageBox::Cancel;
- if (!overWriteAll) {
- sel = KMessageBox::questionTwoActionsCancel(m_dialog,
- i18n("The file <b>%1</b> already exists.\n"
- "Overwrite?",
- outpath),
- i18n("Overwrite Existing File?"),
- KStandardGuiItem::overwrite(),
- KGuiItem(i18n("Overwrite All")),
- KStandardGuiItem::cancel());
- }
- if (sel == KMessageBox::Cancel) {
- qCDebug(KLEOPATRA_LOG) << "Overwriting canceled for: " << outpath;
- continue;
- }
- if (sel == KMessageBox::ButtonCode::SecondaryAction) { // Overwrite All
- overWriteAll = true;
- }
- if (!QFile::remove(outpath)) {
- reportError(makeGnuPGError(GPG_ERR_GENERAL), xi18n("Failed to delete <filename>%1</filename>.", outpath));
+ const auto newPath = overwritePolicy.obtainOverwritePermission(outpath);
+ if (newPath.isEmpty()) {
+ if (overwritePolicy.policy() == OverwritePolicy::Cancel) {
+ qCDebug(KLEOPATRA_LOG) << "Overwriting canceled for: " << outpath;
+ break;
+ }
+ // else Skip
continue;
+ } else if (newPath == outpath) {
+ // overwrite existing file
+ if (!QFile::remove(outpath)) {
+ reportError(makeGnuPGError(GPG_ERR_GENERAL), xi18n("Failed to delete <filename>%1</filename>.", outpath));
+ continue;
+ }
+ } else {
+ // use new name for file
+ outpath = newPath;
}
}
if (!QFile::rename(inpath, outpath)) {
reportError(makeGnuPGError(GPG_ERR_GENERAL), xi18n("Failed to move <filename>%1</filename> to <filename>%2</filename>.", inpath, outpath));
}
}
}
q->emitDoneOrError();
}
QVector<AutoDecryptVerifyFilesController::Private::CryptoFile> AutoDecryptVerifyFilesController::Private::classifyAndSortFiles(const QStringList &files)
{
const auto isSignature = [](int classification) -> bool {
return mayBeDetachedSignature(classification) //
|| mayBeOpaqueSignature(classification) //
|| (classification & Class::TypeMask) == Class::ClearsignedMessage;
};
QVector<CryptoFile> out;
for (const auto &file : files) {
CryptoFile cFile;
cFile.fileName = file;
cFile.baseName = stripSuffix(file);
cFile.classification = classify(file);
cFile.protocol = findProtocol(cFile.classification);
auto it = std::find_if(out.begin(), out.end(), [&cFile](const CryptoFile &other) {
return other.protocol == cFile.protocol && other.baseName == cFile.baseName;
});
if (it != out.end()) {
// If we found a file with the same basename, make sure that encrypted
// file is before the signature file, so that we first decrypt and then
// verify
if (isSignature(cFile.classification) && isCipherText(it->classification)) {
out.insert(it + 1, cFile);
} else if (isCipherText(cFile.classification) && isSignature(it->classification)) {
out.insert(it, cFile);
} else {
// both are signatures or both are encrypted files, in which
// case order does not matter
out.insert(it, cFile);
}
} else {
out.push_back(cFile);
}
}
return out;
}
static bool archiveJobsCanBeUsed([[maybe_unused]] GpgME::Protocol protocol)
{
return (protocol == GpgME::OpenPGP) && QGpgME::DecryptVerifyArchiveJob::isSupported();
}
std::vector<std::shared_ptr<Task>> AutoDecryptVerifyFilesController::Private::buildTasks(const QStringList &fileNames, QStringList &undetected)
{
// sort files so that we make sure we first decrypt and then verify
QVector<CryptoFile> cryptoFiles = classifyAndSortFiles(fileNames);
std::vector<std::shared_ptr<Task>> tasks;
for (auto it = cryptoFiles.begin(), end = cryptoFiles.end(); it != end; ++it) {
auto &cFile = (*it);
QFileInfo fi(cFile.fileName);
qCDebug(KLEOPATRA_LOG) << "classified" << cFile.fileName << "as" << printableClassification(cFile.classification);
if (!fi.isReadable()) {
reportError(makeGnuPGError(GPG_ERR_ASS_NO_INPUT), xi18n("Cannot open <filename>%1</filename> for reading.", cFile.fileName));
continue;
}
if (mayBeAnyCertStoreType(cFile.classification)) {
// Trying to verify a certificate. Possible because extensions are often similar
// for PGP Keys.
reportError(makeGnuPGError(GPG_ERR_ASS_NO_INPUT),
xi18n("The file <filename>%1</filename> contains certificates and can't be decrypted or verified.", cFile.fileName));
qCDebug(KLEOPATRA_LOG) << "reported error";
continue;
}
// We can't reliably detect CMS detached signatures, so we will try to do
// our best to use the current file as a detached signature and fallback to
// opaque signature otherwise.
if (cFile.protocol == GpgME::CMS && mayBeDetachedSignature(cFile.classification)) {
// First, see if previous task was a decryption task for the same file
// and "pipe" it's output into our input
std::shared_ptr<Input> input;
bool prepend = false;
if (it != cryptoFiles.begin()) {
const auto prev = it - 1;
if (prev->protocol == cFile.protocol && prev->baseName == cFile.baseName) {
input = Input::createFromOutput(prev->output);
prepend = true;
}
}
if (!input) {
if (QFile::exists(cFile.baseName)) {
input = Input::createFromFile(cFile.baseName);
}
}
if (input) {
qCDebug(KLEOPATRA_LOG) << "Detached CMS verify: " << cFile.fileName;
std::shared_ptr<VerifyDetachedTask> t(new VerifyDetachedTask);
t->setInput(Input::createFromFile(cFile.fileName));
t->setSignedData(input);
t->setProtocol(cFile.protocol);
if (prepend) {
// Put the verify task BEFORE the decrypt task in the tasks queue,
// because the tasks are executed in reverse order!
tasks.insert(tasks.end() - 1, t);
} else {
tasks.push_back(t);
}
continue;
} else {
// No signed data, maybe not a detached signature
}
}
if (isDetachedSignature(cFile.classification)) {
// Detached signature, try to find data or ask the user.
QString signedDataFileName = cFile.baseName;
if (!QFile::exists(signedDataFileName)) {
signedDataFileName = QFileDialog::getOpenFileName(nullptr,
xi18n("Select the file to verify with the signature <filename>%1</filename>", fi.fileName()),
fi.path());
}
if (signedDataFileName.isEmpty()) {
qCDebug(KLEOPATRA_LOG) << "No signed data selected. Verify aborted.";
} else {
qCDebug(KLEOPATRA_LOG) << "Detached verify: " << cFile.fileName << " Data: " << signedDataFileName;
std::shared_ptr<VerifyDetachedTask> t(new VerifyDetachedTask);
#if QGPGME_FILE_JOBS_SUPPORT_DIRECT_FILE_IO
if (cFile.protocol == GpgME::OpenPGP) {
t->setSignatureFile(cFile.fileName);
t->setSignedFile(signedDataFileName);
} else {
t->setInput(Input::createFromFile(cFile.fileName));
t->setSignedData(Input::createFromFile(signedDataFileName));
}
#else
t->setInput(Input::createFromFile(cFile.fileName));
t->setSignedData(Input::createFromFile(signedDataFileName));
#endif
t->setProtocol(cFile.protocol);
tasks.push_back(t);
}
continue;
}
if (!mayBeAnyMessageType(cFile.classification)) {
// Not a Message? Maybe there is a signature for this file?
const auto signatures = findSignatures(cFile.fileName);
bool foundSig = false;
if (!signatures.empty()) {
for (const QString &sig : signatures) {
const auto classification = classify(sig);
qCDebug(KLEOPATRA_LOG) << "Guessing: " << sig << " is a signature for: " << cFile.fileName << "Classification: " << classification;
const auto proto = findProtocol(classification);
if (proto == GpgME::UnknownProtocol) {
qCDebug(KLEOPATRA_LOG) << "Could not determine protocol. Skipping guess.";
continue;
}
foundSig = true;
std::shared_ptr<VerifyDetachedTask> t(new VerifyDetachedTask);
#if QGPGME_FILE_JOBS_SUPPORT_DIRECT_FILE_IO
if (cFile.protocol == GpgME::OpenPGP) {
t->setSignatureFile(sig);
t->setSignedFile(cFile.fileName);
} else {
t->setInput(Input::createFromFile(sig));
t->setSignedData(Input::createFromFile(cFile.fileName));
}
#else
t->setInput(Input::createFromFile(sig));
t->setSignedData(Input::createFromFile(cFile.fileName));
#endif
t->setProtocol(proto);
tasks.push_back(t);
}
}
if (!foundSig) {
undetected << cFile.fileName;
qCDebug(KLEOPATRA_LOG) << "Failed detection for: " << cFile.fileName << " adding to undetected.";
}
} else {
const FileOperationsPreferences fileOpSettings;
// Any Message type so we have input and output.
std::shared_ptr<Input> input;
#if QGPGME_FILE_JOBS_SUPPORT_DIRECT_FILE_IO
if (cFile.protocol != GpgME::OpenPGP) {
input = Input::createFromFile(cFile.fileName);
}
#else
input = Input::createFromFile(cFile.fileName);
#endif
std::shared_ptr<ArchiveDefinition> ad;
if (fileOpSettings.autoExtractArchives()) {
const auto archiveDefinitions = ArchiveDefinition::getArchiveDefinitions();
ad = q->pick_archive_definition(cFile.protocol, archiveDefinitions, cFile.fileName);
}
if (fileOpSettings.dontUseTmpDir()) {
if (!m_workDir) {
m_workDir = std::make_unique<QTemporaryDir>(heuristicBaseDirectory(fileNames) + QStringLiteral("/kleopatra-XXXXXX"));
}
if (!m_workDir->isValid()) {
qCDebug(KLEOPATRA_LOG) << heuristicBaseDirectory(fileNames) << "not a valid temporary directory.";
m_workDir.reset();
}
}
if (!m_workDir) {
m_workDir = std::make_unique<QTemporaryDir>();
}
qCDebug(KLEOPATRA_LOG) << "Using:" << m_workDir->path() << "as temporary directory.";
const auto wd = QDir(m_workDir->path());
std::shared_ptr<Output> output;
QString outputFilePath;
if (ad) {
if ((ad->id() == QLatin1String{"tar"}) && archiveJobsCanBeUsed(cFile.protocol)) {
// we don't need an output
} else {
output = ad->createOutputFromUnpackCommand(cFile.protocol, ad->stripExtension(cFile.protocol, cFile.baseName), wd);
}
} else {
outputFilePath = wd.absoluteFilePath(outputFileName(fi.fileName()));
#if QGPGME_FILE_JOBS_SUPPORT_DIRECT_FILE_IO
if (cFile.protocol != GpgME::OpenPGP) {
output = Output::createFromFile(outputFilePath, false);
}
#else
output = Output::createFromFile(outputFilePath, false);
#endif
}
// If this might be opaque CMS signature, then try that. We already handled
// detached CMS signature above
const auto isCMSOpaqueSignature = cFile.protocol == GpgME::CMS && mayBeOpaqueSignature(cFile.classification);
if (isOpaqueSignature(cFile.classification) || isCMSOpaqueSignature) {
qCDebug(KLEOPATRA_LOG) << "creating a VerifyOpaqueTask";
std::shared_ptr<VerifyOpaqueTask> t(new VerifyOpaqueTask);
if (input) {
t->setInput(input);
}
if (output) {
t->setOutput(output);
}
t->setProtocol(cFile.protocol);
if (ad) {
t->setExtractArchive(true);
t->setInputFile(cFile.fileName);
if (output) {
t->setOutputDirectory(m_workDir->path());
} else {
// make gpgtar extract to a subfolder of the work directory based on the input file name
const auto baseFileName = QFileInfo{ad->stripExtension(cFile.protocol, cFile.baseName)}.fileName();
t->setOutputDirectory(QDir{m_workDir->path()}.filePath(baseFileName));
}
#if QGPGME_FILE_JOBS_SUPPORT_DIRECT_FILE_IO
} else if (cFile.protocol == GpgME::OpenPGP) {
t->setInputFile(cFile.fileName);
t->setOutputFile(outputFilePath);
#endif
}
tasks.push_back(t);
} else {
// Any message. That is not an opaque signature needs to be
// decrypted. Verify we always do because we can't know if
// an encrypted message is also signed.
qCDebug(KLEOPATRA_LOG) << "creating a DecryptVerifyTask";
std::shared_ptr<DecryptVerifyTask> t(new DecryptVerifyTask);
if (input) {
t->setInput(input);
}
if (output) {
t->setOutput(output);
}
t->setProtocol(cFile.protocol);
if (ad) {
t->setExtractArchive(true);
t->setInputFile(cFile.fileName);
if (output) {
t->setOutputDirectory(m_workDir->path());
} else {
// make gpgtar extract to a subfolder of the work directory based on the input file name
const auto baseFileName = QFileInfo{ad->stripExtension(cFile.protocol, cFile.baseName)}.fileName();
t->setOutputDirectory(QDir{m_workDir->path()}.filePath(baseFileName));
}
#if QGPGME_FILE_JOBS_SUPPORT_DIRECT_FILE_IO
} else if (cFile.protocol == GpgME::OpenPGP) {
t->setInputFile(cFile.fileName);
t->setOutputFile(outputFilePath);
#endif
}
cFile.output = output;
tasks.push_back(t);
}
}
}
return tasks;
}
void AutoDecryptVerifyFilesController::setFiles(const QStringList &files)
{
d->m_passedFiles = files;
}
AutoDecryptVerifyFilesController::AutoDecryptVerifyFilesController(QObject *parent)
: DecryptVerifyFilesController(parent)
, d(new Private(this))
{
}
AutoDecryptVerifyFilesController::AutoDecryptVerifyFilesController(const std::shared_ptr<const ExecutionContext> &ctx, QObject *parent)
: DecryptVerifyFilesController(ctx, parent)
, d(new Private(this))
{
}
AutoDecryptVerifyFilesController::~AutoDecryptVerifyFilesController()
{
qCDebug(KLEOPATRA_LOG);
}
void AutoDecryptVerifyFilesController::start()
{
d->exec();
}
void AutoDecryptVerifyFilesController::setOperation(DecryptVerifyOperation op)
{
d->m_operation = op;
}
DecryptVerifyOperation AutoDecryptVerifyFilesController::operation() const
{
return d->m_operation;
}
void AutoDecryptVerifyFilesController::Private::cancelAllTasks()
{
// we just kill all runnable tasks - this will not result in
// signal emissions.
m_runnableTasks.clear();
// a cancel() will result in a call to
if (m_runningTask) {
m_runningTask->cancel();
}
}
void AutoDecryptVerifyFilesController::cancel()
{
qCDebug(KLEOPATRA_LOG) << this << __func__;
try {
d->m_errorDetected = true;
if (d->m_dialog) {
d->m_dialog->close();
}
d->cancelAllTasks();
} catch (const std::exception &e) {
qCDebug(KLEOPATRA_LOG) << "Caught exception: " << e.what();
}
}
void AutoDecryptVerifyFilesController::doTaskDone(const Task *task, const std::shared_ptr<const Task::Result> &result)
{
Q_ASSERT(task);
Q_UNUSED(task)
// We could just delete the tasks here, but we can't use
// Qt::QueuedConnection here (we need sender()) and other slots
// might not yet have executed. Therefore, we push completed tasks
// into a burial container
d->m_completedTasks.push_back(d->m_runningTask);
d->m_runningTask.reset();
if (const std::shared_ptr<const DecryptVerifyResult> &dvr = std::dynamic_pointer_cast<const DecryptVerifyResult>(result)) {
d->m_results.push_back(dvr);
}
QTimer::singleShot(0, this, SLOT(schedule()));
}
#include "moc_autodecryptverifyfilescontroller.cpp"
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Dec 12, 11:59 AM (1 d, 15 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a3/41/313340ab86e7473f2efbc5accaf4
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment