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 <config-messagelib.h>
9
10#include "job/encryptjob.h"
11
12#include "contentjobbase_p.h"
13#include "job/protectedheadersjob.h"
14#include "utils/util_p.h"
15
16#include <QGpgME/EncryptJob>
17#include <QGpgME/Protocol>
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);
179 if (job->error()) {
180 return;
181 }
182 d->content = pJob->content();
183 });
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) {
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
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#if QGPGME_SUPPORTS_ENCRYPTION_JOB_SET_INPUT_ENCODING
244 if (!(d->format & Kleo::InlineOpenPGPFormat)) {
245 eJob->setInputEncoding(GpgME::Data::MimeEncoding);
246 }
247#endif
248
249 if (!d->gnupgHome.isEmpty()) {
250 QGpgME::Job::context(eJob)->setEngineHomeDirectory(d->gnupgHome.toUtf8().constData());
251 }
252
254 eJob,
255 &QGpgME::EncryptJob::result,
256 this,
257 [this, d](const GpgME::EncryptionResult &result, const QByteArray &cipherText, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) {
258 Q_UNUSED(auditLogAsHtml)
259 Q_UNUSED(auditLogError)
260 if (result.error()) {
261 setError(result.error().code());
262 setErrorText(QString::fromLocal8Bit(result.error().asString()));
263 emitResult();
264 return;
265 }
266 d->resultContent = MessageComposer::Util::composeHeadersAndBody(d->content, cipherText, d->format, false);
267
268 emitResult();
269 });
270
271 const auto error = eJob->start(d->keys, content, true);
272 if (error.code()) {
273 eJob->deleteLater();
274 setError(error.code());
276 emitResult();
277 }
278}
279
280#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)
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 Tue Mar 26 2024 11:12:43 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.