Messagelib

encryptjob.cpp
1/*
2 SPDX-FileCopyrightText: 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
3 SPDX-FileCopyrightText: 2009 Leo Franchi <lfranchi@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "job/encryptjob.h"
9
10#include "contentjobbase_p.h"
11#include "job/protectedheadersjob.h"
12#include "utils/util_p.h"
13
14#include <QGpgME/EncryptJob>
15#include <QGpgME/Protocol>
16
17#include <Libkleo/Formatting>
18
19#include "messagecomposer_debug.h"
20
21#include <gpgme++/encryptionresult.h>
22#include <gpgme++/global.h>
23#include <gpgme++/signingresult.h>
24#include <sstream>
25
26using namespace MessageComposer;
27
28class MessageComposer::EncryptJobPrivate : public ContentJobBasePrivate
29{
30public:
31 EncryptJobPrivate(EncryptJob *qq)
32 : ContentJobBasePrivate(qq)
33 {
34 }
35
36 QString gnupgHome;
37 QStringList recipients;
38 std::vector<GpgME::Key> keys;
39 Kleo::CryptoMessageFormat format;
40 KMime::Content *content = nullptr;
41 KMime::Message *skeletonMessage = nullptr;
42
43 bool protectedHeaders = true;
44 bool protectedHeadersObvoscate = false;
45
46 // copied from messagecomposer.cpp
47 bool binaryHint(Kleo::CryptoMessageFormat f)
48 {
49 switch (f) {
50 case Kleo::SMIMEFormat:
51 case Kleo::SMIMEOpaqueFormat:
52 return true;
53 default:
54 case Kleo::OpenPGPMIMEFormat:
55 case Kleo::InlineOpenPGPFormat:
56 return false;
57 }
58 }
59
60 GpgME::SignatureMode signingMode(Kleo::CryptoMessageFormat f)
61 {
62 switch (f) {
63 case Kleo::SMIMEOpaqueFormat:
64 return GpgME::NormalSignatureMode;
65 case Kleo::InlineOpenPGPFormat:
66 return GpgME::Clearsigned;
67 default:
68 case Kleo::SMIMEFormat:
69 case Kleo::OpenPGPMIMEFormat:
70 return GpgME::Detached;
71 }
72 }
73
74 Q_DECLARE_PUBLIC(EncryptJob)
75};
76
77EncryptJob::EncryptJob(QObject *parent)
78 : ContentJobBase(*new EncryptJobPrivate(this), parent)
79{
80}
81
82EncryptJob::~EncryptJob() = default;
83
84void EncryptJob::setContent(KMime::Content *content)
85{
87
88 d->content = content;
89 d->content->assemble();
90}
91
92void EncryptJob::setCryptoMessageFormat(Kleo::CryptoMessageFormat format)
93{
95
96 d->format = format;
97}
98
99void EncryptJob::setEncryptionKeys(const std::vector<GpgME::Key> &keys)
100{
102
103 d->keys = keys;
104}
105
106void EncryptJob::setRecipients(const QStringList &recipients)
107{
109
110 d->recipients = recipients;
111}
112
113void EncryptJob::setSkeletonMessage(KMime::Message *skeletonMessage)
114{
116
117 d->skeletonMessage = skeletonMessage;
118}
119
120void EncryptJob::setProtectedHeaders(bool protectedHeaders)
121{
123
124 d->protectedHeaders = protectedHeaders;
125}
126
127void EncryptJob::setProtectedHeadersObvoscate(bool protectedHeadersObvoscate)
128{
130
131 d->protectedHeadersObvoscate = protectedHeadersObvoscate;
132}
133
134void EncryptJob::setGnupgHome(const QString &path)
135{
137
138 d->gnupgHome = path;
139}
140
141QStringList EncryptJob::recipients() const
142{
143 Q_D(const EncryptJob);
144
145 return d->recipients;
146}
147
148std::vector<GpgME::Key> EncryptJob::encryptionKeys() const
149{
150 Q_D(const EncryptJob);
151
152 return d->keys;
153}
154
155void EncryptJob::doStart()
156{
158 Q_ASSERT(d->resultContent == nullptr); // Not processed before.
159
160 if (d->keys.size() == 0) { // should not happen---resolver should have dealt with it earlier
161 qCDebug(MESSAGECOMPOSER_LOG) << "HELP! Encrypt job but have no keys to encrypt with.";
162 return;
163 }
164
165 // if setContent hasn't been called, we assume that a subjob was added
166 // and we want to use that
167 if (!d->content || !d->content->hasContent()) {
168 if (d->subjobContents.size() == 1) {
169 d->content = d->subjobContents.constFirst();
170 }
171 }
172
173 if (d->protectedHeaders && d->skeletonMessage && d->format & Kleo::OpenPGPMIMEFormat) {
174 auto pJob = new ProtectedHeadersJob;
175 pJob->setContent(d->content);
176 pJob->setSkeletonMessage(d->skeletonMessage);
177 pJob->setObvoscate(d->protectedHeadersObvoscate);
178 QObject::connect(pJob, &ProtectedHeadersJob::finished, this, [d, pJob](KJob *job) {
179 if (job->error()) {
180 return;
181 }
182 d->content = pJob->content();
183 });
184 appendSubjob(pJob);
185 }
186
188}
189
190void EncryptJob::slotResult(KJob *job)
191{
192 // Q_D(EncryptJob);
193 if (error() || job->error()) {
194 ContentJobBase::slotResult(job);
195 return;
196 }
197 if (subjobs().size() == 2) {
198 auto pjob = static_cast<ProtectedHeadersJob *>(subjobs().last());
199 if (pjob) {
200 auto cjob = qobject_cast<ContentJobBase *>(job);
201 Q_ASSERT(cjob);
202 pjob->setContent(cjob->content());
203 }
204 }
205
206 ContentJobBase::slotResult(job);
207}
208
209void EncryptJob::process()
210{
212
213 // if setContent hasn't been called, we assume that a subjob was added
214 // and we want to use that
215 if (!d->content || !d->content->hasContent()) {
216 Q_ASSERT(d->subjobContents.size() == 1);
217 d->content = d->subjobContents.constFirst();
218 }
219
220 const QGpgME::Protocol *proto = nullptr;
221 if (d->format & Kleo::AnyOpenPGP) {
222 proto = QGpgME::openpgp();
223 } else if (d->format & Kleo::AnySMIME) {
224 proto = QGpgME::smime();
225 } else {
226 qCDebug(MESSAGECOMPOSER_LOG) << "HELP! Encrypt job but have protocol to encrypt with.";
227 return;
228 }
229
230 Q_ASSERT(proto);
231
232 // for now just do the main recipients
234 d->content->assemble();
235 if (d->format & Kleo::InlineOpenPGPFormat) {
236 content = d->content->body();
237 } else {
239 }
240
241 qCDebug(MESSAGECOMPOSER_LOG) << "got backend, starting job";
242 QGpgME::EncryptJob *eJob = proto->encryptJob(!d->binaryHint(d->format), d->format == Kleo::InlineOpenPGPFormat);
243
244 if (!d->gnupgHome.isEmpty()) {
245 QGpgME::Job::context(eJob)->setEngineHomeDirectory(d->gnupgHome.toUtf8().constData());
246 }
247
249 eJob,
250 &QGpgME::EncryptJob::result,
251 this,
252 [this, d](const GpgME::EncryptionResult &result, const QByteArray &cipherText, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) {
253 Q_UNUSED(auditLogAsHtml)
254 Q_UNUSED(auditLogError)
255 if (result.error()) {
256 setError(result.error().code());
257 setErrorText(Kleo::Formatting::errorAsString(result.error()));
258 emitResult();
259 return;
260 }
261 d->resultContent = MessageComposer::Util::composeHeadersAndBody(d->content, cipherText, d->format, false);
262
263 emitResult();
264 });
265
266 const auto error = eJob->start(d->keys, content, true);
267 if (error.code()) {
268 eJob->deleteLater();
269 setError(error.code());
270 setErrorText(Kleo::Formatting::errorAsString(error));
271 emitResult();
272 }
273}
274
275#include "moc_encryptjob.cpp"
const QList< KJob * > & subjobs() const
void setErrorText(const QString &errorText)
void emitResult()
int error() const
void result(KJob *job)
void finished(KJob *job)
void setError(int errorCode)
Content * content(const ContentIndex &index) const
QByteArray body() const
QByteArray encodedContent(bool useCrLf=false) const
The ContentJobBase class.
virtual void doStart()
Reimplement to do additional stuff before processing children, such as adding more subjobs.
bool appendSubjob(ContentJobBase *job)
This is meant to be used instead of KCompositeJob::addSubjob(), making it possible to add subjobs fro...
KMime::Content * content() const
Get the resulting KMime::Content that the ContentJobBase has generated.
Encrypt the contents of a message .
Definition encryptjob.h:34
Copies headers from skeleton message to content.
QString path(const QString &relativePath)
Simple interface that both EncryptJob and SignEncryptJob implement so the composer can extract some e...
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:08:46 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.