Commit e02882f9 authored by Sandro Knauß's avatar Sandro Knauß

Move process*MimePart logic into bodyPartFormatters

parent 9d046e22
......@@ -11,6 +11,12 @@ include_directories(${GPGME_INCLUDES})
set(libmimetreeparser_main_SRCS
bodyformatter/applicationpgpencrypted.cpp
bodyformatter/mailman.cpp
bodyformatter/multipartalternative.cpp
bodyformatter/multipartencrypted.cpp
bodyformatter/multipartmixed.cpp
bodyformatter/multipartsigned.cpp
bodyformatter/textplain.cpp
bodyformatter/texthtml.cpp
bodyformatter/utils.cpp
interfaces/bodypartformatter.cpp
job/kleojobexecutor.cpp
......
/*
Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "multipartalternative.h"
#include "utils.h"
#include "viewer/objecttreeparser.h"
#include "viewer/messagepart.h"
#include <MessageCore/NodeHelper>
#include <KMime/Content>
#include "mimetreeparser_debug.h"
using namespace MimeTreeParser;
const MultiPartAlternativeBodyPartFormatter *MultiPartAlternativeBodyPartFormatter::self;
const Interface::BodyPartFormatter *MultiPartAlternativeBodyPartFormatter::create()
{
if (!self) {
self = new MultiPartAlternativeBodyPartFormatter();
}
return self;
}
Interface::BodyPartFormatter::Result MultiPartAlternativeBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const
{
Q_UNUSED(writer)
const auto p = process(*part);
const auto mp = static_cast<MessagePart *>(p.data());
if (mp) {
mp->html(false);
return Ok;
}
return Failed;
}
Interface::MessagePart::Ptr MultiPartAlternativeBodyPartFormatter::process(Interface::BodyPart &part) const
{
const KMime::Content *node = part.content();
KMime::Content *child = MessageCore::NodeHelper::firstChild(node);
if (!child) {
return MessagePart::Ptr();
}
KMime::Content *dataHtml = findType(child, "text/html", false, true);
KMime::Content *dataPlain = findType(child, "text/plain", false, true);
if (!dataHtml) {
// If we didn't find the HTML part as the first child of the multipart/alternative, it might
// be that this is a HTML message with images, and text/plain and multipart/related are the
// immediate children of this multipart/alternative node.
// In this case, the HTML node is a child of multipart/related.
dataHtml = findType(child, "multipart/related", false, true);
// Still not found? Stupid apple mail actually puts the attachments inside of the
// multipart/alternative, which is wrong. Therefore we also have to look for multipart/mixed
// here.
// Do this only when prefering HTML mail, though, since otherwise the attachments are hidden
// when displaying plain text.
if (!dataHtml && part.source()->htmlMail()) {
dataHtml = findType(child, "multipart/mixed", false, true);
}
}
if (dataPlain || dataHtml) {
AlternativeMessagePart::Ptr mp(new AlternativeMessagePart(part.objectTreeParser(), dataPlain, dataHtml));
if ((part.source()->htmlMail() && dataHtml) ||
(dataHtml && dataPlain && dataPlain->body().isEmpty())) {
if (dataPlain) {
part.nodeHelper()->setNodeProcessed(dataPlain, false);
}
part.source()->setHtmlMode(Util::MultipartHtml);
mp->setViewHtml(true);
}
if (!part.source()->htmlMail() && dataPlain) {
part.nodeHelper()->setNodeProcessed(dataHtml, false);
part.source()->setHtmlMode(Util::MultipartPlain);
mp->setViewHtml(false);
}
return mp;
}
MimeMessagePart::Ptr mp(new MimeMessagePart(part.objectTreeParser(), child, false));
return mp;
}
/*
Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTALTERNATIVE_H__
#define __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTALTERNATIVE_H__
#include "interfaces/bodypartformatter.h"
#include "interfaces/bodypart.h"
namespace MimeTreeParser
{
class MultiPartAlternativeBodyPartFormatter : public Interface::BodyPartFormatter
{
static const MultiPartAlternativeBodyPartFormatter *self;
public:
Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE;
Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE;
using Interface::BodyPartFormatter::format;
static const Interface::BodyPartFormatter *create();
};
}
#endif
/*
Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "multipartencrypted.h"
#include "utils.h"
#include "viewer/objecttreeparser.h"
#include "viewer/messagepart.h"
#include <MessageCore/NodeHelper>
#include <KMime/Content>
#include <Libkleo/CryptoBackendFactory>
#include "mimetreeparser_debug.h"
using namespace MimeTreeParser;
const MultiPartEncryptedBodyPartFormatter *MultiPartEncryptedBodyPartFormatter::self;
const Interface::BodyPartFormatter *MultiPartEncryptedBodyPartFormatter::create()
{
if (!self) {
self = new MultiPartEncryptedBodyPartFormatter();
}
return self;
}
Interface::BodyPartFormatter::Result MultiPartEncryptedBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const
{
Q_UNUSED(writer)
const auto p = process(*part);
const auto mp = static_cast<MessagePart *>(p.data());
if (mp) {
mp->html(false);
return Ok;
}
return Failed;
}
Interface::MessagePart::Ptr MultiPartEncryptedBodyPartFormatter::process(Interface::BodyPart &part) const
{
KMime::Content *node = part.content();
KMime::Content *child = MessageCore::NodeHelper::firstChild(node);
if (!child) {
Q_ASSERT(false);
return MessagePart::Ptr();
}
const Kleo::CryptoBackend::Protocol *useThisCryptProto = Q_NULLPTR;
/*
ATTENTION: This code is to be replaced by the new 'auto-detect' feature. --------------------------------------
*/
KMime::Content *data = findType(child, "application/octet-stream", false, true);
if (data) {
useThisCryptProto = Kleo::CryptoBackendFactory::instance()->openpgp();
}
if (!data) {
data = findType(child, "application/pkcs7-mime", false, true);
if (data) {
useThisCryptProto = Kleo::CryptoBackendFactory::instance()->smime();
}
}
/*
---------------------------------------------------------------------------------------------------------------
*/
if (!data) {
return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), child, false));
}
KMime::Content *dataChild = MessageCore::NodeHelper::firstChild(data);
if (dataChild) {
Q_ASSERT(false);
return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), dataChild, false));
}
part.nodeHelper()->setEncryptionState(node, KMMsgFullyEncrypted);
CryptoMessagePart::Ptr mp(new CryptoMessagePart(part.objectTreeParser(),
data->decodedText(), useThisCryptProto,
NodeHelper::fromAsString(data), node));
mp->setIsEncrypted(true);
mp->setDecryptMessage(part.source()->decryptMessage());
PartMetaData *messagePart(mp->partMetaData());
if (!part.source()->decryptMessage()) {
part.nodeHelper()->setNodeProcessed(data, false); // Set the data node to done to prevent it from being processed
} else if (KMime::Content *newNode = part.nodeHelper()->decryptedNodeForContent(data)) {
// if we already have a decrypted node for part.objectTreeParser() encrypted node, don't do the decryption again
return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), newNode, part.objectTreeParser()->showOnlyOneMimePart()));
} else {
mp->startDecryption(data);
qCDebug(MIMETREEPARSER_LOG) << "decrypted, signed?:" << messagePart->isSigned;
if (!messagePart->inProgress) {
part.nodeHelper()->setNodeProcessed(data, false); // Set the data node to done to prevent it from being processed
if (messagePart->isDecryptable && messagePart->isSigned) {
// Note: Multipart/Encrypted might also be signed
// without encapsulating a nicely formatted
// ~~~~~~~ Multipart/Signed part.
// (see RFC 3156 --> 6.2)
// In part.objectTreeParser() case we paint a _2nd_ frame inside the
// encryption frame, but we do _not_ show a respective
// encapsulated MIME part in the Mime Tree Viewer
// since we do want to show the _true_ structure of the
// message there - not the structure that the sender's
// MUA 'should' have sent. :-D (khz, 12.09.2002)
part.nodeHelper()->setSignatureState(node, KMMsgFullySigned);
qCDebug(MIMETREEPARSER_LOG) << "setting FULLY SIGNED to:" << node;
}
}
}
return mp;
}
/*
Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTENCRYPTED_H__
#define __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTENCRYPTED_H__
#include "interfaces/bodypartformatter.h"
#include "interfaces/bodypart.h"
namespace MimeTreeParser
{
class MultiPartEncryptedBodyPartFormatter : public Interface::BodyPartFormatter
{
static const MultiPartEncryptedBodyPartFormatter *self;
public:
Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE;
Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE;
using Interface::BodyPartFormatter::format;
static const Interface::BodyPartFormatter *create();
};
}
#endif
/*
Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "multipartmixed.h"
#include "viewer/objecttreeparser.h"
#include "viewer/messagepart.h"
#include <MessageCore/NodeHelper>
#include <KMime/Content>
#include "mimetreeparser_debug.h"
using namespace MimeTreeParser;
const MultiPartMixedBodyPartFormatter *MultiPartMixedBodyPartFormatter::self;
const Interface::BodyPartFormatter *MultiPartMixedBodyPartFormatter::create()
{
if (!self) {
self = new MultiPartMixedBodyPartFormatter();
}
return self;
}
Interface::BodyPartFormatter::Result MultiPartMixedBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const
{
Q_UNUSED(writer)
const auto p = process(*part);
const auto mp = static_cast<MessagePart *>(p.data());
if (mp) {
mp->html(false);
return Ok;
}
return Failed;
}
Interface::MessagePart::Ptr MultiPartMixedBodyPartFormatter::process(Interface::BodyPart &part) const
{
KMime::Content *child = MessageCore::NodeHelper::firstChild(part.content());
if (!child) {
return MessagePart::Ptr();
}
// normal treatment of the parts in the mp/mixed container
MimeMessagePart::Ptr mp(new MimeMessagePart(part.objectTreeParser(), child, false));
return mp;
}
/*
Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTMIXED_H__
#define __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTMIXED_H__
#include "interfaces/bodypartformatter.h"
#include "interfaces/bodypart.h"
namespace MimeTreeParser
{
class MultiPartMixedBodyPartFormatter : public Interface::BodyPartFormatter
{
static const MultiPartMixedBodyPartFormatter *self;
public:
Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE;
Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE;
using Interface::BodyPartFormatter::format;
static const Interface::BodyPartFormatter *create();
};
}
#endif
/*
Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "multipartsigned.h"
#include "viewer/objecttreeparser.h"
#include "viewer/messagepart.h"
#include <MessageCore/NodeHelper>
#include <KMime/Content>
#include <Libkleo/CryptoBackendFactory>
#include "mimetreeparser_debug.h"
#include <QTextCodec>
using namespace MimeTreeParser;
const MultiPartSignedBodyPartFormatter *MultiPartSignedBodyPartFormatter::self;
const Interface::BodyPartFormatter *MultiPartSignedBodyPartFormatter::create()
{
if (!self) {
self = new MultiPartSignedBodyPartFormatter();
}
return self;
}
Interface::BodyPartFormatter::Result MultiPartSignedBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const
{
Q_UNUSED(writer)
const auto p = process(*part);
const auto mp = static_cast<MessagePart *>(p.data());
if (mp) {
mp->html(false);
return Ok;
}
return Failed;
}
Interface::MessagePart::Ptr MultiPartSignedBodyPartFormatter::process(Interface::BodyPart &part) const
{
KMime::Content *node = part.content();
KMime::Content *signedData = MessageCore::NodeHelper::firstChild(node);
assert(signedData);
if (node->contents().size() != 2) {
qCDebug(MIMETREEPARSER_LOG) << "mulitpart/signed must have exactly two child parts!" << endl
<< "processing as multipart/mixed";
return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), signedData, false));
}
KMime::Content *signature = node->contents().at(1);
assert(signature);
QString protocolContentType = node->contentType()->parameter(QStringLiteral("protocol")).toLower();
const QString signatureContentType = QLatin1String(signature->contentType()->mimeType().toLower());
if (protocolContentType.isEmpty()) {
qCWarning(MIMETREEPARSER_LOG) << "Message doesn't set the protocol for the multipart/signed content-type, "
"using content-type of the signature:" << signatureContentType;
protocolContentType = signatureContentType;
}
const Kleo::CryptoBackend::Protocol *protocol = Q_NULLPTR;
if (protocolContentType == QLatin1String("application/pkcs7-signature") ||
protocolContentType == QLatin1String("application/x-pkcs7-signature")) {
protocol = Kleo::CryptoBackendFactory::instance()->smime();
} else if (protocolContentType == QLatin1String("application/pgp-signature") ||
protocolContentType == QLatin1String("application/x-pgp-signature")) {
protocol = Kleo::CryptoBackendFactory::instance()->openpgp();
}
if (!protocol) {
return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), signedData, false));
}
part.nodeHelper()->setNodeProcessed(signature, true);
part.nodeHelper()->setSignatureState(node, KMMsgFullySigned);
const QByteArray cleartext = KMime::LFtoCRLF(signedData->encodedContent());
const QTextCodec *aCodec(part.objectTreeParser()->codecFor(signedData));
CryptoMessagePart::Ptr mp(new CryptoMessagePart(part.objectTreeParser(),
aCodec->toUnicode(cleartext), protocol,
NodeHelper::fromAsString(node), signature));
PartMetaData *messagePart(mp->partMetaData());
messagePart->isSigned = true;
if (protocol) {
mp->startVerificationDetached(cleartext, signedData, signature->decodedContent());
} else {
messagePart->auditLogError = GpgME::Error(GPG_ERR_NOT_IMPLEMENTED);
}
return mp;
}
/*
Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTSIGNED_H__
#define __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTSIGNED_H__
#include "interfaces/bodypartformatter.h"
#include "interfaces/bodypart.h"
namespace MimeTreeParser
{
class MultiPartSignedBodyPartFormatter : public Interface::BodyPartFormatter
{
static const MultiPartSignedBodyPartFormatter *self;
public:
Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE;
Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE;
using Interface::BodyPartFormatter::format;