diff options
6 files changed, 64 insertions, 25 deletions
diff --git a/framework/src/domain/mime/mimetreeparser/bodypartformatter.cpp b/framework/src/domain/mime/mimetreeparser/bodypartformatter.cpp index 232973df..2753bb4b 100644 --- a/framework/src/domain/mime/mimetreeparser/bodypartformatter.cpp +++ b/framework/src/domain/mime/mimetreeparser/bodypartformatter.cpp | |||
@@ -46,5 +46,14 @@ MessagePart::Ptr BodyPartFormatter::process(BodyPart &) const | |||
46 | { | 46 | { |
47 | return {}; | 47 | return {}; |
48 | } | 48 | } |
49 | |||
50 | QVector<MessagePart::Ptr> BodyPartFormatter::processList(BodyPart &part) const | ||
51 | { | ||
52 | if (auto p = process(part)) { | ||
53 | return {p}; | ||
54 | } | ||
55 | return {}; | ||
56 | } | ||
57 | |||
49 | } | 58 | } |
50 | } | 59 | } |
diff --git a/framework/src/domain/mime/mimetreeparser/bodypartformatter.h b/framework/src/domain/mime/mimetreeparser/bodypartformatter.h index 7e1fc74e..18428443 100644 --- a/framework/src/domain/mime/mimetreeparser/bodypartformatter.h +++ b/framework/src/domain/mime/mimetreeparser/bodypartformatter.h | |||
@@ -63,6 +63,7 @@ public: | |||
63 | enum Result { Ok, NeedContent, AsIcon, Failed }; | 63 | enum Result { Ok, NeedContent, AsIcon, Failed }; |
64 | 64 | ||
65 | virtual MessagePart::Ptr process(BodyPart &part) const; | 65 | virtual MessagePart::Ptr process(BodyPart &part) const; |
66 | virtual QVector<MessagePart::Ptr> processList(Interface::BodyPart &part) const; | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | /** | 69 | /** |
diff --git a/framework/src/domain/mime/mimetreeparser/bodypartformatter_impl.cpp b/framework/src/domain/mime/mimetreeparser/bodypartformatter_impl.cpp index 882dfc05..d4dfd647 100644 --- a/framework/src/domain/mime/mimetreeparser/bodypartformatter_impl.cpp +++ b/framework/src/domain/mime/mimetreeparser/bodypartformatter_impl.cpp | |||
@@ -115,14 +115,25 @@ const HeadersBodyPartFormatter *HeadersBodyPartFormatter::self = nullptr; | |||
115 | class MultiPartRelatedBodyPartFormatter: public MimeTreeParser::Interface::BodyPartFormatter { | 115 | class MultiPartRelatedBodyPartFormatter: public MimeTreeParser::Interface::BodyPartFormatter { |
116 | static const MultiPartRelatedBodyPartFormatter *self; | 116 | static const MultiPartRelatedBodyPartFormatter *self; |
117 | public: | 117 | public: |
118 | MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE { | 118 | |
119 | QVector<MessagePart::Ptr> processList(Interface::BodyPart &part) const Q_DECL_OVERRIDE { | ||
119 | if (part.content()->contents().isEmpty()) { | 120 | if (part.content()->contents().isEmpty()) { |
120 | return MessagePart::Ptr(); | 121 | return {}; |
121 | } | 122 | } |
122 | //We rely on the order of the parts. | 123 | //We rely on the order of the parts. |
123 | //Theoretically there could also be a Start parameter which would break this.. | 124 | //Theoretically there could also be a Start parameter which would break this.. |
124 | //https://tools.ietf.org/html/rfc2387#section-4 | 125 | //https://tools.ietf.org/html/rfc2387#section-4 |
125 | return MimeMessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), part.content()->contents().at(0), true)); | 126 | |
127 | //We want to display attachments even if displayed inline. | ||
128 | QVector<MessagePart::Ptr> list; | ||
129 | list.append(MimeMessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), part.content()->contents().at(0), true))); | ||
130 | for (int i = 1; i < part.content()->contents().size(); i++) { | ||
131 | auto p = part.content()->contents().at(i); | ||
132 | if (KMime::isAttachment(p)) { | ||
133 | list.append(MimeMessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), p, true))); | ||
134 | } | ||
135 | } | ||
136 | return list; | ||
126 | } | 137 | } |
127 | 138 | ||
128 | static const MimeTreeParser::Interface::BodyPartFormatter *create() { | 139 | static const MimeTreeParser::Interface::BodyPartFormatter *create() { |
@@ -142,9 +153,6 @@ public: | |||
142 | if (part.content()->contents().isEmpty()) { | 153 | if (part.content()->contents().isEmpty()) { |
143 | return {}; | 154 | return {}; |
144 | } | 155 | } |
145 | //FIXME sometimes we get attachments in here as well | ||
146 | //TODO look for attachment parts anyways | ||
147 | // normal treatment of the parts in the mp/mixed container | ||
148 | return MimeMessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), part.content()->contents().at(0), false)); | 156 | return MimeMessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), part.content()->contents().at(0), false)); |
149 | } | 157 | } |
150 | 158 | ||
diff --git a/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp b/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp index fced7997..f44816b0 100644 --- a/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp +++ b/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp | |||
@@ -399,7 +399,7 @@ MessagePartPtr ObjectTreeParser::parsedPart() const | |||
399 | return mParsedPart; | 399 | return mParsedPart; |
400 | } | 400 | } |
401 | 401 | ||
402 | MessagePartPtr ObjectTreeParser::processType(KMime::Content *node, const QByteArray &mediaType, const QByteArray &subType) | 402 | QVector<MessagePartPtr> ObjectTreeParser::processType(KMime::Content *node, const QByteArray &mediaType, const QByteArray &subType) |
403 | { | 403 | { |
404 | static MimeTreeParser::BodyPartFormatterBaseFactory factory; | 404 | static MimeTreeParser::BodyPartFormatterBaseFactory factory; |
405 | const auto sub = factory.subtypeRegistry(mediaType.constData()); | 405 | const auto sub = factory.subtypeRegistry(mediaType.constData()); |
@@ -410,8 +410,9 @@ MessagePartPtr ObjectTreeParser::processType(KMime::Content *node, const QByteAr | |||
410 | continue; | 410 | continue; |
411 | } | 411 | } |
412 | PartNodeBodyPart part(this, mTopLevelContent, node, mNodeHelper); | 412 | PartNodeBodyPart part(this, mTopLevelContent, node, mNodeHelper); |
413 | if (const MessagePart::Ptr result = formatter->process(part)) { | 413 | const auto list = formatter->processList(part); |
414 | return result; | 414 | if (!list.isEmpty()) { |
415 | return list; | ||
415 | } | 416 | } |
416 | } | 417 | } |
417 | return {}; | 418 | return {}; |
@@ -458,16 +459,35 @@ MessagePart::Ptr ObjectTreeParser::parseObjectTreeInternal(KMime::Content *node, | |||
458 | subType = node->contentType()->subType(); | 459 | subType = node->contentType()->subType(); |
459 | } | 460 | } |
460 | 461 | ||
461 | //Try the specific type handler | 462 | auto mp = [&] { |
462 | if (auto mp = processType(node, mediaType, subType)) { | 463 | //Try the specific type handler |
463 | parsedPart->appendSubPart(mp); | 464 | { |
464 | //Fallback to the generic handler | 465 | auto list = processType(node, mediaType, subType); |
465 | } else if (auto mp = processType(node, mediaType, "*")) { | 466 | if (!list.isEmpty()) { |
466 | parsedPart->appendSubPart(mp); | 467 | return list; |
467 | //Fallback to the default handler | 468 | } |
468 | } else if (auto mp = defaultHandling(node)) { | 469 | } |
469 | parsedPart->appendSubPart(mp); | 470 | //Fallback to the generic handler |
471 | { | ||
472 | auto list = processType(node, mediaType, "*"); | ||
473 | if (!list.isEmpty()) { | ||
474 | return list; | ||
475 | } | ||
476 | } | ||
477 | //Fallback to the default handler | ||
478 | { | ||
479 | auto list = defaultHandling(node); | ||
480 | if (!list.isEmpty()) { | ||
481 | return list; | ||
482 | } | ||
483 | } | ||
484 | return QVector<MessagePart::Ptr>{}; | ||
485 | }(); | ||
486 | |||
487 | for (const auto p : mp) { | ||
488 | parsedPart->appendSubPart(p); | ||
470 | } | 489 | } |
490 | |||
471 | mNodeHelper->setNodeProcessed(node, false); | 491 | mNodeHelper->setNodeProcessed(node, false); |
472 | 492 | ||
473 | if (onlyOneMimePart) { | 493 | if (onlyOneMimePart) { |
@@ -478,19 +498,20 @@ MessagePart::Ptr ObjectTreeParser::parseObjectTreeInternal(KMime::Content *node, | |||
478 | return parsedPart; | 498 | return parsedPart; |
479 | } | 499 | } |
480 | 500 | ||
481 | MessagePart::Ptr ObjectTreeParser::defaultHandling(KMime::Content *node) | 501 | QVector<MessagePart::Ptr> ObjectTreeParser::defaultHandling(KMime::Content *node) |
482 | { | 502 | { |
483 | if (node->contentType()->mimeType() == QByteArrayLiteral("application/octet-stream") && | 503 | if (node->contentType()->mimeType() == QByteArrayLiteral("application/octet-stream") && |
484 | (node->contentType()->name().endsWith(QLatin1String("p7m")) || | 504 | (node->contentType()->name().endsWith(QLatin1String("p7m")) || |
485 | node->contentType()->name().endsWith(QLatin1String("p7s")) || | 505 | node->contentType()->name().endsWith(QLatin1String("p7s")) || |
486 | node->contentType()->name().endsWith(QLatin1String("p7c")) | 506 | node->contentType()->name().endsWith(QLatin1String("p7c")) |
487 | )) { | 507 | )) { |
488 | if (auto mp = processType(node, "application", "pkcs7-mime")) { | 508 | auto list = processType(node, "application", "pkcs7-mime"); |
489 | return mp; | 509 | if (!list.isEmpty()) { |
510 | return list; | ||
490 | } | 511 | } |
491 | } | 512 | } |
492 | 513 | ||
493 | return AttachmentMessagePart::Ptr(new AttachmentMessagePart(this, node)); | 514 | return {AttachmentMessagePart::Ptr(new AttachmentMessagePart(this, node))}; |
494 | } | 515 | } |
495 | 516 | ||
496 | const QTextCodec *ObjectTreeParser::codecFor(KMime::Content *node) const | 517 | const QTextCodec *ObjectTreeParser::codecFor(KMime::Content *node) const |
diff --git a/framework/src/domain/mime/mimetreeparser/objecttreeparser.h b/framework/src/domain/mime/mimetreeparser/objecttreeparser.h index 1795c79c..1109d859 100644 --- a/framework/src/domain/mime/mimetreeparser/objecttreeparser.h +++ b/framework/src/domain/mime/mimetreeparser/objecttreeparser.h | |||
@@ -282,9 +282,9 @@ private: | |||
282 | * top-level content. | 282 | * top-level content. |
283 | */ | 283 | */ |
284 | MessagePartPtr parseObjectTreeInternal(KMime::Content *node, bool mOnlyOneMimePart); | 284 | MessagePartPtr parseObjectTreeInternal(KMime::Content *node, bool mOnlyOneMimePart); |
285 | MessagePartPtr processType(KMime::Content *node, const QByteArray &mediaType, const QByteArray &subType); | 285 | QVector<MessagePartPtr> processType(KMime::Content *node, const QByteArray &mediaType, const QByteArray &subType); |
286 | 286 | ||
287 | MessagePartPtr defaultHandling(KMime::Content *node); | 287 | QVector<MessagePartPtr> defaultHandling(KMime::Content *node); |
288 | 288 | ||
289 | private: | 289 | private: |
290 | 290 | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp b/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp index 38857d58..97c79fe7 100644 --- a/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp +++ b/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp | |||
@@ -261,7 +261,7 @@ private slots: | |||
261 | QVERIFY(bool(part)); | 261 | QVERIFY(bool(part)); |
262 | QCOMPARE(part->encryptions().size(), 0); | 262 | QCOMPARE(part->encryptions().size(), 0); |
263 | QCOMPARE(part->signatures().size(), 0); | 263 | QCOMPARE(part->signatures().size(), 0); |
264 | QCOMPARE(otp.collectAttachmentParts().size(), 0); | 264 | QCOMPARE(otp.collectAttachmentParts().size(), 1); |
265 | } | 265 | } |
266 | 266 | ||
267 | void testAttachmentPart() | 267 | void testAttachmentPart() |