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 "messagecomposer_debug.h"
18
19#include <gpgme++/encryptionresult.h>
20#include <gpgme++/global.h>
21#include <gpgme++/signingresult.h>
22#include <sstream>
23
24using namespace MessageComposer;
25
26class MessageComposer::EncryptJobPrivate : public ContentJobBasePrivate
27{
28public:
29 EncryptJobPrivate(EncryptJob *qq)
30 : ContentJobBasePrivate(qq)
31 {
32 }
33
34 QString gnupgHome;
35 QStringList recipients;
36 std::vector<GpgME::Key> keys;
37 Kleo::CryptoMessageFormat format;
38 KMime::Content *content = nullptr;
39 KMime::Message *skeletonMessage = nullptr;
40
41 bool protectedHeaders = true;
42 bool protectedHeadersObvoscate = false;
43
44 // copied from messagecomposer.cpp
45 bool binaryHint(Kleo::CryptoMessageFormat f)
46 {
47 switch (f) {
48 case Kleo::SMIMEFormat:
49 case Kleo::SMIMEOpaqueFormat:
50 return true;
51 default:
52 case Kleo::OpenPGPMIMEFormat:
53 case Kleo::InlineOpenPGPFormat:
54 return false;
55 }
56 }
57
58 GpgME::SignatureMode signingMode(Kleo::CryptoMessageFormat f)
59 {
60 switch (f) {
61 case Kleo::SMIMEOpaqueFormat:
62 return GpgME::NormalSignatureMode;
63 case Kleo::InlineOpenPGPFormat:
64 return GpgME::Clearsigned;
65 default:
66 case Kleo::SMIMEFormat:
67 case Kleo::OpenPGPMIMEFormat:
68 return GpgME::Detached;
69 }
70 }
71
72 Q_DECLARE_PUBLIC(EncryptJob)
73};
74
75EncryptJob::EncryptJob(QObject *parent)
76 : ContentJobBase(*new EncryptJobPrivate(this), parent)
77{
78}
79
80EncryptJob::~EncryptJob() = default;
81
82void EncryptJob::setContent(KMime::Content *content)
83{
85
86 d->content = content;
87 d->content->assemble();
88}
89
90void EncryptJob::setCryptoMessageFormat(Kleo::CryptoMessageFormat format)
91{
93
94 d->format = format;
95}
96
97void EncryptJob::setEncryptionKeys(const std::vector<GpgME::Key> &keys)
98{
100
101 d->keys = keys;
102}
103
104void EncryptJob::setRecipients(const QStringList &recipients)
105{
107
108 d->recipients = recipients;
109}
110
111void EncryptJob::setSkeletonMessage(KMime::Message *skeletonMessage)
112{
114
115 d->skeletonMessage = skeletonMessage;
116}
117
118void EncryptJob::setProtectedHeaders(bool protectedHeaders)
119{
121
122 d->protectedHeaders = protectedHeaders;
123}
124
125void EncryptJob::setProtectedHeadersObvoscate(bool protectedHeadersObvoscate)
126{
128
129 d->protectedHeadersObvoscate = protectedHeadersObvoscate;
130}
131
132void EncryptJob::setGnupgHome(const QString &path)
133{
135
136 d->gnupgHome = path;
137}
138
139QStringList EncryptJob::recipients() const
140{
141 Q_D(const EncryptJob);
142
143 return d->recipients;
144}
145
146std::vector<GpgME::Key> EncryptJob::encryptionKeys() const
147{
148 Q_D(const EncryptJob);
149
150 return d->keys;
151}
152
153void EncryptJob::doStart()
154{
156 Q_ASSERT(d->resultContent == nullptr); // Not processed before.
157
158 if (d->keys.size() == 0) { // should not happen---resolver should have dealt with it earlier
159 qCDebug(MESSAGECOMPOSER_LOG) << "HELP! Encrypt job but have no keys to encrypt with.";
160 return;
161 }
162
163 // if setContent hasn't been called, we assume that a subjob was added
164 // and we want to use that
165 if (!d->content || !d->content->hasContent()) {
166 if (d->subjobContents.size() == 1) {
167 d->content = d->subjobContents.constFirst();
168 }
169 }
170
171 if (d->protectedHeaders && d->skeletonMessage && d->format & Kleo::OpenPGPMIMEFormat) {
172 auto pJob = new ProtectedHeadersJob;
173 pJob->setContent(d->content);
174 pJob->setSkeletonMessage(d->skeletonMessage);
175 pJob->setObvoscate(d->protectedHeadersObvoscate);
176 QObject::connect(pJob, &ProtectedHeadersJob::finished, this, [d, pJob](KJob *job) {
177 if (job->error()) {
178 return;
179 }
180 d->content = pJob->content();
181 });
182 appendSubjob(pJob);
183 }
184
186}
187
188void EncryptJob::slotResult(KJob *job)
189{
190 // Q_D(EncryptJob);
191 if (error() || job->error()) {
192 ContentJobBase::slotResult(job);
193 return;
194 }
195 if (subjobs().size() == 2) {
196 auto pjob = static_cast<ProtectedHeadersJob *>(subjobs().last());
197 if (pjob) {
198 auto cjob = qobject_cast<ContentJobBase *>(job);
199 Q_ASSERT(cjob);
200 pjob->setContent(cjob->content());
201 }
202 }
203
204 ContentJobBase::slotResult(job);
205}
206
207void EncryptJob::process()
208{
210
211 // if setContent hasn't been called, we assume that a subjob was added
212 // and we want to use that
213 if (!d->content || !d->content->hasContent()) {
214 Q_ASSERT(d->subjobContents.size() == 1);
215 d->content = d->subjobContents.constFirst();
216 }
217
218 const QGpgME::Protocol *proto = nullptr;
219 if (d->format & Kleo::AnyOpenPGP) {
220 proto = QGpgME::openpgp();
221 } else if (d->format & Kleo::AnySMIME) {
222 proto = QGpgME::smime();
223 } else {
224 qCDebug(MESSAGECOMPOSER_LOG) << "HELP! Encrypt job but have protocol to encrypt with.";
225 return;
226 }
227
228 Q_ASSERT(proto);
229
230 // for now just do the main recipients
232 d->content->assemble();
233 if (d->format & Kleo::InlineOpenPGPFormat) {
234 content = d->content->body();
235 } else {
237 }
238
239 qCDebug(MESSAGECOMPOSER_LOG) << "got backend, starting job";
240 QGpgME::EncryptJob *eJob = proto->encryptJob(!d->binaryHint(d->format), d->format == Kleo::InlineOpenPGPFormat);
241
242 if (!d->gnupgHome.isEmpty()) {
243 QGpgME::Job::context(eJob)->setEngineHomeDirectory(d->gnupgHome.toUtf8().constData());
244 }
245
247 eJob,
248 &QGpgME::EncryptJob::result,
249 this,
250 [this, d](const GpgME::EncryptionResult &result, const QByteArray &cipherText, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) {
251 Q_UNUSED(auditLogAsHtml)
252 Q_UNUSED(auditLogError)
253 if (result.error()) {
254 setError(result.error().code());
255 setErrorText(QString::fromLocal8Bit(result.error().asString()));
256 emitResult();
257 return;
258 }
259 d->resultContent = MessageComposer::Util::composeHeadersAndBody(d->content, cipherText, d->format, false);
260
261 emitResult();
262 });
263
264 const auto error = eJob->start(d->keys, content, true);
265 if (error.code()) {
266 eJob->deleteLater();
267 setError(error.code());
269 emitResult();
270 }
271}
272
273#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)
QString fromLocal8Bit(QByteArrayView str)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:54:19 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.