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