From 241a446b0661b668e24e297753d4dfc762fb1fd4 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 30 Jun 2017 17:36:55 +0200 Subject: Reply to signed messages. --- framework/src/domain/mime/mailtemplates.cpp | 1 + .../mime/mimetreeparser/objecttreeparser.cpp | 133 ++++++++++----------- .../domain/mime/mimetreeparser/objecttreeparser.h | 20 +--- .../src/domain/mime/tests/mailtemplatetest.cpp | 4 +- 4 files changed, 71 insertions(+), 87 deletions(-) diff --git a/framework/src/domain/mime/mailtemplates.cpp b/framework/src/domain/mime/mailtemplates.cpp index c202af80..6d02124d 100644 --- a/framework/src/domain/mime/mailtemplates.cpp +++ b/framework/src/domain/mime/mailtemplates.cpp @@ -842,6 +842,7 @@ void MailTemplates::reply(const KMime::Message::Ptr &origMsg, const std::functio MimeTreeParser::ObjectTreeParser otp; otp.parseObjectTree(origMsg.data()); + otp.decryptParts(); const auto plainTextContent = otp.plainTextContent(); const auto htmlContent = otp.htmlContent(); diff --git a/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp b/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp index 0c3f60aa..7e2be0e4 100644 --- a/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp +++ b/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp @@ -60,6 +60,32 @@ using namespace MimeTreeParser; +/* + * Collect message parts bottom up. + * Filter to avoid evaluating a subtree. + * Select parts to include it in the result set. Selecting a part in a branch will keep any parent parts from being selected. + */ +static QVector collect(MessagePart::Ptr start, const std::function &evaluateSubtree, const std::function &select) +{ + MessagePartPtr ptr = start.dynamicCast(); + Q_ASSERT(ptr); + QVector list; + if (evaluateSubtree(ptr)) { + for (const auto &p: ptr->subParts()) { + list << ::collect(p, evaluateSubtree, select); + } + } + + //Don't consider this part if we already selected a subpart + if (list.isEmpty()) { + if (select(ptr)) { + list << start; + } + } + return list; +} + + ObjectTreeParser::ObjectTreeParser() : mNodeHelper(nullptr), @@ -96,14 +122,46 @@ ObjectTreeParser::~ObjectTreeParser() } } -QString ObjectTreeParser::plainTextContent() const +QString ObjectTreeParser::plainTextContent() { - return mPlainTextContent; + QString content; + if (mParsedPart) { + auto plainParts = ::collect(mParsedPart, + [] (const MessagePartPtr &part) { + return true; + }, + [] (const MessagePartPtr &part) { + if (dynamic_cast(part.data())) { + return true; + } + return false; + }); + for (const auto &part : plainParts) { + content += part->text(); + } + } + return content; } -QString ObjectTreeParser::htmlContent() const +QString ObjectTreeParser::htmlContent() { - return mHtmlContent; + QString content; + if (mParsedPart) { + QVector contentParts = ::collect(mParsedPart, + [] (const MessagePartPtr &part) { + return true; + }, + [] (const MessagePartPtr &part) { + if (dynamic_cast(part.data())) { + return true; + } + return false; + }); + for (const auto &part : contentParts) { + content += part->text(); + } + } + return content; } static void print(KMime::Content *node, const QString prefix = {}) @@ -165,31 +223,6 @@ KMime::Content *ObjectTreeParser::find(const std::function collect(MessagePart::Ptr start, const std::function &evaluateSubtree, const std::function &select) -{ - MessagePartPtr ptr = start.dynamicCast(); - Q_ASSERT(ptr); - QVector list; - if (evaluateSubtree(ptr)) { - for (const auto &p: ptr->subParts()) { - list << ::collect(p, evaluateSubtree, select); - } - } - - //Don't consider this part if we already selected a subpart - if (list.isEmpty()) { - if (select(ptr)) { - list << start; - } - } - return list; -} - QVector ObjectTreeParser::collectContentParts() { return collectContentParts(mParsedPart); @@ -341,38 +374,6 @@ void ObjectTreeParser::parseObjectTree(KMime::Content *node) { mTopLevelContent = node; mParsedPart = parseObjectTreeInternal(node, showOnlyOneMimePart()); - - //Gather plaintext and html content - if (mParsedPart) { - //Find relevant plaintext parts and set plaintext - if (auto mp = toplevelTextNode(mParsedPart)) { - if (auto _mp = mp.dynamicCast()) { - mPlainTextContent += _mp->mNode->decodedText(); - mPlainTextContentCharset += NodeHelper::charset(_mp->mNode); - } else if (auto _mp = mp.dynamicCast()) { - if (_mp->mChildNodes.contains(Util::MultipartPlain)) { - mPlainTextContent += _mp->mChildNodes[Util::MultipartPlain]->decodedText(); - mPlainTextContentCharset += NodeHelper::charset(_mp->mChildNodes[Util::MultipartPlain]); - } - } - } - - //Find html parts and copy content - QVector contentParts = ::collect(mParsedPart, - [] (const MessagePartPtr &part) { - return true; - }, - [] (const MessagePartPtr &part) { - if (dynamic_cast(part.data())) { - return true; - } - return false; - }); - for (const auto &part : contentParts) { - mHtmlContent += part->text(); - mHtmlContentCharset = part->charset(); - } - } } MessagePartPtr ObjectTreeParser::parsedPart() const @@ -487,16 +488,6 @@ const QTextCodec *ObjectTreeParser::codecFor(KMime::Content *node) const return mNodeHelper->codec(node); } -QByteArray ObjectTreeParser::plainTextContentCharset() const -{ - return mPlainTextContentCharset; -} - -QByteArray ObjectTreeParser::htmlContentCharset() const -{ - return mHtmlContentCharset; -} - bool ObjectTreeParser::showOnlyOneMimePart() const { return mShowOnlyOneMimePart; diff --git a/framework/src/domain/mime/mimetreeparser/objecttreeparser.h b/framework/src/domain/mime/mimetreeparser/objecttreeparser.h index 9a3f5a5c..d2076be4 100644 --- a/framework/src/domain/mime/mimetreeparser/objecttreeparser.h +++ b/framework/src/domain/mime/mimetreeparser/objecttreeparser.h @@ -250,24 +250,12 @@ public: * composer's text editor if this was edited or replied to. * This is usually the content of the first text/plain MIME part. */ - QString plainTextContent() const; + QString plainTextContent(); /** * Similar to plainTextContent(), but returns the HTML source of the first text/html MIME part. - * - * Not to be consfused with the HTML code that the message viewer widget displays, that HTML - * is written out by htmlWriter() and a totally different pair of shoes. */ - QString htmlContent() const; - - /** - * The original charset of MIME part the plain text was extracted from. - * - * If there were more than one text/plain MIME parts in the mail, the this is the charset - * of the last MIME part processed. - */ - QByteArray plainTextContentCharset() const; - QByteArray htmlContentCharset() const; + QString htmlContent(); bool showOnlyOneMimePart() const; void setShowOnlyOneMimePart(bool show); @@ -283,7 +271,11 @@ public: QVector collectContentParts(); QVector collectContentParts(MessagePart::Ptr start); QVector collectAttachmentParts(); + + /** Decrypt parts and verify signatures */ void decryptParts(); + + /** Import any certificates found in the message */ void importCertificates(); /** Embedd content referenced by cid by inlining */ diff --git a/framework/src/domain/mime/tests/mailtemplatetest.cpp b/framework/src/domain/mime/tests/mailtemplatetest.cpp index 18f315f1..4dc8e2bd 100644 --- a/framework/src/domain/mime/tests/mailtemplatetest.cpp +++ b/framework/src/domain/mime/tests/mailtemplatetest.cpp @@ -36,6 +36,7 @@ static QString normalize(const QString &s) auto text = s; text.replace(">", ""); text.replace("\n", ""); + text.replace("=", ""); text.replace(" ", ""); return text; } @@ -87,9 +88,8 @@ private slots: result = r; }); QTRY_VERIFY(result); - auto content = normalize(removeFirstLine(result->body())); + auto content = removeFirstLine(result->body()); QVERIFY(!content.isEmpty()); - QEXPECT_FAIL("", "Not implemented yet.", Continue); QVERIFY(content.contains("i noticed a new branch")); } -- cgit v1.2.3