diff options
Diffstat (limited to 'framework/domain/mimetreeparser/interface.cpp')
-rw-r--r-- | framework/domain/mimetreeparser/interface.cpp | 821 |
1 files changed, 821 insertions, 0 deletions
diff --git a/framework/domain/mimetreeparser/interface.cpp b/framework/domain/mimetreeparser/interface.cpp new file mode 100644 index 00000000..c3ecf79c --- /dev/null +++ b/framework/domain/mimetreeparser/interface.cpp | |||
@@ -0,0 +1,821 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <knauss@kolabsystems.com> | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU Library General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or (at your | ||
7 | option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, but WITHOUT | ||
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | ||
12 | License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this library; see the file COPYING.LIB. If not, write to the | ||
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
17 | 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #include "interface.h" | ||
21 | #include "interface_p.h" | ||
22 | |||
23 | #include "stringhtmlwriter.h" | ||
24 | #include "objecttreesource.h" | ||
25 | |||
26 | #include <KMime/Content> | ||
27 | #include <MimeTreeParser/ObjectTreeParser> | ||
28 | #include <MimeTreeParser/MessagePart> | ||
29 | #include <MimeTreeParser/NodeHelper> | ||
30 | |||
31 | #include <QMimeDatabase> | ||
32 | #include <QMimeType> | ||
33 | #include <QDebug> | ||
34 | |||
35 | class MailMimePrivate | ||
36 | { | ||
37 | public: | ||
38 | KMime::Content *mNode; | ||
39 | MailMime *q; | ||
40 | }; | ||
41 | |||
42 | MailMime::MailMime() | ||
43 | : d(std::unique_ptr<MailMimePrivate>(new MailMimePrivate())) | ||
44 | { | ||
45 | d->q = this; | ||
46 | } | ||
47 | |||
48 | bool MailMime::isFirstTextPart() const | ||
49 | { | ||
50 | if (!d->mNode || !d->mNode->topLevel()) { | ||
51 | return false; | ||
52 | } | ||
53 | return (d->mNode->topLevel()->textContent() == d->mNode); | ||
54 | } | ||
55 | |||
56 | bool MailMime::isTopLevelPart() const | ||
57 | { | ||
58 | if (!d->mNode) { | ||
59 | return false; | ||
60 | } | ||
61 | return (d->mNode->topLevel() == d->mNode); | ||
62 | } | ||
63 | |||
64 | MailMime::Disposition MailMime::disposition() const | ||
65 | { | ||
66 | if (!d->mNode) { | ||
67 | return Invalid; | ||
68 | } | ||
69 | const auto cd = d->mNode->contentDisposition(false); | ||
70 | if (!cd) { | ||
71 | return Invalid; | ||
72 | } | ||
73 | switch (cd->disposition()){ | ||
74 | case KMime::Headers::CDinline: | ||
75 | return Inline; | ||
76 | case KMime::Headers::CDattachment: | ||
77 | return Attachment; | ||
78 | default: | ||
79 | return Invalid; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | QString MailMime::filename() const | ||
84 | { | ||
85 | if (!d->mNode) { | ||
86 | return QString(); | ||
87 | } | ||
88 | const auto cd = d->mNode->contentDisposition(false); | ||
89 | if (!cd) { | ||
90 | return QString(); | ||
91 | } | ||
92 | return cd->filename(); | ||
93 | } | ||
94 | |||
95 | QMimeType MailMime::mimetype() const | ||
96 | { | ||
97 | if (!d->mNode) { | ||
98 | return QMimeType(); | ||
99 | } | ||
100 | |||
101 | const auto ct = d->mNode->contentType(false); | ||
102 | if (!ct) { | ||
103 | return QMimeType(); | ||
104 | } | ||
105 | |||
106 | QMimeDatabase mimeDb; | ||
107 | return mimeDb.mimeTypeForName(ct->mimeType()); | ||
108 | } | ||
109 | |||
110 | class PartPrivate | ||
111 | { | ||
112 | public: | ||
113 | PartPrivate(Part *part); | ||
114 | void appendSubPart(Part::Ptr subpart); | ||
115 | |||
116 | QVector<Part::Ptr> subParts(); | ||
117 | |||
118 | Part *parent() const; | ||
119 | |||
120 | const MailMime::Ptr &mailMime() const; | ||
121 | void createMailMime(const MimeTreeParser::MimeMessagePart::Ptr &part); | ||
122 | void createMailMime(const MimeTreeParser::TextMessagePart::Ptr &part); | ||
123 | void createMailMime(const MimeTreeParser::AlternativeMessagePart::Ptr &part); | ||
124 | void createMailMime(const MimeTreeParser::HtmlMessagePart::Ptr &part); | ||
125 | |||
126 | void appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr &part); | ||
127 | void appendSignature(const MimeTreeParser::SignedMessagePart::Ptr &part); | ||
128 | |||
129 | void setSignatures(const QVector<Signature::Ptr> &sigs); | ||
130 | void setEncryptions(const QVector<Encryption::Ptr> &encs); | ||
131 | |||
132 | const QVector<Encryption::Ptr> &encryptions() const; | ||
133 | const QVector<Signature::Ptr> &signatures() const; | ||
134 | private: | ||
135 | Part *q; | ||
136 | Part *mParent; | ||
137 | QVector<Part::Ptr> mSubParts; | ||
138 | QVector<Encryption::Ptr> mEncryptions; | ||
139 | QVector<Signature::Ptr> mSignatures; | ||
140 | MailMime::Ptr mMailMime; | ||
141 | }; | ||
142 | |||
143 | PartPrivate::PartPrivate(Part* part) | ||
144 | : q(part) | ||
145 | , mParent(Q_NULLPTR) | ||
146 | { | ||
147 | |||
148 | } | ||
149 | |||
150 | void PartPrivate::createMailMime(const MimeTreeParser::HtmlMessagePart::Ptr& part) | ||
151 | { | ||
152 | mMailMime = MailMime::Ptr(new MailMime); | ||
153 | mMailMime->d->mNode = part->mNode; | ||
154 | } | ||
155 | |||
156 | void PartPrivate::createMailMime(const MimeTreeParser::AlternativeMessagePart::Ptr& part) | ||
157 | { | ||
158 | mMailMime = MailMime::Ptr(new MailMime); | ||
159 | mMailMime->d->mNode = part->mNode; | ||
160 | } | ||
161 | |||
162 | void PartPrivate::createMailMime(const MimeTreeParser::TextMessagePart::Ptr& part) | ||
163 | { | ||
164 | mMailMime = MailMime::Ptr(new MailMime); | ||
165 | mMailMime->d->mNode = part->mNode; | ||
166 | } | ||
167 | |||
168 | void PartPrivate::createMailMime(const MimeTreeParser::MimeMessagePart::Ptr& part) | ||
169 | { | ||
170 | mMailMime = MailMime::Ptr(new MailMime); | ||
171 | mMailMime->d->mNode = part->mNode; | ||
172 | } | ||
173 | |||
174 | void PartPrivate::appendSubPart(Part::Ptr subpart) | ||
175 | { | ||
176 | subpart->d->mParent = q; | ||
177 | mSubParts.append(subpart); | ||
178 | } | ||
179 | |||
180 | void PartPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part) | ||
181 | { | ||
182 | mEncryptions.append(Encryption::Ptr(new Encryption)); | ||
183 | } | ||
184 | |||
185 | void PartPrivate::setEncryptions(const QVector< Encryption::Ptr >& encs) | ||
186 | { | ||
187 | mEncryptions = encs; | ||
188 | } | ||
189 | |||
190 | void PartPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& part) | ||
191 | { | ||
192 | mSignatures.append(Signature::Ptr(new Signature)); | ||
193 | } | ||
194 | |||
195 | |||
196 | void PartPrivate::setSignatures(const QVector< Signature::Ptr >& sigs) | ||
197 | { | ||
198 | mSignatures = sigs; | ||
199 | } | ||
200 | |||
201 | Part *PartPrivate::parent() const | ||
202 | { | ||
203 | return mParent; | ||
204 | } | ||
205 | |||
206 | QVector< Part::Ptr > PartPrivate::subParts() | ||
207 | { | ||
208 | return mSubParts; | ||
209 | } | ||
210 | |||
211 | const MailMime::Ptr& PartPrivate::mailMime() const | ||
212 | { | ||
213 | return mMailMime; | ||
214 | } | ||
215 | |||
216 | const QVector< Encryption::Ptr >& PartPrivate::encryptions() const | ||
217 | { | ||
218 | return mEncryptions; | ||
219 | } | ||
220 | |||
221 | const QVector< Signature::Ptr >& PartPrivate::signatures() const | ||
222 | { | ||
223 | return mSignatures; | ||
224 | } | ||
225 | |||
226 | Part::Part() | ||
227 | : d(std::unique_ptr<PartPrivate>(new PartPrivate(this))) | ||
228 | { | ||
229 | |||
230 | } | ||
231 | |||
232 | bool Part::hasSubParts() const | ||
233 | { | ||
234 | return !subParts().isEmpty(); | ||
235 | } | ||
236 | |||
237 | QVector<Part::Ptr> Part::subParts() const | ||
238 | { | ||
239 | return d->subParts(); | ||
240 | } | ||
241 | |||
242 | QByteArray Part::type() const | ||
243 | { | ||
244 | return "Part"; | ||
245 | } | ||
246 | |||
247 | QVector<QByteArray> Part::availableContents() const | ||
248 | { | ||
249 | return QVector<QByteArray>(); | ||
250 | } | ||
251 | |||
252 | QVector<Content::Ptr> Part::content() const | ||
253 | { | ||
254 | return content(availableContents().first()); | ||
255 | } | ||
256 | |||
257 | QVector<Content::Ptr> Part::content(const QByteArray& ct) const | ||
258 | { | ||
259 | return QVector<Content::Ptr>(); | ||
260 | } | ||
261 | |||
262 | QVector<Encryption::Ptr> Part::encryptions() const | ||
263 | { | ||
264 | auto ret = d->encryptions(); | ||
265 | auto parent = d->parent(); | ||
266 | if (parent) { | ||
267 | ret.append(parent->encryptions()); | ||
268 | } | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | QVector<Signature::Ptr> Part::signatures() const | ||
273 | { | ||
274 | auto ret = d->signatures(); | ||
275 | auto parent = d->parent(); | ||
276 | if (parent) { | ||
277 | ret.append(parent->signatures()); | ||
278 | } | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | MailMime::Ptr Part::mailMime() const | ||
283 | { | ||
284 | return d->mailMime(); | ||
285 | } | ||
286 | |||
287 | class ContentPrivate | ||
288 | { | ||
289 | public: | ||
290 | QByteArray mContent; | ||
291 | QByteArray mCodec; | ||
292 | Part *mParent; | ||
293 | Content *q; | ||
294 | MailMime::Ptr mMailMime; | ||
295 | QVector<Encryption::Ptr> mEncryptions; | ||
296 | QVector<Signature::Ptr> mSignatures; | ||
297 | void appendSignature(const MimeTreeParser::SignedMessagePart::Ptr &sig); | ||
298 | void appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr &enc); | ||
299 | }; | ||
300 | |||
301 | void ContentPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& enc) | ||
302 | { | ||
303 | mEncryptions.append(Encryption::Ptr(new Encryption)); | ||
304 | } | ||
305 | |||
306 | void ContentPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& sig) | ||
307 | { | ||
308 | mSignatures.append(Signature::Ptr(new Signature)); | ||
309 | } | ||
310 | |||
311 | |||
312 | Content::Content(const QByteArray& content, Part *parent) | ||
313 | : d(std::unique_ptr<ContentPrivate>(new ContentPrivate)) | ||
314 | { | ||
315 | d->q = this; | ||
316 | d->mContent = content; | ||
317 | d->mCodec = "utf-8"; | ||
318 | d->mParent = parent; | ||
319 | } | ||
320 | |||
321 | Content::Content(ContentPrivate* d_ptr) | ||
322 | : d(std::unique_ptr<ContentPrivate>(d_ptr)) | ||
323 | { | ||
324 | d->q = this; | ||
325 | } | ||
326 | |||
327 | Content::~Content() | ||
328 | { | ||
329 | } | ||
330 | |||
331 | QVector<Encryption::Ptr> Content::encryptions() const | ||
332 | { | ||
333 | auto ret = d->mEncryptions; | ||
334 | if (d->mParent) { | ||
335 | ret.append(d->mParent->encryptions()); | ||
336 | } | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | QVector<Signature::Ptr> Content::signatures() const | ||
341 | { | ||
342 | auto ret = d->mSignatures; | ||
343 | if (d->mParent) { | ||
344 | ret.append(d->mParent->signatures()); | ||
345 | } | ||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | QByteArray Content::content() const | ||
350 | { | ||
351 | return d->mContent; | ||
352 | } | ||
353 | |||
354 | QByteArray Content::charset() const | ||
355 | { | ||
356 | return d->mCodec; | ||
357 | } | ||
358 | |||
359 | QByteArray Content::type() const | ||
360 | { | ||
361 | return "Content"; | ||
362 | } | ||
363 | |||
364 | MailMime::Ptr Content::mailMime() const | ||
365 | { | ||
366 | if (d->mMailMime) { | ||
367 | return d->mMailMime; | ||
368 | } else { | ||
369 | return d->mParent->mailMime(); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | Part *Content::parent() const | ||
374 | { | ||
375 | return d->mParent; | ||
376 | } | ||
377 | |||
378 | HtmlContent::HtmlContent(const QByteArray& content, Part* parent) | ||
379 | : Content(content, parent) | ||
380 | { | ||
381 | |||
382 | } | ||
383 | |||
384 | QByteArray HtmlContent::type() const | ||
385 | { | ||
386 | return "HtmlContent"; | ||
387 | } | ||
388 | |||
389 | PlainTextContent::PlainTextContent(const QByteArray& content, Part* parent) | ||
390 | : Content(content, parent) | ||
391 | { | ||
392 | |||
393 | } | ||
394 | |||
395 | PlainTextContent::PlainTextContent(ContentPrivate* d_ptr) | ||
396 | : Content(d_ptr) | ||
397 | { | ||
398 | |||
399 | } | ||
400 | |||
401 | HtmlContent::HtmlContent(ContentPrivate* d_ptr) | ||
402 | : Content(d_ptr) | ||
403 | { | ||
404 | |||
405 | } | ||
406 | |||
407 | |||
408 | QByteArray PlainTextContent::type() const | ||
409 | { | ||
410 | return "PlainTextContent"; | ||
411 | } | ||
412 | |||
413 | class AlternativePartPrivate | ||
414 | { | ||
415 | public: | ||
416 | void fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part); | ||
417 | |||
418 | QVector<Content::Ptr> content(const QByteArray &ct) const; | ||
419 | |||
420 | AlternativePart *q; | ||
421 | |||
422 | QVector<QByteArray> types() const; | ||
423 | |||
424 | private: | ||
425 | QMap<QByteArray, QVector<Content::Ptr>> mContent; | ||
426 | QVector<QByteArray> mTypes; | ||
427 | }; | ||
428 | |||
429 | void AlternativePartPrivate::fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part) | ||
430 | { | ||
431 | mTypes = QVector<QByteArray>() << "html" << "plaintext"; | ||
432 | |||
433 | Content::Ptr content = std::make_shared<HtmlContent>(part->htmlContent().toLocal8Bit(), q); | ||
434 | mContent["html"].append(content); | ||
435 | content = std::make_shared<PlainTextContent>(part->plaintextContent().toLocal8Bit(), q); | ||
436 | mContent["plaintext"].append(content); | ||
437 | q->reachParentD()->createMailMime(part); | ||
438 | } | ||
439 | |||
440 | QVector<QByteArray> AlternativePartPrivate::types() const | ||
441 | { | ||
442 | return mTypes; | ||
443 | } | ||
444 | |||
445 | QVector<Content::Ptr> AlternativePartPrivate::content(const QByteArray& ct) const | ||
446 | { | ||
447 | return mContent[ct]; | ||
448 | } | ||
449 | |||
450 | AlternativePart::AlternativePart() | ||
451 | : d(std::unique_ptr<AlternativePartPrivate>(new AlternativePartPrivate)) | ||
452 | { | ||
453 | d->q = this; | ||
454 | } | ||
455 | |||
456 | AlternativePart::~AlternativePart() | ||
457 | { | ||
458 | |||
459 | } | ||
460 | |||
461 | QByteArray AlternativePart::type() const | ||
462 | { | ||
463 | return "AlternativePart"; | ||
464 | } | ||
465 | |||
466 | QVector<QByteArray> AlternativePart::availableContents() const | ||
467 | { | ||
468 | return d->types(); | ||
469 | } | ||
470 | |||
471 | QVector<Content::Ptr> AlternativePart::content(const QByteArray& ct) const | ||
472 | { | ||
473 | return d->content(ct); | ||
474 | } | ||
475 | |||
476 | PartPrivate* AlternativePart::reachParentD() const | ||
477 | { | ||
478 | return Part::d.get(); | ||
479 | } | ||
480 | |||
481 | class SinglePartPrivate | ||
482 | { | ||
483 | public: | ||
484 | void fillFrom(MimeTreeParser::TextMessagePart::Ptr part); | ||
485 | void fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part); | ||
486 | void fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part); | ||
487 | SinglePart *q; | ||
488 | |||
489 | QVector<Content::Ptr> mContent; | ||
490 | QByteArray mType; | ||
491 | }; | ||
492 | |||
493 | void SinglePartPrivate::fillFrom(MimeTreeParser::TextMessagePart::Ptr part) | ||
494 | { | ||
495 | mType = "plaintext"; | ||
496 | mContent.clear(); | ||
497 | foreach (const auto &mp, part->subParts()) { | ||
498 | auto d_ptr = new ContentPrivate; | ||
499 | d_ptr->mContent = part->text().toLocal8Bit(); | ||
500 | d_ptr->mParent = q; | ||
501 | d_ptr->mCodec = "utf-8"; | ||
502 | const auto enc = mp.dynamicCast<MimeTreeParser::EncryptedMessagePart>(); | ||
503 | auto sig = mp.dynamicCast<MimeTreeParser::SignedMessagePart>(); | ||
504 | if (enc) { | ||
505 | d_ptr->appendEncryption(enc); | ||
506 | const auto s = enc->subParts(); | ||
507 | if (s.size() == 1) { | ||
508 | sig = s[0].dynamicCast<MimeTreeParser::SignedMessagePart>(); | ||
509 | } | ||
510 | } | ||
511 | if (sig) { | ||
512 | d_ptr->appendSignature(sig); | ||
513 | } | ||
514 | mContent.append(std::make_shared<PlainTextContent>(d_ptr)); | ||
515 | q->reachParentD()->createMailMime(part); | ||
516 | } | ||
517 | } | ||
518 | |||
519 | void SinglePartPrivate::fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part) | ||
520 | { | ||
521 | mType = "html"; | ||
522 | mContent.clear(); | ||
523 | mContent.append(std::make_shared<HtmlContent>(part->text().toLocal8Bit(), q)); | ||
524 | q->reachParentD()->createMailMime(part); | ||
525 | } | ||
526 | |||
527 | void SinglePartPrivate::fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part) | ||
528 | { | ||
529 | q->reachParentD()->createMailMime(part.staticCast<MimeTreeParser::TextMessagePart>()); | ||
530 | mType = q->mailMime()->mimetype().name().toUtf8(); | ||
531 | mContent.clear(); | ||
532 | mContent.append(std::make_shared<Content>(part->text().toLocal8Bit(), q)); | ||
533 | } | ||
534 | |||
535 | SinglePart::SinglePart() | ||
536 | : d(std::unique_ptr<SinglePartPrivate>(new SinglePartPrivate)) | ||
537 | { | ||
538 | d->q = this; | ||
539 | } | ||
540 | |||
541 | SinglePart::~SinglePart() | ||
542 | { | ||
543 | |||
544 | } | ||
545 | |||
546 | QVector<QByteArray> SinglePart::availableContents() const | ||
547 | { | ||
548 | return QVector<QByteArray>() << d->mType; | ||
549 | } | ||
550 | |||
551 | QVector< Content::Ptr > SinglePart::content(const QByteArray &ct) const | ||
552 | { | ||
553 | if (ct == d->mType) { | ||
554 | return d->mContent; | ||
555 | } | ||
556 | return QVector<Content::Ptr>(); | ||
557 | } | ||
558 | |||
559 | QByteArray SinglePart::type() const | ||
560 | { | ||
561 | return "SinglePart"; | ||
562 | } | ||
563 | |||
564 | PartPrivate* SinglePart::reachParentD() const | ||
565 | { | ||
566 | return Part::d.get(); | ||
567 | } | ||
568 | |||
569 | class SignaturePrivate | ||
570 | { | ||
571 | public: | ||
572 | Signature *q; | ||
573 | }; | ||
574 | |||
575 | Signature::Signature() | ||
576 | :d(std::unique_ptr<SignaturePrivate>(new SignaturePrivate)) | ||
577 | { | ||
578 | d->q = this; | ||
579 | } | ||
580 | |||
581 | |||
582 | Signature::Signature(SignaturePrivate *d_ptr) | ||
583 | :d(std::unique_ptr<SignaturePrivate>(d_ptr)) | ||
584 | { | ||
585 | d->q = this; | ||
586 | } | ||
587 | |||
588 | Signature::~Signature() | ||
589 | { | ||
590 | |||
591 | } | ||
592 | |||
593 | |||
594 | class EncryptionPrivate | ||
595 | { | ||
596 | public: | ||
597 | Encryption *q; | ||
598 | }; | ||
599 | |||
600 | Encryption::Encryption(EncryptionPrivate *d_ptr) | ||
601 | :d(std::unique_ptr<EncryptionPrivate>(d_ptr)) | ||
602 | { | ||
603 | d->q = this; | ||
604 | } | ||
605 | |||
606 | Encryption::Encryption() | ||
607 | :d(std::unique_ptr<EncryptionPrivate>(new EncryptionPrivate)) | ||
608 | { | ||
609 | d->q = this; | ||
610 | } | ||
611 | |||
612 | Encryption::~Encryption() | ||
613 | { | ||
614 | |||
615 | } | ||
616 | |||
617 | ParserPrivate::ParserPrivate(Parser* parser) | ||
618 | : q(parser) | ||
619 | , mNodeHelper(std::make_shared<MimeTreeParser::NodeHelper>()) | ||
620 | { | ||
621 | |||
622 | } | ||
623 | |||
624 | void ParserPrivate::setMessage(const QByteArray& mimeMessage) | ||
625 | { | ||
626 | const auto mailData = KMime::CRLFtoLF(mimeMessage); | ||
627 | mMsg = KMime::Message::Ptr(new KMime::Message); | ||
628 | mMsg->setContent(mailData); | ||
629 | mMsg->parse(); | ||
630 | |||
631 | // render the mail | ||
632 | StringHtmlWriter htmlWriter; | ||
633 | ObjectTreeSource source(&htmlWriter); | ||
634 | MimeTreeParser::ObjectTreeParser otp(&source, mNodeHelper.get()); | ||
635 | |||
636 | otp.parseObjectTree(mMsg.data()); | ||
637 | mPartTree = otp.parsedPart().dynamicCast<MimeTreeParser::MessagePart>(); | ||
638 | |||
639 | mEmbeddedPartMap = htmlWriter.embeddedParts(); | ||
640 | mHtml = htmlWriter.html(); | ||
641 | |||
642 | mTree = std::make_shared<Part>(); | ||
643 | createTree(mPartTree, mTree); | ||
644 | } | ||
645 | |||
646 | |||
647 | void ParserPrivate::createTree(const MimeTreeParser::MessagePart::Ptr &start, const Part::Ptr &tree) | ||
648 | { | ||
649 | foreach (const auto &mp, start->subParts()) { | ||
650 | const auto m = mp.dynamicCast<MimeTreeParser::MessagePart>(); | ||
651 | const auto text = mp.dynamicCast<MimeTreeParser::TextMessagePart>(); | ||
652 | const auto alternative = mp.dynamicCast<MimeTreeParser::AlternativeMessagePart>(); | ||
653 | const auto html = mp.dynamicCast<MimeTreeParser::HtmlMessagePart>(); | ||
654 | const auto attachment = mp.dynamicCast<MimeTreeParser::AttachmentMessagePart>(); | ||
655 | if (attachment) { | ||
656 | auto part = std::make_shared<SinglePart>(); | ||
657 | part->d->fillFrom(attachment); | ||
658 | tree->d->appendSubPart(part); | ||
659 | } else if (text) { | ||
660 | auto part = std::make_shared<SinglePart>(); | ||
661 | part->d->fillFrom(text); | ||
662 | tree->d->appendSubPart(part); | ||
663 | } else if (alternative) { | ||
664 | auto part = std::make_shared<AlternativePart>(); | ||
665 | part->d->fillFrom(alternative); | ||
666 | tree->d->appendSubPart(part); | ||
667 | } else if (html) { | ||
668 | auto part = std::make_shared<SinglePart>(); | ||
669 | part->d->fillFrom(html); | ||
670 | tree->d->appendSubPart(part); | ||
671 | } else { | ||
672 | const auto enc = mp.dynamicCast<MimeTreeParser::EncryptedMessagePart>(); | ||
673 | const auto sig = mp.dynamicCast<MimeTreeParser::SignedMessagePart>(); | ||
674 | if (enc || sig) { | ||
675 | auto subTree = std::make_shared<Part>(); | ||
676 | if (enc) { | ||
677 | subTree->d->appendEncryption(enc); | ||
678 | } | ||
679 | if (sig) { | ||
680 | subTree->d->appendSignature(sig); | ||
681 | } | ||
682 | createTree(m, subTree); | ||
683 | foreach(const auto &p, subTree->subParts()) { | ||
684 | tree->d->appendSubPart(p); | ||
685 | if (enc) { | ||
686 | p->d->setEncryptions(subTree->d->encryptions()); | ||
687 | } | ||
688 | if (sig) { | ||
689 | p->d->setSignatures(subTree->d->signatures()); | ||
690 | } | ||
691 | } | ||
692 | } else { | ||
693 | createTree(m, tree); | ||
694 | } | ||
695 | } | ||
696 | } | ||
697 | } | ||
698 | |||
699 | Parser::Parser(const QByteArray& mimeMessage) | ||
700 | :d(std::unique_ptr<ParserPrivate>(new ParserPrivate(this))) | ||
701 | { | ||
702 | d->setMessage(mimeMessage); | ||
703 | } | ||
704 | |||
705 | Parser::~Parser() | ||
706 | { | ||
707 | } | ||
708 | |||
709 | QUrl Parser::getPart(const QByteArray &cid) | ||
710 | { | ||
711 | return d->mEmbeddedPartMap.value(cid); | ||
712 | } | ||
713 | |||
714 | QVector<Part::Ptr> Parser::collectContentParts() const | ||
715 | { | ||
716 | return collect(d->mTree, [](const Part::Ptr &p){return p->type() != "EncapsulatedPart";}, | ||
717 | [](const Content::Ptr &content){ | ||
718 | const auto mime = content->mailMime(); | ||
719 | |||
720 | if (!mime) { | ||
721 | return true; | ||
722 | } | ||
723 | |||
724 | if (mime->isFirstTextPart()) { | ||
725 | return true; | ||
726 | } | ||
727 | |||
728 | { | ||
729 | const auto parent = content->parent(); | ||
730 | if (parent) { | ||
731 | const auto _mime = parent->mailMime(); | ||
732 | if (_mime && (_mime->isTopLevelPart() || _mime->isFirstTextPart())) { | ||
733 | return true; | ||
734 | } | ||
735 | } | ||
736 | } | ||
737 | const auto cd = mime->disposition(); | ||
738 | if (cd && cd == MailMime::Inline) { | ||
739 | // explict "inline" disposition: | ||
740 | return true; | ||
741 | } | ||
742 | if (cd && cd == MailMime::Attachment) { | ||
743 | // explicit "attachment" disposition: | ||
744 | return false; | ||
745 | } | ||
746 | |||
747 | const auto ct = mime->mimetype(); | ||
748 | if (ct.name().trimmed().toLower() == "text" && ct.name().trimmed().isEmpty() && | ||
749 | (!mime || mime->filename().trimmed().isEmpty())) { | ||
750 | // text/* w/o filename parameter: | ||
751 | return true; | ||
752 | } | ||
753 | return false; | ||
754 | }); | ||
755 | } | ||
756 | |||
757 | |||
758 | QVector<Part::Ptr> Parser::collectAttachmentParts() const | ||
759 | { | ||
760 | return collect(d->mTree, [](const Part::Ptr &p){return p->type() != "EncapsulatedPart";}, | ||
761 | [](const Content::Ptr &content){ | ||
762 | const auto mime = content->mailMime(); | ||
763 | |||
764 | if (!mime) { | ||
765 | return false; | ||
766 | } | ||
767 | |||
768 | if (mime->isFirstTextPart()) { | ||
769 | return false; | ||
770 | } | ||
771 | |||
772 | { | ||
773 | const auto parent = content->parent(); | ||
774 | if (parent) { | ||
775 | const auto _mime = parent->mailMime(); | ||
776 | if (_mime && (_mime->isTopLevelPart() || _mime->isFirstTextPart())) { | ||
777 | return false; | ||
778 | } | ||
779 | } | ||
780 | } | ||
781 | const auto cd = mime->disposition(); | ||
782 | if (cd && cd == MailMime::Inline) { | ||
783 | // explict "inline" disposition: | ||
784 | return false; | ||
785 | } | ||
786 | if (cd && cd == MailMime::Attachment) { | ||
787 | // explicit "attachment" disposition: | ||
788 | return true; | ||
789 | } | ||
790 | |||
791 | const auto ct = mime->mimetype(); | ||
792 | if (ct.name().trimmed().toLower() == "text" && ct.name().trimmed().isEmpty() && | ||
793 | (!mime || mime->filename().trimmed().isEmpty())) { | ||
794 | // text/* w/o filename parameter: | ||
795 | return false; | ||
796 | } | ||
797 | return true; | ||
798 | }); | ||
799 | } | ||
800 | QVector<Part::Ptr> Parser::collect(const Part::Ptr &start, std::function<bool(const Part::Ptr &)> select, std::function<bool(const Content::Ptr &)> filter) const | ||
801 | { | ||
802 | QVector<Part::Ptr> ret; | ||
803 | foreach (const auto &part, start->subParts()) { | ||
804 | QVector<QByteArray> contents; | ||
805 | foreach(const auto &ct, part->availableContents()) { | ||
806 | foreach(const auto &content, part->content(ct)) { | ||
807 | if (filter(content)) { | ||
808 | contents.append(ct); | ||
809 | break; | ||
810 | } | ||
811 | } | ||
812 | } | ||
813 | if (!contents.isEmpty()) { | ||
814 | ret.append(part); | ||
815 | } | ||
816 | if (select(part)){ | ||
817 | ret += collect(part, select, filter); | ||
818 | } | ||
819 | } | ||
820 | return ret; | ||
821 | } \ No newline at end of file | ||