diff --git a/framework/domain/mimetreeparser/CMakeLists.txt b/framework/domain/mimetreeparser/CMakeLists.txt index e1c04893..07ec28df 100644 --- a/framework/domain/mimetreeparser/CMakeLists.txt +++ b/framework/domain/mimetreeparser/CMakeLists.txt @@ -1,12 +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 +# add_subdirectory(tests) \ No newline at end of file diff --git a/framework/domain/mimetreeparser/interface.cpp b/framework/domain/mimetreeparser/interface.cpp index e34ffda7..aa7e3911 100644 --- a/framework/domain/mimetreeparser/interface.cpp +++ b/framework/domain/mimetreeparser/interface.cpp @@ -1,367 +1,396 @@ /* 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 "interface_p.h" #include "stringhtmlwriter.h" #include "objecttreesource.h" #include #include #include #include #include class PartPrivate { public: PartPrivate(Part *part); void appendSubPart(Part::Ptr subpart); QVector subParts(); Part *parent() const; private: Part *q; Part *mParent; QVector mSubParts; }; PartPrivate::PartPrivate(Part* part) : q(part) , mParent(Q_NULLPTR) { } void PartPrivate::appendSubPart(Part::Ptr subpart) { subpart->d->mParent = q; mSubParts.append(subpart); } Part *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::availableContents() const +{ + return QVector(); +} + +QVector Part::content() const +{ + return QVector(); +} + QVector Part::encryptions() const { auto parent = d->parent(); if (parent) { return parent->encryptions(); } else { return QVector(); } } QVector Part::signatures() const { auto parent = d->parent(); 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) +Content::Content(const QByteArray& content, Part *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(); } QByteArray Content::content() const { return d->mContent; } QByteArray Content::charset() const { return d->mCodec; } -class ContentPartPrivate +class AlternativePartPrivate { public: - void fillFrom(MimeTreeParser::TextMessagePart::Ptr part); - void fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part); void fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part); - QVector content(ContentPart::Type ct) const; + QVector content(const QByteArray &ct) const; - ContentPart *q; + AlternativePart *q; - ContentPart::Types types() const; + QVector types() const; private: - QMap> mContent; - ContentPart::Types mTypes; + QMap> mContent; + QVector mTypes; }; -void ContentPartPrivate::fillFrom(MimeTreeParser::TextMessagePart::Ptr part) +void AlternativePartPrivate::fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part) { - qDebug() << "jepp"; - mTypes = ContentPart::PlainText; - foreach (const auto &mp, part->subParts()) { - auto content = std::make_shared(mp->text().toLocal8Bit(), q); - mContent[ContentPart::PlainText].append(content); - } + mTypes = QVector() << "html" << "plaintext"; + + auto content = std::make_shared(part->htmlContent().toLocal8Bit(), q); + mContent["html"].append(content); + content = std::make_shared(part->plaintextContent().toLocal8Bit(), q); + mContent["plaintext"].append(content); } -void ContentPartPrivate::fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part) +QVector AlternativePartPrivate::types() const { - mTypes = ContentPart::Html; - auto content = std::make_shared(part->text().toLocal8Bit(), q); - mContent[ContentPart::Html].append(content); + return mTypes; } -void ContentPartPrivate::fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part) +QVector AlternativePartPrivate::content(const QByteArray& ct) const { - mTypes = ContentPart::Html | ContentPart::PlainText; + return mContent[ct]; +} - auto content = std::make_shared(part->htmlContent().toLocal8Bit(), q); - mContent[ContentPart::Html].append(content); - content = std::make_shared(part->plaintextContent().toLocal8Bit(), q); - mContent[ContentPart::PlainText].append(content); +AlternativePart::AlternativePart() + : d(std::unique_ptr(new AlternativePartPrivate)) +{ + d->q = this; } -ContentPart::Types ContentPartPrivate::types() const +AlternativePart::~AlternativePart() { - return mTypes; + } -QVector ContentPartPrivate::content(ContentPart::Type ct) const +QByteArray AlternativePart::type() const { - return mContent[ct]; + return "AlternativePart"; } -QVector ContentPart::content(ContentPart::Type ct) const +QVector AlternativePart::availableContents() const { - return d->content(ct); + return d->types(); } +QVector AlternativePart::content() const +{ + return d->content(availableContents().first()); +} -ContentPart::ContentPart() - : d(std::unique_ptr(new ContentPartPrivate)) +QVector AlternativePart::content(const QByteArray& ct) const { - d->q = this; + return d->content(ct); } -ContentPart::~ContentPart() +class SinglePartPrivate { +public: + void fillFrom(MimeTreeParser::TextMessagePart::Ptr part); + void fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part); + void fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part); + SinglePart *q; + + QVector mContent; + QByteArray mType; +}; +void SinglePartPrivate::fillFrom(MimeTreeParser::TextMessagePart::Ptr part) +{ + mType = "plaintext"; + mContent.clear(); + foreach (const auto &mp, part->subParts()) { + mContent.append(std::make_shared(mp->text().toLocal8Bit(), q)); + } } -QByteArray ContentPart::type() const +void SinglePartPrivate::fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part) { - return "ContentPart"; + mType = "html"; + mContent.clear(); + mContent.append(std::make_shared(part->text().toLocal8Bit(), q)); } -ContentPart::Types ContentPart::availableContents() const +void SinglePartPrivate::fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part) { - return d->types(); + } -class MimePartPrivate +SinglePart::SinglePart() + : d(std::unique_ptr(new SinglePartPrivate)) { -public: - void fillFrom(MimeTreeParser::MessagePart::Ptr part); -}; + d->q = this; +} -QByteArray MimePart::type() const +SinglePart::~SinglePart() { - return "MimePart"; + } -class AttachmentPartPrivate +QVector SinglePart::availableContents() const { -public: - void fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part); -}; + return QVector() << d->mType; +} -void AttachmentPartPrivate::fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part) +QVector< Content::Ptr > SinglePart::content() const { + return d->mContent; +} +QByteArray SinglePart::type() const +{ + return "SinglePart"; } -QByteArray AttachmentPart::type() const +class MimePartPrivate +{ +public: + void fillFrom(MimeTreeParser::MessagePart::Ptr part); +}; + +QByteArray MimePart::type() const { - return "AttachmentPart"; + return "MimePart"; } 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; 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(const MimeTreeParser::MessagePart::Ptr &start, const 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 (attachment) { auto part = std::make_shared(); part->d->fillFrom(attachment); mTree->d->appendSubPart(part); } else if (text) { - auto part = std::make_shared(); + auto part = std::make_shared(); part->d->fillFrom(text); mTree->d->appendSubPart(part); } else if (alternative) { - auto part = std::make_shared(); + auto part = std::make_shared(); part->d->fillFrom(alternative); mTree->d->appendSubPart(part); } else if (html) { - auto part = std::make_shared(); + auto part = std::make_shared(); part->d->fillFrom(html); 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 +QVector Parser::collectContentParts() const { - const auto ret = collect(start, [](const Part::Ptr &p){return p->type() == "ContentPart";}, [](const ContentPart::Ptr &p){return true;}); - if (ret.size() > 0) { - return ret[0]; - }; - return ContentPart::Ptr(); -} - -ContentPart::Ptr Parser::collectContentPart() const -{ - return collectContentPart(d->mTree); + return collect(d->mTree, [](const Part::Ptr &p){return p->availableContents().indexOf("html") > -1 || p->availableContents().indexOf("text") > -1;}, [](const Part::Ptr &p){return true;}); } template QVector Parser::collect(const Part::Ptr &start, std::function select, std::function filter) const { QVector ret; foreach (const auto &part, start->subParts()) { if (select(part)){ const auto p = std::dynamic_pointer_cast(part); if (p && filter(p)) { ret.append(p); } ret += collect(part, select, filter); } } return ret; -} +} \ No newline at end of file diff --git a/framework/domain/mimetreeparser/interface.h b/framework/domain/mimetreeparser/interface.h index 0aef7fd0..5133b87e 100644 --- a/framework/domain/mimetreeparser/interface.h +++ b/framework/domain/mimetreeparser/interface.h @@ -1,332 +1,330 @@ /* 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. */ #pragma once #include #include #include #include #include class Part; class PartPrivate; -class MimePart; -class MimePartPrivate; +class MailMime; +class MailMimePrivate; -class ContentPart; -class ContentPartPrivate; +class AlternativePart; +class AlternativePartPrivate; + +class SinglePart; +class SinglePartPrivate; class EncryptionPart; class EncryptionPartPrivate; class AttachmentPart; class AttachmentPartPrivate; class EncapsulatedPart; class EncapsulatedPartPrivate; -class CertPart; -class CertPartPrivate; - class Content; class ContentPrivate; +class CertContent; +class CertContentPrivate; + +class EncryptionError; + class Key; class Signature; class Encryption; class Parser; class ParserPrivate; -class Part +/* + * A MessagePart that is based on a KMime::Content + */ +class MailMime { public: - typedef std::shared_ptr Ptr; - Part(); - virtual QByteArray type() const; + typedef std::shared_ptr Ptr; + /** + * Various possible values for the "Content-Disposition" header. + */ + enum Disposition { + Invalid, ///< Default, invalid value + Inline, ///< inline + Attachment ///< attachment + }; - bool hasSubParts() const; - QVector subParts() const; - Part *parent() const; + // interessting header parts of a KMime::Content + QMimeType mimetype() const; + Disposition disposition() const; + QUrl label() const; + QByteArray cid() const; + QByteArray charset() const; + + // 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; - virtual QVector signatures() const; - virtual QVector encryptions() const; private: - std::unique_ptr d; - friend class ParserPrivate; - friend class PartPrivate; + std::unique_ptr d; }; class Content { public: typedef std::shared_ptr Ptr; - Content(const QByteArray &content, ContentPart *parent); + Content(const QByteArray &content, Part *parent); virtual ~Content(); QByteArray content() const; QByteArray charset() const; //Use default charset QString encodedContent() const; // overwrite default charset with given charset QString encodedContent(QByteArray charset) const; virtual QVector signatures() const; virtual QVector encryptions() const; + MailMime::Ptr mailMime() const; + virtual QByteArray type() const; private: std::unique_ptr d; }; -/* - * A MessagePart that is based on a KMime::Content - */ -class MimePart : public Part +class PlainTextContent : public Content { public: - typedef std::shared_ptr Ptr; - /** - * Various possible values for the "Content-Disposition" header. - */ - enum Disposition { - Invalid, ///< Default, invalid value - Inline, ///< inline - Attachment ///< attachment - }; + QByteArray type() const Q_DECL_OVERRIDE; +}; - // interessting header parts of a KMime::Content - QMimeType mimetype() const; - Disposition disposition() const; - QUrl label() const; - QByteArray cid() const; - QByteArray charset() const; +class HtmlContent : public Content +{ +public: + QByteArray type() const Q_DECL_OVERRIDE; +}; - // we wanna overrwrite the charset of the content, because some clients set the charset wrong - void setCharset(QByteArray charset); +/* + * importing a cert GpgMe::ImportResult + * checking a cert (if it is a valid cert) + */ - // Unique identifier to ecactly this KMime::Content - QByteArray link() const; +class CertContent : public Content +{ +public: + typedef std::shared_ptr Ptr; - QByteArray content() const; + QByteArray type() const Q_DECL_OVERRIDE; + enum CertType { + Pgp, + SMime + }; - //Use default charset - QString encodedContent() const; + enum CertSubType { + Public, + Private + }; - // overwrite default charset with given charset - QString encodedContent(QByteArray charset) const; + CertType certType() const; + CertSubType certSubType() const; + int keyLength() const; - QByteArray type() const Q_DECL_OVERRIDE; private: - std::unique_ptr d; + std::unique_ptr d; }; -/* - * The main ContentPart - * is MimePart a good parent class? - * do we wanna need parts of the header of the connected KMime::Contents - * usecases: - * - - * for htmlonly it is representating only one MimePart (ok) - * for plaintext only also only one MimePart (ok) - * 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 ContentPart : public Part +class Part { public: - typedef std::shared_ptr Ptr; - enum Type { - PlainText = 0x0001, - Html = 0x0002 - }; - Q_DECLARE_FLAGS(Types, Type) - - ContentPart(); - virtual ~ContentPart(); - - QVector content(Type ct) const; + typedef std::shared_ptr Ptr; + Part(); + virtual QByteArray type() const; - Types availableContents() const; + virtual QVector availableContents() const; + virtual QVector content() const; - QByteArray type() const Q_DECL_OVERRIDE; + bool hasSubParts() const; + QVector subParts() const; + Part *parent() const; + virtual QVector signatures() const; + virtual QVector encryptions() const; + virtual MailMime::Ptr mailMime() const; private: - std::unique_ptr d; - + std::unique_ptr d; friend class ParserPrivate; + friend class PartPrivate; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(ContentPart::Types); - -class AttachmentPart : public MimePart +class AlternativePart : public Part { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; + + AlternativePart(); + virtual ~AlternativePart(); + + QVector content() const Q_DECL_OVERRIDE; + QVector availableContents() const Q_DECL_OVERRIDE; + QVector content(const QByteArray& ct) const; + QByteArray type() const Q_DECL_OVERRIDE; private: - std::unique_ptr d; + std::unique_ptr d; friend class ParserPrivate; }; -/* - * 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 EncryptionError +class SinglePart : public Part { -public: - int errorId() const; - QString errorString() const; + public: + typedef std::shared_ptr Ptr; + + SinglePart(); + virtual ~SinglePart(); + + QVector content() const Q_DECL_OVERRIDE; + QVector availableContents() const Q_DECL_OVERRIDE; + + QByteArray type() const Q_DECL_OVERRIDE; +private: + std::unique_ptr d; + + friend class ParserPrivate; }; -class EncryptionPart : public MimePart + +class EncryptionPart : public Part { public: typedef std::shared_ptr Ptr; QByteArray type() const Q_DECL_OVERRIDE; EncryptionError error() const; - private: std::unique_ptr d; }; /* * we want to request complete headers like: * from/to... */ -class EncapsulatedPart : public AttachmentPart +class EncapsulatedPart : public SinglePart { public: typedef std::shared_ptr Ptr; QByteArray type() const Q_DECL_OVERRIDE; //template QByteArray header(); private: std::unique_ptr d; }; -/* - * importing a cert GpgMe::ImportResult - * checking a cert (if it is a valid cert) - */ - -class CertPart : public AttachmentPart +class EncryptionError { public: - typedef std::shared_ptr Ptr; - QByteArray type() const Q_DECL_OVERRIDE; - - enum CertType { - Pgp, - SMime - }; - - enum CertSubType { - Public, - Private - }; - - CertType certType() const; - CertSubType certSubType() const; - int keyLength() const; - -private: - std::unique_ptr d; + int errorId() const; + QString errorString() const; }; class Key { QString keyid() const; QString name() const; QString email() const; QString comment() const; QVector emails() const; enum KeyTrust { Unknown, Undefined, Never, Marginal, Full, Ultimate }; KeyTrust keyTrust() const; bool isRevokation() const; bool isInvalid() const; bool isExpired() const; std::vector subkeys(); Key parentkey() const; }; class Signature { Key key() const; QDateTime creationDateTime() const; QDateTime expirationTime() const; bool neverExpires() const; //template <> StatusObject verify() const; }; /* * Normally the Keys for encryption are subkeys * for clients the parentkeys are "more interessting", because they store the name, email etc. * but a client may also wants show to what subkey the mail is really encrypted, an if this subkey isRevoked or something else */ 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(const Part::Ptr &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; + //QVector collectAttachments(Part::Ptr start, std::function select, std::function filter) const; + QVector collectContentParts() 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; friend class InterfaceTest; };