diff options
Diffstat (limited to 'framework/src')
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 | |||
842 | 842 | ||
843 | MimeTreeParser::ObjectTreeParser otp; | 843 | MimeTreeParser::ObjectTreeParser otp; |
844 | otp.parseObjectTree(origMsg.data()); | 844 | otp.parseObjectTree(origMsg.data()); |
845 | otp.decryptParts(); | ||
845 | const auto plainTextContent = otp.plainTextContent(); | 846 | const auto plainTextContent = otp.plainTextContent(); |
846 | const auto htmlContent = otp.htmlContent(); | 847 | const auto htmlContent = otp.htmlContent(); |
847 | 848 | ||
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 @@ | |||
60 | 60 | ||
61 | using namespace MimeTreeParser; | 61 | using namespace MimeTreeParser; |
62 | 62 | ||
63 | /* | ||
64 | * Collect message parts bottom up. | ||
65 | * Filter to avoid evaluating a subtree. | ||
66 | * Select parts to include it in the result set. Selecting a part in a branch will keep any parent parts from being selected. | ||
67 | */ | ||
68 | static QVector<MessagePart::Ptr> collect(MessagePart::Ptr start, const std::function<bool(const MessagePartPtr &)> &evaluateSubtree, const std::function<bool(const MessagePartPtr &)> &select) | ||
69 | { | ||
70 | MessagePartPtr ptr = start.dynamicCast<MessagePart>(); | ||
71 | Q_ASSERT(ptr); | ||
72 | QVector<MessagePart::Ptr> list; | ||
73 | if (evaluateSubtree(ptr)) { | ||
74 | for (const auto &p: ptr->subParts()) { | ||
75 | list << ::collect(p, evaluateSubtree, select); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | //Don't consider this part if we already selected a subpart | ||
80 | if (list.isEmpty()) { | ||
81 | if (select(ptr)) { | ||
82 | list << start; | ||
83 | } | ||
84 | } | ||
85 | return list; | ||
86 | } | ||
87 | |||
88 | |||
63 | 89 | ||
64 | ObjectTreeParser::ObjectTreeParser() | 90 | ObjectTreeParser::ObjectTreeParser() |
65 | : mNodeHelper(nullptr), | 91 | : mNodeHelper(nullptr), |
@@ -96,14 +122,46 @@ ObjectTreeParser::~ObjectTreeParser() | |||
96 | } | 122 | } |
97 | } | 123 | } |
98 | 124 | ||
99 | QString ObjectTreeParser::plainTextContent() const | 125 | QString ObjectTreeParser::plainTextContent() |
100 | { | 126 | { |
101 | return mPlainTextContent; | 127 | QString content; |
128 | if (mParsedPart) { | ||
129 | auto plainParts = ::collect(mParsedPart, | ||
130 | [] (const MessagePartPtr &part) { | ||
131 | return true; | ||
132 | }, | ||
133 | [] (const MessagePartPtr &part) { | ||
134 | if (dynamic_cast<MimeTreeParser::TextMessagePart*>(part.data())) { | ||
135 | return true; | ||
136 | } | ||
137 | return false; | ||
138 | }); | ||
139 | for (const auto &part : plainParts) { | ||
140 | content += part->text(); | ||
141 | } | ||
142 | } | ||
143 | return content; | ||
102 | } | 144 | } |
103 | 145 | ||
104 | QString ObjectTreeParser::htmlContent() const | 146 | QString ObjectTreeParser::htmlContent() |
105 | { | 147 | { |
106 | return mHtmlContent; | 148 | QString content; |
149 | if (mParsedPart) { | ||
150 | QVector<MessagePart::Ptr> contentParts = ::collect(mParsedPart, | ||
151 | [] (const MessagePartPtr &part) { | ||
152 | return true; | ||
153 | }, | ||
154 | [] (const MessagePartPtr &part) { | ||
155 | if (dynamic_cast<MimeTreeParser::HtmlMessagePart*>(part.data())) { | ||
156 | return true; | ||
157 | } | ||
158 | return false; | ||
159 | }); | ||
160 | for (const auto &part : contentParts) { | ||
161 | content += part->text(); | ||
162 | } | ||
163 | } | ||
164 | return content; | ||
107 | } | 165 | } |
108 | 166 | ||
109 | static void print(KMime::Content *node, const QString prefix = {}) | 167 | static void print(KMime::Content *node, const QString prefix = {}) |
@@ -165,31 +223,6 @@ KMime::Content *ObjectTreeParser::find(const std::function<bool(KMime::Content * | |||
165 | return ::find(mTopLevelContent, select); | 223 | return ::find(mTopLevelContent, select); |
166 | } | 224 | } |
167 | 225 | ||
168 | /* | ||
169 | * Collect message parts bottom up. | ||
170 | * Filter to avoid evaluating a subtree. | ||
171 | * Select parts to include it in the result set. Selecting a part in a branch will keep any parent parts from being selected. | ||
172 | */ | ||
173 | static QVector<MessagePart::Ptr> collect(MessagePart::Ptr start, const std::function<bool(const MessagePartPtr &)> &evaluateSubtree, const std::function<bool(const MessagePartPtr &)> &select) | ||
174 | { | ||
175 | MessagePartPtr ptr = start.dynamicCast<MessagePart>(); | ||
176 | Q_ASSERT(ptr); | ||
177 | QVector<MessagePart::Ptr> list; | ||
178 | if (evaluateSubtree(ptr)) { | ||
179 | for (const auto &p: ptr->subParts()) { | ||
180 | list << ::collect(p, evaluateSubtree, select); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | //Don't consider this part if we already selected a subpart | ||
185 | if (list.isEmpty()) { | ||
186 | if (select(ptr)) { | ||
187 | list << start; | ||
188 | } | ||
189 | } | ||
190 | return list; | ||
191 | } | ||
192 | |||
193 | QVector<MessagePartPtr> ObjectTreeParser::collectContentParts() | 226 | QVector<MessagePartPtr> ObjectTreeParser::collectContentParts() |
194 | { | 227 | { |
195 | return collectContentParts(mParsedPart); | 228 | return collectContentParts(mParsedPart); |
@@ -341,38 +374,6 @@ void ObjectTreeParser::parseObjectTree(KMime::Content *node) | |||
341 | { | 374 | { |
342 | mTopLevelContent = node; | 375 | mTopLevelContent = node; |
343 | mParsedPart = parseObjectTreeInternal(node, showOnlyOneMimePart()); | 376 | mParsedPart = parseObjectTreeInternal(node, showOnlyOneMimePart()); |
344 | |||
345 | //Gather plaintext and html content | ||
346 | if (mParsedPart) { | ||
347 | //Find relevant plaintext parts and set plaintext | ||
348 | if (auto mp = toplevelTextNode(mParsedPart)) { | ||
349 | if (auto _mp = mp.dynamicCast<TextMessagePart>()) { | ||
350 | mPlainTextContent += _mp->mNode->decodedText(); | ||
351 | mPlainTextContentCharset += NodeHelper::charset(_mp->mNode); | ||
352 | } else if (auto _mp = mp.dynamicCast<AlternativeMessagePart>()) { | ||
353 | if (_mp->mChildNodes.contains(Util::MultipartPlain)) { | ||
354 | mPlainTextContent += _mp->mChildNodes[Util::MultipartPlain]->decodedText(); | ||
355 | mPlainTextContentCharset += NodeHelper::charset(_mp->mChildNodes[Util::MultipartPlain]); | ||
356 | } | ||
357 | } | ||
358 | } | ||
359 | |||
360 | //Find html parts and copy content | ||
361 | QVector<MessagePart::Ptr> contentParts = ::collect(mParsedPart, | ||
362 | [] (const MessagePartPtr &part) { | ||
363 | return true; | ||
364 | }, | ||
365 | [] (const MessagePartPtr &part) { | ||
366 | if (dynamic_cast<MimeTreeParser::HtmlMessagePart*>(part.data())) { | ||
367 | return true; | ||
368 | } | ||
369 | return false; | ||
370 | }); | ||
371 | for (const auto &part : contentParts) { | ||
372 | mHtmlContent += part->text(); | ||
373 | mHtmlContentCharset = part->charset(); | ||
374 | } | ||
375 | } | ||
376 | } | 377 | } |
377 | 378 | ||
378 | MessagePartPtr ObjectTreeParser::parsedPart() const | 379 | MessagePartPtr ObjectTreeParser::parsedPart() const |
@@ -487,16 +488,6 @@ const QTextCodec *ObjectTreeParser::codecFor(KMime::Content *node) const | |||
487 | return mNodeHelper->codec(node); | 488 | return mNodeHelper->codec(node); |
488 | } | 489 | } |
489 | 490 | ||
490 | QByteArray ObjectTreeParser::plainTextContentCharset() const | ||
491 | { | ||
492 | return mPlainTextContentCharset; | ||
493 | } | ||
494 | |||
495 | QByteArray ObjectTreeParser::htmlContentCharset() const | ||
496 | { | ||
497 | return mHtmlContentCharset; | ||
498 | } | ||
499 | |||
500 | bool ObjectTreeParser::showOnlyOneMimePart() const | 491 | bool ObjectTreeParser::showOnlyOneMimePart() const |
501 | { | 492 | { |
502 | return mShowOnlyOneMimePart; | 493 | 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: | |||
250 | * composer's text editor if this was edited or replied to. | 250 | * composer's text editor if this was edited or replied to. |
251 | * This is usually the content of the first text/plain MIME part. | 251 | * This is usually the content of the first text/plain MIME part. |
252 | */ | 252 | */ |
253 | QString plainTextContent() const; | 253 | QString plainTextContent(); |
254 | 254 | ||
255 | /** | 255 | /** |
256 | * Similar to plainTextContent(), but returns the HTML source of the first text/html MIME part. | 256 | * Similar to plainTextContent(), but returns the HTML source of the first text/html MIME part. |
257 | * | ||
258 | * Not to be consfused with the HTML code that the message viewer widget displays, that HTML | ||
259 | * is written out by htmlWriter() and a totally different pair of shoes. | ||
260 | */ | 257 | */ |
261 | QString htmlContent() const; | 258 | QString htmlContent(); |
262 | |||
263 | /** | ||
264 | * The original charset of MIME part the plain text was extracted from. | ||
265 | * | ||
266 | * If there were more than one text/plain MIME parts in the mail, the this is the charset | ||
267 | * of the last MIME part processed. | ||
268 | */ | ||
269 | QByteArray plainTextContentCharset() const; | ||
270 | QByteArray htmlContentCharset() const; | ||
271 | 259 | ||
272 | bool showOnlyOneMimePart() const; | 260 | bool showOnlyOneMimePart() const; |
273 | void setShowOnlyOneMimePart(bool show); | 261 | void setShowOnlyOneMimePart(bool show); |
@@ -283,7 +271,11 @@ public: | |||
283 | QVector<MessagePartPtr> collectContentParts(); | 271 | QVector<MessagePartPtr> collectContentParts(); |
284 | QVector<MessagePartPtr> collectContentParts(MessagePart::Ptr start); | 272 | QVector<MessagePartPtr> collectContentParts(MessagePart::Ptr start); |
285 | QVector<MessagePartPtr> collectAttachmentParts(); | 273 | QVector<MessagePartPtr> collectAttachmentParts(); |
274 | |||
275 | /** Decrypt parts and verify signatures */ | ||
286 | void decryptParts(); | 276 | void decryptParts(); |
277 | |||
278 | /** Import any certificates found in the message */ | ||
287 | void importCertificates(); | 279 | void importCertificates(); |
288 | 280 | ||
289 | /** Embedd content referenced by cid by inlining */ | 281 | /** 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) | |||
36 | auto text = s; | 36 | auto text = s; |
37 | text.replace(">", ""); | 37 | text.replace(">", ""); |
38 | text.replace("\n", ""); | 38 | text.replace("\n", ""); |
39 | text.replace("=", ""); | ||
39 | text.replace(" ", ""); | 40 | text.replace(" ", ""); |
40 | return text; | 41 | return text; |
41 | } | 42 | } |
@@ -87,9 +88,8 @@ private slots: | |||
87 | result = r; | 88 | result = r; |
88 | }); | 89 | }); |
89 | QTRY_VERIFY(result); | 90 | QTRY_VERIFY(result); |
90 | auto content = normalize(removeFirstLine(result->body())); | 91 | auto content = removeFirstLine(result->body()); |
91 | QVERIFY(!content.isEmpty()); | 92 | QVERIFY(!content.isEmpty()); |
92 | QEXPECT_FAIL("", "Not implemented yet.", Continue); | ||
93 | QVERIFY(content.contains("i noticed a new branch")); | 93 | QVERIFY(content.contains("i noticed a new branch")); |
94 | } | 94 | } |
95 | 95 | ||