From 2fdddd2f795da4645dc9a48fee4865324143a21b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20Knau=C3=9F?= Date: Mon, 18 Jul 2016 15:35:07 +0200 Subject: first tests with mimetreeparser interface --- framework/domain/CMakeLists.txt | 2 + framework/domain/mimetreeparser/CMakeLists.txt | 12 + framework/domain/mimetreeparser/interface.cpp | 335 +++++++++++++++++++++ framework/domain/mimetreeparser/interface.h | 281 ++++++++--------- .../domain/mimetreeparser/objecttreesource.cpp | 151 ++++++++++ framework/domain/mimetreeparser/objecttreesource.h | 57 ++++ .../domain/mimetreeparser/stringhtmlwriter.cpp | 150 +++++++++ framework/domain/mimetreeparser/stringhtmlwriter.h | 71 +++++ framework/domain/mimetreeparser/test.cpp | 148 --------- .../domain/mimetreeparser/tests/CMakeLists.txt | 10 + .../mimetreeparser/tests/data/alternative.mbox | 34 +++ .../domain/mimetreeparser/tests/data/html.mbox | 31 ++ .../domain/mimetreeparser/tests/data/htmlonly.mbox | 21 ++ .../tests/data/htmlonlyexternal.mbox | 21 ++ .../mimetreeparser/tests/data/plaintext.mbox | 17 ++ .../domain/mimetreeparser/tests/interfacetest.cpp | 47 +++ framework/domain/mimetreeparser/thoughts.txt | 148 +++++++++ 17 files changed, 1226 insertions(+), 310 deletions(-) create mode 100644 framework/domain/mimetreeparser/CMakeLists.txt create mode 100644 framework/domain/mimetreeparser/interface.cpp create mode 100644 framework/domain/mimetreeparser/objecttreesource.cpp create mode 100644 framework/domain/mimetreeparser/objecttreesource.h create mode 100644 framework/domain/mimetreeparser/stringhtmlwriter.cpp create mode 100644 framework/domain/mimetreeparser/stringhtmlwriter.h delete mode 100644 framework/domain/mimetreeparser/test.cpp create mode 100644 framework/domain/mimetreeparser/tests/CMakeLists.txt create mode 100644 framework/domain/mimetreeparser/tests/data/alternative.mbox create mode 100644 framework/domain/mimetreeparser/tests/data/html.mbox create mode 100644 framework/domain/mimetreeparser/tests/data/htmlonly.mbox create mode 100644 framework/domain/mimetreeparser/tests/data/htmlonlyexternal.mbox create mode 100644 framework/domain/mimetreeparser/tests/data/plaintext.mbox create mode 100644 framework/domain/mimetreeparser/tests/interfacetest.cpp create mode 100644 framework/domain/mimetreeparser/thoughts.txt diff --git a/framework/domain/CMakeLists.txt b/framework/domain/CMakeLists.txt index ea293655..92a81352 100644 --- a/framework/domain/CMakeLists.txt +++ b/framework/domain/CMakeLists.txt @@ -26,3 +26,5 @@ add_subdirectory(actions/tests) install(TARGETS mailplugin DESTINATION ${QML_INSTALL_DIR}/org/kube/framework/domain) install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kube/framework/domain) + +add_subdirectory(mimetreeparser) \ No newline at end of file diff --git a/framework/domain/mimetreeparser/CMakeLists.txt b/framework/domain/mimetreeparser/CMakeLists.txt new file mode 100644 index 00000000..e1c04893 --- /dev/null +++ b/framework/domain/mimetreeparser/CMakeLists.txt @@ -0,0 +1,12 @@ +set(mimetreeparser_SRCS + interface.cpp + objecttreesource.cpp + stringhtmlwriter.cpp +) + +add_library(mimetreeparser SHARED ${mimetreeparser_SRCS}) + +qt5_use_modules(mimetreeparser Core Gui) +target_link_libraries(mimetreeparser KF5::Mime KF5::MimeTreeParser) + +add_subdirectory(tests) \ No newline at end of file diff --git a/framework/domain/mimetreeparser/interface.cpp b/framework/domain/mimetreeparser/interface.cpp new file mode 100644 index 00000000..6a399015 --- /dev/null +++ b/framework/domain/mimetreeparser/interface.cpp @@ -0,0 +1,335 @@ +/* + Copyright (c) 2016 Sandro Knauß + + 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 "interface.h" + +#include "stringhtmlwriter.h" +#include "objecttreesource.h" + +#include +#include +#include +#include + +#include +#include + +class PartPrivate +{ +public: + PartPrivate(Part *part); + void appendSubPart(Part::Ptr subpart); + + QVector subParts(); + + const std::weak_ptr &parent() const; +private: + Part *q; + std::weak_ptr mParent; + QVector mSubParts; +}; + +PartPrivate::PartPrivate(Part* part) + :q(part) +{ + +} + +void PartPrivate::appendSubPart(Part::Ptr subpart) +{ + subpart->d->mParent = Part::Ptr(q); + mSubParts.append(subpart); +} + +const std::weak_ptr &PartPrivate::parent() const +{ + return mParent; +} + +QVector< Part::Ptr > PartPrivate::subParts() +{ + return mSubParts; +} + +Part::Part() + : d(std::unique_ptr(new PartPrivate(this))) +{ + +} + +bool Part::hasSubParts() const +{ + return !subParts().isEmpty(); +} + +QVector Part::subParts() const +{ + return d->subParts(); +} + +QByteArray Part::type() const +{ + return "Part"; +} + +QVector Part::encryptions() const +{ + auto parent = d->parent().lock(); + if (parent) { + return parent->encryptions(); + } else { + return QVector(); + } +} + +QVector Part::signatures() const +{ + auto parent = d->parent().lock(); + if (parent) { + return parent->signatures(); + } else { + return QVector(); + } +} + +class ContentPrivate +{ +public: + QByteArray mContent; + QByteArray mCodec; + Part *mParent; + Content *q; +}; + +Content::Content(const QByteArray& content, ContentPart *parent) + : d(std::unique_ptr(new ContentPrivate)) +{ + d->q = this; + d->mContent = content; + d->mCodec = "utf-8"; + d->mParent = parent; +} + +Content::~Content() +{ +} + +QVector< Encryption > Content::encryptions() const +{ + if (d->mParent) { + return d->mParent->encryptions(); + } + return QVector(); +} + +QVector< Signature > Content::signatures() const +{ + if (d->mParent) { + return d->mParent->signatures(); + } + return QVector(); +} + +class ContentPartPrivate +{ +public: + void fillFrom(MimeTreeParser::TextMessagePart::Ptr part); + void fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part); + void fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part); + + QVector contents() const; + + ContentPart *q; + +private: + QVector mContents; + ContentPart::Types mTypes; +}; + +void ContentPartPrivate::fillFrom(MimeTreeParser::TextMessagePart::Ptr part) +{ + mTypes = ContentPart::PlainText; + foreach (const auto &mp, part->subParts()) { + auto content = std::make_shared(mp->text().toLocal8Bit(), q); + mContents.append(content); + } +} + +void ContentPartPrivate::fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part) +{ + mTypes = ContentPart::Html; +} + +void ContentPartPrivate::fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part) +{ + mTypes = ContentPart::Html | ContentPart::PlainText; +} + +ContentPart::ContentPart() + : d(std::unique_ptr(new ContentPartPrivate)) +{ + d->q = this; +} + +ContentPart::~ContentPart() +{ + +} + +QByteArray ContentPart::type() const +{ + return "ContentPart"; +} + +class MimePartPrivate +{ +public: + void fillFrom(MimeTreeParser::MessagePart::Ptr part); +}; + +QByteArray MimePart::type() const +{ + return "MimePart"; +} + +class AttachmentPartPrivate +{ +public: + void fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part); +}; + +void AttachmentPartPrivate::fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part) +{ + +} + +QByteArray AttachmentPart::type() const +{ + return "AttachmentPart"; +} + +class ParserPrivate +{ +public: + ParserPrivate(Parser *parser); + + void setMessage(const QByteArray &mimeMessage); + void createTree(MimeTreeParser::MessagePart::Ptr start, Part::Ptr tree); + + Part::Ptr mTree; +private: + Parser *q; + + MimeTreeParser::MessagePart::Ptr mPartTree; + std::shared_ptr mNodeHelper; + QString mHtml; + QMap mEmbeddedPartMap; +}; + +ParserPrivate::ParserPrivate(Parser* parser) + : q(parser) + , mNodeHelper(std::make_shared()) +{ + +} + +void ParserPrivate::setMessage(const QByteArray& mimeMessage) +{ + const auto mailData = KMime::CRLFtoLF(mimeMessage); + KMime::Message::Ptr msg(new KMime::Message); + msg->setContent(mailData); + msg->parse(); + + // render the mail + StringHtmlWriter htmlWriter; + QImage paintDevice; + ObjectTreeSource source(&htmlWriter); + MimeTreeParser::ObjectTreeParser otp(&source, mNodeHelper.get()); + + otp.parseObjectTree(msg.data()); + mPartTree = otp.parsedPart().dynamicCast(); + + mEmbeddedPartMap = htmlWriter.embeddedParts(); + mHtml = htmlWriter.html(); + + mTree = std::make_shared(); + createTree(mPartTree, mTree); +} + + +void ParserPrivate::createTree(MimeTreeParser::MessagePart::Ptr start, Part::Ptr tree) +{ + + foreach (const auto &mp, start->subParts()) { + const auto m = mp.dynamicCast(); + const auto text = mp.dynamicCast(); + const auto alternative = mp.dynamicCast(); + const auto html = mp.dynamicCast(); + const auto attachment = mp.dynamicCast(); + if (text) { + auto part = std::make_shared(); + part->d->fillFrom(text); + mTree->d->appendSubPart(part); + } else if (alternative) { + auto part = std::make_shared(); + part->d->fillFrom(alternative); + mTree->d->appendSubPart(part); + } else if (html) { + auto part = std::make_shared(); + part->d->fillFrom(html); + mTree->d->appendSubPart(part); + } else if (attachment) { + auto part = std::make_shared(); + part->d->fillFrom(attachment); + mTree->d->appendSubPart(part); + } else { + createTree(m, tree); + } + } +} + +Parser::Parser(const QByteArray& mimeMessage) + :d(std::unique_ptr(new ParserPrivate(this))) +{ + d->setMessage(mimeMessage); +} + +Parser::~Parser() +{ +} + +ContentPart::Ptr Parser::collectContentPart(const Part::Ptr &start) const +{ + foreach (const auto &part, start->subParts()) { + if (part->type() == "ContentPart") { + return std::dynamic_pointer_cast(part); + } else { + auto ret = collectContentPart(part); + if (ret) { + return ret; + } + } + } + return ContentPart::Ptr(); +} + +ContentPart::Ptr Parser::collectContentPart() const +{ + return collectContentPart(d->mTree); +} diff --git a/framework/domain/mimetreeparser/interface.h b/framework/domain/mimetreeparser/interface.h index 320030b7..82f88e73 100644 --- a/framework/domain/mimetreeparser/interface.h +++ b/framework/domain/mimetreeparser/interface.h @@ -19,104 +19,70 @@ #pragma once +#include +#include + +#include #include #include class Part; -typedef std::shared_ptr Part::Ptr; -class EncryptionPart; -typedef std::shared_ptr EncryptionPart::Ptr; -class SignaturePart; -typedef std::shared_ptr SignaturePart::Ptr; +class PartPrivate; class MimePart; -typedef std::shared_ptr MimePart::Ptr; class MimePartPrivate; class ContentPart; -typedef std::shared_ptr ContentPart::Ptr; class ContentPartPrivate; -class EncryptionErrorPart; -typedef std::shared_ptr EncryptionErrorPart::Ptr; -class EncryptionErrorPartPrivate; +class EncryptionPart; +class EncryptionPartPrivate; class AttachmentPart; -typedef std::shared_ptr AttachmentPart::Ptr; class AttachmentPartPrivate; class EncapsulatedPart; -typedef std::shared_ptr EncapsulatedPart::Ptr; -class EncapsulatedPart; +class EncapsulatedPartPrivate; class CertPart; -typedef std::shared_ptr CertPart::Ptr; +class CertPartPrivate; + +class Content; +class ContentPrivate; class Key; class Signature; class Encryption; class Parser; -typedef std::shared_ptr Parser::Ptr; class ParserPrivate; -class Parser -{ -public: - Parser(const QByteArray &mimeMessage); - - Part::Ptr getPart(QUrl url); - - QVector collect() const; - QVector collect() const; - QVector collect(Part start, std::function select, std::function filter) const; - -private: - std::unique_ptr d; -}; - - class Part { public: - virtual QByteArray type() const = 0; + typedef std::shared_ptr Ptr; + Part(); + virtual QByteArray type() const; bool hasSubParts() const; - QList subParts() const; - Part parent() const; + QVector subParts() const; + Part::Ptr parent() const; virtual QVector signatures() const; virtual QVector encryptions() const; +private: + std::unique_ptr d; + friend class ParserPrivate; + friend class PartPrivate; }; -//A structure element, that we need to reflect, that there is a Encryption starts -// only add a new Encrption block to encryptions block -class EncryptionPart : public Part -{ -public: - QVector encryptions() const Q_DECL_OVERRIDE; - QByteArray type() const Q_DECL_OVERRIDE; -}; - -// A structure element, that we need to reflect, that there is a Signature starts -// only add a new Signature block to signature block -// With this we can a new Singature type like pep aka -/* - * add a bodypartformatter, that returns a PEPSignaturePart with all signed subparts that are signed with pep. - * subclass Signature aka PEPSignature to reflect different way of properties of PEPSignatures. - */ -class SignaturePart : public Part +class Content { public: - QVector signatures() const Q_DECL_OVERRIDE; - QByteArray type() const Q_DECL_OVERRIDE; -}; - + typedef std::shared_ptr Ptr; + Content(const QByteArray &content, ContentPart *parent); + virtual ~Content(); - -class TextPart : public Part -{ -public: QByteArray content() const; //Use default charset @@ -124,14 +90,20 @@ public: // overwrite default charset with given charset QString encodedContent(QByteArray charset) const; -} + + virtual QVector signatures() const; + virtual QVector encryptions() const; +private: + std::unique_ptr d; +}; /* * A MessagePart that is based on a KMime::Content */ -class MimePart : public TextPart +class MimePart : public Part { public: + typedef std::shared_ptr Ptr; /** * Various possible values for the "Content-Disposition" header. */ @@ -154,6 +126,13 @@ public: // Unique identifier to ecactly this KMime::Content QByteArray link() const; + QByteArray content() const; + + //Use default charset + QString encodedContent() const; + + // overwrite default charset with given charset + QString encodedContent(QByteArray charset) const; QByteArray type() const Q_DECL_OVERRIDE; private: @@ -171,77 +150,84 @@ private: * for alternative, we are represating three messageparts * - "headers" do we return?, we can use setType to make it possible to select and than return these headers */ -class MainContentPart : public MimePart +class ContentPart : public Part { public: - enum Types { - PlainText, - Html + typedef std::shared_ptr Ptr; + enum Type { + PlainText = 0x0001, + Html = 0x0002 }; Q_DECLARE_FLAGS(Types, Type) - QVector content(Content::Type ct) const; + ContentPart(); + virtual ~ContentPart(); + + QVector content(Type ct) const; - Content::Types availableContent() const; + Types availableContents() const; QByteArray type() const Q_DECL_OVERRIDE; private: std::unique_ptr d; + + friend class ParserPrivate; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(ContentPart::Type) +Q_DECLARE_OPERATORS_FOR_FLAGS(ContentPart::Types); class AttachmentPart : public MimePart { public: + typedef std::shared_ptr Ptr; QByteArray type() const Q_DECL_OVERRIDE; private: std::unique_ptr d; + friend class ParserPrivate; }; /* - * Faild to decrypt part - * thigs liks this can happen: - * decryption in progress - * have not tried at all to decrypt - * wrong passphrase - * no private key - * cryptobackend is not configured correctly (no gpg available) - * -> S/Mime and PGP have different meaning in their errors - * * Open Questions: * - How to make the string translateable for multiple clients, so that multiple clients can show same error messages, * that helps users to understand what is going on ? * - Does openpgp have translations already? */ -class EncryptionErrorPart : public Part +class EncryptionError { public: - Error errorId() const; - - CryptoBackend cryptoBackend(); + int errorId() const; + QString errorString() const; +}; +class EncryptionPart : public MimePart +{ +public: + typedef std::shared_ptr Ptr; QByteArray type() const Q_DECL_OVERRIDE; + EncryptionError error() const; + private: - std::unique_ptr d; + std::unique_ptr d; }; + /* * we want to request complete headers like: * from/to... */ -class EncapsulatedPart :: public AttachmentPart +class EncapsulatedPart : public AttachmentPart { public: + typedef std::shared_ptr Ptr; QByteArray type() const Q_DECL_OVERRIDE; - QByteArray header(); + //template QByteArray header(); private: - std::unique_ptr d; + std::unique_ptr d; }; /* @@ -249,64 +235,31 @@ private: * checking a cert (if it is a valid cert) */ -class CertPart :: public AttachmentPart +class CertPart : public AttachmentPart { public: + typedef std::shared_ptr Ptr; QByteArray type() const Q_DECL_OVERRIDE; - bool checkCert() const; - Status importCert() const; - -private: - std::unique_ptr d; -}; - -/* -the ggme error class - -// class GPGMEPP_EXPORT ErrorImportResult -{ -public: - Error() : mErr(0), mMessage() {} - explicit Error(unsigned int e) : mErr(e), mMessage() {} - - const char *source() const; - const char *asString() const; - - int code() const; - int sourceID() const; - - bool isCanceled() const; + enum CertType { + Pgp, + SMime + }; - unsigned int encodedError() const - { - return mErr; - } - int toErrno() const; + enum CertSubType { + Public, + Private + }; - static bool hasSystemError(); - static Error fromSystemError(unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT); - static void setSystemError(gpg_err_code_t err); - static void setErrno(int err); - static Error fromErrno(int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT); - static Error fromCode(unsigned int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT); + CertType certType() const; + CertSubType certSubType() const; + int keyLength() const; - GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(mErr &&!isCanceled()) private: - unsigned int mErr; - mutable std::string mMessage; + std::unique_ptr d; }; -*/ -/* - * a used smime/PGP key - * in the end we also need things like: - bool isRevokation() const; - bool isInvalid() const; - bool isExpired() const; - -> so we end up wrapping GpgME::Key - */ class Key { QString keyid() const; @@ -314,8 +267,14 @@ class Key QString email() const; QString comment() const; QVector emails() const; + enum KeyTrust { + Unknown, Undefined, Never, Marginal, Full, Ultimate + }; KeyTrust keyTrust() const; - CryptoBackend cryptoBackend() const; + + bool isRevokation() const; + bool isInvalid() const; + bool isExpired() const; std::vector subkeys(); Key parentkey() const; @@ -328,35 +287,7 @@ class Signature QDateTime expirationTime() const; bool neverExpires() const; - bool inProgress(); //if the verfication is inProgress - - enum Validity { - Unknown, Undefined, Never, Marginal, Full, Ultimate - }; - Validity validity() const; - - // to determine if we need this in our usecase (email) - // GpgME::VerificationResult - enum Summary { - None = 0x000, - Valid = 0x001, - Green = 0x002, - Red = 0x004, - KeyRevoked = 0x008, - KeyExpired = 0x010, - SigExpired = 0x020, - KeyMissing = 0x040, - CrlMissing = 0x080, - CrlTooOld = 0x100, - BadPolicy = 0x200, - SysError = 0x400 - }; - Summary summary() const; - - const char *policyURL() const; - GpgME::Notation notation(unsigned int index) const; - std::vector notations() const; - + //template <> StatusObject verify() const; }; /* @@ -367,4 +298,30 @@ class Signature class Encryption { std::vector recipients() const; +}; + +class Parser +{ +public: + typedef std::shared_ptr Ptr; + Parser(const QByteArray &mimeMessage); + ~Parser(); + + Part::Ptr getPart(QUrl url); + + //template QVector collect(Part start, std::function select, std::function filter) const; + QVector collectAttachments(Part::Ptr start, std::function select, std::function filter) const; + ContentPart::Ptr collectContentPart(Part::Ptr start, std::function select, std::function filter) const; + ContentPart::Ptr collectContentPart(const Part::Ptr& start) const; + ContentPart::Ptr collectContentPart() const; + //template <> QVector collect() const; + + //template <> static StatusObject verifySignature(const Signature signature) const; + //template <> static StatusObject decrypt(const EncryptedPart part) const; + +signals: + void partsChanged(); + +private: + std::unique_ptr d; }; \ No newline at end of file diff --git a/framework/domain/mimetreeparser/objecttreesource.cpp b/framework/domain/mimetreeparser/objecttreesource.cpp new file mode 100644 index 00000000..12cf88ab --- /dev/null +++ b/framework/domain/mimetreeparser/objecttreesource.cpp @@ -0,0 +1,151 @@ +/* + Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net + Copyright (c) 2009 Andras Mantia + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "objecttreesource.h" + +#include +#include +#include +#include + +class ObjectSourcePrivate +{ +public: + ObjectSourcePrivate() + : mWriter(0) + , mAllowDecryption(true) + , mHtmlLoadExternal(true) + , mHtmlMail(true) + { + + } + MimeTreeParser::HtmlWriter *mWriter; + MimeTreeParser::BodyPartFormatterBaseFactory mBodyPartFormatterBaseFactory; + bool mAllowDecryption; + bool mHtmlLoadExternal; + bool mHtmlMail; +}; + +ObjectTreeSource::ObjectTreeSource(MimeTreeParser::HtmlWriter *writer) + : MimeTreeParser::Interface::ObjectTreeSource() + , d(new ObjectSourcePrivate) + { + d->mWriter = writer; + } + +ObjectTreeSource::~ObjectTreeSource() +{ + delete d; +} + +void ObjectTreeSource::setAllowDecryption(bool allowDecryption) +{ + d->mAllowDecryption = allowDecryption; +} + +MimeTreeParser::HtmlWriter *ObjectTreeSource::htmlWriter() +{ + return d->mWriter; +} + +bool ObjectTreeSource::htmlLoadExternal() const +{ + return d->mHtmlLoadExternal; +} + +void ObjectTreeSource::setHtmlLoadExternal(bool loadExternal) +{ + d->mHtmlLoadExternal = loadExternal; +} + +bool ObjectTreeSource::htmlMail() const +{ + return d->mHtmlMail; +} + +void ObjectTreeSource::setHtmlMail(bool htmlMail) +{ + d->mHtmlMail = htmlMail; +} + +bool ObjectTreeSource::decryptMessage() const +{ + return d->mAllowDecryption; +} + +bool ObjectTreeSource::showSignatureDetails() const +{ + return true; +} + +int ObjectTreeSource::levelQuote() const +{ + return 1; +} + +const QTextCodec *ObjectTreeSource::overrideCodec() +{ + return Q_NULLPTR; +} + +QString ObjectTreeSource::createMessageHeader(KMime::Message *message) +{ + return QString(); +} + +const MimeTreeParser::AttachmentStrategy *ObjectTreeSource::attachmentStrategy() +{ + return MimeTreeParser::AttachmentStrategy::smart(); +} + +QObject *ObjectTreeSource::sourceObject() +{ + return Q_NULLPTR; +} + +void ObjectTreeSource::setHtmlMode(MimeTreeParser::Util::HtmlMode mode) +{ + Q_UNUSED(mode); +} + +bool ObjectTreeSource::autoImportKeys() const +{ + return false; +} + +bool ObjectTreeSource::showEmoticons() const +{ + return false; +} + +bool ObjectTreeSource::showExpandQuotesMark() const +{ + return false; +} + +const MimeTreeParser::BodyPartFormatterBaseFactory *ObjectTreeSource::bodyPartFormatterFactory() +{ + return &(d->mBodyPartFormatterBaseFactory); +} + +MimeTreeParser::Interface::MessagePartRenderer::Ptr ObjectTreeSource::messagePartTheme(MimeTreeParser::Interface::MessagePart::Ptr msgPart) +{ + Q_UNUSED(msgPart); + return MimeTreeParser::Interface::MessagePartRenderer::Ptr(); +} diff --git a/framework/domain/mimetreeparser/objecttreesource.h b/framework/domain/mimetreeparser/objecttreesource.h new file mode 100644 index 00000000..bb0cd679 --- /dev/null +++ b/framework/domain/mimetreeparser/objecttreesource.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net + Copyright (c) 2009 Andras Mantia + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef MAILVIEWER_OBJECTTREEEMPTYSOURCE_H +#define MAILVIEWER_OBJECTTREEEMPTYSOURCE_H + +#include + +class QString; + +class ObjectSourcePrivate; +class ObjectTreeSource : public MimeTreeParser::Interface::ObjectTreeSource +{ +public: + ObjectTreeSource(MimeTreeParser::HtmlWriter *writer); + virtual ~ObjectTreeSource(); + void setHtmlLoadExternal(bool loadExternal); + void setHtmlMail(bool htmlMail); + bool htmlMail() const Q_DECL_OVERRIDE; + bool decryptMessage() const Q_DECL_OVERRIDE; + bool htmlLoadExternal() const Q_DECL_OVERRIDE; + bool showSignatureDetails() const Q_DECL_OVERRIDE; + void setHtmlMode(MimeTreeParser::Util::HtmlMode mode) Q_DECL_OVERRIDE; + void setAllowDecryption(bool allowDecryption); + int levelQuote() const Q_DECL_OVERRIDE; + const QTextCodec *overrideCodec() Q_DECL_OVERRIDE; + QString createMessageHeader(KMime::Message *message) Q_DECL_OVERRIDE; + const MimeTreeParser::AttachmentStrategy *attachmentStrategy() Q_DECL_OVERRIDE; + MimeTreeParser::HtmlWriter *htmlWriter() Q_DECL_OVERRIDE; + QObject *sourceObject() Q_DECL_OVERRIDE; + bool autoImportKeys() const Q_DECL_OVERRIDE; + bool showEmoticons() const Q_DECL_OVERRIDE; + bool showExpandQuotesMark() const Q_DECL_OVERRIDE; + const MimeTreeParser::BodyPartFormatterBaseFactory *bodyPartFormatterFactory() Q_DECL_OVERRIDE; + MimeTreeParser::Interface::MessagePartRendererPtr messagePartTheme(MimeTreeParser::Interface::MessagePartPtr msgPart) Q_DECL_OVERRIDE; +private: + ObjectSourcePrivate *const d; +}; + +#endif + diff --git a/framework/domain/mimetreeparser/stringhtmlwriter.cpp b/framework/domain/mimetreeparser/stringhtmlwriter.cpp new file mode 100644 index 00000000..88034492 --- /dev/null +++ b/framework/domain/mimetreeparser/stringhtmlwriter.cpp @@ -0,0 +1,150 @@ +/* -*- c++ -*- + filehtmlwriter.cpp + + This file is part of KMail, the KDE mail client. + Copyright (c) 2003 Marc Mutz + + KMail is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + KMail 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "stringhtmlwriter.h" + +#include +#include +#include + +StringHtmlWriter::StringHtmlWriter() + : MimeTreeParser::HtmlWriter() + , mState(Ended) +{ +} + +StringHtmlWriter::~StringHtmlWriter() +{ +} + +void StringHtmlWriter::begin(const QString &css) +{ + if (mState != Ended) { + qWarning() << "begin() called on non-ended session!"; + reset(); + } + + mState = Begun; + mExtraHead.clear(); + mHtml.clear(); + + if (!css.isEmpty()) { + write(QLatin1String("\n")); + } +} + +void StringHtmlWriter::end() +{ + if (mState != Begun) { + qWarning() << "Called on non-begun or queued session!"; + } + + if (!mExtraHead.isEmpty()) { + insertExtraHead(); + mExtraHead.clear(); + } + resolveCidUrls(); + mState = Ended; +} + +void StringHtmlWriter::reset() +{ + if (mState != Ended) { + mHtml.clear(); + mExtraHead.clear(); + mState = Begun; // don't run into end()'s warning + end(); + mState = Ended; + } +} + +void StringHtmlWriter::write(const QString &str) +{ + if (mState != Begun) { + qWarning() << "Called in Ended or Queued state!"; + } + mHtml.append(str); +} + +void StringHtmlWriter::queue(const QString &str) +{ + write(str); +} + +void StringHtmlWriter::flush() +{ + mState = Begun; // don't run into end()'s warning + end(); +} + +void StringHtmlWriter::embedPart(const QByteArray &contentId, const QString &url) +{ + write("\n"); + mEmbeddedPartMap.insert(contentId, url); +} + +void StringHtmlWriter::resolveCidUrls() +{ + for (const auto &cid : mEmbeddedPartMap.keys()) { + mHtml.replace(QString("src=\"cid:%1\"").arg(QString(cid)), QString("src=\"%1\"").arg(mEmbeddedPartMap.value(cid).toString())); + } +} + +void StringHtmlWriter::extraHead(const QString &extraHead) +{ + if (mState != Ended) { + qWarning() << "Called on non-started session!"; + } + mExtraHead.append(extraHead); +} + + +void StringHtmlWriter::insertExtraHead() +{ + const QString headTag(QStringLiteral("")); + const int index = mHtml.indexOf(headTag); + if (index != -1) { + mHtml.insert(index + headTag.length(), mExtraHead); + } +} + +QMap StringHtmlWriter::embeddedParts() const +{ + return mEmbeddedPartMap; +} + +QString StringHtmlWriter::html() const +{ + if (mState != Ended) { + qWarning() << "Called on non-ended session!"; + } + return mHtml; +} diff --git a/framework/domain/mimetreeparser/stringhtmlwriter.h b/framework/domain/mimetreeparser/stringhtmlwriter.h new file mode 100644 index 00000000..fa5b760e --- /dev/null +++ b/framework/domain/mimetreeparser/stringhtmlwriter.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- + + Copyright (c) 2016 Sandro Knauß + + Kube is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + Kube 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ +#define __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ + +#include + +#include +#include + +class QString; + +class StringHtmlWriter : public MimeTreeParser::HtmlWriter +{ +public: + explicit StringHtmlWriter(); + virtual ~StringHtmlWriter(); + + void begin(const QString &cssDefs) Q_DECL_OVERRIDE; + void end() Q_DECL_OVERRIDE; + void reset() Q_DECL_OVERRIDE; + void write(const QString &str) Q_DECL_OVERRIDE; + void queue(const QString &str) Q_DECL_OVERRIDE; + void flush() Q_DECL_OVERRIDE; + void embedPart(const QByteArray &contentId, const QString &url) Q_DECL_OVERRIDE; + void extraHead(const QString &str) Q_DECL_OVERRIDE; + + QString html() const; + QMap embeddedParts() const; +private: + void insertExtraHead(); + void resolveCidUrls(); + + QString mHtml; + QString mExtraHead; + enum State { + Begun, + Queued, + Ended + } mState; + QMap mEmbeddedPartMap; +}; + +#endif // __MESSAGEVIEWER_FILEHTMLWRITER_H__ diff --git a/framework/domain/mimetreeparser/test.cpp b/framework/domain/mimetreeparser/test.cpp deleted file mode 100644 index 51aa9871..00000000 --- a/framework/domain/mimetreeparser/test.cpp +++ /dev/null @@ -1,148 +0,0 @@ -Usecases: - -# plaintext msg + attachment -* ContentPart => cp1 -* AttachmentPart => ap1 - -(cp1) == collect(select=NoEncapsulatedMessages) -(ap1) == collect(select=NoEncapsulatedMessages) - -(PlainText) == cp1.availableContent() - -# html msg + related attachment + normal attachment -* ContentPart => cp1 -* AttachmentPart(mimetype="*/related", cid="12345678") => ap1 -* AttachmentPart => ap2 - -(cp1) == collect(select=NoEncapsulatedMessages) -(ap1, ap2) == collect(select=NoEncapsulatedMessages) -(ap2) == collect(select=NoEncapsulatedMessages, filter=filterelated) - -ap1 == getPart("cid:12345678") - -(Html) == cp1.availableContent() - -# alternative msg + attachment -* ContentPart(html=[TextPart("HTML"),], plaintext=[TextPart("Text"),]) => cp1 -* AttachmentPart => ap1 - -(cp1) == collect(select=NoEncapsulatedMessages) -(ap1) == collect(select=NoEncapsulatedMessages) - -(Html, PlainText) == cp1.availableContent() -[TextPart("HTML"),] == cp1.content(Html) -[TextPart("Text"),] == cp1.content(Plaintext) - -# alternative msg with GPGInlin -* ContentPart( - plaintext=[TextPart("Text"), TextPart("foo", encryption=(enc1))], - html=[TextPart("HTML"),] - ) => cp1 - -(Html, PlainText) == cp1.availableContent() - -[TextPart("HTML"),] == cp1.content(Html) -[TextPart("Text"),TextPart("foo", encryption=(enc1))] == cp1.content(Plaintext) - - -# encrypted msg (not encrypted/error) with unencrypted attachment -* EncryptionErrorPart => cp1 -* AttachmentPart => ap1 - -(cp1) == collect(select=NoEncapsulatedMessages) -(ap1) == collect(select=NoEncapsulatedMessages) - -#encrypted msg (decrypted with attachment) + unencrypted attachment -* encrytion=(rec1,rec2) => enc1 - * ContentPart(encrytion = (enc1,)) => cp1 - * AttachmentPart(encryption = (enc1,)) => ap1 -* AttachmentPart => ap2 - -(cp1) == collect(select=NoEncapsulatedMessages) -(ap1, ap2) == collect(select=NoEncapsulatedMessages) - -#INLINE GPG encrypted msg + attachment -* ContentPart => cp1 with - plaintext=[TextPart, TextPart(encrytion = (enc1(rec1,rec2),)), TextPart(signed = (sig1,)), TextPart] -* AttachmentPart => ap1 - -(cp1) == collect(select=NoEncapsulatedMessages) -(ap1) == collect(select=NoEncapsulatedMessages) - -[TextPart, TextPart(encrytion = (enc1(rec1,rec2),)), TextPart(signed = (sig1,)), TextPart] == cp1.content(Plaintext) - -#forwared encrypted msg + attachments -* ContentPart => cp1 -* EncapsulatedPart => ep1 - * Encrytion=(rec1,rec2) => enc1 - * Signature => sig1 - * ContentPart(encrytion = (enc1,), signature = (sig1,)) => cp2 - * TextPart(encrytion = (enc1,), signature = (sig1,)) - * TextPart(encrytion = (enc1, enc2(rec3,rec4),), signature = (sig1,)) - * AttachmentPart(encrytion = (enc1,), signature = (sig1,)) => ap1 -* AttachmentPart => ap2 - -(cp1) = collect(select=NoEncapsulatedMessages) -(ap2) = collect(select=NoEncapsulatedMessages) - -(cp2) = collect(ep1, select=NoEncapsulatedMessages) -(ap1) = collect(ep1, select=NoEncapsulatedMessages) - -(cp1, cp2) == collect() -(ap1, ap2) == collect()[TextPart, TextPart(encrytion = (enc1(rec1,rec2),)), TextPart(signed = (sig1,)), TextPart] - - -# plaintext msg + attachment + cert -* ContentPart => cp1 -* AttachmentPart => ap1 -* CertPart => cep1 - -(cp1) == collect(select=NoEncapsulatedMessages) -(ap1, cep1) == collect(select=NoEncapsulatedMessages) -(ap1) == collect(select=NoEncapsulatedMessages, filter=filterSubAttachmentParts) - -(cep1) == collect(select=NoEncapsulatedMessages) - - -collect function: - -bool noEncapsulatedMessages(Part part) -{ - if (is(part)) { - return false; - } - return true; -} - -bool filterRelated(T part) -{ - if (part.mimetype == related && !part.cid.isEmpty()) { - return false; //filter out related parts - } - return true; -} - -bool filterSubAttachmentParts(AttachmentPart part) -{ - if (isSubPart(part)) { - return false; // filter out CertPart f.ex. - } - return true; -} - -List collect(Part start, std::function select, std::function &)> filter) { - List col; - if (!select(start)) { - return col; - } - - if(isOrSubTypeIs(start) && filter(start.staticCast)){ - col.append(p); - } - foreach(childs as child) { - if (select(child)) { - col.expand(collect(child,select,filter); - } - } - return col; -} \ No newline at end of file diff --git a/framework/domain/mimetreeparser/tests/CMakeLists.txt b/framework/domain/mimetreeparser/tests/CMakeLists.txt new file mode 100644 index 00000000..d3549215 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/CMakeLists.txt @@ -0,0 +1,10 @@ +add_definitions( -DMAIL_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" ) +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ) + +add_executable(mimetreeparsertest interfacetest.cpp) +add_test(mimetreeparsertest mimetreeparsertest) +qt5_use_modules(mimetreeparsertest Core Test) +target_link_libraries(mimetreeparsertest mimetreeparser) \ No newline at end of file diff --git a/framework/domain/mimetreeparser/tests/data/alternative.mbox b/framework/domain/mimetreeparser/tests/data/alternative.mbox new file mode 100644 index 00000000..a2c58591 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/data/alternative.mbox @@ -0,0 +1,34 @@ +Return-Path: +Date: Wed, 8 Jun 2016 20:34:44 -0700 +From: Konqi +To: konqi@kde.org +Subject: A random subject with alternative contenttype +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary="----=_Part_12345678_12345678" + + +------=_Part_12345678_12345678 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +If you can see this text it means that your email client couldn't display o= +ur newsletter properly. +Please visit this link to view the newsletter on our website: http://www.go= +g.com/newsletter/ + +=2D GOG.com Team + + +------=_Part_12345678_12345678 +Content-Transfer-Encoding: 7Bit +Content-Type: text/html; charset="windows-1252" + + + +

Some HTML text

+ + +------=_Part_12345678_12345678-- diff --git a/framework/domain/mimetreeparser/tests/data/html.mbox b/framework/domain/mimetreeparser/tests/data/html.mbox new file mode 100644 index 00000000..eebd4283 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/data/html.mbox @@ -0,0 +1,31 @@ +From foo@example.com Thu, 26 May 2011 01:16:54 +0100 +From: Thomas McGuire +Subject: HTML test +Date: Thu, 26 May 2011 01:16:54 +0100 +Message-ID: <1501334.pROlBb7MZF@herrwackelpudding.localhost> +X-KMail-Transport: GMX +X-KMail-Fcc: 28 +X-KMail-Drafts: 7 +X-KMail-Templates: 9 +User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) +MIME-Version: 1.0 +Content-Type: multipart/alternative; boundary="nextPart8606278.tpV19BTJKu" +Content-Transfer-Encoding: 7Bit + + +--nextPart8606278.tpV19BTJKu +Content-Transfer-Encoding: 7Bit +Content-Type: text/plain; charset="windows-1252" + +Some HTML text +--nextPart8606278.tpV19BTJKu +Content-Transfer-Encoding: 7Bit +Content-Type: text/html; charset="windows-1252" + + + +

