8#include "job/signencryptjob.h"
10#include "contentjobbase_p.h"
11#include "job/protectedheadersjob.h"
12#include "utils/util_p.h"
14#include <QGpgME/Protocol>
15#include <QGpgME/SignEncryptJob>
17#include "messagecomposer_debug.h"
18#include <KMime/Content>
19#include <KMime/Headers>
20#include <KMime/Message>
21#include <Libkleo/Formatting>
23#include <gpgme++/encryptionresult.h>
24#include <gpgme++/global.h>
25#include <gpgme++/signingresult.h>
29class MessageComposer::SignEncryptJobPrivate :
public ContentJobBasePrivate
32 SignEncryptJobPrivate(SignEncryptJob *qq)
33 : ContentJobBasePrivate(qq)
37 std::vector<GpgME::Key> signers;
39 std::vector<GpgME::Key> encKeys;
40 QStringList recipients;
41 Kleo::CryptoMessageFormat format;
42 KMime::Content *content =
nullptr;
43 KMime::Message *skeletonMessage =
nullptr;
45 bool protectedHeaders =
true;
46 bool protectedHeadersObvoscate =
false;
49 [[nodiscard]]
bool binaryHint(Kleo::CryptoMessageFormat f)
52 case Kleo::SMIMEFormat:
53 case Kleo::SMIMEOpaqueFormat:
56 case Kleo::OpenPGPMIMEFormat:
57 case Kleo::InlineOpenPGPFormat:
62 Q_DECLARE_PUBLIC(SignEncryptJob)
65SignEncryptJob::SignEncryptJob(
QObject *parent)
70SignEncryptJob::~SignEncryptJob() =
default;
81void SignEncryptJob::setCryptoMessageFormat(Kleo::CryptoMessageFormat format)
86 Q_ASSERT(format == Kleo::OpenPGPMIMEFormat || format == Kleo::InlineOpenPGPFormat || format == Kleo::SMIMEFormat || format == Kleo::SMIMEOpaqueFormat);
90void SignEncryptJob::setSigningKeys(
const std::vector<GpgME::Key> &signers)
97KMime::Content *SignEncryptJob::origContent()
104void SignEncryptJob::setEncryptionKeys(
const std::vector<GpgME::Key> &keys)
111void SignEncryptJob::setRecipients(
const QStringList &recipients)
115 d->recipients = recipients;
118void SignEncryptJob::setSkeletonMessage(KMime::Message *skeletonMessage)
122 d->skeletonMessage = skeletonMessage;
125void SignEncryptJob::setProtectedHeaders(
bool protectedHeaders)
129 d->protectedHeaders = protectedHeaders;
132void SignEncryptJob::setProtectedHeadersObvoscate(
bool protectedHeadersObvoscate)
136 d->protectedHeadersObvoscate = protectedHeadersObvoscate;
139QStringList SignEncryptJob::recipients()
const
141 Q_D(
const SignEncryptJob);
143 return d->recipients;
146std::vector<GpgME::Key> SignEncryptJob::encryptionKeys()
const
148 Q_D(
const SignEncryptJob);
153void SignEncryptJob::doStart()
156 Q_ASSERT(d->resultContent ==
nullptr);
158 if (d->protectedHeaders && d->skeletonMessage && d->format & Kleo::OpenPGPMIMEFormat) {
159 auto pJob =
new ProtectedHeadersJob;
160 pJob->setContent(d->content);
161 pJob->setSkeletonMessage(d->skeletonMessage);
162 pJob->setObvoscate(d->protectedHeadersObvoscate);
167 d->content = pJob->content();
175void SignEncryptJob::slotResult(KJob *job)
179 ContentJobBase::slotResult(job);
183 auto pjob =
static_cast<ProtectedHeadersJob *
>(
subjobs().last());
187 pjob->setContent(cjob->content());
191 ContentJobBase::slotResult(job);
194void SignEncryptJob::process()
197 Q_ASSERT(d->resultContent ==
nullptr);
201 if (!d->content || !d->content->hasContent()) {
202 Q_ASSERT(d->subjobContents.size() == 1);
203 d->content = d->subjobContents.constFirst();
206 const QGpgME::Protocol *proto =
nullptr;
207 if (d->format & Kleo::AnyOpenPGP) {
208 proto = QGpgME::openpgp();
209 }
else if (d->format & Kleo::AnySMIME) {
210 proto = QGpgME::smime();
217 qCDebug(MESSAGECOMPOSER_LOG) <<
"creating signencrypt from:" << proto->name() << proto->displayName();
220 d->content->assemble();
225 if (d->format & Kleo::InlineOpenPGPFormat) {
227 }
else if (!(d->format & Kleo::SMIMEOpaqueFormat)) {
228 content = KMime::LFtoCRLF(d->content->encodedContent());
230 content = d->content->encodedContent();
233 QGpgME::SignEncryptJob *job(proto->signEncryptJob(!d->binaryHint(d->format), d->format == Kleo::InlineOpenPGPFormat));
235 &QGpgME::SignEncryptJob::result,
237 [
this, d](
const GpgME::SigningResult &signingResult,
238 const GpgME::EncryptionResult &encryptionResult,
239 const QByteArray &cipherText,
240 const QString &auditLogAsHtml,
241 const GpgME::Error &auditLogError) {
242 Q_UNUSED(auditLogAsHtml)
243 Q_UNUSED(auditLogError)
244 if (signingResult.error()) {
245 qCDebug(MESSAGECOMPOSER_LOG) <<
"signing failed:" << Kleo::Formatting::errorAsString(signingResult.error());
246 setError(signingResult.error().code());
247 setErrorText(Kleo::Formatting::errorAsString(signingResult.error()));
251 if (encryptionResult.error()) {
252 qCDebug(MESSAGECOMPOSER_LOG) <<
"encrypting failed:" << Kleo::Formatting::errorAsString(encryptionResult.error());
253 setError(encryptionResult.error().code());
254 setErrorText(Kleo::Formatting::errorAsString(encryptionResult.error()));
259 QByteArray signatureHashAlgo = signingResult.createdSignature(0).hashAlgorithmAsString();
260 d->resultContent = MessageComposer::Util::composeHeadersAndBody(d->content, cipherText, d->format,
false, signatureHashAlgo);
274#include "moc_signencryptjob.cpp"
const QList< KJob * > & subjobs() const
void setErrorText(const QString &errorText)
void setError(int errorCode)
virtual Q_SCRIPTABLE void start()=0
KJob(QObject *parent=nullptr)
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.
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)