Page MenuHome GnuPG

No OneTemporary

diff --git a/client/editor/attachment/attachmentfrompublickeyjob.cpp b/client/editor/attachment/attachmentfrompublickeyjob.cpp
index bf47d05..4939b78 100644
--- a/client/editor/attachment/attachmentfrompublickeyjob.cpp
+++ b/client/editor/attachment/attachmentfrompublickeyjob.cpp
@@ -1,125 +1,125 @@
/*
SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
Based on KMail code by:
Various authors.
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "attachmentfrompublickeyjob.h"
#include <KDialogJobUiDelegate>
#include <KLocalizedString>
#include <QGpgME/ExportJob>
#include <QGpgME/Protocol>
#include <Libkleo/Formatting>
#include <Libkleo/ProgressDialog>
using namespace MessageComposer;
using MessageCore::AttachmentPart;
class MessageComposer::AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJobPrivate
{
public:
AttachmentFromPublicKeyJobPrivate(AttachmentFromPublicKeyJob *qq);
void exportResult(const GpgME::Error &error, const QByteArray &keyData); // slot
void emitGpgError(const GpgME::Error &error);
AttachmentFromPublicKeyJob *const q;
GpgME::Key key;
QByteArray data;
};
AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJobPrivate::AttachmentFromPublicKeyJobPrivate(AttachmentFromPublicKeyJob *qq)
: q(qq)
{
}
void AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJobPrivate::exportResult(const GpgME::Error &error, const QByteArray &keyData)
{
if (error) {
emitGpgError(error);
return;
}
// Create the AttachmentPart.
AttachmentPart::Ptr part = AttachmentPart::Ptr(new AttachmentPart);
const QString fingerprint = QLatin1String(key.primaryFingerprint());
const auto email = Kleo::Formatting::prettyEMail(key);
if (!email.isEmpty()) {
// Add email address when available
part->setName(i18n("OpenPGP Key %1 0x%2", email, fingerprint.right(8)));
part->setFileName(QStringLiteral("OpenPGP-Key_%1_0x%2.asc").arg(email, fingerprint.right(8)));
} else {
part->setName(i18n("OpenPGP Key 0x%1", fingerprint.right(8)));
part->setFileName(QStringLiteral("OpenPGP-Key_0x%1.asc").arg(fingerprint.right(8)));
}
part->setMimeType("application/pgp-keys");
part->setData(keyData);
q->setAttachmentPart(part);
q->emitResult(); // Success.
}
void AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJobPrivate::emitGpgError(const GpgME::Error &error)
{
Q_ASSERT(error);
const QString msg = i18n(
"<p>An error occurred while trying to export "
"the key from the backend:</p>"
"<p><b>%1</b></p>",
- QString::fromLocal8Bit(error.asString()));
+ Kleo::Formatting::errorAsString(error));
q->setError(KJob::UserDefinedError);
q->setErrorText(msg);
q->emitResult();
}
AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJob(const GpgME::Key &key, QObject *parent)
: AttachmentLoadJob(parent)
, d(new AttachmentFromPublicKeyJobPrivate(this))
{
d->key = key;
}
AttachmentFromPublicKeyJob::~AttachmentFromPublicKeyJob() = default;
QString AttachmentFromPublicKeyJob::fingerprint() const
{
return QLatin1String(d->key.primaryFingerprint());
}
GpgME::Key AttachmentFromPublicKeyJob::key() const
{
return d->key;
}
void AttachmentFromPublicKeyJob::setKey(const GpgME::Key &key)
{
d->key = key;
}
void AttachmentFromPublicKeyJob::doStart()
{
QGpgME::ExportJob *job = QGpgME::openpgp()->publicKeyExportJob(true);
Q_ASSERT(job);
connect(job, &QGpgME::ExportJob::result, this, [this](const GpgME::Error &error, const QByteArray &ba) {
d->exportResult(error, ba);
});
const GpgME::Error error = job->start(QStringList(fingerprint()));
if (error) {
d->emitGpgError(error);
// TODO check autodeletion policy of Kleo::Jobs...
return;
} else if (uiDelegate()) {
Q_ASSERT(dynamic_cast<KDialogJobUiDelegate *>(uiDelegate()));
auto delegate = static_cast<KDialogJobUiDelegate *>(uiDelegate());
(void)new Kleo::ProgressDialog(job, i18n("Exporting key..."), delegate->window());
}
}
#include "moc_attachmentfrompublickeyjob.cpp"
diff --git a/client/editor/job/attachmentfrompublickeyjob.cpp b/client/editor/job/attachmentfrompublickeyjob.cpp
index bf47d05..4939b78 100644
--- a/client/editor/job/attachmentfrompublickeyjob.cpp
+++ b/client/editor/job/attachmentfrompublickeyjob.cpp
@@ -1,125 +1,125 @@
/*
SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
Based on KMail code by:
Various authors.
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "attachmentfrompublickeyjob.h"
#include <KDialogJobUiDelegate>
#include <KLocalizedString>
#include <QGpgME/ExportJob>
#include <QGpgME/Protocol>
#include <Libkleo/Formatting>
#include <Libkleo/ProgressDialog>
using namespace MessageComposer;
using MessageCore::AttachmentPart;
class MessageComposer::AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJobPrivate
{
public:
AttachmentFromPublicKeyJobPrivate(AttachmentFromPublicKeyJob *qq);
void exportResult(const GpgME::Error &error, const QByteArray &keyData); // slot
void emitGpgError(const GpgME::Error &error);
AttachmentFromPublicKeyJob *const q;
GpgME::Key key;
QByteArray data;
};
AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJobPrivate::AttachmentFromPublicKeyJobPrivate(AttachmentFromPublicKeyJob *qq)
: q(qq)
{
}
void AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJobPrivate::exportResult(const GpgME::Error &error, const QByteArray &keyData)
{
if (error) {
emitGpgError(error);
return;
}
// Create the AttachmentPart.
AttachmentPart::Ptr part = AttachmentPart::Ptr(new AttachmentPart);
const QString fingerprint = QLatin1String(key.primaryFingerprint());
const auto email = Kleo::Formatting::prettyEMail(key);
if (!email.isEmpty()) {
// Add email address when available
part->setName(i18n("OpenPGP Key %1 0x%2", email, fingerprint.right(8)));
part->setFileName(QStringLiteral("OpenPGP-Key_%1_0x%2.asc").arg(email, fingerprint.right(8)));
} else {
part->setName(i18n("OpenPGP Key 0x%1", fingerprint.right(8)));
part->setFileName(QStringLiteral("OpenPGP-Key_0x%1.asc").arg(fingerprint.right(8)));
}
part->setMimeType("application/pgp-keys");
part->setData(keyData);
q->setAttachmentPart(part);
q->emitResult(); // Success.
}
void AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJobPrivate::emitGpgError(const GpgME::Error &error)
{
Q_ASSERT(error);
const QString msg = i18n(
"<p>An error occurred while trying to export "
"the key from the backend:</p>"
"<p><b>%1</b></p>",
- QString::fromLocal8Bit(error.asString()));
+ Kleo::Formatting::errorAsString(error));
q->setError(KJob::UserDefinedError);
q->setErrorText(msg);
q->emitResult();
}
AttachmentFromPublicKeyJob::AttachmentFromPublicKeyJob(const GpgME::Key &key, QObject *parent)
: AttachmentLoadJob(parent)
, d(new AttachmentFromPublicKeyJobPrivate(this))
{
d->key = key;
}
AttachmentFromPublicKeyJob::~AttachmentFromPublicKeyJob() = default;
QString AttachmentFromPublicKeyJob::fingerprint() const
{
return QLatin1String(d->key.primaryFingerprint());
}
GpgME::Key AttachmentFromPublicKeyJob::key() const
{
return d->key;
}
void AttachmentFromPublicKeyJob::setKey(const GpgME::Key &key)
{
d->key = key;
}
void AttachmentFromPublicKeyJob::doStart()
{
QGpgME::ExportJob *job = QGpgME::openpgp()->publicKeyExportJob(true);
Q_ASSERT(job);
connect(job, &QGpgME::ExportJob::result, this, [this](const GpgME::Error &error, const QByteArray &ba) {
d->exportResult(error, ba);
});
const GpgME::Error error = job->start(QStringList(fingerprint()));
if (error) {
d->emitGpgError(error);
// TODO check autodeletion policy of Kleo::Jobs...
return;
} else if (uiDelegate()) {
Q_ASSERT(dynamic_cast<KDialogJobUiDelegate *>(uiDelegate()));
auto delegate = static_cast<KDialogJobUiDelegate *>(uiDelegate());
(void)new Kleo::ProgressDialog(job, i18n("Exporting key..."), delegate->window());
}
}
#include "moc_attachmentfrompublickeyjob.cpp"
diff --git a/client/editor/job/autocryptheadersjob.cpp b/client/editor/job/autocryptheadersjob.cpp
index 1f9fe56..b9f82b6 100644
--- a/client/editor/job/autocryptheadersjob.cpp
+++ b/client/editor/job/autocryptheadersjob.cpp
@@ -1,284 +1,285 @@
/*
SPDX-FileCopyrightText: 2020 Sandro Knauß <sknauss@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "autocryptheadersjob.h"
#include "contentjobbase_p.h"
#include "../util_p.h"
#include "singlepartjob.h"
#include "editor_debug.h"
#include <QGpgME/ExportJob>
#include <QGpgME/Protocol>
#include <gpgme++/context.h>
#include <KCodecs>
#include <KLocalizedString>
#include <KMime/Content>
#include <KMime/Headers>
+#include <Libkleo/Formatting>
#include <QByteArray>
#include <map>
using namespace MessageComposer;
class MessageComposer::AutocryptHeadersJobPrivate : public ContentJobBasePrivate
{
public:
AutocryptHeadersJobPrivate(AutocryptHeadersJob *qq)
: ContentJobBasePrivate(qq)
{
}
~AutocryptHeadersJobPrivate() override
{
// clean up in case of cancelled job
for (const auto &[key, header] : gossipHeaders) {
delete header;
}
gossipHeaders.clear();
}
void emitGpgError(const GpgME::Error &error);
void emitNotFoundError(const QByteArray &addr, const QByteArray &fingerprint);
void fillHeaderData(KMime::Headers::Generic *header, const QByteArray &addr, bool preferEncrypted, const QByteArray &keydata);
void finishOnLastSubJob();
KMime::Content *content = nullptr;
KMime::Message *skeletonMessage = nullptr;
// used to ensure consistent order based on key order, not random one by async subjobs delivering
std::map<QByteArray, KMime::Headers::Generic *> gossipHeaders;
bool preferEncrypted = false;
int subJobs = 0;
QString gnupgHome;
GpgME::Key recipientKey;
std::vector<GpgME::Key> gossipKeys;
Q_DECLARE_PUBLIC(AutocryptHeadersJob)
};
void AutocryptHeadersJobPrivate::finishOnLastSubJob()
{
Q_Q(AutocryptHeadersJob);
if (subJobs > 0) {
return;
}
for (const auto &[key, header] : gossipHeaders) {
content->appendHeader(header);
}
gossipHeaders.clear();
resultContent = content;
q->emitResult();
}
void AutocryptHeadersJobPrivate::emitGpgError(const GpgME::Error &error)
{
Q_Q(AutocryptHeadersJob);
Q_ASSERT(error);
const QString msg = i18n(
"<p>An error occurred while trying to export "
"the key from the backend:</p>"
"<p><b>%1</b></p>",
- QString::fromLocal8Bit(error.asString()));
+ Kleo::Formatting::errorAsString(error));
q->setError(KJob::UserDefinedError);
q->setErrorText(msg);
q->emitResult();
}
void AutocryptHeadersJobPrivate::emitNotFoundError(const QByteArray &addr, const QByteArray &fingerprint)
{
Q_Q(AutocryptHeadersJob);
const QString msg = i18n(
"<p>An error occurred while trying to export "
"the key from the backend:</p>"
"<p><b>No valid key found for user %1 (%2)</b></p>",
QString::fromLatin1(addr),
QString::fromLatin1(fingerprint));
q->setError(KJob::UserDefinedError);
q->setErrorText(msg);
q->emitResult();
}
void AutocryptHeadersJobPrivate::fillHeaderData(KMime::Headers::Generic *header, const QByteArray &addr, bool preferEncrypted, const QByteArray &keydata)
{
QByteArray parameters = "addr=" + addr + "; ";
if (preferEncrypted) {
parameters += "prefer-encrypt=mutual; ";
}
parameters += "keydata=\n ";
auto encoded = KCodecs::base64Encode(keydata).replace('\n', QByteArray());
const auto length = encoded.size();
const auto lineLength = 76;
auto start = 0;
auto column = 1;
while (start < length) {
const auto midLength = std::min<int>(length - start, lineLength - column);
parameters += encoded.mid(start, midLength);
start += midLength;
column += midLength;
if (column >= lineLength) {
parameters += "\n ";
column = 1;
}
}
header->from7BitString(parameters);
}
AutocryptHeadersJob::AutocryptHeadersJob(QObject *parent)
: ContentJobBase(*new AutocryptHeadersJobPrivate(this), parent)
{
}
AutocryptHeadersJob::~AutocryptHeadersJob() = default;
void AutocryptHeadersJob::setContent(KMime::Content *content)
{
Q_D(AutocryptHeadersJob);
d->content = content;
if (content) {
d->content->assemble();
}
}
void AutocryptHeadersJob::setSkeletonMessage(KMime::Message *skeletonMessage)
{
Q_D(AutocryptHeadersJob);
d->skeletonMessage = skeletonMessage;
}
void AutocryptHeadersJob::setGnupgHome(const QString &path)
{
Q_D(AutocryptHeadersJob);
d->gnupgHome = path;
}
void AutocryptHeadersJob::setSenderKey(const GpgME::Key &key)
{
Q_D(AutocryptHeadersJob);
d->recipientKey = key;
}
void AutocryptHeadersJob::setPreferEncrypted(bool preferEncrypted)
{
Q_D(AutocryptHeadersJob);
d->preferEncrypted = preferEncrypted;
}
void AutocryptHeadersJob::setGossipKeys(const std::vector<GpgME::Key> &gossipKeys)
{
Q_D(AutocryptHeadersJob);
d->gossipKeys = gossipKeys;
}
void AutocryptHeadersJob::process()
{
Q_D(AutocryptHeadersJob);
Q_ASSERT(d->resultContent == nullptr); // Not processed before.
// if setContent hasn't been called, we assume that a subjob was added
// and we want to use that
if (!d->content) {
Q_ASSERT(d->subjobContents.size() == 1);
d->content = d->subjobContents.constFirst();
}
auto job = QGpgME::openpgp()->publicKeyExportJob(false);
Q_ASSERT(job);
if (!d->gnupgHome.isEmpty()) {
QGpgME::Job::context(job)->setEngineHomeDirectory(d->gnupgHome.toUtf8().constData());
}
if (!d->recipientKey.isNull() && !d->recipientKey.isInvalid()) {
connect(job, &QGpgME::ExportJob::result, this, [this, d](const GpgME::Error &error, const QByteArray &keydata) {
d->subJobs--;
if (AutocryptHeadersJob::error()) {
// When the job already has failed do nothing.
return;
}
if (error) {
d->emitGpgError(error);
return;
}
if (keydata.isEmpty()) {
d->emitNotFoundError(d->skeletonMessage->from()->addresses()[0], d->recipientKey.primaryFingerprint());
return;
}
auto autocrypt = new KMime::Headers::Generic("Autocrypt");
d->fillHeaderData(autocrypt, d->skeletonMessage->from()->addresses()[0], d->preferEncrypted, keydata);
d->skeletonMessage->setHeader(autocrypt);
d->skeletonMessage->assemble();
d->finishOnLastSubJob();
});
d->subJobs++;
job->start(QStringList(QString::fromLatin1(d->recipientKey.primaryFingerprint())));
job->setExportFlags(GpgME::Context::ExportMinimal);
}
const auto keys = d->gossipKeys;
for (const auto &key : keys) {
if (QByteArray(key.primaryFingerprint()) == QByteArray(d->recipientKey.primaryFingerprint())) {
continue;
}
auto gossipJob = QGpgME::openpgp()->publicKeyExportJob(false);
Q_ASSERT(gossipJob);
if (!d->gnupgHome.isEmpty()) {
QGpgME::Job::context(gossipJob)->setEngineHomeDirectory(d->gnupgHome.toUtf8().constData());
}
connect(gossipJob, &QGpgME::ExportJob::result, this, [this, d, key](const GpgME::Error &error, const QByteArray &keydata) {
d->subJobs--;
if (AutocryptHeadersJob::error()) {
// When the job already has failed do nothing.
return;
}
if (error) {
d->emitGpgError(error);
return;
}
if (keydata.isEmpty()) {
d->emitNotFoundError(key.userID(0).email(), key.primaryFingerprint());
return;
}
auto header = new KMime::Headers::Generic("Autocrypt-Gossip");
d->fillHeaderData(header, key.userID(0).email(), false, keydata);
d->gossipHeaders.insert({QByteArray(key.primaryFingerprint()), header});
d->finishOnLastSubJob();
});
d->subJobs++;
gossipJob->start(QStringList(QString::fromLatin1(key.primaryFingerprint())));
gossipJob->setExportFlags(GpgME::Context::ExportMinimal);
}
if (d->subJobs == 0) {
d->resultContent = d->content;
emitResult();
}
}
#include "moc_autocryptheadersjob.cpp"
diff --git a/client/editor/job/encryptjob.cpp b/client/editor/job/encryptjob.cpp
index 138eacb..b8ad9ef 100644
--- a/client/editor/job/encryptjob.cpp
+++ b/client/editor/job/encryptjob.cpp
@@ -1,279 +1,281 @@
/*
SPDX-FileCopyrightText: 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
SPDX-FileCopyrightText: 2009 Leo Franchi <lfranchi@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "encryptjob.h"
#include "../part/infopart.h"
#include "../util_p.h"
#include "contentjobbase_p.h"
#include "protectedheadersjob.h"
#include <QGpgME/EncryptJob>
#include <QGpgME/Protocol>
+#include <Libkleo/Formatting>
+
#include "editor_debug.h"
#include <gpgme++/encryptionresult.h>
#include <gpgme++/global.h>
#include <gpgme++/signingresult.h>
#include <sstream>
using namespace MessageComposer;
class MessageComposer::EncryptJobPrivate : public ContentJobBasePrivate
{
public:
EncryptJobPrivate(EncryptJob *qq)
: ContentJobBasePrivate(qq)
{
}
QString gnupgHome;
QStringList recipients;
std::vector<GpgME::Key> keys;
Kleo::CryptoMessageFormat format;
KMime::Content *content = nullptr;
KMime::Message *skeletonMessage = nullptr;
bool protectedHeaders = true;
bool protectedHeadersObvoscate = false;
// copied from messagecomposer.cpp
bool binaryHint(Kleo::CryptoMessageFormat f)
{
switch (f) {
case Kleo::SMIMEFormat:
case Kleo::SMIMEOpaqueFormat:
return true;
default:
case Kleo::OpenPGPMIMEFormat:
case Kleo::InlineOpenPGPFormat:
return false;
}
}
GpgME::SignatureMode signingMode(Kleo::CryptoMessageFormat f)
{
switch (f) {
case Kleo::SMIMEOpaqueFormat:
return GpgME::NormalSignatureMode;
case Kleo::InlineOpenPGPFormat:
return GpgME::Clearsigned;
default:
case Kleo::SMIMEFormat:
case Kleo::OpenPGPMIMEFormat:
return GpgME::Detached;
}
}
Q_DECLARE_PUBLIC(EncryptJob)
};
EncryptJob::EncryptJob(QObject *parent)
: ContentJobBase(*new EncryptJobPrivate(this), parent)
{
}
EncryptJob::~EncryptJob() = default;
void EncryptJob::setContent(KMime::Content *content)
{
Q_D(EncryptJob);
d->content = content;
d->content->assemble();
}
void EncryptJob::setCryptoMessageFormat(Kleo::CryptoMessageFormat format)
{
Q_D(EncryptJob);
d->format = format;
}
void EncryptJob::setEncryptionKeys(const std::vector<GpgME::Key> &keys)
{
Q_D(EncryptJob);
d->keys = keys;
}
void EncryptJob::setRecipients(const QStringList &recipients)
{
Q_D(EncryptJob);
d->recipients = recipients;
}
void EncryptJob::setSkeletonMessage(KMime::Message *skeletonMessage)
{
Q_D(EncryptJob);
d->skeletonMessage = skeletonMessage;
}
void EncryptJob::setProtectedHeaders(bool protectedHeaders)
{
Q_D(EncryptJob);
d->protectedHeaders = protectedHeaders;
}
void EncryptJob::setProtectedHeadersObvoscate(bool protectedHeadersObvoscate)
{
Q_D(EncryptJob);
d->protectedHeadersObvoscate = protectedHeadersObvoscate;
}
void EncryptJob::setGnupgHome(const QString &path)
{
Q_D(EncryptJob);
d->gnupgHome = path;
}
QStringList EncryptJob::recipients() const
{
Q_D(const EncryptJob);
return d->recipients;
}
std::vector<GpgME::Key> EncryptJob::encryptionKeys() const
{
Q_D(const EncryptJob);
return d->keys;
}
void EncryptJob::doStart()
{
Q_D(EncryptJob);
Q_ASSERT(d->resultContent == nullptr); // Not processed before.
if (d->keys.size() == 0) { // should not happen---resolver should have dealt with it earlier
qCDebug(EDITOR_LOG) << "HELP! Encrypt job but have no keys to encrypt with.";
return;
}
// if setContent hasn't been called, we assume that a subjob was added
// and we want to use that
if (!d->content || !d->content->hasContent()) {
if (d->subjobContents.size() == 1) {
d->content = d->subjobContents.constFirst();
}
}
if (d->protectedHeaders && d->skeletonMessage && d->format & Kleo::OpenPGPMIMEFormat) {
auto pJob = new ProtectedHeadersJob;
pJob->setContent(d->content);
pJob->setSkeletonMessage(d->skeletonMessage);
pJob->setObvoscate(d->protectedHeadersObvoscate);
QObject::connect(pJob, &ProtectedHeadersJob::finished, this, [d, pJob](KJob *job) {
if (job->error()) {
return;
}
d->content = pJob->content();
});
if (!appendSubjob(pJob)) {
qCWarning(EDITOR_LOG) << "Impossible to add subjob";
}
}
ContentJobBase::doStart();
}
void EncryptJob::slotResult(KJob *job)
{
// Q_D(EncryptJob);
if (error() || job->error()) {
ContentJobBase::slotResult(job);
return;
}
if (subjobs().size() == 2) {
auto pjob = static_cast<ProtectedHeadersJob *>(subjobs().last());
if (pjob) {
auto cjob = qobject_cast<ContentJobBase *>(job);
Q_ASSERT(cjob);
pjob->setContent(cjob->content());
}
}
ContentJobBase::slotResult(job);
}
void EncryptJob::process()
{
Q_D(EncryptJob);
// if setContent hasn't been called, we assume that a subjob was added
// and we want to use that
if (!d->content || !d->content->hasContent()) {
Q_ASSERT(d->subjobContents.size() == 1);
d->content = d->subjobContents.constFirst();
}
const QGpgME::Protocol *proto = nullptr;
if (d->format & Kleo::AnyOpenPGP) {
proto = QGpgME::openpgp();
} else if (d->format & Kleo::AnySMIME) {
proto = QGpgME::smime();
} else {
qCWarning(EDITOR_LOG) << "HELP! Encrypt job but have protocol to encrypt with.";
return;
}
Q_ASSERT(proto);
// for now just do the main recipients
QByteArray content;
d->content->assemble();
if (d->format & Kleo::InlineOpenPGPFormat) {
content = d->content->body();
} else {
content = d->content->encodedContent();
}
qCDebug(EDITOR_LOG) << "got backend, starting job";
QGpgME::EncryptJob *eJob = proto->encryptJob(!d->binaryHint(d->format), d->format == Kleo::InlineOpenPGPFormat);
if (!(d->format & Kleo::InlineOpenPGPFormat)) {
eJob->setInputEncoding(GpgME::Data::MimeEncoding);
}
if (!d->gnupgHome.isEmpty()) {
QGpgME::Job::context(eJob)->setEngineHomeDirectory(d->gnupgHome.toUtf8().constData());
}
QObject::connect(
eJob,
&QGpgME::EncryptJob::result,
this,
[this, d](const GpgME::EncryptionResult &result, const QByteArray &cipherText, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) {
Q_UNUSED(auditLogAsHtml)
Q_UNUSED(auditLogError)
if (result.error()) {
setError(result.error().code());
- setErrorText(QString::fromLocal8Bit(result.error().asString()));
+ setErrorText(Kleo::Formatting::errorAsString(result.error()));
emitResult();
return;
}
d->resultContent = MessageComposer::Util::composeHeadersAndBody(d->content, cipherText, d->format, false);
emitResult();
});
const auto error = eJob->start(d->keys, content, true);
if (error.code()) {
eJob->deleteLater();
setError(error.code());
- setErrorText(QString::fromLocal8Bit(error.asString()));
+ setErrorText(Kleo::Formatting::errorAsString(error));
emitResult();
}
}
#include "moc_encryptjob.cpp"
diff --git a/client/editor/job/signencryptjob.cpp b/client/editor/job/signencryptjob.cpp
index 5008575..e26bb4f 100644
--- a/client/editor/job/signencryptjob.cpp
+++ b/client/editor/job/signencryptjob.cpp
@@ -1,276 +1,277 @@
/*
SPDX-FileCopyrightText: 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
SPDX-FileCopyrightText: 2009 Leo Franchi <lfranchi@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "signencryptjob.h"
#include "../util_p.h"
#include "contentjobbase_p.h"
#include "protectedheadersjob.h"
#include <QGpgME/Protocol>
#include <QGpgME/SignEncryptJob>
#include "editor_debug.h"
#include <KMime/Content>
#include <KMime/Headers>
#include <KMime/Message>
+#include <Libkleo/Formatting>
#include <gpgme++/encryptionresult.h>
#include <gpgme++/global.h>
#include <gpgme++/signingresult.h>
#include <sstream>
using namespace MessageComposer;
class MessageComposer::SignEncryptJobPrivate : public ContentJobBasePrivate
{
public:
SignEncryptJobPrivate(SignEncryptJob *qq)
: ContentJobBasePrivate(qq)
{
}
std::vector<GpgME::Key> signers;
std::vector<GpgME::Key> encKeys;
QStringList recipients;
Kleo::CryptoMessageFormat format;
KMime::Content *content = nullptr;
KMime::Message *skeletonMessage = nullptr;
bool protectedHeaders = true;
bool protectedHeadersObvoscate = false;
// copied from messagecomposer.cpp
bool binaryHint(Kleo::CryptoMessageFormat f)
{
switch (f) {
case Kleo::SMIMEFormat:
case Kleo::SMIMEOpaqueFormat:
return true;
default:
case Kleo::OpenPGPMIMEFormat:
case Kleo::InlineOpenPGPFormat:
return false;
}
}
Q_DECLARE_PUBLIC(SignEncryptJob)
};
SignEncryptJob::SignEncryptJob(QObject *parent)
: ContentJobBase(*new SignEncryptJobPrivate(this), parent)
{
}
SignEncryptJob::~SignEncryptJob() = default;
void SignEncryptJob::setContent(KMime::Content *content)
{
Q_D(SignEncryptJob);
Q_ASSERT(content);
d->content = content;
}
void SignEncryptJob::setCryptoMessageFormat(Kleo::CryptoMessageFormat format)
{
Q_D(SignEncryptJob);
// There *must* be a concrete format set at this point.
Q_ASSERT(format == Kleo::OpenPGPMIMEFormat || format == Kleo::InlineOpenPGPFormat || format == Kleo::SMIMEFormat || format == Kleo::SMIMEOpaqueFormat);
d->format = format;
}
void SignEncryptJob::setSigningKeys(const std::vector<GpgME::Key> &signers)
{
Q_D(SignEncryptJob);
d->signers = signers;
}
KMime::Content *SignEncryptJob::origContent()
{
Q_D(SignEncryptJob);
return d->content;
}
void SignEncryptJob::setEncryptionKeys(const std::vector<GpgME::Key> &keys)
{
Q_D(SignEncryptJob);
d->encKeys = keys;
}
void SignEncryptJob::setRecipients(const QStringList &recipients)
{
Q_D(SignEncryptJob);
d->recipients = recipients;
}
void SignEncryptJob::setSkeletonMessage(KMime::Message *skeletonMessage)
{
Q_D(SignEncryptJob);
d->skeletonMessage = skeletonMessage;
}
void SignEncryptJob::setProtectedHeaders(bool protectedHeaders)
{
Q_D(SignEncryptJob);
d->protectedHeaders = protectedHeaders;
}
void SignEncryptJob::setProtectedHeadersObvoscate(bool protectedHeadersObvoscate)
{
Q_D(SignEncryptJob);
d->protectedHeadersObvoscate = protectedHeadersObvoscate;
}
QStringList SignEncryptJob::recipients() const
{
Q_D(const SignEncryptJob);
return d->recipients;
}
std::vector<GpgME::Key> SignEncryptJob::encryptionKeys() const
{
Q_D(const SignEncryptJob);
return d->encKeys;
}
void SignEncryptJob::doStart()
{
Q_D(SignEncryptJob);
Q_ASSERT(d->resultContent == nullptr); // Not processed before.
if (d->protectedHeaders && d->skeletonMessage && d->format & Kleo::OpenPGPMIMEFormat) {
auto pJob = new ProtectedHeadersJob;
pJob->setContent(d->content);
pJob->setSkeletonMessage(d->skeletonMessage);
pJob->setObvoscate(d->protectedHeadersObvoscate);
QObject::connect(pJob, &ProtectedHeadersJob::finished, this, [d, pJob](KJob *job) {
if (job->error()) {
return;
}
d->content = pJob->content();
});
if (!appendSubjob(pJob)) {
qCWarning(EDITOR_LOG) << "Impossible to add subjob";
}
}
ContentJobBase::doStart();
}
void SignEncryptJob::slotResult(KJob *job)
{
// Q_D(SignEncryptJob);
if (error() || job->error()) {
ContentJobBase::slotResult(job);
return;
}
if (subjobs().size() == 2) {
auto pjob = static_cast<ProtectedHeadersJob *>(subjobs().last());
if (pjob) {
auto cjob = qobject_cast<ContentJobBase *>(job);
Q_ASSERT(cjob);
pjob->setContent(cjob->content());
}
}
ContentJobBase::slotResult(job);
}
void SignEncryptJob::process()
{
Q_D(SignEncryptJob);
Q_ASSERT(d->resultContent == nullptr); // Not processed before.
// if setContent hasn't been called, we assume that a subjob was added
// and we want to use that
if (!d->content || !d->content->hasContent()) {
Q_ASSERT(d->subjobContents.size() == 1);
d->content = d->subjobContents.constFirst();
}
const QGpgME::Protocol *proto = nullptr;
if (d->format & Kleo::AnyOpenPGP) {
proto = QGpgME::openpgp();
} else if (d->format & Kleo::AnySMIME) {
proto = QGpgME::smime();
} else {
return;
}
Q_ASSERT(proto);
// d->resultContent = new KMime::Content;
qCDebug(EDITOR_LOG) << "creating signencrypt from:" << proto->name() << proto->displayName();
QByteArray encBody;
d->content->assemble();
// replace simple LFs by CRLFs for all MIME supporting CryptPlugs
// according to RfC 2633, 3.1.1 Canonicalization
QByteArray content;
if (d->format & Kleo::InlineOpenPGPFormat) {
content = d->content->body();
} else if (!(d->format & Kleo::SMIMEOpaqueFormat)) {
content = KMime::LFtoCRLF(d->content->encodedContent());
} else { // SMimeOpaque doesn't need LFtoCRLF, else it gets munged
content = d->content->encodedContent();
}
QGpgME::SignEncryptJob *job(proto->signEncryptJob(!d->binaryHint(d->format), d->format == Kleo::InlineOpenPGPFormat));
QObject::connect(job,
&QGpgME::SignEncryptJob::result,
this,
[this, d](const GpgME::SigningResult &signingResult,
const GpgME::EncryptionResult &encryptionResult,
const QByteArray &cipherText,
const QString &auditLogAsHtml,
const GpgME::Error &auditLogError) {
Q_UNUSED(auditLogAsHtml)
Q_UNUSED(auditLogError)
if (signingResult.error()) {
- qCDebug(EDITOR_LOG) << "signing failed:" << signingResult.error().asString();
+ qCDebug(EDITOR_LOG) << "signing failed:" << Kleo::Formatting::errorAsString(signingResult.error());
setError(signingResult.error().code());
- setErrorText(QString::fromLocal8Bit(signingResult.error().asString()));
+ setErrorText(Kleo::Formatting::errorAsString(signingResult.error()));
emitResult();
return;
}
if (encryptionResult.error()) {
- qCDebug(EDITOR_LOG) << "encrypting failed:" << encryptionResult.error().asString();
+ qCDebug(EDITOR_LOG) << "encrypting failed:" << Kleo::Formatting::errorAsString(encryptionResult.error());
setError(encryptionResult.error().code());
- setErrorText(QString::fromLocal8Bit(encryptionResult.error().asString()));
+ setErrorText(Kleo::Formatting::errorAsString(encryptionResult.error()));
emitResult();
return;
}
QByteArray signatureHashAlgo = signingResult.createdSignature(0).hashAlgorithmAsString();
d->resultContent = MessageComposer::Util::composeHeadersAndBody(d->content, cipherText, d->format, false, signatureHashAlgo);
emitResult();
});
const auto error = job->start(d->signers, d->encKeys, content, false);
if (error.code()) {
job->deleteLater();
setError(error.code());
- setErrorText(QString::fromLocal8Bit(error.asString()));
+ setErrorText(Kleo::Formatting::errorAsString(error));
emitResult();
}
}
#include "moc_signencryptjob.cpp"
diff --git a/client/editor/job/signjob.cpp b/client/editor/job/signjob.cpp
index 4a28591..e036b36 100644
--- a/client/editor/job/signjob.cpp
+++ b/client/editor/job/signjob.cpp
@@ -1,295 +1,296 @@
/*
SPDX-FileCopyrightText: 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
SPDX-FileCopyrightText: 2009 Leo Franchi <lfranchi@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "signjob.h"
#include "../util_p.h"
#include "contentjobbase_p.h"
#include "protectedheadersjob.h"
#include <QGpgME/Protocol>
#include <QGpgME/SignJob>
#include <QList>
#include "editor_debug.h"
#include <KMime/Content>
#include <KMime/Headers>
#include <KMime/Message>
+#include <Libkleo/Formatting>
#include <kmime_version.h>
#include <gpgme++/encryptionresult.h>
#include <gpgme++/global.h>
#include <gpgme++/signingresult.h>
#include <sstream>
using namespace MessageComposer;
class MessageComposer::SignJobPrivate : public ContentJobBasePrivate
{
public:
SignJobPrivate(SignJob *qq)
: ContentJobBasePrivate(qq)
{
}
KMime::Content *content = nullptr;
KMime::Message *skeletonMessage = nullptr;
std::vector<GpgME::Key> signers;
Kleo::CryptoMessageFormat format;
bool protectedHeaders = true;
// copied from messagecomposer.cpp
[[nodiscard]] bool binaryHint(Kleo::CryptoMessageFormat f)
{
switch (f) {
case Kleo::SMIMEFormat:
case Kleo::SMIMEOpaqueFormat:
return true;
default:
case Kleo::OpenPGPMIMEFormat:
case Kleo::InlineOpenPGPFormat:
return false;
}
}
[[nodiscard]] GpgME::SignatureMode signingMode(Kleo::CryptoMessageFormat f)
{
switch (f) {
case Kleo::SMIMEOpaqueFormat:
return GpgME::NormalSignatureMode;
case Kleo::InlineOpenPGPFormat:
return GpgME::Clearsigned;
default:
case Kleo::SMIMEFormat:
case Kleo::OpenPGPMIMEFormat:
return GpgME::Detached;
}
}
Q_DECLARE_PUBLIC(SignJob)
};
SignJob::SignJob(QObject *parent)
: ContentJobBase(*new SignJobPrivate(this), parent)
{
}
SignJob::~SignJob() = default;
void SignJob::setContent(KMime::Content *content)
{
Q_D(SignJob);
d->content = content;
}
void SignJob::setCryptoMessageFormat(Kleo::CryptoMessageFormat format)
{
Q_D(SignJob);
// There *must* be a concrete format set at this point.
Q_ASSERT(format == Kleo::OpenPGPMIMEFormat || format == Kleo::InlineOpenPGPFormat || format == Kleo::SMIMEFormat || format == Kleo::SMIMEOpaqueFormat);
d->format = format;
}
void SignJob::setSigningKeys(const std::vector<GpgME::Key> &signers)
{
Q_D(SignJob);
d->signers = signers;
}
void SignJob::setSkeletonMessage(KMime::Message *skeletonMessage)
{
Q_D(SignJob);
d->skeletonMessage = skeletonMessage;
}
void SignJob::setProtectedHeaders(bool protectedHeaders)
{
Q_D(SignJob);
d->protectedHeaders = protectedHeaders;
}
KMime::Content *SignJob::origContent()
{
Q_D(SignJob);
return d->content;
}
void SignJob::doStart()
{
Q_D(SignJob);
Q_ASSERT(d->resultContent == nullptr); // Not processed before.
if (d->protectedHeaders && d->skeletonMessage && d->format & Kleo::OpenPGPMIMEFormat) {
auto pJob = new ProtectedHeadersJob;
pJob->setContent(d->content);
pJob->setSkeletonMessage(d->skeletonMessage);
pJob->setObvoscate(false);
QObject::connect(pJob, &ProtectedHeadersJob::finished, this, [d, pJob](KJob *job) {
if (job->error()) {
return;
}
d->content = pJob->content();
});
if (!appendSubjob(pJob)) {
qCWarning(EDITOR_LOG) << "Impossible to add subjob.";
};
}
ContentJobBase::doStart();
}
void SignJob::slotResult(KJob *job)
{
if (error() || job->error()) {
ContentJobBase::slotResult(job);
return;
}
if (subjobs().size() == 2) {
auto pjob = static_cast<ProtectedHeadersJob *>(subjobs().last());
if (pjob) {
auto cjob = qobject_cast<ContentJobBase *>(job);
Q_ASSERT(cjob);
pjob->setContent(cjob->content());
}
}
ContentJobBase::slotResult(job);
}
void SignJob::process()
{
Q_D(SignJob);
Q_ASSERT(d->resultContent == nullptr); // Not processed before.
// if setContent hasn't been called, we assume that a subjob was added
// and we want to use that
if (!d->content) {
Q_ASSERT(d->subjobContents.size() == 1);
d->content = d->subjobContents.constFirst();
}
// d->resultContent = new KMime::Content;
const QGpgME::Protocol *proto = nullptr;
if (d->format & Kleo::AnyOpenPGP) {
proto = QGpgME::openpgp();
} else if (d->format & Kleo::AnySMIME) {
proto = QGpgME::smime();
}
Q_ASSERT(proto);
qCDebug(EDITOR_LOG) << "creating signJob from:" << proto->name() << proto->displayName();
// for now just do the main recipients
d->content->assemble();
// replace simple LFs by CRLFs for all MIME supporting CryptPlugs
// according to RfC 2633, 3.1.1 Canonicalization
QByteArray content;
if (d->format & Kleo::InlineOpenPGPFormat) {
content = d->content->body();
} else if (!(d->format & Kleo::SMIMEOpaqueFormat)) {
// replace "From " and "--" at the beginning of lines
// with encoded versions according to RfC 3156, 3
// Note: If any line begins with the string "From ", it is strongly
// suggested that either the Quoted-Printable or Base64 MIME encoding
// be applied.
const auto encoding = d->content->contentTransferEncoding()->encoding();
if ((encoding == KMime::Headers::CEquPr || encoding == KMime::Headers::CE7Bit) && !d->content->contentType(false)) {
QByteArray body = d->content->encodedBody();
bool changed = false;
QList<QByteArray> search;
search.reserve(3);
QList<QByteArray> replacements;
replacements.reserve(3);
search << "From "
<< "from "
<< "-";
replacements << "From=20"
<< "from=20"
<< "=2D";
if (d->content->contentTransferEncoding()->encoding() == KMime::Headers::CE7Bit) {
for (int i = 0, total = search.size(); i < total; ++i) {
const auto pos = body.indexOf(search[i]);
if (pos == 0 || (pos > 0 && body.at(pos - 1) == '\n')) {
changed = true;
break;
}
}
if (changed) {
d->content->contentTransferEncoding()->setEncoding(KMime::Headers::CEquPr);
d->content->assemble();
body = d->content->encodedBody();
}
}
for (int i = 0; i < search.size(); ++i) {
const auto pos = body.indexOf(search[i]);
if (pos == 0 || (pos > 0 && body.at(pos - 1) == '\n')) {
changed = true;
body.replace(pos, search[i].size(), replacements[i]);
}
}
if (changed) {
qCDebug(EDITOR_LOG) << "Content changed";
#if KMIME_VERSION >= QT_VERSION_CHECK(6, 1, 41)
d->content->setEncodedBody(body);
#else
d->content->setBody(body);
d->content->contentTransferEncoding()->setDecoded(false);
#endif
}
}
content = KMime::LFtoCRLF(d->content->encodedContent());
} else { // SMimeOpaque doesn't need LFtoCRLF, else it gets munged
content = d->content->encodedContent();
}
QGpgME::SignJob *job(proto->signJob(!d->binaryHint(d->format), d->format == Kleo::InlineOpenPGPFormat));
QObject::connect(
job,
&QGpgME::SignJob::result,
this,
[this, d](const GpgME::SigningResult &result, const QByteArray &signature, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) {
Q_UNUSED(auditLogAsHtml)
Q_UNUSED(auditLogError)
if (result.error().code()) {
- qCDebug(EDITOR_LOG) << "signing failed:" << result.error().asString();
+ qCDebug(EDITOR_LOG) << "signing failed:" << Kleo::Formatting::errorAsString(result.error());
// job->showErrorDialog( globalPart()->parentWidgetForGui() );
setError(result.error().code());
- setErrorText(QString::fromLocal8Bit(result.error().asString()));
+ setErrorText(Kleo::Formatting::errorAsString(result.error()));
emitResult();
return;
}
QByteArray signatureHashAlgo = result.createdSignature(0).hashAlgorithmAsString();
d->resultContent = MessageComposer::Util::composeHeadersAndBody(d->content, signature, d->format, true, signatureHashAlgo);
emitResult();
});
const auto error = job->start(d->signers, content, d->signingMode(d->format));
if (error.code()) {
job->deleteLater();
setError(error.code());
- setErrorText(QString::fromLocal8Bit(error.asString()));
+ setErrorText(Kleo::Formatting::errorAsString(error));
emitResult();
}
}
#include "moc_signjob.cpp"

File Metadata

Mime Type
text/x-diff
Expires
Mon, Dec 23, 5:02 PM (10 h, 47 s)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
78/c6/22d21f7f044c43fc14bd8dc190b8

Event Timeline