Page MenuHome GnuPG

No OneTemporary

diff --git a/client/editor/job/composerjob.h b/client/editor/job/composerjob.h
index 0f7f851..a622e2b 100644
--- a/client/editor/job/composerjob.h
+++ b/client/editor/job/composerjob.h
@@ -1,88 +1,88 @@
// SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
// SPDX-FileCopyrightText: 2023 g10 code GmbH
// SPDX-Contributor: Carl Schwan <carl.schwan@gnupg.com>
// SPDX-License-Identifier: LGPL-2.0-or-later
#pragma once
#include <Libkleo/Enum>
#include <QList>
#include <QStringList>
-#include <KMime/KMimeMessage>
+#include <KMime/Message>
#include <gpgme++/key.h>
#include <vector>
#include "editor/attachment/attachmentpart.h"
#include "jobbase.h"
namespace MessageComposer
{
class ComposerJobPrivate;
class GlobalPart;
class InfoPart;
class TextPart;
class ItipPart;
class ComposerJob : public JobBase
{
Q_OBJECT
public:
explicit ComposerJob(QObject *parent = nullptr);
~ComposerJob() override;
[[nodiscard]] QList<KMime::Message::Ptr> resultMessages() const;
[[nodiscard]] GlobalPart *globalPart() const;
[[nodiscard]] InfoPart *infoPart() const;
[[nodiscard]] TextPart *textPart() const;
[[nodiscard]] ItipPart *itipPart() const;
void clearTextPart();
void clearItipPart();
[[nodiscard]] MessageCore::AttachmentPart::List attachmentParts() const;
void addAttachmentPart(MessageCore::AttachmentPart::Ptr part, bool autoresizeImage = false);
void addAttachmentParts(const MessageCore::AttachmentPart::List &parts, bool autoresizeImage = false);
void removeAttachmentPart(MessageCore::AttachmentPart::Ptr part);
// if the message and attachments should not be encrypted regardless of settings
void setNoCrypto(bool noCrypto);
void setSignAndEncrypt(const bool doSign, const bool doEncrypt);
void setCryptoMessageFormat(Kleo::CryptoMessageFormat format);
void setSigningKeys(const std::vector<GpgME::Key> &signers);
void setEncryptionKeys(const QList<QPair<QStringList, std::vector<GpgME::Key>>> &data);
void setSenderEncryptionKey(const GpgME::Key &senderKey);
void setGnupgHome(const QString &path);
[[nodiscard]] QString gnupgHome() const;
/// Sets if this message being composed is an auto-saved message.
/// If so, it will be handled differently like without support for crypto attachment.
void setAutoSave(bool isAutoSave);
[[nodiscard]] bool autoSave() const;
/// Sets if this message being composed is a draft message.
/// If so, it will be handled differently like with only encrypted for the sender.
void setDraft(bool isAutoSave);
[[nodiscard]] bool draft() const;
[[nodiscard]] bool finished() const;
public Q_SLOTS:
void start() override;
protected Q_SLOTS:
void slotResult(KJob *job) override;
void doStart();
void contentJobFinished(KJob *);
void attachmentsFinished(KJob *);
private:
Q_DECLARE_PRIVATE(ComposerJob)
};
}
diff --git a/client/editor/job/protectedheadersjob.cpp b/client/editor/job/protectedheadersjob.cpp
index 698bd87..64c649f 100644
--- a/client/editor/job/protectedheadersjob.cpp
+++ b/client/editor/job/protectedheadersjob.cpp
@@ -1,159 +1,159 @@
/*
SPDX-FileCopyrightText: 2020 Sandro Knauß <sknauss@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "protectedheadersjob.h"
#include "contentjobbase_p.h"
#include "editor_debug.h"
#include "singlepartjob.h"
#include <KMime/Content>
-#include <KMime/KMimeMessage>
+#include <KMime/Message>
using namespace MessageComposer;
class MessageComposer::ProtectedHeadersJobPrivate : public ContentJobBasePrivate
{
public:
ProtectedHeadersJobPrivate(ProtectedHeadersJob *qq)
: ContentJobBasePrivate(qq)
{
}
KMime::Content *content = nullptr;
KMime::Message *skeletonMessage = nullptr;
bool obvoscate = false;
Q_DECLARE_PUBLIC(ProtectedHeadersJob)
};
ProtectedHeadersJob::ProtectedHeadersJob(QObject *parent)
: ContentJobBase(*new ProtectedHeadersJobPrivate(this), parent)
{
}
ProtectedHeadersJob::~ProtectedHeadersJob() = default;
void ProtectedHeadersJob::setContent(KMime::Content *content)
{
Q_D(ProtectedHeadersJob);
d->content = content;
if (content) {
d->content->assemble();
}
}
void ProtectedHeadersJob::setSkeletonMessage(KMime::Message *skeletonMessage)
{
Q_D(ProtectedHeadersJob);
d->skeletonMessage = skeletonMessage;
}
void ProtectedHeadersJob::setObvoscate(bool obvoscate)
{
Q_D(ProtectedHeadersJob);
d->obvoscate = obvoscate;
}
void ProtectedHeadersJob::doStart()
{
Q_D(ProtectedHeadersJob);
Q_ASSERT(d->resultContent == nullptr); // Not processed before.
Q_ASSERT(d->skeletonMessage); // We need a skeletonMessage to proceed
auto subject = d->skeletonMessage->header<KMime::Headers::Subject>();
if (d->obvoscate && subject) {
// Create protected header lagacy mimepart with replaced headers
auto cjob = new SinglepartJob;
auto ct = cjob->contentType();
ct->setMimeType("text/plain");
ct->setCharset(subject->rfc2047Charset());
ct->setParameter(QStringLiteral("protected-headers"), QStringLiteral("v1"));
cjob->contentDisposition()->setDisposition(KMime::Headers::contentDisposition::CDinline);
cjob->setData(subject->type() + QByteArray(": ") + subject->asUnicodeString().toUtf8());
QObject::connect(cjob, &SinglepartJob::finished, this, [d, cjob]() {
auto mixedPart = new KMime::Content();
const QByteArray boundary = KMime::multiPartBoundary();
mixedPart->contentType()->setMimeType("multipart/mixed");
mixedPart->contentType(false)->setBoundary(boundary);
mixedPart->appendContent(cjob->content());
// 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();
}
mixedPart->appendContent(d->content);
d->content = mixedPart;
});
if (!appendSubjob(cjob)) {
qCWarning(EDITOR_LOG) << "Impossible to add subjob";
}
}
ContentJobBase::doStart();
}
void ProtectedHeadersJob::process()
{
Q_D(ProtectedHeadersJob);
// 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();
}
auto subject = d->skeletonMessage->header<KMime::Headers::Subject>();
const auto headers = d->skeletonMessage->headers();
for (const auto &header : headers) {
const QByteArray headerType(header->type());
if (headerType.startsWith("X-KMail-")) {
continue;
}
if (headerType == "Bcc") {
continue;
}
if (headerType.startsWith("Content-")) {
continue;
}
// A workaround for #439958
// KMime strips sometimes the newlines from long headers, if those
// headers are in the signature block, this breaks the signature.
// The simplest workaround is not to sign those headers until this
// get fixed in KMime.
if (header->as7BitString().length() > 70) {
continue;
}
auto copyHeader = KMime::Headers::createHeader(headerType);
if (!copyHeader) {
copyHeader = new KMime::Headers::Generic(headerType.constData(), headerType.size());
}
copyHeader->from7BitString(header->as7BitString(false));
d->content->appendHeader(copyHeader);
}
if (d->obvoscate && subject) {
subject->clear();
subject->from7BitString("...");
}
auto contentType = d->content->header<KMime::Headers::ContentType>();
contentType->setParameter(QStringLiteral("protected-headers"), QStringLiteral("v1"));
d->resultContent = d->content;
emitResult();
}
#include "moc_protectedheadersjob.cpp"
diff --git a/client/editor/job/signencryptjob.cpp b/client/editor/job/signencryptjob.cpp
index b70eda6..5008575 100644
--- a/client/editor/job/signencryptjob.cpp
+++ b/client/editor/job/signencryptjob.cpp
@@ -1,276 +1,276 @@
/*
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/KMimeMessage>
+#include <KMime/Message>
#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();
setError(signingResult.error().code());
setErrorText(QString::fromLocal8Bit(signingResult.error().asString()));
emitResult();
return;
}
if (encryptionResult.error()) {
qCDebug(EDITOR_LOG) << "encrypting failed:" << encryptionResult.error().asString();
setError(encryptionResult.error().code());
setErrorText(QString::fromLocal8Bit(encryptionResult.error().asString()));
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()));
emitResult();
}
}
#include "moc_signencryptjob.cpp"
diff --git a/client/editor/job/signjob.cpp b/client/editor/job/signjob.cpp
index 2beeb31..ee537bd 100644
--- a/client/editor/job/signjob.cpp
+++ b/client/editor/job/signjob.cpp
@@ -1,290 +1,290 @@
/*
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/KMimeMessage>
+#include <KMime/Message>
#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";
d->content->setBody(body);
d->content->contentTransferEncoding()->setDecoded(false);
}
}
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();
// job->showErrorDialog( globalPart()->parentWidgetForGui() );
setError(result.error().code());
setErrorText(QString::fromLocal8Bit(result.error().asString()));
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()));
emitResult();
}
}
#include "moc_signjob.cpp"
diff --git a/client/editor/job/skeletonmessagejob.cpp b/client/editor/job/skeletonmessagejob.cpp
index 6473a9e..27aaa50 100644
--- a/client/editor/job/skeletonmessagejob.cpp
+++ b/client/editor/job/skeletonmessagejob.cpp
@@ -1,273 +1,273 @@
/*
SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "skeletonmessagejob.h"
#include "../part/globalpart.h"
#include "../part/infopart.h"
#include "jobbase_p.h"
#include "messagecomposersettings.h"
#include <QHostInfo>
#include <QUrl>
#include "editor_debug.h"
#include <KEmailAddress>
-#include <KMime/KMimeMessage>
+#include <KMime/Message>
using namespace MessageComposer;
class MessageComposer::SkeletonMessageJobPrivate : public JobBasePrivate
{
public:
SkeletonMessageJobPrivate(SkeletonMessageJob *qq)
: JobBasePrivate(qq)
{
}
void doStart(); // slot
InfoPart *infoPart = nullptr;
GlobalPart *globalPart = nullptr;
KMime::Message *message = nullptr;
Q_DECLARE_PUBLIC(SkeletonMessageJob)
};
void SkeletonMessageJobPrivate::doStart()
{
Q_Q(SkeletonMessageJob);
Q_ASSERT(infoPart);
Q_ASSERT(message == nullptr);
message = new KMime::Message;
// From:
{
auto from = new KMime::Headers::From;
KMime::Types::Mailbox address;
address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(infoPart->from()));
from->fromUnicodeString(QString::fromLatin1(address.as7BitString("utf-8")), "utf-8");
message->setHeader(from);
}
// To:
{
auto to = new KMime::Headers::To;
QByteArray sTo;
const QStringList lstTo = infoPart->to();
for (const QString &a : lstTo) {
KMime::Types::Mailbox address;
address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(a));
if (!sTo.isEmpty()) {
sTo.append(",");
}
sTo.append(address.as7BitString("utf-8"));
}
to->fromUnicodeString(QString::fromLatin1(sTo), "utf-8");
message->setHeader(to);
}
// Reply To:
if (!infoPart->replyTo().isEmpty()) {
auto replyTo = new KMime::Headers::ReplyTo;
const QStringList lstReplyTo = infoPart->replyTo();
QByteArray sReplyTo;
for (const QString &a : lstReplyTo) {
KMime::Types::Mailbox address;
address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(a));
if (!sReplyTo.isEmpty()) {
sReplyTo.append(",");
}
sReplyTo.append(address.as7BitString("utf-8"));
}
replyTo->fromUnicodeString(QString::fromLatin1(sReplyTo), "utf-8");
message->setHeader(replyTo);
}
// Cc:
{
auto cc = new KMime::Headers::Cc;
QByteArray sCc;
const QStringList lstCc = infoPart->cc();
for (const QString &a : lstCc) {
KMime::Types::Mailbox address;
address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(a));
if (!sCc.isEmpty()) {
sCc.append(",");
}
sCc.append(address.as7BitString("utf-8"));
}
cc->fromUnicodeString(QString::fromLatin1(sCc), "utf-8");
message->setHeader(cc);
}
// Bcc:
{
auto bcc = new KMime::Headers::Bcc;
QByteArray sBcc;
const QStringList lstBcc = infoPart->bcc();
for (const QString &a : lstBcc) {
KMime::Types::Mailbox address;
address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(a));
if (!sBcc.isEmpty()) {
sBcc.append(",");
}
sBcc.append(address.as7BitString("utf-8"));
}
bcc->fromUnicodeString(QString::fromLatin1(sBcc), "utf-8");
message->setHeader(bcc);
}
// Subject:
{
auto subject = new KMime::Headers::Subject;
subject->fromUnicodeString(infoPart->subject(), "utf-8");
// TODO should we be more specific about the charset?
message->setHeader(subject);
}
// Date:
{
auto date = new KMime::Headers::Date;
date->setDateTime(QDateTime::currentDateTime());
message->setHeader(date);
}
// Fcc:
if (!infoPart->fcc().isEmpty()) {
auto header = new KMime::Headers::Generic("X-KMail-Fcc");
header->fromUnicodeString(infoPart->fcc(), "utf-8");
message->setHeader(header);
}
// Message-ID
{
auto messageId = new KMime::Headers::MessageID();
QByteArray fqdn;
if (MessageComposer::MessageComposerSettings::self()->useCustomMessageIdSuffix()) {
fqdn = QUrl::toAce(MessageComposer::MessageComposerSettings::self()->customMsgIDSuffix());
}
if (fqdn.isEmpty()) {
fqdn = QUrl::toAce(QHostInfo::localHostName());
}
if (fqdn.isEmpty()) {
qCWarning(EDITOR_LOG) << "Unable to generate a Message-ID, falling back to 'localhost.localdomain'.";
fqdn = "local.domain";
}
messageId->generate(fqdn);
message->setHeader(messageId);
}
// Extras
const KMime::Headers::Base::List extraHeaders = infoPart->extraHeaders();
for (KMime::Headers::Base *extra : extraHeaders) {
const QByteArray headerType(extra->type());
auto copyHeader = KMime::Headers::createHeader(headerType);
if (!copyHeader) {
copyHeader = new KMime::Headers::Generic(headerType.constData(), headerType.size());
}
copyHeader->from7BitString(extra->as7BitString(false));
message->setHeader(copyHeader);
}
// Request Delivery Confirmation
{
if (globalPart->requestDeleveryConfirmation()) {
// TODO fix me multi address
const QString addr = infoPart->replyTo().isEmpty() ? infoPart->from() : infoPart->replyTo().at(0);
auto requestDeleveryConfirmation = new KMime::Headers::Generic("Return-Receipt-To");
requestDeleveryConfirmation->fromUnicodeString(addr, "utf-8");
message->setHeader(requestDeleveryConfirmation);
}
}
// MDN
{
if (globalPart->MDNRequested()) {
// TODO fix me multi address
const QString addr = infoPart->replyTo().isEmpty() ? infoPart->from() : infoPart->replyTo().at(0);
auto mdn = new KMime::Headers::Generic("Disposition-Notification-To");
mdn->fromUnicodeString(addr, "utf-8");
message->setHeader(mdn);
}
}
// Urgent header
if (infoPart->urgent()) {
auto urg1 = new KMime::Headers::Generic("X-PRIORITY");
urg1->fromUnicodeString(QStringLiteral("2 (High)"), "utf-8");
auto urg2 = new KMime::Headers::Generic("Priority");
urg2->fromUnicodeString(QStringLiteral("urgent"), "utf-8");
message->setHeader(urg1);
message->setHeader(urg2);
}
// In-Reply-To
if (!infoPart->inReplyTo().isEmpty()) {
auto header = new KMime::Headers::InReplyTo;
header->fromUnicodeString(infoPart->inReplyTo(), "utf-8");
message->setHeader(header);
}
// References
if (!infoPart->references().isEmpty()) {
auto header = new KMime::Headers::References;
header->fromUnicodeString(infoPart->references(), "utf-8");
message->setHeader(header);
}
q->emitResult(); // Success.
}
SkeletonMessageJob::SkeletonMessageJob(InfoPart *infoPart, GlobalPart *globalPart, QObject *parent)
: JobBase(*new SkeletonMessageJobPrivate(this), parent)
{
Q_D(SkeletonMessageJob);
d->infoPart = infoPart;
d->globalPart = globalPart;
}
SkeletonMessageJob::~SkeletonMessageJob() = default;
InfoPart *SkeletonMessageJob::infoPart() const
{
Q_D(const SkeletonMessageJob);
return d->infoPart;
}
void SkeletonMessageJob::setInfoPart(InfoPart *part)
{
Q_D(SkeletonMessageJob);
d->infoPart = part;
}
GlobalPart *SkeletonMessageJob::globalPart() const
{
Q_D(const SkeletonMessageJob);
return d->globalPart;
}
void SkeletonMessageJob::setGlobalPart(GlobalPart *part)
{
Q_D(SkeletonMessageJob);
d->globalPart = part;
}
KMime::Message *SkeletonMessageJob::message() const
{
Q_D(const SkeletonMessageJob);
return d->message;
}
void SkeletonMessageJob::start()
{
Q_D(SkeletonMessageJob);
d->doStart();
}
#include "moc_skeletonmessagejob.cpp"
diff --git a/client/editor/job/transparentjob.cpp b/client/editor/job/transparentjob.cpp
index 087f5ae..43a430a 100644
--- a/client/editor/job/transparentjob.cpp
+++ b/client/editor/job/transparentjob.cpp
@@ -1,51 +1,51 @@
/*
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 "transparentjob.h"
#include "contentjobbase_p.h"
#include <KMime/Content>
-#include <KMime/KMimeMessage>
+#include <KMime/Message>
using namespace MessageComposer;
class MessageComposer::TransparentJobPrivate : public MessageComposer::ContentJobBasePrivate
{
public:
TransparentJobPrivate(TransparentJob *qq)
: ContentJobBasePrivate(qq)
{
}
KMime::Content *content = nullptr;
Q_DECLARE_PUBLIC(TransparentJob)
};
TransparentJob::TransparentJob(QObject *parent)
: MessageComposer::ContentJobBase(*new TransparentJobPrivate(this), parent)
{
}
TransparentJob::~TransparentJob() = default;
void TransparentJob::setContent(KMime::Content *content)
{
Q_D(TransparentJob);
d->content = content;
}
void TransparentJob::process()
{
Q_D(TransparentJob);
d->resultContent = d->content;
emitResult();
}
#include "moc_transparentjob.cpp"
diff --git a/client/editor/nodehelper.cpp b/client/editor/nodehelper.cpp
index 0345987..d414b40 100644
--- a/client/editor/nodehelper.cpp
+++ b/client/editor/nodehelper.cpp
@@ -1,66 +1,66 @@
/*
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
SPDX-FileCopyrightText: 2009 Andras Mantia <andras@kdab.net>
SPDX-FileCopyrightText: 2010 Leo Franchi <lfranchi@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "nodehelper.h"
#include <KMime/Content>
-#include <KMime/KMimeMessage>
+#include <KMime/Message>
KMime::Content *MessageCore::NodeHelper::nextSibling(const KMime::Content *node)
{
if (!node) {
return nullptr;
}
KMime::Content *next = nullptr;
- KMime::Content *parent = node->parent();
+ const KMime::Content *parent = node->parent();
if (parent) {
const auto contents = parent->contents();
const int index = contents.indexOf(const_cast<KMime::Content *>(node)) + 1;
if (index < contents.size()) { // next on the same level
next = contents.at(index);
}
}
return next;
}
KMime::Content *MessageCore::NodeHelper::next(KMime::Content *node, bool allowChildren)
{
if (allowChildren) {
if (KMime::Content *child = firstChild(node)) {
return child;
}
}
if (KMime::Content *sibling = nextSibling(node)) {
return sibling;
}
for (KMime::Content *parent = node->parent(); parent; parent = parent->parent()) {
if (KMime::Content *sibling = nextSibling(parent)) {
return sibling;
}
}
return nullptr;
}
KMime::Content *MessageCore::NodeHelper::firstChild(const KMime::Content *node)
{
if (!node) {
return nullptr;
}
KMime::Content *child = nullptr;
if (!node->contents().isEmpty()) {
child = node->contents().at(0);
}
return child;
}
diff --git a/client/editor/part/infopart.h b/client/editor/part/infopart.h
index b74d832..115731b 100644
--- a/client/editor/part/infopart.h
+++ b/client/editor/part/infopart.h
@@ -1,109 +1,109 @@
/*
SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#pragma once
#include "messagepart.h"
#include <QStringList>
#include <KMime/Headers>
-#include <KMime/KMimeMessage>
+#include <KMime/Message>
#include <memory>
namespace MessageComposer
{
/**
* @brief The InfoPart class contains the message header.
*/
class InfoPart : public MessageComposer::MessagePart
{
Q_OBJECT
/// The email address and optionally the name of the author of the mail.
Q_PROPERTY(QString from READ from WRITE setFrom NOTIFY fromChanged)
/// The email address and optionally the name of the primary recipients.
Q_PROPERTY(QStringList to READ to WRITE setTo NOTIFY toChanged)
/// Carbon copy: The email address and optionally the name of the secondary recipients.
Q_PROPERTY(QStringList cc READ cc WRITE setCc NOTIFY ccChanged)
/// Blind Carbon copy: The email address and optionally the name of the secondary recipients.
/// Only specified during SMTP delivery but not in the final mail delivery.
Q_PROPERTY(QStringList bcc READ bcc WRITE setBcc NOTIFY bccChanged)
/// Reply-To: Email address that should be used to reply to this mail.
Q_PROPERTY(QStringList replyTo READ replyTo WRITE setReplyTo NOTIFY replyToChanged)
/// Subject of the message.
Q_PROPERTY(QString subject READ subject WRITE setSubject NOTIFY subjectChanged)
/// The name of a file, to which a copy of the sent message should be appended.
Q_PROPERTY(QString fcc READ fcc WRITE setFcc NOTIFY fccChanged)
/// User agent of the sender.
Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent NOTIFY userAgentChanged)
/// Set urgency of the message.
Q_PROPERTY(bool urgent READ urgent WRITE setUrgent NOTIFY urgentChanged)
/// In-Reply-To: Id of the message this message is a reply to.
Q_PROPERTY(QString inReplyTo READ inReplyTo WRITE setInReplyTo NOTIFY inReplyToChanged)
public:
explicit InfoPart(QObject *parent = nullptr);
~InfoPart() override;
[[nodiscard]] QString from() const;
void setFrom(const QString &from);
[[nodiscard]] QStringList to() const;
void setTo(const QStringList &to);
[[nodiscard]] QStringList cc() const;
void setCc(const QStringList &cc);
[[nodiscard]] QStringList bcc() const;
void setBcc(const QStringList &bcc);
[[nodiscard]] QStringList replyTo() const;
void setReplyTo(const QStringList &replyTo);
[[nodiscard]] QString subject() const;
void setSubject(const QString &subject);
[[nodiscard]] QString fcc() const;
void setFcc(const QString &fcc);
[[nodiscard]] QString userAgent() const;
void setUserAgent(const QString &userAgent);
[[nodiscard]] bool urgent() const;
void setUrgent(bool);
[[nodiscard]] QString inReplyTo() const;
void setInReplyTo(const QString &inReplyTo);
[[nodiscard]] QString references() const;
void setReferences(const QString &references);
void setExtraHeaders(const KMime::Headers::Base::List &headers);
[[nodiscard]] KMime::Headers::Base::List extraHeaders() const;
Q_SIGNALS:
void toChanged();
void fromChanged();
void ccChanged();
void bccChanged();
void replyToChanged();
void subjectChanged();
void urgentChanged();
void userAgentChanged();
void inReplyToChanged();
void fccChanged();
private:
class InfoPartPrivate;
std::unique_ptr<InfoPartPrivate> const d;
};
} // namespace MessageComposer

File Metadata

Mime Type
text/x-diff
Expires
Sat, Feb 7, 5:32 PM (1 d, 10 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
78/29/a6c2590ad83feeb22e587400684b

Event Timeline