Some HTML text

+--nextPart8606278.tpV19BTJKu-- + diff --git a/framework/domain/mimetreeparser/tests/data/htmlonly.mbox b/framework/domain/mimetreeparser/tests/data/htmlonly.mbox new file mode 100644 index 00000000..e45b1c4d --- /dev/null +++ b/framework/domain/mimetreeparser/tests/data/htmlonly.mbox @@ -0,0 +1,21 @@ +From foo@example.com Thu, 26 May 2011 01:16:54 +0100 +From: Thomas McGuire +Subject: HTML test +Date: Thu, 26 May 2011 01:16:54 +0100 +Message-ID: <1501334.pROlBb7MZF@herrwackelpudding.localhost> +X-KMail-Transport: GMX +X-KMail-Fcc: 28 +X-KMail-Drafts: 7 +X-KMail-Templates: 9 +User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) +MIME-Version: 1.0 +Content-Type: text/html +Content-Transfer-Encoding: 7Bit + + + + + +SOME HTML text. + + diff --git a/framework/domain/mimetreeparser/tests/data/htmlonlyexternal.mbox b/framework/domain/mimetreeparser/tests/data/htmlonlyexternal.mbox new file mode 100644 index 00000000..4eb3e2c3 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/data/htmlonlyexternal.mbox @@ -0,0 +1,21 @@ +From foo@example.com Thu, 26 May 2011 01:16:54 +0100 +From: Thomas McGuire +Subject: HTML test +Date: Thu, 26 May 2011 01:16:54 +0100 +Message-ID: <1501334.pROlBb7MZF@herrwackelpudding.localhost> +X-KMail-Transport: GMX +X-KMail-Fcc: 28 +X-KMail-Drafts: 7 +X-KMail-Templates: 9 +User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) +MIME-Version: 1.0 +Content-Type: text/html +Content-Transfer-Encoding: 7Bit + + + + + +SOME HTML text. + + diff --git a/framework/domain/mimetreeparser/tests/data/plaintext.mbox b/framework/domain/mimetreeparser/tests/data/plaintext.mbox new file mode 100644 index 00000000..c2e00a35 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/data/plaintext.mbox @@ -0,0 +1,17 @@ +Return-Path: +Date: Wed, 8 Jun 2016 20:34:44 -0700 +From: Konqi +To: konqi@kde.org +Subject: A random subject with alternative contenttype +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +If you can see this text it means that your email client couldn't display o= +ur newsletter properly. +Please visit this link to view the newsletter on our website: http://www.go= +g.com/newsletter/ + +=2D GOG.com Team + + diff --git a/framework/domain/mimetreeparser/tests/interfacetest.cpp b/framework/domain/mimetreeparser/tests/interfacetest.cpp new file mode 100644 index 00000000..1e8c5302 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/interfacetest.cpp @@ -0,0 +1,47 @@ +/* + Copyright (c) 2016 Sandro Knauß + + 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 "interface.h" + +#include + +QByteArray readMailFromFile(const QString &mailFile) +{ + QFile file(QLatin1String(MAIL_DATA_DIR) + QLatin1Char('/') + mailFile); + file.open(QIODevice::ReadOnly); + Q_ASSERT(file.isOpen()); + return file.readAll(); +} + + +class InterfaceTest : public QObject +{ + Q_OBJECT +private slots: + + void testTextMail() + { + Parser parser(readMailFromFile("plaintext.mbox")); + auto contentPart = parser.collectContentPart(); + //QVERIFY((bool)contentPart); + } +}; + +QTEST_GUILESS_MAIN(InterfaceTest) +#include "interfacetest.moc" \ No newline at end of file diff --git a/framework/domain/mimetreeparser/thoughts.txt b/framework/domain/mimetreeparser/thoughts.txt new file mode 100644 index 00000000..3340347a --- /dev/null +++ b/framework/domain/mimetreeparser/thoughts.txt @@ -0,0 +1,148 @@ +Usecases: + +# plaintext msg + attachment +* ContentPart => cp1 +* AttachmentPart => ap1 + +(cp1) == collect(select=NoEncapsulatedMessages) +(ap1) == collect(select=NoEncapsulatedMessages) + +(PlainText) == cp1.availableContent() + +# html msg + related attachment + normal attachment +* ContentPart => cp1 +* AttachmentPart(mimetype="*/related", cid="12345678") => ap1 +* AttachmentPart => ap2 + +(cp1) == collect(select=NoEncapsulatedMessages) +(ap1, ap2) == collect(select=NoEncapsulatedMessages) +(ap2) == collect(select=NoEncapsulatedMessages, filter=filterelated) + +ap1 == getPart("cid:12345678") + +(Html) == cp1.availableContent() + +# alternative msg + attachment +* ContentPart(html=[Content("HTML"),], plaintext=[Content("Text"),]) => cp1 +* AttachmentPart => ap1 + +(cp1) == collect(select=NoEncapsulatedMessages) +(ap1) == collect(select=NoEncapsulatedMessages) + +(Html, PlainText) == cp1.availableContent() +[Content("HTML"),] == cp1.content(Html) +[Content("Text"),] == cp1.content(Plaintext) + +# alternative msg with GPGInlin +* ContentPart( + plaintext=[Content("Text"), Content("foo", encryption=(enc1))], + html=[Content("HTML"),] + ) => cp1 + +(Html, PlainText) == cp1.availableContent() + +[Content("HTML"),] == cp1.content(Html) +[Content("Text"),Content("foo", encryption=(enc1))] == cp1.content(Plaintext) + + +# encrypted msg (not encrypted/error) with unencrypted attachment +* EncryptionErrorPart => cp1 +* AttachmentPart => ap1 + +(cp1) == collect(select=NoEncapsulatedMessages) +(ap1) == collect(select=NoEncapsulatedMessages) + +#encrypted msg (decrypted with attachment) + unencrypted attachment +* encrytion=(rec1,rec2) => enc1 + * ContentPart(encrytion = (enc1,)) => cp1 + * AttachmentPart(encryption = (enc1,)) => ap1 +* AttachmentPart => ap2 + +(cp1) == collect(select=NoEncapsulatedMessages) +(ap1, ap2) == collect(select=NoEncapsulatedMessages) + +#INLINE GPG encrypted msg + attachment +* ContentPart => cp1 with + plaintext=[Content, Content(encrytion = (enc1(rec1,rec2),)), Content(signed = (sig1,)), Content] +* AttachmentPart => ap1 + +(cp1) == collect(select=NoEncapsulatedMessages) +(ap1) == collect(select=NoEncapsulatedMessages) + +[Content, Content(encrytion = (enc1(rec1,rec2),)), Content(signed = (sig1,)), Content] == cp1.content(Plaintext) + +#forwared encrypted msg + attachments +* ContentPart => cp1 +* EncapsulatedPart => ep1 + * Encrytion=(rec1,rec2) => enc1 + * Signature => sig1 + * ContentPart(encrytion = (enc1,), signature = (sig1,)) => cp2 + * Content(encrytion = (enc1,), signature = (sig1,)) + * Content(encrytion = (enc1, enc2(rec3,rec4),), signature = (sig1,)) + * AttachmentPart(encrytion = (enc1,), signature = (sig1,)) => ap1 +* AttachmentPart => ap2 + +(cp1) = collect(select=NoEncapsulatedMessages) +(ap2) = collect(select=NoEncapsulatedMessages) + +(cp2) = collect(ep1, select=NoEncapsulatedMessages) +(ap1) = collect(ep1, select=NoEncapsulatedMessages) + +(cp1, cp2) == collect() +(ap1, ap2) == collect()[Content, Content(encrytion = (enc1(rec1,rec2),)), Content(signed = (sig1,)), Content] + + +# plaintext msg + attachment + cert +* ContentPart => cp1 +* AttachmentPart => ap1 +* CertPart => cep1 + +(cp1) == collect(select=NoEncapsulatedMessages) +(ap1, cep1) == collect(select=NoEncapsulatedMessages) +(ap1) == collect(select=NoEncapsulatedMessages, filter=filterSubAttachmentParts) + +(cep1) == collect(select=NoEncapsulatedMessages) + + +collect function: + +bool noEncapsulatedMessages(Part part) +{ + if (is(part)) { + return false; + } + return true; +} + +bool filterRelated(T part) +{ + if (part.mimetype == related && !part.cid.isEmpty()) { + return false; //filter out related parts + } + return true; +} + +bool filterSubAttachmentParts(AttachmentPart part) +{ + if (isSubPart(part)) { + return false; // filter out CertPart f.ex. + } + return true; +} + +List collect(Part start, std::function select, std::function &)> filter) { + List col; + if (!select(start)) { + return col; + } + + if(isOrSubTypeIs(start) && filter(start.staticCast)){ + col.append(p); + } + foreach(childs as child) { + if (select(child)) { + col.expand(collect(child,select,filter); + } + } + return col; +} \ No newline at end of file -- cgit v1.2.3