diff options
Diffstat (limited to 'framework/domain/mimetreeparser/interface.cpp')
-rw-r--r-- | framework/domain/mimetreeparser/interface.cpp | 335 |
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 | |||
33 | class PartPrivate | ||
34 | { | ||
35 | public: | ||
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; | ||
42 | private: | ||
43 | Part *q; | ||
44 | std::weak_ptr<Part> mParent; | ||
45 | QVector<Part::Ptr> mSubParts; | ||
46 | }; | ||
47 | |||
48 | PartPrivate::PartPrivate(Part* part) | ||
49 | :q(part) | ||
50 | { | ||
51 | |||
52 | } | ||
53 | |||
54 | void PartPrivate::appendSubPart(Part::Ptr subpart) | ||
55 | { | ||
56 | subpart->d->mParent = Part::Ptr(q); | ||
57 | mSubParts.append(subpart); | ||
58 | } | ||
59 | |||
60 | const std::weak_ptr<Part> &PartPrivate::parent() const | ||
61 | { | ||
62 | return mParent; | ||
63 | } | ||
64 | |||
65 | QVector< Part::Ptr > PartPrivate::subParts() | ||
66 | { | ||
67 | return mSubParts; | ||
68 | } | ||
69 | |||
70 | Part::Part() | ||
71 | : d(std::unique_ptr<PartPrivate>(new PartPrivate(this))) | ||
72 | { | ||
73 | |||
74 | } | ||
75 | |||
76 | bool Part::hasSubParts() const | ||
77 | { | ||
78 | return !subParts().isEmpty(); | ||
79 | } | ||
80 | |||
81 | QVector<Part::Ptr> Part::subParts() const | ||
82 | { | ||
83 | return d->subParts(); | ||
84 | } | ||
85 | |||
86 | QByteArray Part::type() const | ||
87 | { | ||
88 | return "Part"; | ||
89 | } | ||
90 | |||
91 | QVector<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 | |||
101 | QVector<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 | |||
111 | class ContentPrivate | ||
112 | { | ||
113 | public: | ||
114 | QByteArray mContent; | ||
115 | QByteArray mCodec; | ||
116 | Part *mParent; | ||
117 | Content *q; | ||
118 | }; | ||
119 | |||
120 | Content::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 | |||
129 | Content::~Content() | ||
130 | { | ||
131 | } | ||
132 | |||
133 | QVector< Encryption > Content::encryptions() const | ||
134 | { | ||
135 | if (d->mParent) { | ||
136 | return d->mParent->encryptions(); | ||
137 | } | ||
138 | return QVector<Encryption>(); | ||
139 | } | ||
140 | |||
141 | QVector< Signature > Content::signatures() const | ||
142 | { | ||
143 | if (d->mParent) { | ||
144 | return d->mParent->signatures(); | ||
145 | } | ||
146 | return QVector<Signature>(); | ||
147 | } | ||
148 | |||
149 | class ContentPartPrivate | ||
150 | { | ||
151 | public: | ||
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 | |||
160 | private: | ||
161 | QVector<Content::Ptr> mContents; | ||
162 | ContentPart::Types mTypes; | ||
163 | }; | ||
164 | |||
165 | void 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 | |||
174 | void ContentPartPrivate::fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part) | ||
175 | { | ||
176 | mTypes = ContentPart::Html; | ||
177 | } | ||
178 | |||
179 | void ContentPartPrivate::fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part) | ||
180 | { | ||
181 | mTypes = ContentPart::Html | ContentPart::PlainText; | ||
182 | } | ||
183 | |||
184 | ContentPart::ContentPart() | ||
185 | : d(std::unique_ptr<ContentPartPrivate>(new ContentPartPrivate)) | ||
186 | { | ||
187 | d->q = this; | ||
188 | } | ||
189 | |||
190 | ContentPart::~ContentPart() | ||
191 | { | ||
192 | |||
193 | } | ||
194 | |||
195 | QByteArray ContentPart::type() const | ||
196 | { | ||
197 | return "ContentPart"; | ||
198 | } | ||
199 | |||
200 | class MimePartPrivate | ||
201 | { | ||
202 | public: | ||
203 | void fillFrom(MimeTreeParser::MessagePart::Ptr part); | ||
204 | }; | ||
205 | |||
206 | QByteArray MimePart::type() const | ||
207 | { | ||
208 | return "MimePart"; | ||
209 | } | ||
210 | |||
211 | class AttachmentPartPrivate | ||
212 | { | ||
213 | public: | ||
214 | void fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part); | ||
215 | }; | ||
216 | |||
217 | void AttachmentPartPrivate::fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part) | ||
218 | { | ||
219 | |||
220 | } | ||
221 | |||
222 | QByteArray AttachmentPart::type() const | ||
223 | { | ||
224 | return "AttachmentPart"; | ||
225 | } | ||
226 | |||
227 | class ParserPrivate | ||
228 | { | ||
229 | public: | ||
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; | ||
236 | private: | ||
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 | |||
245 | ParserPrivate::ParserPrivate(Parser* parser) | ||
246 | : q(parser) | ||
247 | , mNodeHelper(std::make_shared<MimeTreeParser::NodeHelper>()) | ||
248 | { | ||
249 | |||
250 | } | ||
251 | |||
252 | void 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 | |||
276 | void 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 | |||
307 | Parser::Parser(const QByteArray& mimeMessage) | ||
308 | :d(std::unique_ptr<ParserPrivate>(new ParserPrivate(this))) | ||
309 | { | ||
310 | d->setMessage(mimeMessage); | ||
311 | } | ||
312 | |||
313 | Parser::~Parser() | ||
314 | { | ||
315 | } | ||
316 | |||
317 | ContentPart::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 | |||
332 | ContentPart::Ptr Parser::collectContentPart() const | ||
333 | { | ||
334 | return collectContentPart(d->mTree); | ||
335 | } | ||