File indexing completed on 2024-06-23 05:13: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"