File indexing completed on 2024-06-16 04:55:57

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     crypto/encryptemailtask.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "encryptemailtask.h"
0013 
0014 #include <utils/input.h>
0015 #include <utils/kleo_assert.h>
0016 #include <utils/output.h>
0017 
0018 #include <Libkleo/AuditLogEntry>
0019 #include <Libkleo/Formatting>
0020 #include <Libkleo/Stl_Util>
0021 
0022 #include <QGpgME/EncryptJob>
0023 #include <QGpgME/Protocol>
0024 
0025 #include <gpgme++/encryptionresult.h>
0026 #include <gpgme++/key.h>
0027 
0028 #include <KLocalizedString>
0029 
0030 #include <QPointer>
0031 #include <QTextDocument> // for Qt::escape
0032 
0033 using namespace Kleo;
0034 using namespace Kleo::Crypto;
0035 using namespace GpgME;
0036 
0037 namespace
0038 {
0039 
0040 class EncryptEMailResult : public Task::Result
0041 {
0042     const EncryptionResult m_result;
0043     const AuditLogEntry m_auditLog;
0044 
0045 public:
0046     EncryptEMailResult(const EncryptionResult &r, const AuditLogEntry &auditLog)
0047         : Task::Result()
0048         , m_result(r)
0049         , m_auditLog(auditLog)
0050     {
0051     }
0052 
0053     QString overview() const override;
0054     QString details() const override;
0055     GpgME::Error error() const override;
0056     QString errorString() const override;
0057     VisualCode code() const override;
0058     AuditLogEntry auditLog() const override;
0059 };
0060 
0061 QString makeResultString(const EncryptionResult &res)
0062 {
0063     const Error err = res.error();
0064 
0065     if (err.isCanceled()) {
0066         return i18n("Encryption canceled.");
0067     }
0068 
0069     if (err) {
0070         return i18n("Encryption failed: %1", Formatting::errorAsString(err).toHtmlEscaped());
0071     }
0072 
0073     return i18n("Encryption succeeded.");
0074 }
0075 
0076 }
0077 
0078 class EncryptEMailTask::Private
0079 {
0080     friend class ::Kleo::Crypto::EncryptEMailTask;
0081     EncryptEMailTask *const q;
0082 
0083 public:
0084     explicit Private(EncryptEMailTask *qq);
0085 
0086 private:
0087     std::unique_ptr<QGpgME::EncryptJob> createJob(GpgME::Protocol proto);
0088 
0089 private:
0090     void slotResult(const EncryptionResult &);
0091 
0092 private:
0093     std::shared_ptr<Input> input;
0094     std::shared_ptr<Output> output;
0095     std::vector<Key> recipients;
0096 
0097     QPointer<QGpgME::EncryptJob> job;
0098 };
0099 
0100 EncryptEMailTask::Private::Private(EncryptEMailTask *qq)
0101     : q(qq)
0102     , input()
0103     , output()
0104     , job(nullptr)
0105 {
0106 }
0107 
0108 EncryptEMailTask::EncryptEMailTask(QObject *p)
0109     : Task(p)
0110     , d(new Private(this))
0111 {
0112 }
0113 
0114 EncryptEMailTask::~EncryptEMailTask()
0115 {
0116 }
0117 
0118 void EncryptEMailTask::setInput(const std::shared_ptr<Input> &input)
0119 {
0120     kleo_assert(!d->job);
0121     kleo_assert(input);
0122     d->input = input;
0123 }
0124 
0125 void EncryptEMailTask::setOutput(const std::shared_ptr<Output> &output)
0126 {
0127     kleo_assert(!d->job);
0128     kleo_assert(output);
0129     d->output = output;
0130 }
0131 
0132 void EncryptEMailTask::setRecipients(const std::vector<Key> &recipients)
0133 {
0134     kleo_assert(!d->job);
0135     kleo_assert(!recipients.empty());
0136     d->recipients = recipients;
0137 }
0138 
0139 Protocol EncryptEMailTask::protocol() const
0140 {
0141     kleo_assert(!d->recipients.empty());
0142     return d->recipients.front().protocol();
0143 }
0144 
0145 QString EncryptEMailTask::label() const
0146 {
0147     return d->input ? d->input->label() : QString();
0148 }
0149 
0150 unsigned long long EncryptEMailTask::inputSize() const
0151 {
0152     return d->input ? d->input->size() : 0;
0153 }
0154 
0155 void EncryptEMailTask::doStart()
0156 {
0157     kleo_assert(!d->job);
0158     kleo_assert(d->input);
0159     kleo_assert(d->output);
0160     kleo_assert(!d->recipients.empty());
0161 
0162     std::unique_ptr<QGpgME::EncryptJob> job = d->createJob(protocol());
0163     kleo_assert(job.get());
0164 
0165     job->start(d->recipients,
0166                d->input->ioDevice(),
0167                d->output->ioDevice(),
0168                /*alwaysTrust=*/true);
0169 
0170     d->job = job.release();
0171 }
0172 
0173 void EncryptEMailTask::cancel()
0174 {
0175     if (d->job) {
0176         d->job->slotCancel();
0177     }
0178 }
0179 
0180 std::unique_ptr<QGpgME::EncryptJob> EncryptEMailTask::Private::createJob(GpgME::Protocol proto)
0181 {
0182     const QGpgME::Protocol *const backend = (proto == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime();
0183     kleo_assert(backend);
0184     bool shouldArmor = (proto == OpenPGP || q->asciiArmor()) && !output->binaryOpt();
0185     std::unique_ptr<QGpgME::EncryptJob> encryptJob(backend->encryptJob(shouldArmor, /*textmode=*/false));
0186     kleo_assert(encryptJob.get());
0187     if (proto == CMS && !q->asciiArmor() && !output->binaryOpt()) {
0188         encryptJob->setOutputIsBase64Encoded(true);
0189     }
0190     connect(encryptJob.get(), &QGpgME::Job::jobProgress, q, &EncryptEMailTask::setProgress);
0191     connect(encryptJob.get(), SIGNAL(result(GpgME::EncryptionResult, QByteArray)), q, SLOT(slotResult(GpgME::EncryptionResult)));
0192     return encryptJob;
0193 }
0194 
0195 void EncryptEMailTask::Private::slotResult(const EncryptionResult &result)
0196 {
0197     const auto *const job = qobject_cast<const QGpgME::Job *>(q->sender());
0198     if (result.error().code()) {
0199         output->cancel();
0200     } else {
0201         output->finalize();
0202     }
0203     q->emitResult(std::shared_ptr<Result>(new EncryptEMailResult(result, AuditLogEntry::fromJob(job))));
0204 }
0205 
0206 QString EncryptEMailResult::overview() const
0207 {
0208     return makeOverview(makeResultString(m_result));
0209 }
0210 
0211 QString EncryptEMailResult::details() const
0212 {
0213     return QString();
0214 }
0215 
0216 GpgME::Error EncryptEMailResult::error() const
0217 {
0218     return m_result.error();
0219 }
0220 
0221 QString EncryptEMailResult::errorString() const
0222 {
0223     return hasError() ? makeResultString(m_result) : QString();
0224 }
0225 
0226 AuditLogEntry EncryptEMailResult::auditLog() const
0227 {
0228     return m_auditLog;
0229 }
0230 
0231 Task::Result::VisualCode EncryptEMailResult::code() const
0232 {
0233     if (m_result.error().isCanceled()) {
0234         return Warning;
0235     }
0236     return m_result.error().code() ? NeutralError : NeutralSuccess;
0237 }
0238 
0239 #include "moc_encryptemailtask.cpp"