summaryrefslogtreecommitdiffstats
path: root/framework/domain/mimetreeparser/interface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'framework/domain/mimetreeparser/interface.cpp')
-rw-r--r--framework/domain/mimetreeparser/interface.cpp335
1 files changed, 335 insertions, 0 deletions
diff --git a/framework/domain/mimetreeparser/interface.cpp b/framework/domain/mimetreeparser/interface.cpp
new file mode 100644
index 00000000..6a399015
--- /dev/null
+++ b/framework/domain/mimetreeparser/interface.cpp
@@ -0,0 +1,335 @@
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
22#include "stringhtmlwriter.h"
23#include "objecttreesource.h"
24
25#include <KMime/Content>
26#include <MimeTreeParser/ObjectTreeParser>
27#include <MimeTreeParser/MessagePart>
28#include <MimeTreeParser/NodeHelper>
29
30#include <QDebug>
31#include <QImage>
32
33class PartPrivate
34{
35public:
36 PartPrivate(Part *part);
37 void appendSubPart(Part::Ptr subpart);
38
39 QVector<Part::Ptr> subParts();
40
41 const std::weak_ptr<Part> &parent() const;
42private:
43 Part *q;
44 std::weak_ptr<Part> mParent;
45 QVector<Part::Ptr> mSubParts;
46};
47
48PartPrivate::PartPrivate(Part* part)
49 :q(part)
50{
51
52}
53
54void PartPrivate::appendSubPart(Part::Ptr subpart)
55{
56 subpart->d->mParent = Part::Ptr(q);
57 mSubParts.append(subpart);
58}
59
60const std::weak_ptr<Part> &PartPrivate::parent() const
61{
62 return mParent;
63}
64
65QVector< Part::Ptr > PartPrivate::subParts()
66{
67 return mSubParts;
68}
69
70Part::Part()
71 : d(std::unique_ptr<PartPrivate>(new PartPrivate(this)))
72{
73
74}
75
76bool Part::hasSubParts() const
77{
78 return !subParts().isEmpty();
79}
80
81QVector<Part::Ptr> Part::subParts() const
82{
83 return d->subParts();
84}
85
86QByteArray Part::type() const
87{
88 return "Part";
89}
90
91QVector<Encryption> Part::encryptions() const
92{
93 auto parent = d->parent().lock();
94 if (parent) {
95 return parent->encryptions();
96 } else {
97 return QVector<Encryption>();
98 }
99}
100
101QVector<Signature> Part::signatures() const
102{
103 auto parent = d->parent().lock();
104 if (parent) {
105 return parent->signatures();
106 } else {
107 return QVector<Signature>();
108 }
109}
110
111class ContentPrivate
112{
113public:
114 QByteArray mContent;
115 QByteArray mCodec;
116 Part *mParent;
117 Content *q;
118};
119
120Content::Content(const QByteArray& content, ContentPart *parent)
121 : d(std::unique_ptr<ContentPrivate>(new ContentPrivate))
122{
123 d->q = this;
124 d->mContent = content;
125 d->mCodec = "utf-8";
126 d->mParent = parent;
127}
128
129Content::~Content()
130{
131}
132
133QVector< Encryption > Content::encryptions() const
134{
135 if (d->mParent) {
136 return d->mParent->encryptions();
137 }
138 return QVector<Encryption>();
139}
140
141QVector< Signature > Content::signatures() const
142{
143 if (d->mParent) {
144 return d->mParent->signatures();
145 }
146 return QVector<Signature>();
147}
148
149class ContentPartPrivate
150{
151public:
152 void fillFrom(MimeTreeParser::TextMessagePart::Ptr part);
153 void fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part);
154 void fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part);
155
156 QVector<Content::Ptr> contents() const;
157
158 ContentPart *q;
159
160private:
161 QVector<Content::Ptr> mContents;
162 ContentPart::Types mTypes;
163};
164
165void ContentPartPrivate::fillFrom(MimeTreeParser::TextMessagePart::Ptr part)
166{
167 mTypes = ContentPart::PlainText;
168 foreach (const auto &mp, part->subParts()) {
169 auto content = std::make_shared<Content>(mp->text().toLocal8Bit(), q);
170 mContents.append(content);
171 }
172}
173
174void ContentPartPrivate::fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part)
175{
176 mTypes = ContentPart::Html;
177}
178
179void ContentPartPrivate::fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part)
180{
181 mTypes = ContentPart::Html | ContentPart::PlainText;
182}
183
184ContentPart::ContentPart()
185 : d(std::unique_ptr<ContentPartPrivate>(new ContentPartPrivate))
186{
187 d->q = this;
188}
189
190ContentPart::~ContentPart()
191{
192
193}
194
195QByteArray ContentPart::type() const
196{
197 return "ContentPart";
198}
199
200class MimePartPrivate
201{
202public:
203 void fillFrom(MimeTreeParser::MessagePart::Ptr part);
204};
205
206QByteArray MimePart::type() const
207{
208 return "MimePart";
209}
210
211class AttachmentPartPrivate
212{
213public:
214 void fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part);
215};
216
217void AttachmentPartPrivate::fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part)
218{
219
220}
221
222QByteArray AttachmentPart::type() const
223{
224 return "AttachmentPart";
225}
226
227class ParserPrivate
228{
229public:
230 ParserPrivate(Parser *parser);
231
232 void setMessage(const QByteArray &mimeMessage);
233 void createTree(MimeTreeParser::MessagePart::Ptr start, Part::Ptr tree);
234
235 Part::Ptr mTree;
236private:
237 Parser *q;
238
239 MimeTreeParser::MessagePart::Ptr mPartTree;
240 std::shared_ptr<MimeTreeParser::NodeHelper> mNodeHelper;
241 QString mHtml;
242 QMap<QByteArray, QUrl> mEmbeddedPartMap;
243};
244
245ParserPrivate::ParserPrivate(Parser* parser)
246 : q(parser)
247 , mNodeHelper(std::make_shared<MimeTreeParser::NodeHelper>())
248{
249
250}
251
252void ParserPrivate::setMessage(const QByteArray& mimeMessage)
253{
254 const auto mailData = KMime::CRLFtoLF(mimeMessage);
255 KMime::Message::Ptr msg(new KMime::Message);
256 msg->setContent(mailData);
257 msg->parse();
258
259 // render the mail
260 StringHtmlWriter htmlWriter;
261 QImage paintDevice;
262 ObjectTreeSource source(&htmlWriter);
263 MimeTreeParser::ObjectTreeParser otp(&source, mNodeHelper.get());
264
265 otp.parseObjectTree(msg.data());
266 mPartTree = otp.parsedPart().dynamicCast<MimeTreeParser::MessagePart>();
267
268 mEmbeddedPartMap = htmlWriter.embeddedParts();
269 mHtml = htmlWriter.html();
270
271 mTree = std::make_shared<Part>();
272 createTree(mPartTree, mTree);
273}
274
275
276void ParserPrivate::createTree(MimeTreeParser::MessagePart::Ptr start, Part::Ptr tree)
277{
278
279 foreach (const auto &mp, start->subParts()) {
280 const auto m = mp.dynamicCast<MimeTreeParser::MessagePart>();
281 const auto text = mp.dynamicCast<MimeTreeParser::TextMessagePart>();
282 const auto alternative = mp.dynamicCast<MimeTreeParser::AlternativeMessagePart>();
283 const auto html = mp.dynamicCast<MimeTreeParser::HtmlMessagePart>();
284 const auto attachment = mp.dynamicCast<MimeTreeParser::AttachmentMessagePart>();
285 if (text) {
286 auto part = std::make_shared<ContentPart>();
287 part->d->fillFrom(text);
288 mTree->d->appendSubPart(part);
289 } else if (alternative) {
290 auto part = std::make_shared<ContentPart>();
291 part->d->fillFrom(alternative);
292 mTree->d->appendSubPart(part);
293 } else if (html) {
294 auto part = std::make_shared<ContentPart>();
295 part->d->fillFrom(html);
296 mTree->d->appendSubPart(part);
297 } else if (attachment) {
298 auto part = std::make_shared<AttachmentPart>();
299 part->d->fillFrom(attachment);
300 mTree->d->appendSubPart(part);
301 } else {
302 createTree(m, tree);
303 }
304 }
305}
306
307Parser::Parser(const QByteArray& mimeMessage)
308 :d(std::unique_ptr<ParserPrivate>(new ParserPrivate(this)))
309{
310 d->setMessage(mimeMessage);
311}
312
313Parser::~Parser()
314{
315}
316
317ContentPart::Ptr Parser::collectContentPart(const Part::Ptr &start) const
318{
319 foreach (const auto &part, start->subParts()) {
320 if (part->type() == "ContentPart") {
321 return std::dynamic_pointer_cast<ContentPart>(part);
322 } else {
323 auto ret = collectContentPart(part);
324 if (ret) {
325 return ret;
326 }
327 }
328 }
329 return ContentPart::Ptr();
330}
331
332ContentPart::Ptr Parser::collectContentPart() const
333{
334 return collectContentPart(d->mTree);
335}