diff options
Diffstat (limited to 'framework/src/domain/mime')
326 files changed, 27234 insertions, 0 deletions
diff --git a/framework/src/domain/mime/attachmentmodel.cpp b/framework/src/domain/mime/attachmentmodel.cpp new file mode 100644 index 00000000..e98c6fc0 --- /dev/null +++ b/framework/src/domain/mime/attachmentmodel.cpp | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <knauss@kolabsys.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 "messageparser.h" | ||
21 | #include "mimetreeparser/interface.h" | ||
22 | |||
23 | #include <QIcon> | ||
24 | #include <QDebug> | ||
25 | |||
26 | QString sizeHuman(const Content::Ptr &content) | ||
27 | { | ||
28 | float num = content->content().size(); | ||
29 | QStringList list; | ||
30 | list << "KB" << "MB" << "GB" << "TB"; | ||
31 | |||
32 | QStringListIterator i(list); | ||
33 | QString unit("Bytes"); | ||
34 | |||
35 | while(num >= 1024.0 && i.hasNext()) | ||
36 | { | ||
37 | unit = i.next(); | ||
38 | num /= 1024.0; | ||
39 | } | ||
40 | |||
41 | if (unit == "Bytes") { | ||
42 | return QString().setNum(num) + " " + unit; | ||
43 | } else { | ||
44 | return QString().setNum(num,'f',2)+" "+unit; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | class AttachmentModelPrivate | ||
49 | { | ||
50 | public: | ||
51 | AttachmentModelPrivate(AttachmentModel *q_ptr, const std::shared_ptr<Parser> &parser); | ||
52 | |||
53 | AttachmentModel *q; | ||
54 | std::shared_ptr<Parser> mParser; | ||
55 | QVector<Part::Ptr> mAttachments; | ||
56 | }; | ||
57 | |||
58 | AttachmentModelPrivate::AttachmentModelPrivate(AttachmentModel* q_ptr, const std::shared_ptr<Parser>& parser) | ||
59 | : q(q_ptr) | ||
60 | , mParser(parser) | ||
61 | { | ||
62 | mAttachments = mParser->collectAttachmentParts(); | ||
63 | } | ||
64 | |||
65 | AttachmentModel::AttachmentModel(std::shared_ptr<Parser> parser) | ||
66 | : d(std::unique_ptr<AttachmentModelPrivate>(new AttachmentModelPrivate(this, parser))) | ||
67 | { | ||
68 | } | ||
69 | |||
70 | AttachmentModel::~AttachmentModel() | ||
71 | { | ||
72 | } | ||
73 | |||
74 | QHash<int, QByteArray> AttachmentModel::roleNames() const | ||
75 | { | ||
76 | QHash<int, QByteArray> roles; | ||
77 | roles[TypeRole] = "type"; | ||
78 | roles[NameRole] = "name"; | ||
79 | roles[SizeRole] = "size"; | ||
80 | roles[IconRole] = "icon"; | ||
81 | roles[IsEncryptedRole] = "encrypted"; | ||
82 | roles[IsSignedRole] = "signed"; | ||
83 | return roles; | ||
84 | } | ||
85 | |||
86 | QModelIndex AttachmentModel::index(int row, int column, const QModelIndex &parent) const | ||
87 | { | ||
88 | if (row < 0 || column != 0) { | ||
89 | return QModelIndex(); | ||
90 | } | ||
91 | |||
92 | if (row < d->mAttachments.size()) { | ||
93 | return createIndex(row, column, d->mAttachments.at(row).get()); | ||
94 | } | ||
95 | return QModelIndex(); | ||
96 | } | ||
97 | |||
98 | QVariant AttachmentModel::data(const QModelIndex &index, int role) const | ||
99 | { | ||
100 | if (!index.isValid()) { | ||
101 | switch (role) { | ||
102 | case Qt::DisplayRole: | ||
103 | return QString("root"); | ||
104 | } | ||
105 | return QVariant(); | ||
106 | } | ||
107 | |||
108 | if (index.internalPointer()) { | ||
109 | const auto entry = static_cast<Part *>(index.internalPointer()); | ||
110 | const auto content = entry->content().at(0); | ||
111 | switch(role) { | ||
112 | case TypeRole: | ||
113 | return content->mailMime()->mimetype().name(); | ||
114 | case NameRole: | ||
115 | return entry->mailMime()->filename(); | ||
116 | case IconRole: | ||
117 | return QIcon::fromTheme(content->mailMime()->mimetype().iconName()); | ||
118 | case SizeRole: | ||
119 | return sizeHuman(content); | ||
120 | case IsEncryptedRole: | ||
121 | return content->encryptions().size() > 0; | ||
122 | case IsSignedRole: | ||
123 | return content->signatures().size() > 0; | ||
124 | } | ||
125 | } | ||
126 | return QVariant(); | ||
127 | } | ||
128 | |||
129 | QModelIndex AttachmentModel::parent(const QModelIndex &index) const | ||
130 | { | ||
131 | return QModelIndex(); | ||
132 | } | ||
133 | |||
134 | int AttachmentModel::rowCount(const QModelIndex &parent) const | ||
135 | { | ||
136 | if (!parent.isValid()) { | ||
137 | return d->mAttachments.size(); | ||
138 | } | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int AttachmentModel::columnCount(const QModelIndex &parent) const | ||
143 | { | ||
144 | return 1; | ||
145 | } | ||
diff --git a/framework/src/domain/mime/htmlutils.cpp b/framework/src/domain/mime/htmlutils.cpp new file mode 100644 index 00000000..156bcc48 --- /dev/null +++ b/framework/src/domain/mime/htmlutils.cpp | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | Copyright (c) 2017 Christian Mollekopf <mollekopf@kolabsys.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 | #include "htmlutils.h" | ||
20 | |||
21 | #include <QTextDocument> | ||
22 | |||
23 | static QString resolveEntities(const QString &in) | ||
24 | { | ||
25 | QString out; | ||
26 | |||
27 | for(int i = 0; i < (int)in.length(); ++i) { | ||
28 | if(in[i] == '&') { | ||
29 | // find a semicolon | ||
30 | ++i; | ||
31 | int n = in.indexOf(';', i); | ||
32 | if(n == -1) | ||
33 | break; | ||
34 | QString type = in.mid(i, (n-i)); | ||
35 | i = n; // should be n+1, but we'll let the loop increment do it | ||
36 | |||
37 | if(type == "amp") | ||
38 | out += '&'; | ||
39 | else if(type == "lt") | ||
40 | out += '<'; | ||
41 | else if(type == "gt") | ||
42 | out += '>'; | ||
43 | else if(type == "quot") | ||
44 | out += '\"'; | ||
45 | else if(type == "apos") | ||
46 | out += '\''; | ||
47 | else if(type == "nbsp") | ||
48 | out += 0xa0; | ||
49 | } else { | ||
50 | out += in[i]; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | return out; | ||
55 | } | ||
56 | |||
57 | |||
58 | static bool linkify_pmatch(const QString &str1, int at, const QString &str2) | ||
59 | { | ||
60 | if(str2.length() > (str1.length()-at)) | ||
61 | return false; | ||
62 | |||
63 | for(int n = 0; n < (int)str2.length(); ++n) { | ||
64 | if(str1.at(n+at).toLower() != str2.at(n).toLower()) | ||
65 | return false; | ||
66 | } | ||
67 | |||
68 | return true; | ||
69 | } | ||
70 | |||
71 | static bool linkify_isOneOf(const QChar &c, const QString &charlist) | ||
72 | { | ||
73 | for(int i = 0; i < (int)charlist.length(); ++i) { | ||
74 | if(c == charlist.at(i)) | ||
75 | return true; | ||
76 | } | ||
77 | |||
78 | return false; | ||
79 | } | ||
80 | |||
81 | // encodes a few dangerous html characters | ||
82 | static QString linkify_htmlsafe(const QString &in) | ||
83 | { | ||
84 | QString out; | ||
85 | |||
86 | for(int n = 0; n < in.length(); ++n) { | ||
87 | if(linkify_isOneOf(in.at(n), "\"\'`<>")) { | ||
88 | // hex encode | ||
89 | QString hex; | ||
90 | hex.sprintf("%%%02X", in.at(n).toLatin1()); | ||
91 | out.append(hex); | ||
92 | } else { | ||
93 | out.append(in.at(n)); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | return out; | ||
98 | } | ||
99 | |||
100 | static bool linkify_okUrl(const QString &url) | ||
101 | { | ||
102 | if(url.at(url.length()-1) == '.') | ||
103 | return false; | ||
104 | |||
105 | return true; | ||
106 | } | ||
107 | |||
108 | static bool linkify_okEmail(const QString &addy) | ||
109 | { | ||
110 | // this makes sure that there is an '@' and a '.' after it, and that there is | ||
111 | // at least one char for each of the three sections | ||
112 | int n = addy.indexOf('@'); | ||
113 | if(n == -1 || n == 0) | ||
114 | return false; | ||
115 | int d = addy.indexOf('.', n+1); | ||
116 | if(d == -1 || d == 0) | ||
117 | return false; | ||
118 | if((addy.length()-1) - d <= 0) | ||
119 | return false; | ||
120 | if(addy.indexOf("..") != -1) | ||
121 | return false; | ||
122 | |||
123 | return true; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * takes a richtext string and heuristically adds links for uris of common protocols | ||
128 | * @return a richtext string with link markup added | ||
129 | */ | ||
130 | QString HtmlUtils::linkify(const QString &in) | ||
131 | { | ||
132 | QString out = in; | ||
133 | int x1, x2; | ||
134 | bool isUrl, isAtStyle; | ||
135 | QString linked, link, href; | ||
136 | |||
137 | for(int n = 0; n < (int)out.length(); ++n) { | ||
138 | isUrl = false; | ||
139 | isAtStyle = false; | ||
140 | x1 = n; | ||
141 | |||
142 | if(linkify_pmatch(out, n, "xmpp:")) { | ||
143 | n += 5; | ||
144 | isUrl = true; | ||
145 | href = ""; | ||
146 | } | ||
147 | else if(linkify_pmatch(out, n, "mailto:")) { | ||
148 | n += 7; | ||
149 | isUrl = true; | ||
150 | href = ""; | ||
151 | } | ||
152 | else if(linkify_pmatch(out, n, "http://")) { | ||
153 | n += 7; | ||
154 | isUrl = true; | ||
155 | href = ""; | ||
156 | } | ||
157 | else if(linkify_pmatch(out, n, "https://")) { | ||
158 | n += 8; | ||
159 | isUrl = true; | ||
160 | href = ""; | ||
161 | } | ||
162 | else if(linkify_pmatch(out, n, "ftp://")) { | ||
163 | n += 6; | ||
164 | isUrl = true; | ||
165 | href = ""; | ||
166 | } | ||
167 | else if(linkify_pmatch(out, n, "news://")) { | ||
168 | n += 7; | ||
169 | isUrl = true; | ||
170 | href = ""; | ||
171 | } | ||
172 | else if (linkify_pmatch(out, n, "ed2k://")) { | ||
173 | n += 7; | ||
174 | isUrl = true; | ||
175 | href = ""; | ||
176 | } | ||
177 | else if (linkify_pmatch(out, n, "magnet:")) { | ||
178 | n += 7; | ||
179 | isUrl = true; | ||
180 | href = ""; | ||
181 | } | ||
182 | else if(linkify_pmatch(out, n, "www.")) { | ||
183 | isUrl = true; | ||
184 | href = "http://"; | ||
185 | } | ||
186 | else if(linkify_pmatch(out, n, "ftp.")) { | ||
187 | isUrl = true; | ||
188 | href = "ftp://"; | ||
189 | } | ||
190 | else if(linkify_pmatch(out, n, "@")) { | ||
191 | isAtStyle = true; | ||
192 | href = "x-psi-atstyle:"; | ||
193 | } | ||
194 | |||
195 | if(isUrl) { | ||
196 | // make sure the previous char is not alphanumeric | ||
197 | if(x1 > 0 && out.at(x1-1).isLetterOrNumber()) | ||
198 | continue; | ||
199 | |||
200 | // find whitespace (or end) | ||
201 | QMap<QChar, int> brackets; | ||
202 | brackets['('] = brackets[')'] = brackets['['] = brackets[']'] = brackets['{'] = brackets['}'] = 0; | ||
203 | QMap<QChar, QChar> openingBracket; | ||
204 | openingBracket[')'] = '('; | ||
205 | openingBracket[']'] = '['; | ||
206 | openingBracket['}'] = '{'; | ||
207 | for(x2 = n; x2 < (int)out.length(); ++x2) { | ||
208 | if(out.at(x2).isSpace() || linkify_isOneOf(out.at(x2), "\"\'`<>") | ||
209 | || linkify_pmatch(out, x2, """) || linkify_pmatch(out, x2, "'") | ||
210 | || linkify_pmatch(out, x2, ">") || linkify_pmatch(out, x2, "<") ) { | ||
211 | break; | ||
212 | } | ||
213 | if(brackets.keys().contains(out.at(x2))) { | ||
214 | ++brackets[out.at(x2)]; | ||
215 | } | ||
216 | } | ||
217 | int len = x2-x1; | ||
218 | QString pre = resolveEntities(out.mid(x1, x2-x1)); | ||
219 | |||
220 | // go backward hacking off unwanted punctuation | ||
221 | int cutoff; | ||
222 | for(cutoff = pre.length()-1; cutoff >= 0; --cutoff) { | ||
223 | if(!linkify_isOneOf(pre.at(cutoff), "!?,.()[]{}<>\"")) | ||
224 | break; | ||
225 | if(linkify_isOneOf(pre.at(cutoff), ")]}") | ||
226 | && brackets[pre.at(cutoff)] - brackets[openingBracket[pre.at(cutoff)]] <= 0 ) { | ||
227 | break; // in theory, there could be == above, but these are urls, not math ;) | ||
228 | } | ||
229 | if(brackets.keys().contains(pre.at(cutoff))) { | ||
230 | --brackets[pre.at(cutoff)]; | ||
231 | } | ||
232 | |||
233 | } | ||
234 | ++cutoff; | ||
235 | //++x2; | ||
236 | |||
237 | link = pre.mid(0, cutoff); | ||
238 | if(!linkify_okUrl(link)) { | ||
239 | n = x1 + link.length(); | ||
240 | continue; | ||
241 | } | ||
242 | href += link; | ||
243 | // attributes need to be encoded too. | ||
244 | href = href.toHtmlEscaped(); | ||
245 | href = linkify_htmlsafe(href); | ||
246 | //printf("link: [%s], href=[%s]\n", link.latin1(), href.latin1()); | ||
247 | linked = QString("<a href=\"%1\">").arg(href) + link.toHtmlEscaped() + "</a>" + pre.mid(cutoff).toHtmlEscaped(); | ||
248 | out.replace(x1, len, linked); | ||
249 | n = x1 + linked.length() - 1; | ||
250 | } else if(isAtStyle) { | ||
251 | // go backward till we find the beginning | ||
252 | if(x1 == 0) | ||
253 | continue; | ||
254 | --x1; | ||
255 | for(; x1 >= 0; --x1) { | ||
256 | if(!linkify_isOneOf(out.at(x1), "_.-+") && !out.at(x1).isLetterOrNumber()) | ||
257 | break; | ||
258 | } | ||
259 | ++x1; | ||
260 | |||
261 | // go forward till we find the end | ||
262 | x2 = n + 1; | ||
263 | for(; x2 < (int)out.length(); ++x2) { | ||
264 | if(!linkify_isOneOf(out.at(x2), "_.-+") && !out.at(x2).isLetterOrNumber()) | ||
265 | break; | ||
266 | } | ||
267 | |||
268 | int len = x2-x1; | ||
269 | link = out.mid(x1, len); | ||
270 | //link = resolveEntities(link); | ||
271 | |||
272 | if(!linkify_okEmail(link)) { | ||
273 | n = x1 + link.length(); | ||
274 | continue; | ||
275 | } | ||
276 | |||
277 | href += link; | ||
278 | //printf("link: [%s], href=[%s]\n", link.latin1(), href.latin1()); | ||
279 | linked = QString("<a href=\"%1\">").arg(href) + link + "</a>"; | ||
280 | out.replace(x1, len, linked); | ||
281 | n = x1 + linked.length() - 1; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | return out; | ||
286 | } | ||
diff --git a/framework/src/domain/mime/htmlutils.h b/framework/src/domain/mime/htmlutils.h new file mode 100644 index 00000000..b59da1dc --- /dev/null +++ b/framework/src/domain/mime/htmlutils.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | Copyright (c) 2017 Christian Mollekopf <mollekopf@kolabsys.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 | #pragma once | ||
20 | |||
21 | #include <QString> | ||
22 | |||
23 | namespace HtmlUtils { | ||
24 | QString linkify(const QString &in); | ||
25 | } | ||
diff --git a/framework/src/domain/mime/mailtemplates.cpp b/framework/src/domain/mime/mailtemplates.cpp new file mode 100644 index 00000000..254dbba3 --- /dev/null +++ b/framework/src/domain/mime/mailtemplates.cpp | |||
@@ -0,0 +1,840 @@ | |||
1 | /* | ||
2 | Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com | ||
3 | Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> | ||
4 | Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com> | ||
5 | |||
6 | This library is free software; you can redistribute it and/or modify it | ||
7 | under the terms of the GNU Library General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | This library is distributed in the hope that it will be useful, but WITHOUT | ||
12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | ||
14 | License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU Library General Public License | ||
17 | along with this library; see the file COPYING.LIB. If not, write to the | ||
18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
19 | 02110-1301, USA. | ||
20 | */ | ||
21 | #include "mailtemplates.h" | ||
22 | |||
23 | #include <functional> | ||
24 | #include <QByteArray> | ||
25 | #include <QList> | ||
26 | #include <QDebug> | ||
27 | #include <QWebEnginePage> | ||
28 | #include <QWebEngineProfile> | ||
29 | #include <QWebEngineSettings> | ||
30 | #include <QWebEngineScript> | ||
31 | #include <QSysInfo> | ||
32 | #include <QTextCodec> | ||
33 | |||
34 | #include <KCodecs/KCharsets> | ||
35 | #include <KMime/Types> | ||
36 | |||
37 | #include "stringhtmlwriter.h" | ||
38 | #include "objecttreesource.h" | ||
39 | |||
40 | #include <otp/objecttreeparser.h> | ||
41 | |||
42 | namespace KMime { | ||
43 | namespace Types { | ||
44 | static bool operator==(const KMime::Types::AddrSpec &left, const KMime::Types::AddrSpec &right) | ||
45 | { | ||
46 | return (left.asString() == right.asString()); | ||
47 | } | ||
48 | |||
49 | static bool operator==(const KMime::Types::Mailbox &left, const KMime::Types::Mailbox &right) | ||
50 | { | ||
51 | return (left.addrSpec().asString() == right.addrSpec().asString()); | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | |||
56 | static KMime::Types::Mailbox::List stripMyAddressesFromAddressList(const KMime::Types::Mailbox::List &list, const KMime::Types::AddrSpecList me) | ||
57 | { | ||
58 | KMime::Types::Mailbox::List addresses(list); | ||
59 | for (KMime::Types::Mailbox::List::Iterator it = addresses.begin(); it != addresses.end();) { | ||
60 | if (me.contains(it->addrSpec())) { | ||
61 | it = addresses.erase(it); | ||
62 | } else { | ||
63 | ++it; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | return addresses; | ||
68 | } | ||
69 | |||
70 | void initHeader(const KMime::Message::Ptr &message) | ||
71 | { | ||
72 | message->removeHeader<KMime::Headers::To>(); | ||
73 | message->removeHeader<KMime::Headers::Subject>(); | ||
74 | message->date()->setDateTime(QDateTime::currentDateTime()); | ||
75 | |||
76 | const QStringList extraInfo = QStringList() << QSysInfo::prettyProductName(); | ||
77 | message->userAgent()->fromUnicodeString(QString("%1/%2(%3)").arg(QString::fromLocal8Bit("Kube")).arg("0.1").arg(extraInfo.join(",")), "utf-8"); | ||
78 | // This will allow to change Content-Type: | ||
79 | message->contentType()->setMimeType("text/plain"); | ||
80 | } | ||
81 | |||
82 | QString replacePrefixes(const QString &str, const QStringList &prefixRegExps, | ||
83 | bool replace, const QString &newPrefix) | ||
84 | { | ||
85 | bool recognized = false; | ||
86 | // construct a big regexp that | ||
87 | // 1. is anchored to the beginning of str (sans whitespace) | ||
88 | // 2. matches at least one of the part regexps in prefixRegExps | ||
89 | QString bigRegExp = QStringLiteral("^(?:\\s+|(?:%1))+\\s*").arg(prefixRegExps.join(QStringLiteral(")|(?:"))); | ||
90 | QRegExp rx(bigRegExp, Qt::CaseInsensitive); | ||
91 | if (rx.isValid()) { | ||
92 | QString tmp = str; | ||
93 | if (rx.indexIn(tmp) == 0) { | ||
94 | recognized = true; | ||
95 | if (replace) { | ||
96 | return tmp.replace(0, rx.matchedLength(), newPrefix + QLatin1String(" ")); | ||
97 | } | ||
98 | } | ||
99 | } else { | ||
100 | qWarning() << "bigRegExp = \"" | ||
101 | << bigRegExp << "\"\n" | ||
102 | << "prefix regexp is invalid!"; | ||
103 | // try good ole Re/Fwd: | ||
104 | recognized = str.startsWith(newPrefix); | ||
105 | } | ||
106 | |||
107 | if (!recognized) { | ||
108 | return newPrefix + QLatin1String(" ") + str; | ||
109 | } else { | ||
110 | return str; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | QString cleanSubject(const KMime::Message::Ptr &msg, const QStringList &prefixRegExps, bool replace, const QString &newPrefix) | ||
115 | { | ||
116 | return replacePrefixes(msg->subject()->asUnicodeString(), prefixRegExps, replace, newPrefix); | ||
117 | } | ||
118 | |||
119 | QString forwardSubject(const KMime::Message::Ptr &msg) | ||
120 | { | ||
121 | bool replaceForwardPrefix = true; | ||
122 | QStringList forwardPrefixes; | ||
123 | forwardPrefixes << "Fwd:"; | ||
124 | forwardPrefixes << "FW:"; | ||
125 | return cleanSubject(msg, forwardPrefixes, replaceForwardPrefix, QStringLiteral("Fwd:")); | ||
126 | } | ||
127 | |||
128 | QString replySubject(const KMime::Message::Ptr &msg) | ||
129 | { | ||
130 | bool replaceReplyPrefix = true; | ||
131 | QStringList replyPrefixes; | ||
132 | //We're escaping the regex escape sequences. awesome | ||
133 | replyPrefixes << "Re\\\\s*:"; | ||
134 | replyPrefixes << "Re[\\\\d+\\\\]:"; | ||
135 | replyPrefixes << "Re\\\\d+:"; | ||
136 | return cleanSubject(msg, replyPrefixes, replaceReplyPrefix, QStringLiteral("Re:")); | ||
137 | } | ||
138 | |||
139 | QByteArray getRefStr(const KMime::Message::Ptr &msg) | ||
140 | { | ||
141 | QByteArray firstRef, lastRef, refStr, retRefStr; | ||
142 | int i, j; | ||
143 | |||
144 | if (auto hdr = msg->references(false)) { | ||
145 | refStr = hdr->as7BitString(false).trimmed(); | ||
146 | } | ||
147 | |||
148 | if (refStr.isEmpty()) { | ||
149 | return msg->messageID()->as7BitString(false); | ||
150 | } | ||
151 | |||
152 | i = refStr.indexOf('<'); | ||
153 | j = refStr.indexOf('>'); | ||
154 | firstRef = refStr.mid(i, j - i + 1); | ||
155 | if (!firstRef.isEmpty()) { | ||
156 | retRefStr = firstRef + ' '; | ||
157 | } | ||
158 | |||
159 | i = refStr.lastIndexOf('<'); | ||
160 | j = refStr.lastIndexOf('>'); | ||
161 | |||
162 | lastRef = refStr.mid(i, j - i + 1); | ||
163 | if (!lastRef.isEmpty() && lastRef != firstRef) { | ||
164 | retRefStr += lastRef + ' '; | ||
165 | } | ||
166 | |||
167 | retRefStr += msg->messageID()->as7BitString(false); | ||
168 | return retRefStr; | ||
169 | } | ||
170 | |||
171 | KMime::Content *createPlainPartContent(const KMime::Message::Ptr &msg, const QString &plainBody) | ||
172 | { | ||
173 | KMime::Content *textPart = new KMime::Content(msg.data()); | ||
174 | textPart->contentType()->setMimeType("text/plain"); | ||
175 | //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text | ||
176 | // QTextCodec *charset = selectCharset(m_charsets, plainBody); | ||
177 | // textPart->contentType()->setCharset(charset->name()); | ||
178 | textPart->contentType()->setCharset("utf-8"); | ||
179 | textPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit); | ||
180 | textPart->fromUnicodeString(plainBody); | ||
181 | return textPart; | ||
182 | } | ||
183 | |||
184 | KMime::Content *createMultipartAlternativeContent(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody) | ||
185 | { | ||
186 | KMime::Content *multipartAlternative = new KMime::Content(msg.data()); | ||
187 | multipartAlternative->contentType()->setMimeType("multipart/alternative"); | ||
188 | const QByteArray boundary = KMime::multiPartBoundary(); | ||
189 | multipartAlternative->contentType()->setBoundary(boundary); | ||
190 | |||
191 | KMime::Content *textPart = createPlainPartContent(msg, plainBody); | ||
192 | multipartAlternative->addContent(textPart); | ||
193 | |||
194 | KMime::Content *htmlPart = new KMime::Content(msg.data()); | ||
195 | htmlPart->contentType()->setMimeType("text/html"); | ||
196 | //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text | ||
197 | // QTextCodec *charset = selectCharset(m_charsets, htmlBody); | ||
198 | // htmlPart->contentType()->setCharset(charset->name()); | ||
199 | textPart->contentType()->setCharset("utf-8"); | ||
200 | htmlPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit); | ||
201 | htmlPart->fromUnicodeString(htmlBody); | ||
202 | multipartAlternative->addContent(htmlPart); | ||
203 | |||
204 | return multipartAlternative; | ||
205 | } | ||
206 | |||
207 | void addProcessedBodyToMessage(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody, bool forward) | ||
208 | { | ||
209 | //FIXME | ||
210 | // MessageCore::ImageCollector ic; | ||
211 | // ic.collectImagesFrom(mOrigMsg.data()); | ||
212 | |||
213 | // Now, delete the old content and set the new content, which | ||
214 | // is either only the new text or the new text with some attachments. | ||
215 | auto parts = msg->contents(); | ||
216 | foreach (KMime::Content *content, parts) { | ||
217 | msg->removeContent(content, true/*delete*/); | ||
218 | } | ||
219 | |||
220 | msg->contentType()->clear(); // to get rid of old boundary | ||
221 | |||
222 | const QByteArray boundary = KMime::multiPartBoundary(); | ||
223 | KMime::Content *const mainTextPart = | ||
224 | htmlBody.isEmpty() ? | ||
225 | createPlainPartContent(msg, plainBody) : | ||
226 | createMultipartAlternativeContent(msg, plainBody, htmlBody); | ||
227 | mainTextPart->assemble(); | ||
228 | |||
229 | KMime::Content *textPart = mainTextPart; | ||
230 | // if (!ic.images().empty()) { | ||
231 | // textPart = createMultipartRelated(ic, mainTextPart); | ||
232 | // textPart->assemble(); | ||
233 | // } | ||
234 | |||
235 | // If we have some attachments, create a multipart/mixed mail and | ||
236 | // add the normal body as well as the attachments | ||
237 | KMime::Content *mainPart = textPart; | ||
238 | //FIXME | ||
239 | // if (forward) { | ||
240 | // auto attachments = mOrigMsg->attachments(); | ||
241 | // attachments += mOtp->nodeHelper()->attachmentsOfExtraContents(); | ||
242 | // if (!attachments.isEmpty()) { | ||
243 | // mainPart = createMultipartMixed(attachments, textPart); | ||
244 | // mainPart->assemble(); | ||
245 | // } | ||
246 | // } | ||
247 | |||
248 | msg->setBody(mainPart->encodedBody()); | ||
249 | msg->setHeader(mainPart->contentType()); | ||
250 | msg->setHeader(mainPart->contentTransferEncoding()); | ||
251 | msg->assemble(); | ||
252 | msg->parse(); | ||
253 | } | ||
254 | |||
255 | QString plainToHtml(const QString &body) | ||
256 | { | ||
257 | QString str = body; | ||
258 | str = str.toHtmlEscaped(); | ||
259 | str.replace(QStringLiteral("\n"), QStringLiteral("<br />\n")); | ||
260 | return str; | ||
261 | } | ||
262 | |||
263 | //TODO implement this function using a DOM tree parser | ||
264 | void makeValidHtml(QString &body, const QString &headElement) | ||
265 | { | ||
266 | QRegExp regEx; | ||
267 | regEx.setMinimal(true); | ||
268 | regEx.setPattern(QStringLiteral("<html.*>")); | ||
269 | |||
270 | if (!body.isEmpty() && !body.contains(regEx)) { | ||
271 | regEx.setPattern(QStringLiteral("<body.*>")); | ||
272 | if (!body.contains(regEx)) { | ||
273 | body = QLatin1String("<body>") + body + QLatin1String("<br/></body>"); | ||
274 | } | ||
275 | regEx.setPattern(QStringLiteral("<head.*>")); | ||
276 | if (!body.contains(regEx)) { | ||
277 | body = QLatin1String("<head>") + headElement + QLatin1String("</head>") + body; | ||
278 | } | ||
279 | body = QLatin1String("<html>") + body + QLatin1String("</html>"); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | //FIXME strip signature works partially for HTML mails | ||
284 | QString stripSignature(const QString &msg) | ||
285 | { | ||
286 | // Following RFC 3676, only > before -- | ||
287 | // I prefer to not delete a SB instead of delete good mail content. | ||
288 | const QRegExp sbDelimiterSearch = QRegExp(QLatin1String("(^|\n)[> ]*-- \n")); | ||
289 | // The regular expression to look for prefix change | ||
290 | const QRegExp commonReplySearch = QRegExp(QLatin1String("^[ ]*>")); | ||
291 | |||
292 | QString res = msg; | ||
293 | int posDeletingStart = 1; // to start looking at 0 | ||
294 | |||
295 | // While there are SB delimiters (start looking just before the deleted SB) | ||
296 | while ((posDeletingStart = res.indexOf(sbDelimiterSearch, posDeletingStart - 1)) >= 0) { | ||
297 | QString prefix; // the current prefix | ||
298 | QString line; // the line to check if is part of the SB | ||
299 | int posNewLine = -1; | ||
300 | |||
301 | // Look for the SB beginning | ||
302 | int posSignatureBlock = res.indexOf(QLatin1Char('-'), posDeletingStart); | ||
303 | // The prefix before "-- "$ | ||
304 | if (res.at(posDeletingStart) == QLatin1Char('\n')) { | ||
305 | ++posDeletingStart; | ||
306 | } | ||
307 | |||
308 | prefix = res.mid(posDeletingStart, posSignatureBlock - posDeletingStart); | ||
309 | posNewLine = res.indexOf(QLatin1Char('\n'), posSignatureBlock) + 1; | ||
310 | |||
311 | // now go to the end of the SB | ||
312 | while (posNewLine < res.size() && posNewLine > 0) { | ||
313 | // handle the undefined case for mid ( x , -n ) where n>1 | ||
314 | int nextPosNewLine = res.indexOf(QLatin1Char('\n'), posNewLine); | ||
315 | |||
316 | if (nextPosNewLine < 0) { | ||
317 | nextPosNewLine = posNewLine - 1; | ||
318 | } | ||
319 | |||
320 | line = res.mid(posNewLine, nextPosNewLine - posNewLine); | ||
321 | |||
322 | // check when the SB ends: | ||
323 | // * does not starts with prefix or | ||
324 | // * starts with prefix+(any substring of prefix) | ||
325 | if ((prefix.isEmpty() && line.indexOf(commonReplySearch) < 0) || | ||
326 | (!prefix.isEmpty() && line.startsWith(prefix) && | ||
327 | line.mid(prefix.size()).indexOf(commonReplySearch) < 0)) { | ||
328 | posNewLine = res.indexOf(QLatin1Char('\n'), posNewLine) + 1; | ||
329 | } else { | ||
330 | break; // end of the SB | ||
331 | } | ||
332 | } | ||
333 | |||
334 | // remove the SB or truncate when is the last SB | ||
335 | if (posNewLine > 0) { | ||
336 | res.remove(posDeletingStart, posNewLine - posDeletingStart); | ||
337 | } else { | ||
338 | res.truncate(posDeletingStart); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | return res; | ||
343 | } | ||
344 | |||
345 | void setupPage(QWebEnginePage *page) | ||
346 | { | ||
347 | page->profile()->setHttpCacheType(QWebEngineProfile::MemoryHttpCache); | ||
348 | page->profile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies); | ||
349 | page->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false); | ||
350 | page->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, false); | ||
351 | page->settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false); | ||
352 | page->settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, false); | ||
353 | page->settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, false); | ||
354 | page->settings()->setAttribute(QWebEngineSettings::XSSAuditingEnabled, false); | ||
355 | page->settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); | ||
356 | page->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, false); | ||
357 | page->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, false); | ||
358 | page->settings()->setAttribute(QWebEngineSettings::HyperlinkAuditingEnabled, false); | ||
359 | page->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, false); | ||
360 | page->settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, false); | ||
361 | page->settings()->setAttribute(QWebEngineSettings::WebGLEnabled, false); | ||
362 | page->settings()->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, false); | ||
363 | page->settings()->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled, false); | ||
364 | page->settings()->setAttribute(QWebEngineSettings::WebGLEnabled, false); | ||
365 | |||
366 | #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) | ||
367 | page->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, false); | ||
368 | page->settings()->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, false); | ||
369 | #endif | ||
370 | } | ||
371 | |||
372 | void plainMessageText(const QString &plainTextContent, const QString &htmlContent, bool aStripSignature, const std::function<void(const QString &)> &callback) | ||
373 | { | ||
374 | QString result = plainTextContent; | ||
375 | if (plainTextContent.isEmpty()) { //HTML-only mails | ||
376 | auto page = new QWebEnginePage; | ||
377 | setupPage(page); | ||
378 | page->setHtml(htmlContent); | ||
379 | page->toPlainText([=] (const QString &plaintext) { | ||
380 | page->deleteLater(); | ||
381 | callback(plaintext); | ||
382 | }); | ||
383 | return; | ||
384 | } | ||
385 | |||
386 | if (aStripSignature) { | ||
387 | result = stripSignature(result); | ||
388 | } | ||
389 | callback(result); | ||
390 | } | ||
391 | |||
392 | QString extractHeaderBodyScript() | ||
393 | { | ||
394 | const QString source = QStringLiteral("(function() {" | ||
395 | "var res = {" | ||
396 | " body: document.getElementsByTagName('body')[0].innerHTML," | ||
397 | " header: document.getElementsByTagName('head')[0].innerHTML" | ||
398 | "};" | ||
399 | "return res;" | ||
400 | "})()"); | ||
401 | return source; | ||
402 | } | ||
403 | |||
404 | void htmlMessageText(const QString &plainTextContent, const QString &htmlContent, bool aStripSignature, const std::function<void(const QString &body, QString &head)> &callback) | ||
405 | { | ||
406 | QString htmlElement = htmlContent; | ||
407 | |||
408 | if (htmlElement.isEmpty()) { //plain mails only | ||
409 | QString htmlReplace = plainTextContent.toHtmlEscaped(); | ||
410 | htmlReplace = htmlReplace.replace(QStringLiteral("\n"), QStringLiteral("<br />")); | ||
411 | htmlElement = QStringLiteral("<html><head></head><body>%1</body></html>\n").arg(htmlReplace); | ||
412 | } | ||
413 | |||
414 | auto page = new QWebEnginePage; | ||
415 | setupPage(page); | ||
416 | |||
417 | page->setHtml(htmlElement); | ||
418 | page->runJavaScript(extractHeaderBodyScript(), QWebEngineScript::ApplicationWorld, [=](const QVariant &result){ | ||
419 | page->deleteLater(); | ||
420 | const QVariantMap map = result.toMap(); | ||
421 | auto bodyElement = map.value(QStringLiteral("body")).toString(); | ||
422 | auto headerElement = map.value(QStringLiteral("header")).toString(); | ||
423 | if (!bodyElement.isEmpty()) { | ||
424 | if (aStripSignature) { | ||
425 | callback(stripSignature(bodyElement), headerElement); | ||
426 | } | ||
427 | return callback(bodyElement, headerElement); | ||
428 | } | ||
429 | |||
430 | if (aStripSignature) { | ||
431 | return callback(stripSignature(htmlElement), headerElement); | ||
432 | } | ||
433 | return callback(htmlElement, headerElement); | ||
434 | }); | ||
435 | } | ||
436 | |||
437 | QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString) | ||
438 | { | ||
439 | QString result; | ||
440 | |||
441 | if (wildString.isEmpty()) { | ||
442 | return wildString; | ||
443 | } | ||
444 | |||
445 | unsigned int strLength(wildString.length()); | ||
446 | for (uint i = 0; i < strLength;) { | ||
447 | QChar ch = wildString[i++]; | ||
448 | if (ch == QLatin1Char('%') && i < strLength) { | ||
449 | ch = wildString[i++]; | ||
450 | switch (ch.toLatin1()) { | ||
451 | case 'f': { // sender's initals | ||
452 | if (fromDisplayString.isEmpty()) { | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | uint j = 0; | ||
457 | const unsigned int strLength(fromDisplayString.length()); | ||
458 | for (; j < strLength && fromDisplayString[j] > QLatin1Char(' '); ++j) | ||
459 | ; | ||
460 | for (; j < strLength && fromDisplayString[j] <= QLatin1Char(' '); ++j) | ||
461 | ; | ||
462 | result += fromDisplayString[0]; | ||
463 | if (j < strLength && fromDisplayString[j] > QLatin1Char(' ')) { | ||
464 | result += fromDisplayString[j]; | ||
465 | } else if (strLength > 1) { | ||
466 | if (fromDisplayString[1] > QLatin1Char(' ')) { | ||
467 | result += fromDisplayString[1]; | ||
468 | } | ||
469 | } | ||
470 | } | ||
471 | break; | ||
472 | case '_': | ||
473 | result += QLatin1Char(' '); | ||
474 | break; | ||
475 | case '%': | ||
476 | result += QLatin1Char('%'); | ||
477 | break; | ||
478 | default: | ||
479 | result += QLatin1Char('%'); | ||
480 | result += ch; | ||
481 | break; | ||
482 | } | ||
483 | } else { | ||
484 | result += ch; | ||
485 | } | ||
486 | } | ||
487 | return result; | ||
488 | } | ||
489 | |||
490 | QString quotedPlainText(const QString &selection, const QString &fromDisplayString) | ||
491 | { | ||
492 | QString content = selection; | ||
493 | // Remove blank lines at the beginning: | ||
494 | const int firstNonWS = content.indexOf(QRegExp(QLatin1String("\\S"))); | ||
495 | const int lineStart = content.lastIndexOf(QLatin1Char('\n'), firstNonWS); | ||
496 | if (lineStart >= 0) { | ||
497 | content.remove(0, static_cast<unsigned int>(lineStart)); | ||
498 | } | ||
499 | |||
500 | const auto quoteString = QStringLiteral("> "); | ||
501 | const QString indentStr = formatQuotePrefix(quoteString, fromDisplayString); | ||
502 | //FIXME | ||
503 | // if (TemplateParserSettings::self()->smartQuote() && mWrap) { | ||
504 | // content = MessageCore::StringUtil::smartQuote(content, mColWrap - indentStr.length()); | ||
505 | // } | ||
506 | content.replace(QLatin1Char('\n'), QLatin1Char('\n') + indentStr); | ||
507 | content.prepend(indentStr); | ||
508 | content += QLatin1Char('\n'); | ||
509 | |||
510 | return content; | ||
511 | } | ||
512 | |||
513 | QString quotedHtmlText(const QString &selection) | ||
514 | { | ||
515 | QString content = selection; | ||
516 | //TODO 1) look for all the variations of <br> and remove the blank lines | ||
517 | //2) implement vertical bar for quoted HTML mail. | ||
518 | //3) After vertical bar is implemented, If a user wants to edit quoted message, | ||
519 | // then the <blockquote> tags below should open and close as when required. | ||
520 | |||
521 | //Add blockquote tag, so that quoted message can be differentiated from normal message | ||
522 | content = QLatin1String("<blockquote>") + content + QLatin1String("</blockquote>"); | ||
523 | return content; | ||
524 | } | ||
525 | |||
526 | void applyCharset(const KMime::Message::Ptr msg, const KMime::Message::Ptr &origMsg) | ||
527 | { | ||
528 | // first convert the body from its current encoding to unicode representation | ||
529 | QTextCodec *bodyCodec = KCharsets::charsets()->codecForName(QString::fromLatin1(msg->contentType()->charset())); | ||
530 | if (!bodyCodec) { | ||
531 | bodyCodec = KCharsets::charsets()->codecForName(QStringLiteral("UTF-8")); | ||
532 | } | ||
533 | |||
534 | const QString body = bodyCodec->toUnicode(msg->body()); | ||
535 | |||
536 | // then apply the encoding of the original message | ||
537 | msg->contentType()->setCharset(origMsg->contentType()->charset()); | ||
538 | |||
539 | QTextCodec *codec = KCharsets::charsets()->codecForName(QString::fromLatin1(msg->contentType()->charset())); | ||
540 | if (!codec) { | ||
541 | qCritical() << "Could not get text codec for charset" << msg->contentType()->charset(); | ||
542 | } else if (!codec->canEncode(body)) { // charset can't encode body, fall back to preferred | ||
543 | const QStringList charsets /*= preferredCharsets() */; | ||
544 | |||
545 | QList<QByteArray> chars; | ||
546 | chars.reserve(charsets.count()); | ||
547 | foreach (const QString &charset, charsets) { | ||
548 | chars << charset.toLatin1(); | ||
549 | } | ||
550 | |||
551 | //FIXME | ||
552 | QByteArray fallbackCharset/* = selectCharset(chars, body)*/; | ||
553 | if (fallbackCharset.isEmpty()) { // UTF-8 as fall-through | ||
554 | fallbackCharset = "UTF-8"; | ||
555 | } | ||
556 | |||
557 | codec = KCharsets::charsets()->codecForName(QString::fromLatin1(fallbackCharset)); | ||
558 | msg->setBody(codec->fromUnicode(body)); | ||
559 | } else { | ||
560 | msg->setBody(codec->fromUnicode(body)); | ||
561 | } | ||
562 | } | ||
563 | |||
564 | enum ReplyStrategy { | ||
565 | ReplyList, | ||
566 | ReplySmart, | ||
567 | ReplyAll, | ||
568 | ReplyAuthor, | ||
569 | ReplyNone | ||
570 | }; | ||
571 | |||
572 | void MailTemplates::reply(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback) | ||
573 | { | ||
574 | //FIXME | ||
575 | const bool alwaysPlain = true; | ||
576 | //FIXME | ||
577 | const ReplyStrategy replyStrategy = ReplySmart; | ||
578 | KMime::Message::Ptr msg(new KMime::Message); | ||
579 | //FIXME | ||
580 | //Personal email addresses | ||
581 | KMime::Types::AddrSpecList me; | ||
582 | KMime::Types::Mailbox::List toList; | ||
583 | KMime::Types::Mailbox::List replyToList; | ||
584 | KMime::Types::Mailbox::List mailingListAddresses; | ||
585 | |||
586 | // const uint originalIdentity = identityUoid(origMsg); | ||
587 | initHeader(msg); | ||
588 | replyToList = origMsg->replyTo()->mailboxes(); | ||
589 | |||
590 | msg->contentType()->setCharset("utf-8"); | ||
591 | |||
592 | if (origMsg->headerByType("List-Post") && | ||
593 | origMsg->headerByType("List-Post")->asUnicodeString().contains(QStringLiteral("mailto:"), Qt::CaseInsensitive)) { | ||
594 | |||
595 | const QString listPost = origMsg->headerByType("List-Post")->asUnicodeString(); | ||
596 | QRegExp rx(QStringLiteral("<mailto:([^@>]+)@([^>]+)>"), Qt::CaseInsensitive); | ||
597 | if (rx.indexIn(listPost, 0) != -1) { // matched | ||
598 | KMime::Types::Mailbox mailbox; | ||
599 | mailbox.fromUnicodeString(rx.cap(1) + QLatin1Char('@') + rx.cap(2)); | ||
600 | mailingListAddresses << mailbox; | ||
601 | } | ||
602 | } | ||
603 | |||
604 | switch (replyStrategy) { | ||
605 | case ReplySmart: { | ||
606 | if (auto hdr = origMsg->headerByType("Mail-Followup-To")) { | ||
607 | toList << KMime::Types::Mailbox::listFrom7BitString(hdr->as7BitString(false)); | ||
608 | } else if (!replyToList.isEmpty()) { | ||
609 | toList = replyToList; | ||
610 | } else if (!mailingListAddresses.isEmpty()) { | ||
611 | toList = (KMime::Types::Mailbox::List() << mailingListAddresses.at(0)); | ||
612 | } else { | ||
613 | // doesn't seem to be a mailing list, reply to From: address | ||
614 | toList = origMsg->from()->mailboxes(); | ||
615 | |||
616 | bool listContainsMe = false; | ||
617 | for (const auto &m : me) { | ||
618 | KMime::Types::Mailbox mailbox; | ||
619 | mailbox.setAddress(m); | ||
620 | if (toList.contains(mailbox)) { | ||
621 | listContainsMe = true; | ||
622 | } | ||
623 | } | ||
624 | if (listContainsMe) { | ||
625 | // sender seems to be one of our own identities, so we assume that this | ||
626 | // is a reply to a "sent" mail where the users wants to add additional | ||
627 | // information for the recipient. | ||
628 | toList = origMsg->to()->mailboxes(); | ||
629 | } | ||
630 | } | ||
631 | // strip all my addresses from the list of recipients | ||
632 | const KMime::Types::Mailbox::List recipients = toList; | ||
633 | |||
634 | toList = stripMyAddressesFromAddressList(recipients, me); | ||
635 | |||
636 | // ... unless the list contains only my addresses (reply to self) | ||
637 | if (toList.isEmpty() && !recipients.isEmpty()) { | ||
638 | toList << recipients.first(); | ||
639 | } | ||
640 | } | ||
641 | break; | ||
642 | case ReplyList: { | ||
643 | if (auto hdr = origMsg->headerByType("Mail-Followup-To")) { | ||
644 | KMime::Types::Mailbox mailbox; | ||
645 | mailbox.from7BitString(hdr->as7BitString(false)); | ||
646 | toList << mailbox; | ||
647 | } else if (!mailingListAddresses.isEmpty()) { | ||
648 | toList << mailingListAddresses[ 0 ]; | ||
649 | } else if (!replyToList.isEmpty()) { | ||
650 | // assume a Reply-To header mangling mailing list | ||
651 | toList = replyToList; | ||
652 | } | ||
653 | |||
654 | //FIXME | ||
655 | // strip all my addresses from the list of recipients | ||
656 | const KMime::Types::Mailbox::List recipients = toList; | ||
657 | toList = stripMyAddressesFromAddressList(recipients, me); | ||
658 | } | ||
659 | break; | ||
660 | case ReplyAll: { | ||
661 | KMime::Types::Mailbox::List recipients; | ||
662 | KMime::Types::Mailbox::List ccRecipients; | ||
663 | |||
664 | // add addresses from the Reply-To header to the list of recipients | ||
665 | if (!replyToList.isEmpty()) { | ||
666 | recipients = replyToList; | ||
667 | |||
668 | // strip all possible mailing list addresses from the list of Reply-To addresses | ||
669 | foreach (const KMime::Types::Mailbox &mailbox, mailingListAddresses) { | ||
670 | foreach (const KMime::Types::Mailbox &recipient, recipients) { | ||
671 | if (mailbox == recipient) { | ||
672 | recipients.removeAll(recipient); | ||
673 | } | ||
674 | } | ||
675 | } | ||
676 | } | ||
677 | |||
678 | if (!mailingListAddresses.isEmpty()) { | ||
679 | // this is a mailing list message | ||
680 | if (recipients.isEmpty() && !origMsg->from()->asUnicodeString().isEmpty()) { | ||
681 | // The sender didn't set a Reply-to address, so we add the From | ||
682 | // address to the list of CC recipients. | ||
683 | ccRecipients += origMsg->from()->mailboxes(); | ||
684 | qDebug() << "Added" << origMsg->from()->asUnicodeString() << "to the list of CC recipients"; | ||
685 | } | ||
686 | |||
687 | // if it is a mailing list, add the posting address | ||
688 | recipients.prepend(mailingListAddresses[ 0 ]); | ||
689 | } else { | ||
690 | // this is a normal message | ||
691 | if (recipients.isEmpty() && !origMsg->from()->asUnicodeString().isEmpty()) { | ||
692 | // in case of replying to a normal message only then add the From | ||
693 | // address to the list of recipients if there was no Reply-to address | ||
694 | recipients += origMsg->from()->mailboxes(); | ||
695 | qDebug() << "Added" << origMsg->from()->asUnicodeString() << "to the list of recipients"; | ||
696 | } | ||
697 | } | ||
698 | |||
699 | // strip all my addresses from the list of recipients | ||
700 | toList = stripMyAddressesFromAddressList(recipients, me); | ||
701 | |||
702 | // merge To header and CC header into a list of CC recipients | ||
703 | if (!origMsg->cc()->asUnicodeString().isEmpty() || !origMsg->to()->asUnicodeString().isEmpty()) { | ||
704 | KMime::Types::Mailbox::List list; | ||
705 | if (!origMsg->to()->asUnicodeString().isEmpty()) { | ||
706 | list += origMsg->to()->mailboxes(); | ||
707 | } | ||
708 | if (!origMsg->cc()->asUnicodeString().isEmpty()) { | ||
709 | list += origMsg->cc()->mailboxes(); | ||
710 | } | ||
711 | |||
712 | foreach (const KMime::Types::Mailbox &mailbox, list) { | ||
713 | if (!recipients.contains(mailbox) && | ||
714 | !ccRecipients.contains(mailbox)) { | ||
715 | ccRecipients += mailbox; | ||
716 | qDebug() << "Added" << mailbox.prettyAddress() << "to the list of CC recipients"; | ||
717 | } | ||
718 | } | ||
719 | } | ||
720 | |||
721 | if (!ccRecipients.isEmpty()) { | ||
722 | // strip all my addresses from the list of CC recipients | ||
723 | ccRecipients = stripMyAddressesFromAddressList(ccRecipients, me); | ||
724 | |||
725 | // in case of a reply to self, toList might be empty. if that's the case | ||
726 | // then propagate a cc recipient to To: (if there is any). | ||
727 | if (toList.isEmpty() && !ccRecipients.isEmpty()) { | ||
728 | toList << ccRecipients.at(0); | ||
729 | ccRecipients.pop_front(); | ||
730 | } | ||
731 | |||
732 | foreach (const KMime::Types::Mailbox &mailbox, ccRecipients) { | ||
733 | msg->cc()->addAddress(mailbox); | ||
734 | } | ||
735 | } | ||
736 | |||
737 | if (toList.isEmpty() && !recipients.isEmpty()) { | ||
738 | // reply to self without other recipients | ||
739 | toList << recipients.at(0); | ||
740 | } | ||
741 | } | ||
742 | break; | ||
743 | case ReplyAuthor: { | ||
744 | if (!replyToList.isEmpty()) { | ||
745 | KMime::Types::Mailbox::List recipients = replyToList; | ||
746 | |||
747 | // strip the mailing list post address from the list of Reply-To | ||
748 | // addresses since we want to reply in private | ||
749 | foreach (const KMime::Types::Mailbox &mailbox, mailingListAddresses) { | ||
750 | foreach (const KMime::Types::Mailbox &recipient, recipients) { | ||
751 | if (mailbox == recipient) { | ||
752 | recipients.removeAll(recipient); | ||
753 | } | ||
754 | } | ||
755 | } | ||
756 | |||
757 | if (!recipients.isEmpty()) { | ||
758 | toList = recipients; | ||
759 | } else { | ||
760 | // there was only the mailing list post address in the Reply-To header, | ||
761 | // so use the From address instead | ||
762 | toList = origMsg->from()->mailboxes(); | ||
763 | } | ||
764 | } else if (!origMsg->from()->asUnicodeString().isEmpty()) { | ||
765 | toList = origMsg->from()->mailboxes(); | ||
766 | } | ||
767 | } | ||
768 | break; | ||
769 | case ReplyNone: | ||
770 | // the addressees will be set by the caller | ||
771 | break; | ||
772 | } | ||
773 | |||
774 | foreach (const KMime::Types::Mailbox &mailbox, toList) { | ||
775 | msg->to()->addAddress(mailbox); | ||
776 | } | ||
777 | |||
778 | const QByteArray refStr = getRefStr(origMsg); | ||
779 | if (!refStr.isEmpty()) { | ||
780 | msg->references()->fromUnicodeString(QString::fromLocal8Bit(refStr), "utf-8"); | ||
781 | } | ||
782 | |||
783 | //In-Reply-To = original msg-id | ||
784 | msg->inReplyTo()->from7BitString(origMsg->messageID()->as7BitString(false)); | ||
785 | |||
786 | msg->subject()->fromUnicodeString(replySubject(origMsg), "utf-8"); | ||
787 | |||
788 | auto definedLocale = QLocale::system(); | ||
789 | |||
790 | //TODO set empty source instead | ||
791 | StringHtmlWriter htmlWriter; | ||
792 | MimeTreeParser::NodeHelper nodeHelper; | ||
793 | ObjectTreeSource source(&htmlWriter); | ||
794 | MimeTreeParser::ObjectTreeParser otp(&source, &nodeHelper); | ||
795 | otp.setAllowAsync(false); | ||
796 | otp.parseObjectTree(origMsg.data()); | ||
797 | |||
798 | //Add quoted body | ||
799 | QString plainBody; | ||
800 | QString htmlBody; | ||
801 | |||
802 | //On $datetime you wrote: | ||
803 | const QDateTime date = origMsg->date()->dateTime(); | ||
804 | const auto dateTimeString = QString("%1 %2").arg(definedLocale.toString(date.date(), QLocale::LongFormat)).arg(definedLocale.toString(date.time(), QLocale::LongFormat)); | ||
805 | const auto onDateYouWroteLine = QString("On %1 you wrote:").arg(dateTimeString); | ||
806 | plainBody.append(onDateYouWroteLine); | ||
807 | htmlBody.append(plainToHtml(onDateYouWroteLine)); | ||
808 | |||
809 | //Strip signature for replies | ||
810 | const bool stripSignature = true; | ||
811 | |||
812 | const auto plainTextContent = otp.plainTextContent(); | ||
813 | const auto htmlContent = otp.htmlContent(); | ||
814 | |||
815 | plainMessageText(plainTextContent, htmlContent, stripSignature, [=] (const QString &body) { | ||
816 | //Quoted body | ||
817 | QString plainQuote = quotedPlainText(body, origMsg->from()->displayString()); | ||
818 | if (plainQuote.endsWith(QLatin1Char('\n'))) { | ||
819 | plainQuote.chop(1); | ||
820 | } | ||
821 | //The plain body is complete | ||
822 | auto plainBodyResult = plainBody + plainQuote; | ||
823 | htmlMessageText(plainTextContent, htmlContent, stripSignature, [=] (const QString &body, const QString &headElement) { | ||
824 | //The html body is complete | ||
825 | auto htmlBodyResult = htmlBody + quotedHtmlText(body); | ||
826 | if (alwaysPlain) { | ||
827 | htmlBodyResult.clear(); | ||
828 | } else { | ||
829 | makeValidHtml(htmlBodyResult, headElement); | ||
830 | } | ||
831 | |||
832 | //Assemble the message | ||
833 | addProcessedBodyToMessage(msg, plainBodyResult, htmlBodyResult, false); | ||
834 | applyCharset(msg, origMsg); | ||
835 | msg->assemble(); | ||
836 | //We're done | ||
837 | callback(msg); | ||
838 | }); | ||
839 | }); | ||
840 | } | ||
diff --git a/framework/src/domain/mime/mailtemplates.h b/framework/src/domain/mime/mailtemplates.h new file mode 100644 index 00000000..db269c96 --- /dev/null +++ b/framework/src/domain/mime/mailtemplates.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.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 | #pragma once | ||
21 | |||
22 | #include <QByteArray> | ||
23 | #include <KMime/Message> | ||
24 | #include <functional> | ||
25 | |||
26 | namespace MailTemplates | ||
27 | { | ||
28 | void reply(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback); | ||
29 | }; | ||
diff --git a/framework/src/domain/mime/messageparser.cpp b/framework/src/domain/mime/messageparser.cpp new file mode 100644 index 00000000..76c060f0 --- /dev/null +++ b/framework/src/domain/mime/messageparser.cpp | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.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 | #include "messageparser.h" | ||
20 | |||
21 | #include "modeltest.h" | ||
22 | #include "mimetreeparser/interface.h" | ||
23 | |||
24 | #include <QDebug> | ||
25 | |||
26 | class MessagePartPrivate | ||
27 | { | ||
28 | public: | ||
29 | std::shared_ptr<Parser> mParser; | ||
30 | }; | ||
31 | |||
32 | MessageParser::MessageParser(QObject *parent) | ||
33 | : QObject(parent) | ||
34 | , d(std::unique_ptr<MessagePartPrivate>(new MessagePartPrivate)) | ||
35 | { | ||
36 | |||
37 | } | ||
38 | |||
39 | MessageParser::~MessageParser() | ||
40 | { | ||
41 | |||
42 | } | ||
43 | |||
44 | QVariant MessageParser::message() const | ||
45 | { | ||
46 | return QVariant(); | ||
47 | } | ||
48 | |||
49 | void MessageParser::setMessage(const QVariant &message) | ||
50 | { | ||
51 | d->mParser = std::shared_ptr<Parser>(new Parser(message.toByteArray())); | ||
52 | emit htmlChanged(); | ||
53 | } | ||
54 | |||
55 | QAbstractItemModel *MessageParser::newTree() const | ||
56 | { | ||
57 | if (!d->mParser) { | ||
58 | return nullptr; | ||
59 | } | ||
60 | const auto model = new NewModel(d->mParser); | ||
61 | // new ModelTest(model, model); | ||
62 | return model; | ||
63 | } | ||
64 | |||
65 | QAbstractItemModel *MessageParser::attachments() const | ||
66 | { | ||
67 | if (!d->mParser) { | ||
68 | return nullptr; | ||
69 | } | ||
70 | const auto model = new AttachmentModel(d->mParser); | ||
71 | // new ModelTest(model, model); | ||
72 | return model; | ||
73 | } | ||
diff --git a/framework/src/domain/mime/messageparser.h b/framework/src/domain/mime/messageparser.h new file mode 100644 index 00000000..de4d8838 --- /dev/null +++ b/framework/src/domain/mime/messageparser.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.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 | #pragma once | ||
21 | |||
22 | #include <QObject> | ||
23 | #include <QString> | ||
24 | #include <QStringList> | ||
25 | |||
26 | #include <QAbstractItemModel> | ||
27 | #include <QModelIndex> | ||
28 | |||
29 | #include <memory> | ||
30 | |||
31 | class QAbstractItemModel; | ||
32 | |||
33 | class Parser; | ||
34 | class MessagePartPrivate; | ||
35 | |||
36 | class NewModelPrivate; | ||
37 | class AttachmentModelPrivate; | ||
38 | |||
39 | class MessageParser : public QObject | ||
40 | { | ||
41 | Q_OBJECT | ||
42 | Q_PROPERTY (QVariant message READ message WRITE setMessage) | ||
43 | Q_PROPERTY (QAbstractItemModel* newTree READ newTree NOTIFY htmlChanged) | ||
44 | Q_PROPERTY (QAbstractItemModel* attachments READ attachments NOTIFY htmlChanged) | ||
45 | |||
46 | public: | ||
47 | explicit MessageParser(QObject *parent = Q_NULLPTR); | ||
48 | ~MessageParser(); | ||
49 | |||
50 | QVariant message() const; | ||
51 | void setMessage(const QVariant &to); | ||
52 | QAbstractItemModel *newTree() const; | ||
53 | QAbstractItemModel *attachments() const; | ||
54 | |||
55 | signals: | ||
56 | void htmlChanged(); | ||
57 | |||
58 | private: | ||
59 | std::unique_ptr<MessagePartPrivate> d; | ||
60 | }; | ||
61 | |||
62 | class NewModel : public QAbstractItemModel { | ||
63 | Q_OBJECT | ||
64 | public: | ||
65 | NewModel(std::shared_ptr<Parser> parser); | ||
66 | ~NewModel(); | ||
67 | |||
68 | public: | ||
69 | enum Roles { | ||
70 | TypeRole = Qt::UserRole + 1, | ||
71 | ContentsRole, | ||
72 | ContentRole, | ||
73 | IsComplexHtmlContentRole, | ||
74 | IsEmbededRole, | ||
75 | SecurityLevelRole, | ||
76 | EncryptionErrorType, | ||
77 | EncryptionErrorString | ||
78 | }; | ||
79 | |||
80 | QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; | ||
81 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
82 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; | ||
83 | QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; | ||
84 | int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
85 | int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
86 | |||
87 | private: | ||
88 | std::unique_ptr<NewModelPrivate> d; | ||
89 | }; | ||
90 | |||
91 | class AttachmentModel : public QAbstractItemModel { | ||
92 | Q_OBJECT | ||
93 | public: | ||
94 | AttachmentModel(std::shared_ptr<Parser> parser); | ||
95 | ~AttachmentModel(); | ||
96 | |||
97 | public: | ||
98 | enum Roles { | ||
99 | TypeRole = Qt::UserRole + 1, | ||
100 | IconRole, | ||
101 | NameRole, | ||
102 | SizeRole, | ||
103 | IsEncryptedRole, | ||
104 | IsSignedRole | ||
105 | }; | ||
106 | |||
107 | QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; | ||
108 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
109 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; | ||
110 | QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; | ||
111 | int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
112 | int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
113 | |||
114 | private: | ||
115 | std::unique_ptr<AttachmentModelPrivate> d; | ||
116 | }; | ||
diff --git a/framework/src/domain/mime/messageparser_new.cpp b/framework/src/domain/mime/messageparser_new.cpp new file mode 100644 index 00000000..7e7dbfa6 --- /dev/null +++ b/framework/src/domain/mime/messageparser_new.cpp | |||
@@ -0,0 +1,513 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <knauss@kolabsys.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 "messageparser.h" | ||
21 | #include "mimetreeparser/interface.h" | ||
22 | #include "htmlutils.h" | ||
23 | |||
24 | #include <QDebug> | ||
25 | #include <QTextDocument> | ||
26 | |||
27 | Q_DECLARE_METATYPE(Part *) | ||
28 | Q_DECLARE_METATYPE(Content *) | ||
29 | Q_DECLARE_METATYPE(Signature *) | ||
30 | Q_DECLARE_METATYPE(Encryption *) | ||
31 | |||
32 | class Entry; | ||
33 | |||
34 | class NewModelPrivate | ||
35 | { | ||
36 | public: | ||
37 | NewModelPrivate(NewModel *q_ptr, const std::shared_ptr<Parser> &parser); | ||
38 | ~NewModelPrivate(); | ||
39 | |||
40 | void createTree(); | ||
41 | |||
42 | QSharedPointer<QVariant> getVar(const std::shared_ptr<Signature> &sig); | ||
43 | QSharedPointer<QVariant> getVar(const std::shared_ptr<Encryption> &enc); | ||
44 | QSharedPointer<QVariant> getVar(const std::shared_ptr<Part> &part); | ||
45 | QSharedPointer<QVariant> getVar(Part *part); | ||
46 | QSharedPointer<QVariant> getVar(const std::shared_ptr<Content> &content); | ||
47 | QSharedPointer<QVariant> getVar(Content *content); | ||
48 | |||
49 | int getPos(Signature *sig); | ||
50 | int getPos(Encryption *enc); | ||
51 | int getPos(Part *part); | ||
52 | int getPos(Content *content); | ||
53 | |||
54 | NewModel *q; | ||
55 | QVector<Part::Ptr> mParts; | ||
56 | std::unique_ptr<Entry> mRoot; | ||
57 | |||
58 | std::shared_ptr<Parser> mParser; | ||
59 | private: | ||
60 | QMap<std::shared_ptr<Signature>, QSharedPointer<QVariant>> mSignatureMap; | ||
61 | QMap<std::shared_ptr<Encryption>, QSharedPointer<QVariant>> mEncryptionMap; | ||
62 | QMap<Part *, QSharedPointer<QVariant>> mPartMap; | ||
63 | QMap<Content *, QSharedPointer<QVariant>> mCMap; | ||
64 | }; | ||
65 | |||
66 | class Entry | ||
67 | { | ||
68 | public: | ||
69 | Entry(NewModelPrivate *model) | ||
70 | : mParent(nullptr) | ||
71 | , mNewModelPrivate(model) | ||
72 | { | ||
73 | } | ||
74 | |||
75 | ~Entry() | ||
76 | { | ||
77 | foreach(auto child, mChildren) { | ||
78 | delete child; | ||
79 | } | ||
80 | mChildren.clear(); | ||
81 | } | ||
82 | |||
83 | void addChild(Entry *entry) | ||
84 | { | ||
85 | mChildren.append(entry); | ||
86 | entry->mParent = this; | ||
87 | } | ||
88 | |||
89 | Entry *addSignatures(QVector<Signature::Ptr> signatures) | ||
90 | { | ||
91 | auto ret = this; | ||
92 | foreach(const auto &sig, signatures) { | ||
93 | auto entry = new Entry(mNewModelPrivate); | ||
94 | entry->mData = mNewModelPrivate->getVar(sig); | ||
95 | ret->addChild(entry); | ||
96 | ret = entry; | ||
97 | } | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | Entry *addEncryptions(QVector<Encryption::Ptr> encryptions) | ||
102 | { | ||
103 | auto ret = this; | ||
104 | foreach(const auto &enc, encryptions) { | ||
105 | auto entry = new Entry(mNewModelPrivate); | ||
106 | entry->mData = mNewModelPrivate->getVar(enc); | ||
107 | ret->addChild(entry); | ||
108 | ret = entry; | ||
109 | } | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | Entry *addPart(Part *part) | ||
114 | { | ||
115 | auto entry = new Entry(mNewModelPrivate); | ||
116 | entry->mData = mNewModelPrivate->getVar(part); | ||
117 | addChild(entry); | ||
118 | |||
119 | foreach(const auto &content, part->content()) { | ||
120 | auto _entry = entry; | ||
121 | _entry = _entry->addEncryptions(content->encryptions().mid(part->encryptions().size())); | ||
122 | _entry = _entry->addSignatures(content->signatures().mid(part->signatures().size())); | ||
123 | auto c = new Entry(mNewModelPrivate); | ||
124 | c->mData = mNewModelPrivate->getVar(content); | ||
125 | _entry->addChild(c); | ||
126 | } | ||
127 | // foreach(const auto &content, part->availableContents()) { | ||
128 | // foreach(const auto &contentPart, part->content(content)) { | ||
129 | // auto _entry = entry; | ||
130 | // _entry = _entry->addEncryptions(contentPart->encryptions().mid(part->encryptions().size())); | ||
131 | // _entry = _entry->addSignatures(contentPart->signatures().mid(part->signatures().size())); | ||
132 | // auto c = new Entry(mNewModelPrivate); | ||
133 | // c->mData = mNewModelPrivate->getVar(contentPart); | ||
134 | // _entry->addChild(c); | ||
135 | // } | ||
136 | // } | ||
137 | foreach(const auto &sp, part->subParts()) { | ||
138 | auto _entry = entry; | ||
139 | _entry = _entry->addEncryptions(sp->encryptions().mid(part->encryptions().size())); | ||
140 | _entry = _entry->addSignatures(sp->signatures().mid(part->signatures().size())); | ||
141 | _entry->addPart(sp.get()); | ||
142 | } | ||
143 | return entry; | ||
144 | } | ||
145 | |||
146 | int pos() | ||
147 | { | ||
148 | if(!mParent) { | ||
149 | return -1; | ||
150 | } | ||
151 | int i=0; | ||
152 | foreach(const auto &child, mParent->mChildren) { | ||
153 | if (child == this) { | ||
154 | return i; | ||
155 | } | ||
156 | i++; | ||
157 | } | ||
158 | return -1; | ||
159 | } | ||
160 | |||
161 | QSharedPointer<QVariant> mData; | ||
162 | |||
163 | Entry *mParent; | ||
164 | QVector<Entry *> mChildren; | ||
165 | NewModelPrivate *mNewModelPrivate; | ||
166 | }; | ||
167 | |||
168 | |||
169 | NewModelPrivate::NewModelPrivate(NewModel *q_ptr, const std::shared_ptr<Parser> &parser) | ||
170 | : q(q_ptr) | ||
171 | , mRoot(std::unique_ptr<Entry>(new Entry(this))) | ||
172 | , mParser(parser) | ||
173 | { | ||
174 | mParts = mParser->collectContentParts(); | ||
175 | createTree(); | ||
176 | } | ||
177 | |||
178 | NewModelPrivate::~NewModelPrivate() | ||
179 | { | ||
180 | } | ||
181 | |||
182 | void NewModelPrivate::createTree() | ||
183 | { | ||
184 | auto root = mRoot.get(); | ||
185 | auto parent = root; | ||
186 | Part *pPart = nullptr; | ||
187 | QVector<Signature::Ptr> signatures; | ||
188 | QVector<Encryption::Ptr> encryptions; | ||
189 | foreach(const auto part, mParts) { | ||
190 | auto _parent = parent; | ||
191 | if (pPart != part->parent()) { | ||
192 | auto _parent = root; | ||
193 | _parent = _parent->addEncryptions(part->parent()->encryptions()); | ||
194 | _parent = _parent->addSignatures(part->parent()->signatures()); | ||
195 | signatures = part->parent()->signatures(); | ||
196 | encryptions = part->parent()->encryptions(); | ||
197 | parent = _parent; | ||
198 | pPart = part->parent(); | ||
199 | } | ||
200 | _parent = _parent->addEncryptions(part->encryptions().mid(encryptions.size())); | ||
201 | _parent = _parent->addSignatures(part->signatures().mid(signatures.size())); | ||
202 | _parent->addPart(part.get()); | ||
203 | } | ||
204 | } | ||
205 | |||
206 | QSharedPointer<QVariant> NewModelPrivate::getVar(const std::shared_ptr<Signature> &sig) | ||
207 | { | ||
208 | if (!mSignatureMap.contains(sig)) { | ||
209 | auto var = new QVariant(); | ||
210 | var->setValue(sig.get()); | ||
211 | mSignatureMap.insert(sig, QSharedPointer<QVariant>(var)); | ||
212 | } | ||
213 | return mSignatureMap.value(sig); | ||
214 | } | ||
215 | |||
216 | QSharedPointer<QVariant> NewModelPrivate::getVar(const std::shared_ptr<Encryption> &enc) | ||
217 | { | ||
218 | if (!mEncryptionMap.contains(enc)) { | ||
219 | auto var = new QVariant(); | ||
220 | var->setValue(enc.get()); | ||
221 | mEncryptionMap.insert(enc, QSharedPointer<QVariant>(var)); | ||
222 | } | ||
223 | return mEncryptionMap.value(enc); | ||
224 | } | ||
225 | |||
226 | QSharedPointer<QVariant> NewModelPrivate::getVar(const std::shared_ptr<Part> &part) | ||
227 | { | ||
228 | return getVar(part.get()); | ||
229 | } | ||
230 | |||
231 | QSharedPointer<QVariant> NewModelPrivate::getVar(Part *part) | ||
232 | { | ||
233 | if (!mPartMap.contains(part)) { | ||
234 | auto var = new QVariant(); | ||
235 | var->setValue(part); | ||
236 | mPartMap.insert(part, QSharedPointer<QVariant>(var)); | ||
237 | } | ||
238 | return mPartMap.value(part); | ||
239 | } | ||
240 | |||
241 | QSharedPointer<QVariant> NewModelPrivate::getVar(const std::shared_ptr<Content> &content) | ||
242 | { | ||
243 | return getVar(content.get()); | ||
244 | } | ||
245 | |||
246 | QSharedPointer<QVariant> NewModelPrivate::getVar(Content *content) | ||
247 | { | ||
248 | if (!mCMap.contains(content)) { | ||
249 | auto var = new QVariant(); | ||
250 | var->setValue(content); | ||
251 | mCMap.insert(content, QSharedPointer<QVariant>(var)); | ||
252 | } | ||
253 | return mCMap.value(content); | ||
254 | } | ||
255 | |||
256 | int NewModelPrivate::getPos(Signature *signature) | ||
257 | { | ||
258 | const auto first = mParts.first(); | ||
259 | int i = 0; | ||
260 | foreach(const auto &sig, first->signatures()) { | ||
261 | if (sig.get() == signature) { | ||
262 | break; | ||
263 | } | ||
264 | i++; | ||
265 | } | ||
266 | return i; | ||
267 | } | ||
268 | |||
269 | int NewModelPrivate::getPos(Encryption *encryption) | ||
270 | { | ||
271 | const auto first = mParts.first(); | ||
272 | int i = 0; | ||
273 | foreach(const auto &enc, first->encryptions()) { | ||
274 | if (enc.get() == encryption) { | ||
275 | break; | ||
276 | } | ||
277 | i++; | ||
278 | } | ||
279 | return i; | ||
280 | } | ||
281 | |||
282 | int NewModelPrivate::getPos(Part *part) | ||
283 | { | ||
284 | int i = 0; | ||
285 | foreach(const auto &p, mParts) { | ||
286 | if (p.get() == part) { | ||
287 | break; | ||
288 | } | ||
289 | i++; | ||
290 | } | ||
291 | return i; | ||
292 | } | ||
293 | |||
294 | int NewModelPrivate::getPos(Content *content) | ||
295 | { | ||
296 | int i = 0; | ||
297 | foreach(const auto &c, content->parent()->content()) { | ||
298 | if (c.get() == content) { | ||
299 | break; | ||
300 | } | ||
301 | i++; | ||
302 | } | ||
303 | return i; | ||
304 | } | ||
305 | |||
306 | NewModel::NewModel(std::shared_ptr<Parser> parser) | ||
307 | : d(std::unique_ptr<NewModelPrivate>(new NewModelPrivate(this, parser))) | ||
308 | { | ||
309 | } | ||
310 | |||
311 | NewModel::~NewModel() | ||
312 | { | ||
313 | } | ||
314 | |||
315 | QHash<int, QByteArray> NewModel::roleNames() const | ||
316 | { | ||
317 | QHash<int, QByteArray> roles; | ||
318 | roles[TypeRole] = "type"; | ||
319 | roles[ContentRole] = "content"; | ||
320 | roles[IsComplexHtmlContentRole] = "complexHtmlContent"; | ||
321 | roles[IsEmbededRole] = "embeded"; | ||
322 | roles[SecurityLevelRole] = "securityLevel"; | ||
323 | roles[EncryptionErrorType] = "errorType"; | ||
324 | roles[EncryptionErrorString] = "errorString"; | ||
325 | return roles; | ||
326 | } | ||
327 | |||
328 | QModelIndex NewModel::index(int row, int column, const QModelIndex &parent) const | ||
329 | { | ||
330 | if (row < 0 || column != 0) { | ||
331 | return QModelIndex(); | ||
332 | } | ||
333 | Entry *entry = d->mRoot.get(); | ||
334 | if (parent.isValid()) { | ||
335 | entry = static_cast<Entry *>(parent.internalPointer()); | ||
336 | } | ||
337 | |||
338 | if (row < entry->mChildren.size()) { | ||
339 | return createIndex(row, column, entry->mChildren.at(row)); | ||
340 | } | ||
341 | return QModelIndex(); | ||
342 | } | ||
343 | |||
344 | QVariant NewModel::data(const QModelIndex &index, int role) const | ||
345 | { | ||
346 | if (!index.isValid()) { | ||
347 | switch (role) { | ||
348 | case Qt::DisplayRole: | ||
349 | return QString("root"); | ||
350 | case IsEmbededRole: | ||
351 | return false; | ||
352 | } | ||
353 | return QVariant(); | ||
354 | } | ||
355 | |||
356 | if (index.internalPointer()) { | ||
357 | const auto entry = static_cast<Entry *>(index.internalPointer()); | ||
358 | const auto _data = entry->mData; | ||
359 | if (entry == d->mRoot.get()|| !_data) { | ||
360 | switch (role) { | ||
361 | case Qt::DisplayRole: | ||
362 | return QString("root"); | ||
363 | case IsEmbededRole: | ||
364 | return false; | ||
365 | } | ||
366 | return QVariant(); | ||
367 | } | ||
368 | if (_data->userType() == qMetaTypeId<Signature *>()) { | ||
369 | const auto signature = _data->value<Signature *>(); | ||
370 | int i = d->getPos(signature); | ||
371 | switch(role) { | ||
372 | case Qt::DisplayRole: | ||
373 | return QStringLiteral("Signature%1").arg(i); | ||
374 | case TypeRole: | ||
375 | return QStringLiteral("Signature"); | ||
376 | case SecurityLevelRole: | ||
377 | return QStringLiteral("RED"); | ||
378 | case IsEmbededRole: | ||
379 | return data(index.parent(), IsEmbededRole); | ||
380 | } | ||
381 | } else if (_data->userType() == qMetaTypeId<Encryption *>()) { | ||
382 | const auto encryption = _data->value<Encryption *>(); | ||
383 | int i = d->getPos(encryption); | ||
384 | switch(role) { | ||
385 | case Qt::DisplayRole: | ||
386 | return QStringLiteral("Encryption%1").arg(i); | ||
387 | case TypeRole: | ||
388 | return QStringLiteral("Encryption"); | ||
389 | case SecurityLevelRole: | ||
390 | return QStringLiteral("GREEN"); | ||
391 | case IsEmbededRole: | ||
392 | return data(index.parent(), IsEmbededRole); | ||
393 | case EncryptionErrorType: | ||
394 | { | ||
395 | switch(encryption->errorType()) { | ||
396 | case Encryption::NoError: | ||
397 | return QString(); | ||
398 | case Encryption::PassphraseError: | ||
399 | return QStringLiteral("PassphraseError"); | ||
400 | case Encryption::KeyMissing: | ||
401 | return QStringLiteral("KeyMissing"); | ||
402 | default: | ||
403 | return QStringLiteral("UnknownError"); | ||
404 | } | ||
405 | } | ||
406 | case EncryptionErrorString: | ||
407 | return encryption->errorString(); | ||
408 | } | ||
409 | } else if (_data->userType() == qMetaTypeId<Part *>()) { | ||
410 | const auto part = _data->value<Part *>(); | ||
411 | switch (role) { | ||
412 | case Qt::DisplayRole: | ||
413 | case TypeRole: | ||
414 | return QString::fromLatin1(part->type()); | ||
415 | case IsEmbededRole: | ||
416 | return data(index.parent(), IsEmbededRole); | ||
417 | } | ||
418 | } else if (_data->userType() == qMetaTypeId<Content *>()) { | ||
419 | const auto content = _data->value<Content *>(); | ||
420 | int i = d->getPos(content); | ||
421 | switch(role) { | ||
422 | case Qt::DisplayRole: | ||
423 | return QStringLiteral("Content%1").arg(i); | ||
424 | case TypeRole: | ||
425 | return QString::fromLatin1(content->type()); | ||
426 | case IsEmbededRole: | ||
427 | return data(index.parent(), IsEmbededRole); | ||
428 | case IsComplexHtmlContentRole: { | ||
429 | const auto contentType = data(index, TypeRole).toString(); | ||
430 | if (contentType == "HtmlContent") { | ||
431 | const auto text = content->encodedContent(); | ||
432 | if (text.contains("<!DOCTYPE html PUBLIC")) { | ||
433 | return true; | ||
434 | } | ||
435 | //Media queries are too advanced | ||
436 | if (text.contains("@media")) { | ||
437 | return true; | ||
438 | } | ||
439 | if (text.contains("<style")) { | ||
440 | return true; | ||
441 | } | ||
442 | return false; | ||
443 | } else { | ||
444 | return false; | ||
445 | } | ||
446 | break; | ||
447 | } | ||
448 | case ContentRole: { | ||
449 | auto text = content->encodedContent(); | ||
450 | const auto contentType = data(index, TypeRole).toString(); | ||
451 | if (contentType == "HtmlContent") { | ||
452 | const auto rx = QRegExp("(src)\\s*=\\s*(\"|')(cid:[^\"']+)\\2"); | ||
453 | int pos = 0; | ||
454 | while ((pos = rx.indexIn(text, pos)) != -1) { | ||
455 | const auto link = QUrl(rx.cap(3).toUtf8()); | ||
456 | pos += rx.matchedLength(); | ||
457 | const auto repl = d->mParser->getPart(link); | ||
458 | if (!repl) { | ||
459 | continue; | ||
460 | } | ||
461 | const auto content = repl->content(); | ||
462 | if(content.size() < 1) { | ||
463 | continue; | ||
464 | } | ||
465 | const auto mailMime = content.first()->mailMime(); | ||
466 | const auto mimetype = mailMime->mimetype().name(); | ||
467 | if (mimetype.startsWith("image/")) { | ||
468 | const auto data = content.first()->content(); | ||
469 | text.replace(rx.cap(0), QString("src=\"data:%1;base64,%2\"").arg(mimetype, QString::fromLatin1(data.toBase64()))); | ||
470 | } | ||
471 | } | ||
472 | } else { //We assume plain | ||
473 | //We alwas do richtext (so we get highlighted links and stuff). | ||
474 | return HtmlUtils::linkify(Qt::convertFromPlainText(text)); | ||
475 | } | ||
476 | return text; | ||
477 | } | ||
478 | } | ||
479 | } | ||
480 | } | ||
481 | return QVariant(); | ||
482 | } | ||
483 | |||
484 | QModelIndex NewModel::parent(const QModelIndex &index) const | ||
485 | { | ||
486 | if (!index.internalPointer()) { | ||
487 | return QModelIndex(); | ||
488 | } | ||
489 | const auto entry = static_cast<Entry *>(index.internalPointer()); | ||
490 | if (entry->mParent && entry->mParent != d->mRoot.get()) { | ||
491 | return createIndex(entry->pos(), 0, entry->mParent); | ||
492 | } | ||
493 | return QModelIndex(); | ||
494 | } | ||
495 | |||
496 | int NewModel::rowCount(const QModelIndex &parent) const | ||
497 | { | ||
498 | if (!parent.isValid()) { | ||
499 | return d->mRoot->mChildren.size(); | ||
500 | } else { | ||
501 | if (!parent.internalPointer()) { | ||
502 | return 0; | ||
503 | } | ||
504 | const auto entry = static_cast<Entry *>(parent.internalPointer()); | ||
505 | return entry->mChildren.size(); | ||
506 | } | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | int NewModel::columnCount(const QModelIndex &parent) const | ||
511 | { | ||
512 | return 1; | ||
513 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/CMakeLists.txt b/framework/src/domain/mime/mimetreeparser/CMakeLists.txt new file mode 100644 index 00000000..517fb7e5 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/CMakeLists.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | include_directories(.) | ||
2 | |||
3 | set(mimetreeparser_SRCS | ||
4 | interface.cpp | ||
5 | objecttreesource.cpp | ||
6 | stringhtmlwriter.cpp | ||
7 | ) | ||
8 | |||
9 | add_library(mimetreeparser SHARED ${mimetreeparser_SRCS}) | ||
10 | |||
11 | qt5_use_modules(mimetreeparser Core Gui) | ||
12 | target_link_libraries(mimetreeparser KF5::Mime kube_otp) | ||
13 | |||
14 | install(TARGETS mimetreeparser DESTINATION ${LIB_INSTALL_DIR}) | ||
15 | |||
16 | add_subdirectory(tests) | ||
17 | add_subdirectory(otp) | ||
diff --git a/framework/src/domain/mime/mimetreeparser/interface.cpp b/framework/src/domain/mime/mimetreeparser/interface.cpp new file mode 100644 index 00000000..b8556336 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/interface.cpp | |||
@@ -0,0 +1,1179 @@ | |||
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 <QGpgME/KeyListJob> | ||
27 | #include <QGpgME/Protocol> | ||
28 | #include <gpgme++/key.h> | ||
29 | #include <gpgme++/keylistresult.h> | ||
30 | |||
31 | #include <KMime/Content> | ||
32 | #include <otp/objecttreeparser.h> | ||
33 | #include <otp/messagepart.h> | ||
34 | #include <otp/nodehelper.h> | ||
35 | |||
36 | #include <QMimeDatabase> | ||
37 | #include <QMimeType> | ||
38 | #include <QTextCodec> | ||
39 | #include <QDebug> | ||
40 | |||
41 | class MailMimePrivate | ||
42 | { | ||
43 | public: | ||
44 | MailMimePrivate(MailMime *p); | ||
45 | |||
46 | MailMime *q; | ||
47 | KMime::Content *mNode; | ||
48 | std::shared_ptr<MailMime> parent; | ||
49 | }; | ||
50 | |||
51 | MailMimePrivate::MailMimePrivate(MailMime* p) | ||
52 | : q(p) | ||
53 | , mNode(nullptr) | ||
54 | , parent(nullptr) | ||
55 | { | ||
56 | } | ||
57 | |||
58 | |||
59 | MailMime::MailMime() | ||
60 | : d(std::unique_ptr<MailMimePrivate>(new MailMimePrivate(this))) | ||
61 | { | ||
62 | } | ||
63 | |||
64 | QByteArray MailMime::cid() const | ||
65 | { | ||
66 | if (!d->mNode || !d->mNode->contentID()) { | ||
67 | return QByteArray(); | ||
68 | } | ||
69 | return d->mNode->contentID()->identifier(); | ||
70 | } | ||
71 | |||
72 | QByteArray MailMime::charset() const | ||
73 | { | ||
74 | if(!d->mNode || !d->mNode->contentType(false)) { | ||
75 | return QByteArray(); | ||
76 | } | ||
77 | if (d->mNode->contentType(false)) { | ||
78 | return d->mNode->contentType(false)->charset(); | ||
79 | } | ||
80 | return d->mNode->defaultCharset(); | ||
81 | } | ||
82 | |||
83 | bool MailMime::isFirstTextPart() const | ||
84 | { | ||
85 | if (!d->mNode || !d->mNode->topLevel()) { | ||
86 | return false; | ||
87 | } | ||
88 | return (d->mNode->topLevel()->textContent() == d->mNode); | ||
89 | } | ||
90 | |||
91 | bool MailMime::isFirstPart() const | ||
92 | { | ||
93 | if (!d->mNode || !d->mNode->parent()) { | ||
94 | return false; | ||
95 | } | ||
96 | return (d->mNode->parent()->contents().first() == d->mNode); | ||
97 | } | ||
98 | |||
99 | bool MailMime::isTopLevelPart() const | ||
100 | { | ||
101 | if (!d->mNode) { | ||
102 | return false; | ||
103 | } | ||
104 | return (d->mNode->topLevel() == d->mNode); | ||
105 | } | ||
106 | |||
107 | MailMime::Disposition MailMime::disposition() const | ||
108 | { | ||
109 | if (!d->mNode) { | ||
110 | return Invalid; | ||
111 | } | ||
112 | const auto cd = d->mNode->contentDisposition(false); | ||
113 | if (!cd) { | ||
114 | return Invalid; | ||
115 | } | ||
116 | switch (cd->disposition()){ | ||
117 | case KMime::Headers::CDinline: | ||
118 | return Inline; | ||
119 | case KMime::Headers::CDattachment: | ||
120 | return Attachment; | ||
121 | default: | ||
122 | return Invalid; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | QString MailMime::filename() const | ||
127 | { | ||
128 | if (!d->mNode) { | ||
129 | return QString(); | ||
130 | } | ||
131 | const auto cd = d->mNode->contentDisposition(false); | ||
132 | if (!cd) { | ||
133 | return QString(); | ||
134 | } | ||
135 | return cd->filename(); | ||
136 | } | ||
137 | |||
138 | QMimeType MailMime::mimetype() const | ||
139 | { | ||
140 | if (!d->mNode) { | ||
141 | return QMimeType(); | ||
142 | } | ||
143 | |||
144 | const auto ct = d->mNode->contentType(false); | ||
145 | if (!ct) { | ||
146 | return QMimeType(); | ||
147 | } | ||
148 | |||
149 | QMimeDatabase mimeDb; | ||
150 | return mimeDb.mimeTypeForName(ct->mimeType()); | ||
151 | } | ||
152 | |||
153 | MailMime::Ptr MailMime::parent() const | ||
154 | { | ||
155 | if (!d->parent) { | ||
156 | d->parent = std::shared_ptr<MailMime>(new MailMime()); | ||
157 | d->parent->d->mNode = d->mNode->parent(); | ||
158 | } | ||
159 | return d->parent; | ||
160 | } | ||
161 | |||
162 | QByteArray MailMime::decodedContent() const | ||
163 | { | ||
164 | if (!d->mNode) { | ||
165 | return QByteArray(); | ||
166 | } | ||
167 | return d->mNode->decodedContent(); | ||
168 | } | ||
169 | |||
170 | class KeyPrivate | ||
171 | { | ||
172 | public: | ||
173 | Key *q; | ||
174 | GpgME::Key mKey; | ||
175 | QByteArray mKeyID; | ||
176 | }; | ||
177 | |||
178 | Key::Key() | ||
179 | :d(std::unique_ptr<KeyPrivate>(new KeyPrivate)) | ||
180 | { | ||
181 | d->q = this; | ||
182 | } | ||
183 | |||
184 | |||
185 | Key::Key(KeyPrivate *d_ptr) | ||
186 | :d(std::unique_ptr<KeyPrivate>(d_ptr)) | ||
187 | { | ||
188 | d->q = this; | ||
189 | } | ||
190 | |||
191 | Key::~Key() | ||
192 | { | ||
193 | |||
194 | } | ||
195 | |||
196 | QString Key::keyid() const | ||
197 | { | ||
198 | if (!d->mKey.isNull()) { | ||
199 | return d->mKey.keyID(); | ||
200 | } | ||
201 | |||
202 | return d->mKeyID; | ||
203 | } | ||
204 | |||
205 | QString Key::name() const | ||
206 | { | ||
207 | //FIXME: is this the correct way to get the primary UID? | ||
208 | if (!d->mKey.isNull()) { | ||
209 | return d->mKey.userID(0).name(); | ||
210 | } | ||
211 | |||
212 | return QString(); | ||
213 | } | ||
214 | |||
215 | QString Key::email() const | ||
216 | { | ||
217 | if (!d->mKey.isNull()) { | ||
218 | return d->mKey.userID(0).email(); | ||
219 | } | ||
220 | return QString(); | ||
221 | } | ||
222 | |||
223 | QString Key::comment() const | ||
224 | { | ||
225 | if (!d->mKey.isNull()) { | ||
226 | return d->mKey.userID(0).comment(); | ||
227 | } | ||
228 | return QString(); | ||
229 | } | ||
230 | |||
231 | class SignaturePrivate | ||
232 | { | ||
233 | public: | ||
234 | Signature *q; | ||
235 | GpgME::Signature mSignature; | ||
236 | Key::Ptr mKey; | ||
237 | }; | ||
238 | |||
239 | Signature::Signature() | ||
240 | :d(std::unique_ptr<SignaturePrivate>(new SignaturePrivate)) | ||
241 | { | ||
242 | d->q = this; | ||
243 | } | ||
244 | |||
245 | |||
246 | Signature::Signature(SignaturePrivate *d_ptr) | ||
247 | :d(std::unique_ptr<SignaturePrivate>(d_ptr)) | ||
248 | { | ||
249 | d->q = this; | ||
250 | } | ||
251 | |||
252 | Signature::~Signature() | ||
253 | { | ||
254 | |||
255 | } | ||
256 | |||
257 | QDateTime Signature::creationDateTime() const | ||
258 | { | ||
259 | QDateTime dt; | ||
260 | dt.setTime_t(d->mSignature.creationTime()); | ||
261 | return dt; | ||
262 | } | ||
263 | |||
264 | QDateTime Signature::expirationDateTime() const | ||
265 | { | ||
266 | QDateTime dt; | ||
267 | dt.setTime_t(d->mSignature.expirationTime()); | ||
268 | return dt; | ||
269 | } | ||
270 | |||
271 | bool Signature::neverExpires() const | ||
272 | { | ||
273 | return d->mSignature.neverExpires(); | ||
274 | } | ||
275 | |||
276 | Key::Ptr Signature::key() const | ||
277 | { | ||
278 | return d->mKey; | ||
279 | } | ||
280 | |||
281 | class EncryptionPrivate | ||
282 | { | ||
283 | public: | ||
284 | Encryption *q; | ||
285 | std::vector<Key::Ptr> mRecipients; | ||
286 | Encryption::ErrorType mErrorType; | ||
287 | QString mErrorString; | ||
288 | }; | ||
289 | |||
290 | Encryption::Encryption(EncryptionPrivate *d_ptr) | ||
291 | :d(std::unique_ptr<EncryptionPrivate>(d_ptr)) | ||
292 | { | ||
293 | d->q = this; | ||
294 | } | ||
295 | |||
296 | Encryption::Encryption() | ||
297 | :d(std::unique_ptr<EncryptionPrivate>(new EncryptionPrivate)) | ||
298 | { | ||
299 | d->q = this; | ||
300 | d->mErrorType = Encryption::NoError; | ||
301 | } | ||
302 | |||
303 | Encryption::~Encryption() | ||
304 | { | ||
305 | |||
306 | } | ||
307 | |||
308 | std::vector<Key::Ptr> Encryption::recipients() const | ||
309 | { | ||
310 | return d->mRecipients; | ||
311 | } | ||
312 | |||
313 | QString Encryption::errorString() | ||
314 | { | ||
315 | return d->mErrorString; | ||
316 | } | ||
317 | |||
318 | Encryption::ErrorType Encryption::errorType() | ||
319 | { | ||
320 | return d->mErrorType; | ||
321 | } | ||
322 | |||
323 | |||
324 | class PartPrivate | ||
325 | { | ||
326 | public: | ||
327 | PartPrivate(Part *part); | ||
328 | void appendSubPart(Part::Ptr subpart); | ||
329 | |||
330 | QVector<Part::Ptr> subParts(); | ||
331 | |||
332 | Part *parent() const; | ||
333 | |||
334 | const MailMime::Ptr &mailMime() const; | ||
335 | void createMailMime(const MimeTreeParser::MimeMessagePart::Ptr &part); | ||
336 | void createMailMime(const MimeTreeParser::TextMessagePart::Ptr &part); | ||
337 | void createMailMime(const MimeTreeParser::AlternativeMessagePart::Ptr &part); | ||
338 | void createMailMime(const MimeTreeParser::HtmlMessagePart::Ptr &part); | ||
339 | void createMailMime(const MimeTreeParser::EncryptedMessagePart::Ptr &part); | ||
340 | |||
341 | static Encryption::Ptr createEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part); | ||
342 | void appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr &part); | ||
343 | static QVector<Signature::Ptr> createSignature(const MimeTreeParser::SignedMessagePart::Ptr& part); | ||
344 | void appendSignature(const MimeTreeParser::SignedMessagePart::Ptr &part); | ||
345 | |||
346 | void setSignatures(const QVector<Signature::Ptr> &sigs); | ||
347 | void setEncryptions(const QVector<Encryption::Ptr> &encs); | ||
348 | |||
349 | const QVector<Encryption::Ptr> &encryptions() const; | ||
350 | const QVector<Signature::Ptr> &signatures() const; | ||
351 | private: | ||
352 | Part *q; | ||
353 | Part *mParent; | ||
354 | QVector<Part::Ptr> mSubParts; | ||
355 | QVector<Encryption::Ptr> mEncryptions; | ||
356 | QVector<Signature::Ptr> mSignatures; | ||
357 | MailMime::Ptr mMailMime; | ||
358 | }; | ||
359 | |||
360 | PartPrivate::PartPrivate(Part* part) | ||
361 | : q(part) | ||
362 | , mParent(Q_NULLPTR) | ||
363 | { | ||
364 | |||
365 | } | ||
366 | |||
367 | void PartPrivate::createMailMime(const MimeTreeParser::HtmlMessagePart::Ptr& part) | ||
368 | { | ||
369 | mMailMime = MailMime::Ptr(new MailMime); | ||
370 | mMailMime->d->mNode = part->mNode; | ||
371 | } | ||
372 | |||
373 | void PartPrivate::createMailMime(const MimeTreeParser::AlternativeMessagePart::Ptr& part) | ||
374 | { | ||
375 | mMailMime = MailMime::Ptr(new MailMime); | ||
376 | mMailMime->d->mNode = part->mNode; | ||
377 | } | ||
378 | |||
379 | void PartPrivate::createMailMime(const MimeTreeParser::TextMessagePart::Ptr& part) | ||
380 | { | ||
381 | mMailMime = MailMime::Ptr(new MailMime); | ||
382 | mMailMime->d->mNode = part->mNode; | ||
383 | } | ||
384 | |||
385 | void PartPrivate::createMailMime(const MimeTreeParser::MimeMessagePart::Ptr& part) | ||
386 | { | ||
387 | mMailMime = MailMime::Ptr(new MailMime); | ||
388 | mMailMime->d->mNode = part->mNode; | ||
389 | } | ||
390 | |||
391 | void PartPrivate::createMailMime(const MimeTreeParser::EncryptedMessagePart::Ptr& part) | ||
392 | { | ||
393 | mMailMime = MailMime::Ptr(new MailMime); | ||
394 | mMailMime->d->mNode = part->mNode; | ||
395 | } | ||
396 | |||
397 | void PartPrivate::appendSubPart(Part::Ptr subpart) | ||
398 | { | ||
399 | subpart->d->mParent = q; | ||
400 | mSubParts.append(subpart); | ||
401 | } | ||
402 | |||
403 | Encryption::Ptr PartPrivate::createEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part) | ||
404 | { | ||
405 | QGpgME::KeyListJob *job = part->mCryptoProto->keyListJob(false); // local, no sigs | ||
406 | if (!job) { | ||
407 | qWarning() << "The Crypto backend does not support listing keys. "; | ||
408 | return Encryption::Ptr(); | ||
409 | } | ||
410 | |||
411 | auto encpriv = new EncryptionPrivate(); | ||
412 | if (part->passphraseError()) { | ||
413 | encpriv->mErrorType = Encryption::PassphraseError; | ||
414 | encpriv->mErrorString = part->mMetaData.errorText; | ||
415 | } else if (part->isEncrypted() && !part->isDecryptable()) { | ||
416 | encpriv->mErrorType = Encryption::KeyMissing; | ||
417 | encpriv->mErrorString = part->mMetaData.errorText; | ||
418 | } else if (!part->isEncrypted() && !part->isDecryptable()) { | ||
419 | encpriv->mErrorType = Encryption::UnknownError; | ||
420 | encpriv->mErrorString = part->mMetaData.errorText; | ||
421 | } else { | ||
422 | encpriv->mErrorType = Encryption::NoError; | ||
423 | } | ||
424 | |||
425 | foreach(const auto &recipient, part->mDecryptRecipients) { | ||
426 | std::vector<GpgME::Key> found_keys; | ||
427 | const auto &keyid = recipient.keyID(); | ||
428 | GpgME::KeyListResult res = job->exec(QStringList(QLatin1String(keyid)), false, found_keys); | ||
429 | if (res.error()) { | ||
430 | qWarning() << "Error while searching key for Fingerprint: " << keyid; | ||
431 | continue; | ||
432 | } | ||
433 | if (found_keys.size() > 1) { | ||
434 | // Should not Happen | ||
435 | qWarning() << "Oops: Found more then one Key for Fingerprint: " << keyid; | ||
436 | } | ||
437 | if (found_keys.size() != 1) { | ||
438 | // Should not Happen at this point | ||
439 | qWarning() << "Oops: Found no Key for Fingerprint: " << keyid; | ||
440 | auto keypriv = new KeyPrivate; | ||
441 | keypriv->mKeyID = keyid; | ||
442 | encpriv->mRecipients.push_back(Key::Ptr(new Key(keypriv))); | ||
443 | } else { | ||
444 | auto key = found_keys[0]; | ||
445 | auto keypriv = new KeyPrivate; | ||
446 | keypriv->mKey = key; | ||
447 | encpriv->mRecipients.push_back(Key::Ptr(new Key(keypriv))); | ||
448 | } | ||
449 | } | ||
450 | return Encryption::Ptr(new Encryption(encpriv)); | ||
451 | } | ||
452 | |||
453 | void PartPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part) | ||
454 | { | ||
455 | mEncryptions.append(createEncryption(part)); | ||
456 | } | ||
457 | |||
458 | void PartPrivate::setEncryptions(const QVector< Encryption::Ptr >& encs) | ||
459 | { | ||
460 | mEncryptions = encs; | ||
461 | } | ||
462 | |||
463 | QVector<Signature::Ptr> PartPrivate::createSignature(const MimeTreeParser::SignedMessagePart::Ptr& part) | ||
464 | { | ||
465 | QVector<Signature::Ptr> sigs; | ||
466 | QGpgME::KeyListJob *job = part->mCryptoProto->keyListJob(false); // local, no sigs | ||
467 | if (!job) { | ||
468 | qWarning() << "The Crypto backend does not support listing keys. "; | ||
469 | return sigs; | ||
470 | } | ||
471 | |||
472 | foreach(const auto &sig, part->mSignatures) { | ||
473 | auto sigpriv = new SignaturePrivate(); | ||
474 | sigpriv->mSignature = sig; | ||
475 | auto signature = std::make_shared<Signature>(sigpriv); | ||
476 | sigs.append(signature); | ||
477 | |||
478 | std::vector<GpgME::Key> found_keys; | ||
479 | const auto &keyid = sig.fingerprint(); | ||
480 | GpgME::KeyListResult res = job->exec(QStringList(QLatin1String(keyid)), false, found_keys); | ||
481 | if (res.error()) { | ||
482 | qWarning() << "Error while searching key for Fingerprint: " << keyid; | ||
483 | continue; | ||
484 | } | ||
485 | if (found_keys.size() > 1) { | ||
486 | // Should not Happen | ||
487 | qWarning() << "Oops: Found more then one Key for Fingerprint: " << keyid; | ||
488 | continue; | ||
489 | } | ||
490 | if (found_keys.size() != 1) { | ||
491 | // Should not Happen at this point | ||
492 | qWarning() << "Oops: Found no Key for Fingerprint: " << keyid; | ||
493 | continue; | ||
494 | } else { | ||
495 | auto key = found_keys[0]; | ||
496 | auto keypriv = new KeyPrivate; | ||
497 | keypriv->mKey = key; | ||
498 | sigpriv->mKey = Key::Ptr(new Key(keypriv)); | ||
499 | } | ||
500 | } | ||
501 | return sigs; | ||
502 | } | ||
503 | |||
504 | void PartPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& part) | ||
505 | { | ||
506 | mSignatures.append(createSignature(part)); | ||
507 | } | ||
508 | |||
509 | |||
510 | void PartPrivate::setSignatures(const QVector< Signature::Ptr >& sigs) | ||
511 | { | ||
512 | mSignatures = sigs; | ||
513 | } | ||
514 | |||
515 | Part *PartPrivate::parent() const | ||
516 | { | ||
517 | return mParent; | ||
518 | } | ||
519 | |||
520 | QVector< Part::Ptr > PartPrivate::subParts() | ||
521 | { | ||
522 | return mSubParts; | ||
523 | } | ||
524 | |||
525 | const MailMime::Ptr& PartPrivate::mailMime() const | ||
526 | { | ||
527 | return mMailMime; | ||
528 | } | ||
529 | |||
530 | const QVector< Encryption::Ptr >& PartPrivate::encryptions() const | ||
531 | { | ||
532 | return mEncryptions; | ||
533 | } | ||
534 | |||
535 | const QVector< Signature::Ptr >& PartPrivate::signatures() const | ||
536 | { | ||
537 | return mSignatures; | ||
538 | } | ||
539 | |||
540 | Part::Part() | ||
541 | : d(std::unique_ptr<PartPrivate>(new PartPrivate(this))) | ||
542 | { | ||
543 | |||
544 | } | ||
545 | |||
546 | bool Part::hasSubParts() const | ||
547 | { | ||
548 | return !subParts().isEmpty(); | ||
549 | } | ||
550 | |||
551 | QVector<Part::Ptr> Part::subParts() const | ||
552 | { | ||
553 | return d->subParts(); | ||
554 | } | ||
555 | |||
556 | QByteArray Part::type() const | ||
557 | { | ||
558 | return "Part"; | ||
559 | } | ||
560 | |||
561 | QVector<QByteArray> Part::availableContents() const | ||
562 | { | ||
563 | return QVector<QByteArray>(); | ||
564 | } | ||
565 | |||
566 | QVector<Content::Ptr> Part::content() const | ||
567 | { | ||
568 | return content(availableContents().first()); | ||
569 | } | ||
570 | |||
571 | QVector<Content::Ptr> Part::content(const QByteArray& ct) const | ||
572 | { | ||
573 | return QVector<Content::Ptr>(); | ||
574 | } | ||
575 | |||
576 | QVector<Encryption::Ptr> Part::encryptions() const | ||
577 | { | ||
578 | auto ret = d->encryptions(); | ||
579 | auto parent = d->parent(); | ||
580 | if (parent) { | ||
581 | ret.append(parent->encryptions()); | ||
582 | } | ||
583 | return ret; | ||
584 | } | ||
585 | |||
586 | QVector<Signature::Ptr> Part::signatures() const | ||
587 | { | ||
588 | auto ret = d->signatures(); | ||
589 | auto parent = d->parent(); | ||
590 | if (parent) { | ||
591 | ret.append(parent->signatures()); | ||
592 | } | ||
593 | return ret; | ||
594 | } | ||
595 | |||
596 | MailMime::Ptr Part::mailMime() const | ||
597 | { | ||
598 | return d->mailMime(); | ||
599 | } | ||
600 | |||
601 | Part *Part::parent() const | ||
602 | { | ||
603 | return d->parent(); | ||
604 | } | ||
605 | |||
606 | class ContentPrivate | ||
607 | { | ||
608 | public: | ||
609 | QByteArray mContent; | ||
610 | QByteArray mCodec; | ||
611 | Part *mParent; | ||
612 | Content *q; | ||
613 | MailMime::Ptr mMailMime; | ||
614 | QVector<Encryption::Ptr> mEncryptions; | ||
615 | QVector<Signature::Ptr> mSignatures; | ||
616 | void appendSignature(const MimeTreeParser::SignedMessagePart::Ptr &sig); | ||
617 | void appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr &enc); | ||
618 | }; | ||
619 | |||
620 | void ContentPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& enc) | ||
621 | { | ||
622 | mEncryptions.append(PartPrivate::createEncryption(enc)); | ||
623 | } | ||
624 | |||
625 | void ContentPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& sig) | ||
626 | { | ||
627 | mSignatures.append(PartPrivate::createSignature(sig)); | ||
628 | } | ||
629 | |||
630 | |||
631 | Content::Content(const QByteArray& content, Part *parent) | ||
632 | : d(std::unique_ptr<ContentPrivate>(new ContentPrivate)) | ||
633 | { | ||
634 | d->q = this; | ||
635 | d->mContent = content; | ||
636 | d->mCodec = "utf-8"; | ||
637 | d->mParent = parent; | ||
638 | } | ||
639 | |||
640 | Content::Content(ContentPrivate* d_ptr) | ||
641 | : d(std::unique_ptr<ContentPrivate>(d_ptr)) | ||
642 | { | ||
643 | d->q = this; | ||
644 | } | ||
645 | |||
646 | Content::~Content() | ||
647 | { | ||
648 | } | ||
649 | |||
650 | QVector<Encryption::Ptr> Content::encryptions() const | ||
651 | { | ||
652 | auto ret = d->mEncryptions; | ||
653 | if (d->mParent) { | ||
654 | ret.append(d->mParent->encryptions()); | ||
655 | } | ||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | QVector<Signature::Ptr> Content::signatures() const | ||
660 | { | ||
661 | auto ret = d->mSignatures; | ||
662 | if (d->mParent) { | ||
663 | ret.append(d->mParent->signatures()); | ||
664 | } | ||
665 | return ret; | ||
666 | } | ||
667 | |||
668 | QByteArray Content::content() const | ||
669 | { | ||
670 | return d->mContent; | ||
671 | } | ||
672 | |||
673 | QByteArray Content::charset() const | ||
674 | { | ||
675 | return d->mCodec; | ||
676 | } | ||
677 | |||
678 | QString Content::encodedContent() const | ||
679 | { | ||
680 | return QString::fromUtf8(content()); | ||
681 | // TODO: should set "raw" content not the already utf8 encoded content | ||
682 | // return encodedContent(charset()); | ||
683 | } | ||
684 | |||
685 | QString Content::encodedContent(const QByteArray &charset) const | ||
686 | { | ||
687 | QTextCodec *codec = QTextCodec::codecForName(charset); | ||
688 | return codec->toUnicode(content()); | ||
689 | } | ||
690 | |||
691 | QByteArray Content::type() const | ||
692 | { | ||
693 | return "Content"; | ||
694 | } | ||
695 | |||
696 | MailMime::Ptr Content::mailMime() const | ||
697 | { | ||
698 | if (d->mMailMime) { | ||
699 | return d->mMailMime; | ||
700 | } else { | ||
701 | return d->mParent->mailMime(); | ||
702 | } | ||
703 | } | ||
704 | |||
705 | Part *Content::parent() const | ||
706 | { | ||
707 | return d->mParent; | ||
708 | } | ||
709 | |||
710 | HtmlContent::HtmlContent(const QByteArray& content, Part* parent) | ||
711 | : Content(content, parent) | ||
712 | { | ||
713 | |||
714 | } | ||
715 | |||
716 | QByteArray HtmlContent::type() const | ||
717 | { | ||
718 | return "HtmlContent"; | ||
719 | } | ||
720 | |||
721 | PlainTextContent::PlainTextContent(const QByteArray& content, Part* parent) | ||
722 | : Content(content, parent) | ||
723 | { | ||
724 | |||
725 | } | ||
726 | |||
727 | PlainTextContent::PlainTextContent(ContentPrivate* d_ptr) | ||
728 | : Content(d_ptr) | ||
729 | { | ||
730 | |||
731 | } | ||
732 | |||
733 | HtmlContent::HtmlContent(ContentPrivate* d_ptr) | ||
734 | : Content(d_ptr) | ||
735 | { | ||
736 | |||
737 | } | ||
738 | |||
739 | |||
740 | QByteArray PlainTextContent::type() const | ||
741 | { | ||
742 | return "PlainTextContent"; | ||
743 | } | ||
744 | |||
745 | class AlternativePartPrivate | ||
746 | { | ||
747 | public: | ||
748 | void fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part); | ||
749 | |||
750 | QVector<Content::Ptr> content(const QByteArray &ct) const; | ||
751 | |||
752 | AlternativePart *q; | ||
753 | |||
754 | QVector<QByteArray> types() const; | ||
755 | |||
756 | private: | ||
757 | QMap<QByteArray, QVector<Content::Ptr>> mContent; | ||
758 | QVector<QByteArray> mTypes; | ||
759 | }; | ||
760 | |||
761 | void AlternativePartPrivate::fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part) | ||
762 | { | ||
763 | mTypes = QVector<QByteArray>() << "html" << "plaintext"; | ||
764 | |||
765 | Content::Ptr content = std::make_shared<HtmlContent>(part->htmlContent().toLocal8Bit(), q); | ||
766 | mContent["html"].append(content); | ||
767 | content = std::make_shared<PlainTextContent>(part->plaintextContent().toLocal8Bit(), q); | ||
768 | mContent["plaintext"].append(content); | ||
769 | q->reachParentD()->createMailMime(part); | ||
770 | } | ||
771 | |||
772 | QVector<QByteArray> AlternativePartPrivate::types() const | ||
773 | { | ||
774 | return mTypes; | ||
775 | } | ||
776 | |||
777 | QVector<Content::Ptr> AlternativePartPrivate::content(const QByteArray& ct) const | ||
778 | { | ||
779 | return mContent[ct]; | ||
780 | } | ||
781 | |||
782 | AlternativePart::AlternativePart() | ||
783 | : d(std::unique_ptr<AlternativePartPrivate>(new AlternativePartPrivate)) | ||
784 | { | ||
785 | d->q = this; | ||
786 | } | ||
787 | |||
788 | AlternativePart::~AlternativePart() | ||
789 | { | ||
790 | |||
791 | } | ||
792 | |||
793 | QByteArray AlternativePart::type() const | ||
794 | { | ||
795 | return "AlternativePart"; | ||
796 | } | ||
797 | |||
798 | QVector<QByteArray> AlternativePart::availableContents() const | ||
799 | { | ||
800 | return d->types(); | ||
801 | } | ||
802 | |||
803 | QVector<Content::Ptr> AlternativePart::content(const QByteArray& ct) const | ||
804 | { | ||
805 | return d->content(ct); | ||
806 | } | ||
807 | |||
808 | PartPrivate* AlternativePart::reachParentD() const | ||
809 | { | ||
810 | return Part::d.get(); | ||
811 | } | ||
812 | |||
813 | class SinglePartPrivate | ||
814 | { | ||
815 | public: | ||
816 | void fillFrom(const MimeTreeParser::TextMessagePart::Ptr &part); | ||
817 | void fillFrom(const MimeTreeParser::HtmlMessagePart::Ptr &part); | ||
818 | void fillFrom(const MimeTreeParser::AttachmentMessagePart::Ptr &part); | ||
819 | void createEncryptionFailBlock(const MimeTreeParser::EncryptedMessagePart::Ptr &part); | ||
820 | SinglePart *q; | ||
821 | |||
822 | QVector<Content::Ptr> mContent; | ||
823 | QByteArray mType; | ||
824 | }; | ||
825 | |||
826 | void SinglePartPrivate::fillFrom(const MimeTreeParser::TextMessagePart::Ptr &part) | ||
827 | { | ||
828 | mType = "plaintext"; | ||
829 | mContent.clear(); | ||
830 | foreach (const auto &mp, part->subParts()) { | ||
831 | auto d_ptr = new ContentPrivate; | ||
832 | d_ptr->mContent = mp->text().toUtf8(); // TODO: should set "raw" content not the already utf8 encoded content | ||
833 | d_ptr->mParent = q; | ||
834 | const auto enc = mp.dynamicCast<MimeTreeParser::EncryptedMessagePart>(); | ||
835 | auto sig = mp.dynamicCast<MimeTreeParser::SignedMessagePart>(); | ||
836 | if (enc) { | ||
837 | d_ptr->appendEncryption(enc); | ||
838 | if (!enc->isDecryptable()) { | ||
839 | d_ptr->mContent = QByteArray(); | ||
840 | } | ||
841 | const auto s = enc->subParts(); | ||
842 | if (s.size() == 1) { | ||
843 | sig = s[0].dynamicCast<MimeTreeParser::SignedMessagePart>(); | ||
844 | } | ||
845 | } | ||
846 | if (sig) { | ||
847 | d_ptr->appendSignature(sig); | ||
848 | } | ||
849 | mContent.append(std::make_shared<PlainTextContent>(d_ptr)); | ||
850 | q->reachParentD()->createMailMime(part); | ||
851 | d_ptr->mCodec = q->mailMime()->charset(); | ||
852 | } | ||
853 | } | ||
854 | |||
855 | void SinglePartPrivate::fillFrom(const MimeTreeParser::HtmlMessagePart::Ptr &part) | ||
856 | { | ||
857 | mType = "html"; | ||
858 | mContent.clear(); | ||
859 | mContent.append(std::make_shared<HtmlContent>(part->text().toUtf8(), q)); | ||
860 | q->reachParentD()->createMailMime(part); | ||
861 | } | ||
862 | |||
863 | void SinglePartPrivate::fillFrom(const MimeTreeParser::AttachmentMessagePart::Ptr &part) | ||
864 | { | ||
865 | QMimeDatabase mimeDb; | ||
866 | q->reachParentD()->createMailMime(part.staticCast<MimeTreeParser::TextMessagePart>()); | ||
867 | const auto mimetype = q->mailMime()->mimetype(); | ||
868 | const auto content = q->mailMime()->decodedContent(); | ||
869 | mContent.clear(); | ||
870 | if (mimetype == mimeDb.mimeTypeForName("text/plain")) { | ||
871 | mType = "plaintext"; | ||
872 | mContent.append(std::make_shared<PlainTextContent>(content, q)); | ||
873 | } else if (mimetype == mimeDb.mimeTypeForName("text/html")) { | ||
874 | mType = "html"; | ||
875 | mContent.append(std::make_shared<HtmlContent>(content, q)); | ||
876 | } else { | ||
877 | mType = mimetype.name().toUtf8(); | ||
878 | mContent.append(std::make_shared<Content>(content, q)); | ||
879 | } | ||
880 | } | ||
881 | |||
882 | void SinglePartPrivate::createEncryptionFailBlock(const MimeTreeParser::EncryptedMessagePart::Ptr &part) | ||
883 | { | ||
884 | mType = "plaintext"; | ||
885 | mContent.clear(); | ||
886 | mContent.append(std::make_shared<PlainTextContent>(QByteArray(), q)); | ||
887 | q->reachParentD()->createMailMime(part); | ||
888 | } | ||
889 | |||
890 | SinglePart::SinglePart() | ||
891 | : d(std::unique_ptr<SinglePartPrivate>(new SinglePartPrivate)) | ||
892 | { | ||
893 | d->q = this; | ||
894 | } | ||
895 | |||
896 | SinglePart::~SinglePart() | ||
897 | { | ||
898 | |||
899 | } | ||
900 | |||
901 | QVector<QByteArray> SinglePart::availableContents() const | ||
902 | { | ||
903 | return QVector<QByteArray>() << d->mType; | ||
904 | } | ||
905 | |||
906 | QVector< Content::Ptr > SinglePart::content(const QByteArray &ct) const | ||
907 | { | ||
908 | if (ct == d->mType) { | ||
909 | return d->mContent; | ||
910 | } | ||
911 | return QVector<Content::Ptr>(); | ||
912 | } | ||
913 | |||
914 | QByteArray SinglePart::type() const | ||
915 | { | ||
916 | return "SinglePart"; | ||
917 | } | ||
918 | |||
919 | PartPrivate* SinglePart::reachParentD() const | ||
920 | { | ||
921 | return Part::d.get(); | ||
922 | } | ||
923 | |||
924 | ParserPrivate::ParserPrivate(Parser* parser) | ||
925 | : q(parser) | ||
926 | , mNodeHelper(std::make_shared<MimeTreeParser::NodeHelper>()) | ||
927 | { | ||
928 | |||
929 | } | ||
930 | |||
931 | void ParserPrivate::setMessage(const QByteArray& mimeMessage) | ||
932 | { | ||
933 | const auto mailData = KMime::CRLFtoLF(mimeMessage); | ||
934 | mMsg = KMime::Message::Ptr(new KMime::Message); | ||
935 | mMsg->setContent(mailData); | ||
936 | mMsg->parse(); | ||
937 | |||
938 | // render the mail | ||
939 | StringHtmlWriter htmlWriter; | ||
940 | ObjectTreeSource source(&htmlWriter); | ||
941 | MimeTreeParser::ObjectTreeParser otp(&source, mNodeHelper.get()); | ||
942 | |||
943 | otp.parseObjectTree(mMsg.data()); | ||
944 | mPartTree = otp.parsedPart().dynamicCast<MimeTreeParser::MessagePart>(); | ||
945 | |||
946 | mEmbeddedPartMap = htmlWriter.embeddedParts(); | ||
947 | mHtml = htmlWriter.html(); | ||
948 | |||
949 | mTree = std::make_shared<Part>(); | ||
950 | createTree(mPartTree, mTree); | ||
951 | } | ||
952 | |||
953 | |||
954 | void ParserPrivate::createTree(const MimeTreeParser::MessagePart::Ptr &start, const Part::Ptr &tree) | ||
955 | { | ||
956 | foreach (const auto &mp, start->subParts()) { | ||
957 | const auto m = mp.dynamicCast<MimeTreeParser::MessagePart>(); | ||
958 | const auto text = mp.dynamicCast<MimeTreeParser::TextMessagePart>(); | ||
959 | const auto alternative = mp.dynamicCast<MimeTreeParser::AlternativeMessagePart>(); | ||
960 | const auto html = mp.dynamicCast<MimeTreeParser::HtmlMessagePart>(); | ||
961 | const auto attachment = mp.dynamicCast<MimeTreeParser::AttachmentMessagePart>(); | ||
962 | if (attachment) { | ||
963 | auto part = std::make_shared<SinglePart>(); | ||
964 | part->d->fillFrom(attachment); | ||
965 | tree->d->appendSubPart(part); | ||
966 | } else if (text) { | ||
967 | auto part = std::make_shared<SinglePart>(); | ||
968 | part->d->fillFrom(text); | ||
969 | tree->d->appendSubPart(part); | ||
970 | } else if (alternative) { | ||
971 | auto part = std::make_shared<AlternativePart>(); | ||
972 | part->d->fillFrom(alternative); | ||
973 | tree->d->appendSubPart(part); | ||
974 | } else if (html) { | ||
975 | auto part = std::make_shared<SinglePart>(); | ||
976 | part->d->fillFrom(html); | ||
977 | tree->d->appendSubPart(part); | ||
978 | } else { | ||
979 | const auto enc = mp.dynamicCast<MimeTreeParser::EncryptedMessagePart>(); | ||
980 | const auto sig = mp.dynamicCast<MimeTreeParser::SignedMessagePart>(); | ||
981 | if (enc || sig) { | ||
982 | auto subTree = std::make_shared<Part>(); | ||
983 | if (enc) { | ||
984 | subTree->d->appendEncryption(enc); | ||
985 | if (!enc->isDecryptable()) { | ||
986 | auto part = std::make_shared<SinglePart>(); | ||
987 | part->d->createEncryptionFailBlock(enc); | ||
988 | part->reachParentD()->setEncryptions(subTree->d->encryptions()); | ||
989 | tree->d->appendSubPart(part); | ||
990 | return; | ||
991 | } | ||
992 | } | ||
993 | if (sig) { | ||
994 | subTree->d->appendSignature(sig); | ||
995 | } | ||
996 | createTree(m, subTree); | ||
997 | foreach(const auto &p, subTree->subParts()) { | ||
998 | tree->d->appendSubPart(p); | ||
999 | if (enc) { | ||
1000 | p->d->setEncryptions(subTree->d->encryptions()); | ||
1001 | } | ||
1002 | if (sig) { | ||
1003 | p->d->setSignatures(subTree->d->signatures()); | ||
1004 | } | ||
1005 | } | ||
1006 | } else { | ||
1007 | createTree(m, tree); | ||
1008 | } | ||
1009 | } | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | Parser::Parser(const QByteArray& mimeMessage) | ||
1014 | :d(std::unique_ptr<ParserPrivate>(new ParserPrivate(this))) | ||
1015 | { | ||
1016 | d->setMessage(mimeMessage); | ||
1017 | } | ||
1018 | |||
1019 | Parser::~Parser() | ||
1020 | { | ||
1021 | } | ||
1022 | |||
1023 | Part::Ptr Parser::getPart(const QUrl &url) | ||
1024 | { | ||
1025 | if (url.scheme() == QStringLiteral("cid") && !url.path().isEmpty()) { | ||
1026 | const auto cid = url.path(); | ||
1027 | return find(d->mTree, [&cid](const Part::Ptr &p){ | ||
1028 | const auto mime = p->mailMime(); | ||
1029 | return mime->cid() == cid; | ||
1030 | }); | ||
1031 | } | ||
1032 | return Part::Ptr(); | ||
1033 | } | ||
1034 | |||
1035 | QVector<Part::Ptr> Parser::collectContentParts() const | ||
1036 | { | ||
1037 | return collect(d->mTree, [](const Part::Ptr &p){return p->type() != "EncapsulatedPart";}, | ||
1038 | [](const Content::Ptr &content){ | ||
1039 | const auto mime = content->mailMime(); | ||
1040 | |||
1041 | if (!mime) { | ||
1042 | return true; | ||
1043 | } | ||
1044 | |||
1045 | if (mime->isFirstTextPart()) { | ||
1046 | return true; | ||
1047 | } | ||
1048 | |||
1049 | { | ||
1050 | auto _mime = content->parent()->mailMime(); | ||
1051 | while (_mime) { | ||
1052 | if (_mime && (_mime->isTopLevelPart() || _mime->isFirstTextPart())) { | ||
1053 | return true; | ||
1054 | } | ||
1055 | if (_mime->isFirstPart()) { | ||
1056 | _mime = _mime->parent(); | ||
1057 | } else { | ||
1058 | break; | ||
1059 | } | ||
1060 | } | ||
1061 | } | ||
1062 | |||
1063 | const auto ctname = mime->mimetype().name().trimmed().toLower(); | ||
1064 | bool mightContent = (content->type() != "Content"); //Content we understand | ||
1065 | |||
1066 | const auto cd = mime->disposition(); | ||
1067 | if (cd && cd == MailMime::Inline) { | ||
1068 | return mightContent; | ||
1069 | } | ||
1070 | |||
1071 | if (cd && cd == MailMime::Attachment) { | ||
1072 | return false; | ||
1073 | } | ||
1074 | |||
1075 | if ((ctname.startsWith("text/") || ctname.isEmpty()) && | ||
1076 | (!mime || mime->filename().trimmed().isEmpty())) { | ||
1077 | // text/* w/o filename parameter: | ||
1078 | return true; | ||
1079 | } | ||
1080 | return false; | ||
1081 | }); | ||
1082 | } | ||
1083 | |||
1084 | |||
1085 | QVector<Part::Ptr> Parser::collectAttachmentParts() const | ||
1086 | { | ||
1087 | return collect(d->mTree, [](const Part::Ptr &p){return p->type() != "EncapsulatedPart";}, | ||
1088 | [](const Content::Ptr &content){ | ||
1089 | const auto mime = content->mailMime(); | ||
1090 | |||
1091 | if (!mime) { | ||
1092 | return false; | ||
1093 | } | ||
1094 | |||
1095 | if (mime->isFirstTextPart()) { | ||
1096 | return false; | ||
1097 | } | ||
1098 | |||
1099 | { | ||
1100 | QMimeDatabase mimeDb; | ||
1101 | auto _mime = content->parent()->mailMime(); | ||
1102 | const auto parent = _mime->parent(); | ||
1103 | if (parent) { | ||
1104 | const auto mimetype = parent->mimetype(); | ||
1105 | if (mimetype == mimeDb.mimeTypeForName("multipart/related")) { | ||
1106 | return false; | ||
1107 | } | ||
1108 | } | ||
1109 | while (_mime) { | ||
1110 | if (_mime && (_mime->isTopLevelPart() || _mime->isFirstTextPart())) { | ||
1111 | return false; | ||
1112 | } | ||
1113 | if (_mime->isFirstPart()) { | ||
1114 | _mime = _mime->parent(); | ||
1115 | } else { | ||
1116 | break; | ||
1117 | } | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1121 | const auto ctname = mime->mimetype().name().trimmed().toLower(); | ||
1122 | bool mightContent = (content->type() != "Content"); //Content we understand | ||
1123 | |||
1124 | const auto cd = mime->disposition(); | ||
1125 | if (cd && cd == MailMime::Inline) { | ||
1126 | // explict "inline" disposition: | ||
1127 | return !mightContent; | ||
1128 | } | ||
1129 | if (cd && cd == MailMime::Attachment) { | ||
1130 | // explicit "attachment" disposition: | ||
1131 | return true; | ||
1132 | } | ||
1133 | |||
1134 | const auto ct = mime->mimetype(); | ||
1135 | if ((ctname.startsWith("text/") || ctname.isEmpty()) && | ||
1136 | (!mime || mime->filename().trimmed().isEmpty())) { | ||
1137 | // text/* w/o filename parameter: | ||
1138 | return false; | ||
1139 | } | ||
1140 | return true; | ||
1141 | }); | ||
1142 | } | ||
1143 | |||
1144 | QVector<Part::Ptr> Parser::collect(const Part::Ptr &start, std::function<bool(const Part::Ptr &)> select, std::function<bool(const Content::Ptr &)> filter) const | ||
1145 | { | ||
1146 | QVector<Part::Ptr> ret; | ||
1147 | foreach (const auto &part, start->subParts()) { | ||
1148 | QVector<QByteArray> contents; | ||
1149 | foreach(const auto &ct, part->availableContents()) { | ||
1150 | foreach(const auto &content, part->content(ct)) { | ||
1151 | if (filter(content)) { | ||
1152 | contents.append(ct); | ||
1153 | break; | ||
1154 | } | ||
1155 | } | ||
1156 | } | ||
1157 | if (!contents.isEmpty()) { | ||
1158 | ret.append(part); | ||
1159 | } | ||
1160 | if (select(part)){ | ||
1161 | ret += collect(part, select, filter); | ||
1162 | } | ||
1163 | } | ||
1164 | return ret; | ||
1165 | } | ||
1166 | |||
1167 | Part::Ptr Parser::find(const Part::Ptr &start, std::function<bool(const Part::Ptr &)> select) const | ||
1168 | { | ||
1169 | foreach (const auto &part, start->subParts()) { | ||
1170 | if (select(part)) { | ||
1171 | return part; | ||
1172 | } | ||
1173 | const auto ret = find(part, select); | ||
1174 | if (ret) { | ||
1175 | return ret; | ||
1176 | } | ||
1177 | } | ||
1178 | return Part::Ptr(); | ||
1179 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/interface.h b/framework/src/domain/mime/mimetreeparser/interface.h new file mode 100644 index 00000000..7c3ea28b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/interface.h | |||
@@ -0,0 +1,378 @@ | |||
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 | #pragma once | ||
21 | |||
22 | #include <functional> | ||
23 | #include <memory> | ||
24 | #include <vector> | ||
25 | |||
26 | #include <QDateTime> | ||
27 | #include <QUrl> | ||
28 | #include <QMimeType> | ||
29 | |||
30 | class Part; | ||
31 | class PartPrivate; | ||
32 | |||
33 | class MailMime; | ||
34 | class MailMimePrivate; | ||
35 | |||
36 | class AlternativePart; | ||
37 | class AlternativePartPrivate; | ||
38 | |||
39 | class SinglePart; | ||
40 | class SinglePartPrivate; | ||
41 | |||
42 | class EncryptionPart; | ||
43 | class EncryptionPartPrivate; | ||
44 | |||
45 | class EncapsulatedPart; | ||
46 | class EncapsulatedPartPrivate; | ||
47 | |||
48 | class Content; | ||
49 | class ContentPrivate; | ||
50 | |||
51 | class CertContent; | ||
52 | class CertContentPrivate; | ||
53 | |||
54 | class EncryptionError; | ||
55 | |||
56 | class Key; | ||
57 | class KeyPrivate; | ||
58 | class Signature; | ||
59 | class SignaturePrivate; | ||
60 | class Encryption; | ||
61 | class EncryptionPrivate; | ||
62 | |||
63 | typedef std::shared_ptr<Signature> SignaturePtr; | ||
64 | typedef std::shared_ptr<Encryption> EncryptionPtr; | ||
65 | |||
66 | class Parser; | ||
67 | class ParserPrivate; | ||
68 | |||
69 | /* | ||
70 | * A MessagePart that is based on a KMime::Content | ||
71 | */ | ||
72 | class MailMime | ||
73 | { | ||
74 | public: | ||
75 | typedef std::shared_ptr<MailMime> Ptr; | ||
76 | /** | ||
77 | * Various possible values for the "Content-Disposition" header. | ||
78 | */ | ||
79 | enum Disposition { | ||
80 | Invalid, ///< Default, invalid value | ||
81 | Inline, ///< inline | ||
82 | Attachment ///< attachment | ||
83 | }; | ||
84 | |||
85 | MailMime(); | ||
86 | |||
87 | // interessting header parts of a KMime::Content | ||
88 | QMimeType mimetype() const; | ||
89 | Disposition disposition() const; | ||
90 | QUrl label() const; | ||
91 | QByteArray cid() const; | ||
92 | QByteArray charset() const; | ||
93 | QString filename() const; | ||
94 | |||
95 | // Unique identifier to ecactly this KMime::Content | ||
96 | QByteArray link() const; | ||
97 | |||
98 | QByteArray content() const; | ||
99 | //Use default charset | ||
100 | QString encodedContent() const; | ||
101 | |||
102 | // overwrite default charset with given charset | ||
103 | QString encodedContent(QByteArray charset) const; | ||
104 | |||
105 | QByteArray decodedContent() const; | ||
106 | |||
107 | bool isFirstTextPart() const; | ||
108 | bool isFirstPart() const; | ||
109 | bool isTopLevelPart() const; | ||
110 | |||
111 | MailMime::Ptr parent() const; | ||
112 | |||
113 | private: | ||
114 | std::unique_ptr<MailMimePrivate> d; | ||
115 | |||
116 | friend class PartPrivate; | ||
117 | }; | ||
118 | |||
119 | class Content | ||
120 | { | ||
121 | public: | ||
122 | typedef std::shared_ptr<Content> Ptr; | ||
123 | Content(const QByteArray &content, Part *parent); | ||
124 | Content(ContentPrivate *d_ptr); | ||
125 | virtual ~Content(); | ||
126 | |||
127 | QByteArray content() const; | ||
128 | |||
129 | QByteArray charset() const; | ||
130 | |||
131 | //Use default charset | ||
132 | QString encodedContent() const; | ||
133 | |||
134 | // overwrite default charset with given charset | ||
135 | QString encodedContent(const QByteArray &charset) const; | ||
136 | |||
137 | QVector<SignaturePtr> signatures() const; | ||
138 | QVector<EncryptionPtr> encryptions() const; | ||
139 | MailMime::Ptr mailMime() const; | ||
140 | virtual QByteArray type() const; | ||
141 | Part* parent() const; | ||
142 | private: | ||
143 | std::unique_ptr<ContentPrivate> d; | ||
144 | }; | ||
145 | |||
146 | class PlainTextContent : public Content | ||
147 | { | ||
148 | public: | ||
149 | PlainTextContent(const QByteArray &content, Part *parent); | ||
150 | PlainTextContent(ContentPrivate *d_ptr); | ||
151 | QByteArray type() const Q_DECL_OVERRIDE; | ||
152 | }; | ||
153 | |||
154 | class HtmlContent : public Content | ||
155 | { | ||
156 | public: | ||
157 | HtmlContent(const QByteArray &content, Part *parent); | ||
158 | HtmlContent(ContentPrivate* d_ptr); | ||
159 | QByteArray type() const Q_DECL_OVERRIDE; | ||
160 | }; | ||
161 | |||
162 | /* | ||
163 | * importing a cert GpgMe::ImportResult | ||
164 | * checking a cert (if it is a valid cert) | ||
165 | */ | ||
166 | |||
167 | class CertContent : public Content | ||
168 | { | ||
169 | public: | ||
170 | typedef std::shared_ptr<CertContent> Ptr; | ||
171 | CertContent(const QByteArray &content, Part *parent); | ||
172 | |||
173 | QByteArray type() const Q_DECL_OVERRIDE; | ||
174 | enum CertType { | ||
175 | Pgp, | ||
176 | SMime | ||
177 | }; | ||
178 | |||
179 | enum CertSubType { | ||
180 | Public, | ||
181 | Private | ||
182 | }; | ||
183 | |||
184 | CertType certType() const; | ||
185 | CertSubType certSubType() const; | ||
186 | int keyLength() const; | ||
187 | |||
188 | private: | ||
189 | std::unique_ptr<CertContentPrivate> d; | ||
190 | }; | ||
191 | |||
192 | class Part | ||
193 | { | ||
194 | public: | ||
195 | typedef std::shared_ptr<Part> Ptr; | ||
196 | Part(); | ||
197 | virtual QByteArray type() const; | ||
198 | |||
199 | virtual QVector<QByteArray> availableContents() const; | ||
200 | virtual QVector<Content::Ptr> content(const QByteArray& ct) const; | ||
201 | QVector<Content::Ptr> content() const; | ||
202 | |||
203 | bool hasSubParts() const; | ||
204 | QVector<Part::Ptr> subParts() const; | ||
205 | Part *parent() const; | ||
206 | |||
207 | QVector<SignaturePtr> signatures() const; | ||
208 | QVector<EncryptionPtr> encryptions() const; | ||
209 | virtual MailMime::Ptr mailMime() const; | ||
210 | protected: | ||
211 | std::unique_ptr<PartPrivate> d; | ||
212 | private: | ||
213 | friend class ParserPrivate; | ||
214 | friend class PartPrivate; | ||
215 | }; | ||
216 | |||
217 | class AlternativePart : public Part | ||
218 | { | ||
219 | public: | ||
220 | typedef std::shared_ptr<AlternativePart> Ptr; | ||
221 | |||
222 | AlternativePart(); | ||
223 | virtual ~AlternativePart(); | ||
224 | |||
225 | QVector<QByteArray> availableContents() const Q_DECL_OVERRIDE; | ||
226 | QVector<Content::Ptr> content(const QByteArray& ct) const Q_DECL_OVERRIDE; | ||
227 | |||
228 | QByteArray type() const Q_DECL_OVERRIDE; | ||
229 | |||
230 | private: | ||
231 | PartPrivate *reachParentD() const; | ||
232 | std::unique_ptr<AlternativePartPrivate> d; | ||
233 | |||
234 | friend class ParserPrivate; | ||
235 | friend class AlternativePartPrivate; | ||
236 | }; | ||
237 | |||
238 | class SinglePart : public Part | ||
239 | { | ||
240 | public: | ||
241 | typedef std::shared_ptr<SinglePart> Ptr; | ||
242 | |||
243 | SinglePart(); | ||
244 | virtual ~SinglePart(); | ||
245 | |||
246 | QVector<Content::Ptr> content(const QByteArray& ct) const Q_DECL_OVERRIDE; | ||
247 | QVector<QByteArray> availableContents() const Q_DECL_OVERRIDE; | ||
248 | |||
249 | QByteArray type() const Q_DECL_OVERRIDE; | ||
250 | private: | ||
251 | PartPrivate *reachParentD() const; | ||
252 | std::unique_ptr<SinglePartPrivate> d; | ||
253 | |||
254 | friend class ParserPrivate; | ||
255 | friend class SinglePartPrivate; | ||
256 | }; | ||
257 | |||
258 | /* | ||
259 | * we want to request complete headers like: | ||
260 | * from/to... | ||
261 | */ | ||
262 | |||
263 | class EncapsulatedPart : public SinglePart | ||
264 | { | ||
265 | public: | ||
266 | typedef std::shared_ptr<EncapsulatedPart> Ptr; | ||
267 | QByteArray type() const Q_DECL_OVERRIDE; | ||
268 | |||
269 | //template <class T> QByteArray header<T>(); | ||
270 | private: | ||
271 | std::unique_ptr<EncapsulatedPartPrivate> d; | ||
272 | }; | ||
273 | |||
274 | class EncryptionError | ||
275 | { | ||
276 | public: | ||
277 | int errorId() const; | ||
278 | QString errorString() const; | ||
279 | }; | ||
280 | |||
281 | class Key | ||
282 | { | ||
283 | public: | ||
284 | typedef std::shared_ptr<Key> Ptr; | ||
285 | Key(); | ||
286 | Key(KeyPrivate *); | ||
287 | ~Key(); | ||
288 | |||
289 | QString keyid() const; | ||
290 | QString name() const; | ||
291 | QString email() const; | ||
292 | QString comment() const; | ||
293 | QVector<QString> emails() const; | ||
294 | enum KeyTrust { | ||
295 | Unknown, Undefined, Never, Marginal, Full, Ultimate | ||
296 | }; | ||
297 | KeyTrust keyTrust() const; | ||
298 | |||
299 | bool isRevokation() const; | ||
300 | bool isInvalid() const; | ||
301 | bool isExpired() const; | ||
302 | |||
303 | std::vector<Key::Ptr> subkeys(); | ||
304 | Key parentkey() const; | ||
305 | private: | ||
306 | std::unique_ptr<KeyPrivate> d; | ||
307 | }; | ||
308 | |||
309 | class Signature | ||
310 | { | ||
311 | public: | ||
312 | typedef std::shared_ptr<Signature> Ptr; | ||
313 | Signature(); | ||
314 | Signature(SignaturePrivate *); | ||
315 | ~Signature(); | ||
316 | |||
317 | Key::Ptr key() const; | ||
318 | QDateTime creationDateTime() const; | ||
319 | QDateTime expirationDateTime() const; | ||
320 | bool neverExpires() const; | ||
321 | |||
322 | //template <> StatusObject<SignatureVerificationResult> verify() const; | ||
323 | private: | ||
324 | std::unique_ptr<SignaturePrivate> d; | ||
325 | }; | ||
326 | |||
327 | /* | ||
328 | * Normally the Keys for encryption are subkeys | ||
329 | * for clients the parentkeys are "more interessting", because they store the name, email etc. | ||
330 | * but a client may also wants show to what subkey the mail is really encrypted, an if this subkey isRevoked or something else | ||
331 | */ | ||
332 | class Encryption | ||
333 | { | ||
334 | public: | ||
335 | enum ErrorType { | ||
336 | NoError, | ||
337 | PassphraseError, | ||
338 | KeyMissing, | ||
339 | UnknownError | ||
340 | }; | ||
341 | typedef std::shared_ptr<Encryption> Ptr; | ||
342 | Encryption(); | ||
343 | Encryption(EncryptionPrivate *); | ||
344 | ~Encryption(); | ||
345 | std::vector<Key::Ptr> recipients() const; | ||
346 | QString errorString(); | ||
347 | ErrorType errorType(); | ||
348 | private: | ||
349 | std::unique_ptr<EncryptionPrivate> d; | ||
350 | }; | ||
351 | |||
352 | class Parser | ||
353 | { | ||
354 | public: | ||
355 | typedef std::shared_ptr<Parser> Ptr; | ||
356 | Parser(const QByteArray &mimeMessage); | ||
357 | ~Parser(); | ||
358 | |||
359 | Part::Ptr getPart(const QUrl &url); | ||
360 | |||
361 | QVector<Part::Ptr> collect(const Part::Ptr &start, std::function<bool(const Part::Ptr &)> select, std::function<bool(const Content::Ptr &)> filter) const; | ||
362 | Part::Ptr find(const Part::Ptr &start, std::function<bool(const Part::Ptr &)> select) const; | ||
363 | QVector<Part::Ptr> collectContentParts() const; | ||
364 | QVector<Part::Ptr> collectAttachmentParts() const; | ||
365 | //template <> QVector<ContentPart::Ptr> collect<ContentPart>() const; | ||
366 | |||
367 | //template <> static StatusObject<SignatureVerificationResult> verifySignature(const Signature signature) const; | ||
368 | //template <> static StatusObject<Part> decrypt(const EncryptedPart part) const; | ||
369 | |||
370 | signals: | ||
371 | void partsChanged(); | ||
372 | |||
373 | private: | ||
374 | std::unique_ptr<ParserPrivate> d; | ||
375 | |||
376 | friend class InterfaceTest; | ||
377 | }; | ||
378 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/interface_p.h b/framework/src/domain/mime/mimetreeparser/interface_p.h new file mode 100644 index 00000000..8fab221a --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/interface_p.h | |||
@@ -0,0 +1,56 @@ | |||
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 | #pragma once | ||
21 | |||
22 | #include "interface.h" | ||
23 | |||
24 | #include <QSharedPointer> | ||
25 | #include <QMap> | ||
26 | |||
27 | namespace KMime | ||
28 | { | ||
29 | class Message; | ||
30 | typedef QSharedPointer<Message> MessagePtr; | ||
31 | } | ||
32 | |||
33 | namespace MimeTreeParser | ||
34 | { | ||
35 | class MessagePart; | ||
36 | class NodeHelper; | ||
37 | typedef QSharedPointer<MessagePart> MessagePartPtr; | ||
38 | } | ||
39 | |||
40 | class ParserPrivate | ||
41 | { | ||
42 | public: | ||
43 | ParserPrivate(Parser *parser); | ||
44 | |||
45 | void setMessage(const QByteArray &mimeMessage); | ||
46 | void createTree(const MimeTreeParser::MessagePartPtr& start, const Part::Ptr& tree); | ||
47 | |||
48 | Part::Ptr mTree; | ||
49 | Parser *q; | ||
50 | |||
51 | MimeTreeParser::MessagePartPtr mPartTree; | ||
52 | KMime::MessagePtr mMsg; | ||
53 | std::shared_ptr<MimeTreeParser::NodeHelper> mNodeHelper; | ||
54 | QString mHtml; | ||
55 | QMap<QByteArray, QUrl> mEmbeddedPartMap; | ||
56 | }; | ||
diff --git a/framework/src/domain/mime/mimetreeparser/objecttreesource.cpp b/framework/src/domain/mime/mimetreeparser/objecttreesource.cpp new file mode 100644 index 00000000..186fdf80 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/objecttreesource.cpp | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
3 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along | ||
16 | with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #include "objecttreesource.h" | ||
21 | |||
22 | #include <otp/attachmentstrategy.h> | ||
23 | #include <otp/bodypartformatterbasefactory.h> | ||
24 | #include <otp/messagepart.h> | ||
25 | #include <otp/messagepartrenderer.h> | ||
26 | |||
27 | class ObjectSourcePrivate | ||
28 | { | ||
29 | public: | ||
30 | ObjectSourcePrivate() | ||
31 | : mWriter(0) | ||
32 | , mAllowDecryption(true) | ||
33 | , mHtmlLoadExternal(true) | ||
34 | , mPreferredMode(MimeTreeParser::Util::Html) | ||
35 | { | ||
36 | |||
37 | } | ||
38 | MimeTreeParser::HtmlWriter *mWriter; | ||
39 | MimeTreeParser::BodyPartFormatterBaseFactory mBodyPartFormatterBaseFactory; | ||
40 | bool mAllowDecryption; | ||
41 | bool mHtmlLoadExternal; | ||
42 | MimeTreeParser::Util::HtmlMode mPreferredMode; | ||
43 | }; | ||
44 | |||
45 | ObjectTreeSource::ObjectTreeSource(MimeTreeParser::HtmlWriter *writer) | ||
46 | : MimeTreeParser::Interface::ObjectTreeSource() | ||
47 | , d(new ObjectSourcePrivate) | ||
48 | { | ||
49 | d->mWriter = writer; | ||
50 | } | ||
51 | |||
52 | ObjectTreeSource::~ObjectTreeSource() | ||
53 | { | ||
54 | delete d; | ||
55 | } | ||
56 | |||
57 | void ObjectTreeSource::setAllowDecryption(bool allowDecryption) | ||
58 | { | ||
59 | d->mAllowDecryption = allowDecryption; | ||
60 | } | ||
61 | |||
62 | MimeTreeParser::HtmlWriter *ObjectTreeSource::htmlWriter() | ||
63 | { | ||
64 | return d->mWriter; | ||
65 | } | ||
66 | |||
67 | bool ObjectTreeSource::htmlLoadExternal() const | ||
68 | { | ||
69 | return d->mHtmlLoadExternal; | ||
70 | } | ||
71 | |||
72 | void ObjectTreeSource::setHtmlLoadExternal(bool loadExternal) | ||
73 | { | ||
74 | d->mHtmlLoadExternal = loadExternal; | ||
75 | } | ||
76 | |||
77 | bool ObjectTreeSource::decryptMessage() const | ||
78 | { | ||
79 | return d->mAllowDecryption; | ||
80 | } | ||
81 | |||
82 | bool ObjectTreeSource::showSignatureDetails() const | ||
83 | { | ||
84 | return true; | ||
85 | } | ||
86 | |||
87 | int ObjectTreeSource::levelQuote() const | ||
88 | { | ||
89 | return 1; | ||
90 | } | ||
91 | |||
92 | const QTextCodec *ObjectTreeSource::overrideCodec() | ||
93 | { | ||
94 | return Q_NULLPTR; | ||
95 | } | ||
96 | |||
97 | QString ObjectTreeSource::createMessageHeader(KMime::Message *message) | ||
98 | { | ||
99 | return QString(); | ||
100 | } | ||
101 | |||
102 | const MimeTreeParser::AttachmentStrategy *ObjectTreeSource::attachmentStrategy() | ||
103 | { | ||
104 | return MimeTreeParser::AttachmentStrategy::smart(); | ||
105 | } | ||
106 | |||
107 | QObject *ObjectTreeSource::sourceObject() | ||
108 | { | ||
109 | return Q_NULLPTR; | ||
110 | } | ||
111 | |||
112 | void ObjectTreeSource::setHtmlMode(MimeTreeParser::Util::HtmlMode mode, const QList<MimeTreeParser::Util::HtmlMode> &availableModes) | ||
113 | { | ||
114 | Q_UNUSED(mode); | ||
115 | Q_UNUSED(availableModes); | ||
116 | } | ||
117 | |||
118 | MimeTreeParser::Util::HtmlMode ObjectTreeSource::preferredMode() const | ||
119 | { | ||
120 | return d->mPreferredMode; | ||
121 | } | ||
122 | |||
123 | bool ObjectTreeSource::autoImportKeys() const | ||
124 | { | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | bool ObjectTreeSource::showEmoticons() const | ||
129 | { | ||
130 | return false; | ||
131 | } | ||
132 | |||
133 | bool ObjectTreeSource::showExpandQuotesMark() const | ||
134 | { | ||
135 | return false; | ||
136 | } | ||
137 | |||
138 | bool ObjectTreeSource::isPrinting() const | ||
139 | { | ||
140 | return false; | ||
141 | } | ||
142 | |||
143 | const MimeTreeParser::BodyPartFormatterBaseFactory *ObjectTreeSource::bodyPartFormatterFactory() | ||
144 | { | ||
145 | return &(d->mBodyPartFormatterBaseFactory); | ||
146 | } | ||
147 | |||
148 | MimeTreeParser::Interface::MessagePartRenderer::Ptr ObjectTreeSource::messagePartTheme(MimeTreeParser::Interface::MessagePart::Ptr msgPart) | ||
149 | { | ||
150 | Q_UNUSED(msgPart); | ||
151 | return MimeTreeParser::Interface::MessagePartRenderer::Ptr(); | ||
152 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/objecttreesource.h b/framework/src/domain/mime/mimetreeparser/objecttreesource.h new file mode 100644 index 00000000..2167e06f --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/objecttreesource.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
3 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along | ||
16 | with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef MAILVIEWER_OBJECTTREEEMPTYSOURCE_H | ||
21 | #define MAILVIEWER_OBJECTTREEEMPTYSOURCE_H | ||
22 | |||
23 | #include <otp/objecttreesource.h> | ||
24 | |||
25 | class QString; | ||
26 | |||
27 | class ObjectSourcePrivate; | ||
28 | class ObjectTreeSource : public MimeTreeParser::Interface::ObjectTreeSource | ||
29 | { | ||
30 | public: | ||
31 | ObjectTreeSource(MimeTreeParser::HtmlWriter *writer); | ||
32 | virtual ~ObjectTreeSource(); | ||
33 | void setHtmlLoadExternal(bool loadExternal); | ||
34 | bool decryptMessage() const Q_DECL_OVERRIDE; | ||
35 | bool htmlLoadExternal() const Q_DECL_OVERRIDE; | ||
36 | bool showSignatureDetails() const Q_DECL_OVERRIDE; | ||
37 | void setHtmlMode(MimeTreeParser::Util::HtmlMode mode, const QList<MimeTreeParser::Util::HtmlMode> &availableModes) Q_DECL_OVERRIDE; | ||
38 | MimeTreeParser::Util::HtmlMode preferredMode() const Q_DECL_OVERRIDE; | ||
39 | void setAllowDecryption(bool allowDecryption); | ||
40 | int levelQuote() const Q_DECL_OVERRIDE; | ||
41 | const QTextCodec *overrideCodec() Q_DECL_OVERRIDE; | ||
42 | QString createMessageHeader(KMime::Message *message) Q_DECL_OVERRIDE; | ||
43 | const MimeTreeParser::AttachmentStrategy *attachmentStrategy() Q_DECL_OVERRIDE; | ||
44 | MimeTreeParser::HtmlWriter *htmlWriter() Q_DECL_OVERRIDE; | ||
45 | QObject *sourceObject() Q_DECL_OVERRIDE; | ||
46 | bool autoImportKeys() const Q_DECL_OVERRIDE; | ||
47 | bool showEmoticons() const Q_DECL_OVERRIDE; | ||
48 | bool showExpandQuotesMark() const Q_DECL_OVERRIDE; | ||
49 | bool isPrinting() const Q_DECL_OVERRIDE; | ||
50 | const MimeTreeParser::BodyPartFormatterBaseFactory *bodyPartFormatterFactory() Q_DECL_OVERRIDE; | ||
51 | MimeTreeParser::Interface::MessagePartRendererPtr messagePartTheme(MimeTreeParser::Interface::MessagePartPtr msgPart) Q_DECL_OVERRIDE; | ||
52 | private: | ||
53 | ObjectSourcePrivate *const d; | ||
54 | }; | ||
55 | |||
56 | #endif | ||
57 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/CMakeLists.txt b/framework/src/domain/mime/mimetreeparser/otp/CMakeLists.txt new file mode 100644 index 00000000..f480fa21 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/CMakeLists.txt | |||
@@ -0,0 +1,72 @@ | |||
1 | add_definitions( -DQT_NO_CAST_FROM_ASCII ) | ||
2 | add_definitions( -DQT_NO_CAST_TO_ASCII ) | ||
3 | add_definitions("-fvisibility=default") | ||
4 | |||
5 | find_package(Qt5 COMPONENTS REQUIRED Core Gui) | ||
6 | find_package(KF5Mime "4.87.0" CONFIG REQUIRED) | ||
7 | find_package(QGpgme CONFIG REQUIRED) | ||
8 | find_package(KF5Codecs CONFIG REQUIRED) | ||
9 | find_package(KF5I18n CONFIG REQUIRED) | ||
10 | |||
11 | #add_definitions(-DTRANSLATION_DOMAIN=\"libmimetreeparser\") | ||
12 | |||
13 | # target_include_directories does not handle empty include paths | ||
14 | include_directories(${GPGME_INCLUDES}) | ||
15 | |||
16 | set(libmimetreeparser_SRCS | ||
17 | objecttreeparser.cpp | ||
18 | |||
19 | #Bodyformatter | ||
20 | applicationpgpencrypted.cpp | ||
21 | applicationpkcs7mime.cpp | ||
22 | mailman.cpp | ||
23 | multipartalternative.cpp | ||
24 | multipartencrypted.cpp | ||
25 | multipartmixed.cpp | ||
26 | multipartsigned.cpp | ||
27 | textplain.cpp | ||
28 | texthtml.cpp | ||
29 | utils.cpp | ||
30 | bodypartformatter_impl.cpp | ||
31 | |||
32 | #Interfaces | ||
33 | bodypartformatter.cpp | ||
34 | objecttreesource.cpp | ||
35 | bodypart.cpp | ||
36 | htmlwriter.cpp | ||
37 | messagepartrenderer.cpp | ||
38 | |||
39 | #bodypartformatter.cpp | ||
40 | bodypartformatterbasefactory.cpp | ||
41 | cryptohelper.cpp | ||
42 | nodehelper.cpp | ||
43 | messagepart.cpp | ||
44 | partnodebodypart.cpp | ||
45 | #Mementos | ||
46 | cryptobodypartmemento.cpp | ||
47 | decryptverifybodypartmemento.cpp | ||
48 | verifydetachedbodypartmemento.cpp | ||
49 | verifyopaquebodypartmemento.cpp | ||
50 | #Stuff | ||
51 | mimetreeparser_debug.cpp | ||
52 | qgpgmejobexecutor.cpp | ||
53 | util.cpp | ||
54 | attachmentstrategy.cpp | ||
55 | #HTML Writer | ||
56 | queuehtmlwriter.cpp | ||
57 | attachmenttemporaryfilesdirs.cpp | ||
58 | ) | ||
59 | |||
60 | add_library(kube_otp ${libmimetreeparser_SRCS}) | ||
61 | |||
62 | target_link_libraries(kube_otp | ||
63 | PRIVATE | ||
64 | QGpgme | ||
65 | KF5::Codecs | ||
66 | KF5::I18n | ||
67 | KF5::Mime | ||
68 | Qt5::Gui | ||
69 | ) | ||
70 | install(TARGETS kube_otp DESTINATION ${LIB_INSTALL_DIR}) | ||
71 | |||
72 | add_subdirectory(autotests) | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/applicationpgpencrypted.cpp b/framework/src/domain/mime/mimetreeparser/otp/applicationpgpencrypted.cpp new file mode 100644 index 00000000..e0f8e30c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/applicationpgpencrypted.cpp | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "applicationpgpencrypted.h" | ||
21 | |||
22 | #include "utils.h" | ||
23 | |||
24 | #include "objecttreeparser.h" | ||
25 | #include "messagepart.h" | ||
26 | |||
27 | #include <QGpgME/Protocol> | ||
28 | |||
29 | #include <KMime/Content> | ||
30 | |||
31 | #include "mimetreeparser_debug.h" | ||
32 | |||
33 | using namespace MimeTreeParser; | ||
34 | |||
35 | const ApplicationPGPEncryptedBodyPartFormatter *ApplicationPGPEncryptedBodyPartFormatter::self; | ||
36 | |||
37 | const Interface::BodyPartFormatter *ApplicationPGPEncryptedBodyPartFormatter::create() | ||
38 | { | ||
39 | if (!self) { | ||
40 | self = new ApplicationPGPEncryptedBodyPartFormatter(); | ||
41 | } | ||
42 | return self; | ||
43 | } | ||
44 | |||
45 | Interface::BodyPartFormatter::Result ApplicationPGPEncryptedBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
46 | { | ||
47 | Q_UNUSED(writer) | ||
48 | const auto p = process(*part); | ||
49 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
50 | if (mp) { | ||
51 | mp->html(false); | ||
52 | return Ok; | ||
53 | } | ||
54 | return Failed; | ||
55 | } | ||
56 | |||
57 | Interface::MessagePart::Ptr ApplicationPGPEncryptedBodyPartFormatter::process(Interface::BodyPart &part) const | ||
58 | { | ||
59 | KMime::Content *node(part.content()); | ||
60 | |||
61 | if (node->decodedContent().trimmed() != "Version: 1") { | ||
62 | qCWarning(MIMETREEPARSER_LOG) << "Unknown PGP Version String:" << node->decodedContent().trimmed(); | ||
63 | } | ||
64 | |||
65 | if (!part.content()->parent()) { | ||
66 | return MessagePart::Ptr(); | ||
67 | } | ||
68 | |||
69 | KMime::Content *data = findTypeInDirectChilds(part.content()->parent(), "application/octet-stream"); | ||
70 | |||
71 | if (!data) { | ||
72 | return MessagePart::Ptr(); //new MimeMessagePart(part.objectTreeParser(), node, false)); | ||
73 | } | ||
74 | |||
75 | part.nodeHelper()->setEncryptionState(node, KMMsgFullyEncrypted); | ||
76 | |||
77 | EncryptedMessagePart::Ptr mp(new EncryptedMessagePart(part.objectTreeParser(), | ||
78 | data->decodedText(), QGpgME::openpgp(), | ||
79 | part.nodeHelper()->fromAsString(data), node)); | ||
80 | mp->setIsEncrypted(true); | ||
81 | mp->setDecryptMessage(part.source()->decryptMessage()); | ||
82 | PartMetaData *messagePart(mp->partMetaData()); | ||
83 | if (!part.source()->decryptMessage()) { | ||
84 | part.nodeHelper()->setNodeProcessed(data, false); // Set the data node to done to prevent it from being processed | ||
85 | } else if (KMime::Content *newNode = part.nodeHelper()->decryptedNodeForContent(data)) { | ||
86 | // if we already have a decrypted node for this encrypted node, don't do the decryption again | ||
87 | return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), newNode, part.objectTreeParser()->showOnlyOneMimePart())); | ||
88 | } else { | ||
89 | mp->startDecryption(data); | ||
90 | if (!messagePart->inProgress) { | ||
91 | part.nodeHelper()->setNodeProcessed(data, false); // Set the data node to done to prevent it from being processed | ||
92 | if (messagePart->isDecryptable && messagePart->isSigned) { | ||
93 | part.nodeHelper()->setSignatureState(node, KMMsgFullySigned); | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | return mp; | ||
98 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/applicationpgpencrypted.h b/framework/src/domain/mime/mimetreeparser/otp/applicationpgpencrypted.h new file mode 100644 index 00000000..f0f4865c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/applicationpgpencrypted.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_APPLICATIONPGPENCYPTED_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_APPLICATIONPGPENCYPTED_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "bodypart.h" | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class ApplicationPGPEncryptedBodyPartFormatter : public Interface::BodyPartFormatter | ||
30 | { | ||
31 | static const ApplicationPGPEncryptedBodyPartFormatter *self; | ||
32 | public: | ||
33 | Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; | ||
34 | Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
35 | using Interface::BodyPartFormatter::format; | ||
36 | static const Interface::BodyPartFormatter *create(); | ||
37 | }; | ||
38 | |||
39 | } | ||
40 | |||
41 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/applicationpkcs7mime.cpp b/framework/src/domain/mime/mimetreeparser/otp/applicationpkcs7mime.cpp new file mode 100644 index 00000000..bcfc0616 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/applicationpkcs7mime.cpp | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "applicationpkcs7mime.h" | ||
21 | |||
22 | #include "utils.h" | ||
23 | |||
24 | #include "attachmentstrategy.h" | ||
25 | #include "objecttreeparser.h" | ||
26 | #include "messagepart.h" | ||
27 | |||
28 | #include <QGpgME/Protocol> | ||
29 | |||
30 | #include <KMime/Content> | ||
31 | |||
32 | #include <QTextCodec> | ||
33 | |||
34 | #include "mimetreeparser_debug.h" | ||
35 | |||
36 | using namespace MimeTreeParser; | ||
37 | |||
38 | const ApplicationPkcs7MimeBodyPartFormatter *ApplicationPkcs7MimeBodyPartFormatter::self; | ||
39 | |||
40 | const Interface::BodyPartFormatter *ApplicationPkcs7MimeBodyPartFormatter::create() | ||
41 | { | ||
42 | if (!self) { | ||
43 | self = new ApplicationPkcs7MimeBodyPartFormatter(); | ||
44 | } | ||
45 | return self; | ||
46 | } | ||
47 | Interface::BodyPartFormatter::Result ApplicationPkcs7MimeBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
48 | { | ||
49 | Q_UNUSED(writer) | ||
50 | const auto p = process(*part); | ||
51 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
52 | if (mp) { | ||
53 | mp->html(false); | ||
54 | return Ok; | ||
55 | } | ||
56 | return Failed; | ||
57 | } | ||
58 | |||
59 | Interface::MessagePart::Ptr ApplicationPkcs7MimeBodyPartFormatter::process(Interface::BodyPart &part) const | ||
60 | { | ||
61 | KMime::Content *node = part.content(); | ||
62 | |||
63 | if (node->head().isEmpty()) { | ||
64 | return MessagePart::Ptr(); | ||
65 | } | ||
66 | |||
67 | const auto smimeCrypto = QGpgME::smime(); | ||
68 | if (!smimeCrypto) { | ||
69 | return MessagePart::Ptr(); | ||
70 | } | ||
71 | |||
72 | const QString smimeType = node->contentType()->parameter(QStringLiteral("smime-type")).toLower(); | ||
73 | |||
74 | if (smimeType == QLatin1String("certs-only")) { | ||
75 | part.processResult()->setNeverDisplayInline(true); | ||
76 | |||
77 | CertMessagePart::Ptr mp(new CertMessagePart(part.objectTreeParser(), node, smimeCrypto, part.source()->autoImportKeys())); | ||
78 | return mp; | ||
79 | } | ||
80 | |||
81 | bool isSigned = (smimeType == QLatin1String("signed-data")); | ||
82 | bool isEncrypted = (smimeType == QLatin1String("enveloped-data")); | ||
83 | |||
84 | // Analyze "signTestNode" node to find/verify a signature. | ||
85 | // If zero part.objectTreeParser() verification was successfully done after | ||
86 | // decrypting via recursion by insertAndParseNewChildNode(). | ||
87 | KMime::Content *signTestNode = isEncrypted ? nullptr : node; | ||
88 | |||
89 | // We try decrypting the content | ||
90 | // if we either *know* that it is an encrypted message part | ||
91 | // or there is neither signed nor encrypted parameter. | ||
92 | MessagePart::Ptr mp; | ||
93 | if (!isSigned) { | ||
94 | if (isEncrypted) { | ||
95 | qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime == S/MIME TYPE: enveloped (encrypted) data"; | ||
96 | } else { | ||
97 | qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - type unknown - enveloped (encrypted) data ?"; | ||
98 | } | ||
99 | |||
100 | auto _mp = EncryptedMessagePart::Ptr(new EncryptedMessagePart(part.objectTreeParser(), | ||
101 | node->decodedText(), smimeCrypto, | ||
102 | part.nodeHelper()->fromAsString(node), node)); | ||
103 | mp = _mp; | ||
104 | _mp->setIsEncrypted(true); | ||
105 | _mp->setDecryptMessage(part.source()->decryptMessage()); | ||
106 | PartMetaData *messagePart(_mp->partMetaData()); | ||
107 | if (!part.source()->decryptMessage()) { | ||
108 | isEncrypted = true; | ||
109 | signTestNode = nullptr; // PENDING(marc) to be abs. sure, we'd need to have to look at the content | ||
110 | } else { | ||
111 | _mp->startDecryption(); | ||
112 | if (messagePart->isDecryptable) { | ||
113 | qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - encryption found - enveloped (encrypted) data !"; | ||
114 | isEncrypted = true; | ||
115 | part.nodeHelper()->setEncryptionState(node, KMMsgFullyEncrypted); | ||
116 | signTestNode = nullptr; | ||
117 | |||
118 | } else { | ||
119 | // decryption failed, which could be because the part was encrypted but | ||
120 | // decryption failed, or because we didn't know if it was encrypted, tried, | ||
121 | // and failed. If the message was not actually encrypted, we continue | ||
122 | // assuming it's signed | ||
123 | if (_mp->passphraseError() || (smimeType.isEmpty() && messagePart->isEncrypted)) { | ||
124 | isEncrypted = true; | ||
125 | signTestNode = nullptr; | ||
126 | } | ||
127 | |||
128 | if (isEncrypted) { | ||
129 | qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - ERROR: COULD NOT DECRYPT enveloped data !"; | ||
130 | } else { | ||
131 | qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - NO encryption found"; | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | |||
136 | if (isEncrypted) { | ||
137 | part.nodeHelper()->setEncryptionState(node, KMMsgFullyEncrypted); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | // We now try signature verification if necessarry. | ||
142 | if (signTestNode) { | ||
143 | if (isSigned) { | ||
144 | qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime == S/MIME TYPE: opaque signed data"; | ||
145 | } else { | ||
146 | qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - type unknown - opaque signed data ?"; | ||
147 | } | ||
148 | |||
149 | const QTextCodec *aCodec(part.objectTreeParser()->codecFor(signTestNode)); | ||
150 | const QByteArray signaturetext = signTestNode->decodedContent(); | ||
151 | auto _mp = SignedMessagePart::Ptr(new SignedMessagePart(part.objectTreeParser(), | ||
152 | aCodec->toUnicode(signaturetext), smimeCrypto, | ||
153 | part.nodeHelper()->fromAsString(node), signTestNode)); | ||
154 | mp = _mp; | ||
155 | //mp->setDecryptMessage(part.source()->decryptMessage()); | ||
156 | PartMetaData *messagePart(mp->partMetaData()); | ||
157 | if (smimeCrypto) { | ||
158 | _mp->startVerificationDetached(signaturetext, nullptr, QByteArray()); | ||
159 | } else { | ||
160 | messagePart->auditLogError = GpgME::Error(GPG_ERR_NOT_IMPLEMENTED); | ||
161 | } | ||
162 | |||
163 | if (_mp->isSigned()) { | ||
164 | if (!isSigned) { | ||
165 | qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - signature found - opaque signed data !"; | ||
166 | isSigned = true; | ||
167 | } | ||
168 | |||
169 | if (signTestNode != node) { | ||
170 | part.nodeHelper()->setSignatureState(node, KMMsgFullySigned); | ||
171 | } | ||
172 | } else { | ||
173 | qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - NO signature found :-("; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | return mp; | ||
178 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/applicationpkcs7mime.h b/framework/src/domain/mime/mimetreeparser/otp/applicationpkcs7mime.h new file mode 100644 index 00000000..a9a33f7c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/applicationpkcs7mime.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_APPLICATIONPKCS7MIME_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_APPLICATIONPKCS7MIME_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "bodypart.h" | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class ApplicationPkcs7MimeBodyPartFormatter : public Interface::BodyPartFormatter | ||
30 | { | ||
31 | static const ApplicationPkcs7MimeBodyPartFormatter *self; | ||
32 | public: | ||
33 | Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; | ||
34 | Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
35 | using Interface::BodyPartFormatter::format; | ||
36 | static const Interface::BodyPartFormatter *create(); | ||
37 | }; | ||
38 | |||
39 | } | ||
40 | |||
41 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/attachmentstrategy.cpp b/framework/src/domain/mime/mimetreeparser/otp/attachmentstrategy.cpp new file mode 100644 index 00000000..5ea21133 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/attachmentstrategy.cpp | |||
@@ -0,0 +1,343 @@ | |||
1 | /* -*- c++ -*- | ||
2 | attachmentstrategy.cpp | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
7 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
8 | |||
9 | KMail is free software; you can redistribute it and/or modify it | ||
10 | under the terms of the GNU General Public License, version 2, as | ||
11 | published by the Free Software Foundation. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #include "attachmentstrategy.h" | ||
35 | |||
36 | #include "nodehelper.h" | ||
37 | #include "util.h" | ||
38 | |||
39 | #include <KMime/Content> | ||
40 | |||
41 | #include <QIcon> | ||
42 | |||
43 | #include "mimetreeparser_debug.h" | ||
44 | |||
45 | using namespace MimeTreeParser; | ||
46 | |||
47 | static AttachmentStrategy::Display smartDisplay(KMime::Content *node) | ||
48 | { | ||
49 | const auto cd = node->contentDisposition(false); | ||
50 | |||
51 | if (cd && cd->disposition() == KMime::Headers::CDinline) | ||
52 | // explict "inline" disposition: | ||
53 | { | ||
54 | return AttachmentStrategy::Inline; | ||
55 | } | ||
56 | if (cd && cd->disposition() == KMime::Headers::CDattachment) | ||
57 | // explicit "attachment" disposition: | ||
58 | { | ||
59 | return AttachmentStrategy::AsIcon; | ||
60 | } | ||
61 | |||
62 | const auto ct = node->contentType(false); | ||
63 | if (ct && ct->isText() && ct->name().trimmed().isEmpty() && | ||
64 | (!cd || cd->filename().trimmed().isEmpty())) | ||
65 | // text/* w/o filename parameter: | ||
66 | { | ||
67 | return AttachmentStrategy::Inline; | ||
68 | } | ||
69 | return AttachmentStrategy::AsIcon; | ||
70 | } | ||
71 | |||
72 | // | ||
73 | // IconicAttachmentStrategy: | ||
74 | // show everything but the first text/plain body as icons | ||
75 | // | ||
76 | |||
77 | class IconicAttachmentStrategy : public AttachmentStrategy | ||
78 | { | ||
79 | friend class AttachmentStrategy; | ||
80 | protected: | ||
81 | IconicAttachmentStrategy() : AttachmentStrategy() {} | ||
82 | virtual ~IconicAttachmentStrategy() {} | ||
83 | |||
84 | public: | ||
85 | const char *name() const Q_DECL_OVERRIDE | ||
86 | { | ||
87 | return "iconic"; | ||
88 | } | ||
89 | |||
90 | bool inlineNestedMessages() const Q_DECL_OVERRIDE | ||
91 | { | ||
92 | return false; | ||
93 | } | ||
94 | Display defaultDisplay(KMime::Content *node) const Q_DECL_OVERRIDE | ||
95 | { | ||
96 | if (node->contentType()->isText() && | ||
97 | node->contentDisposition()->filename().trimmed().isEmpty() && | ||
98 | node->contentType()->name().trimmed().isEmpty()) | ||
99 | // text/* w/o filename parameter: | ||
100 | { | ||
101 | return Inline; | ||
102 | } | ||
103 | return AsIcon; | ||
104 | } | ||
105 | }; | ||
106 | |||
107 | // | ||
108 | // SmartAttachmentStrategy: | ||
109 | // in addition to Iconic, show all body parts | ||
110 | // with content-disposition == "inline" and | ||
111 | // all text parts without a filename or name parameter inline | ||
112 | // | ||
113 | |||
114 | class SmartAttachmentStrategy : public AttachmentStrategy | ||
115 | { | ||
116 | friend class AttachmentStrategy; | ||
117 | protected: | ||
118 | SmartAttachmentStrategy() : AttachmentStrategy() {} | ||
119 | virtual ~SmartAttachmentStrategy() {} | ||
120 | |||
121 | public: | ||
122 | const char *name() const Q_DECL_OVERRIDE | ||
123 | { | ||
124 | return "smart"; | ||
125 | } | ||
126 | |||
127 | bool inlineNestedMessages() const Q_DECL_OVERRIDE | ||
128 | { | ||
129 | return true; | ||
130 | } | ||
131 | Display defaultDisplay(KMime::Content *node) const Q_DECL_OVERRIDE | ||
132 | { | ||
133 | return smartDisplay(node); | ||
134 | } | ||
135 | }; | ||
136 | |||
137 | // | ||
138 | // InlinedAttachmentStrategy: | ||
139 | // show everything possible inline | ||
140 | // | ||
141 | |||
142 | class InlinedAttachmentStrategy : public AttachmentStrategy | ||
143 | { | ||
144 | friend class AttachmentStrategy; | ||
145 | protected: | ||
146 | InlinedAttachmentStrategy() : AttachmentStrategy() {} | ||
147 | virtual ~InlinedAttachmentStrategy() {} | ||
148 | |||
149 | public: | ||
150 | const char *name() const Q_DECL_OVERRIDE | ||
151 | { | ||
152 | return "inlined"; | ||
153 | } | ||
154 | |||
155 | bool inlineNestedMessages() const Q_DECL_OVERRIDE | ||
156 | { | ||
157 | return true; | ||
158 | } | ||
159 | Display defaultDisplay(KMime::Content *) const Q_DECL_OVERRIDE | ||
160 | { | ||
161 | return Inline; | ||
162 | } | ||
163 | }; | ||
164 | |||
165 | // | ||
166 | // HiddenAttachmentStrategy | ||
167 | // show nothing except the first text/plain body part _at all_ | ||
168 | // | ||
169 | |||
170 | class HiddenAttachmentStrategy : public AttachmentStrategy | ||
171 | { | ||
172 | friend class AttachmentStrategy; | ||
173 | protected: | ||
174 | HiddenAttachmentStrategy() : AttachmentStrategy() {} | ||
175 | virtual ~HiddenAttachmentStrategy() {} | ||
176 | |||
177 | public: | ||
178 | const char *name() const Q_DECL_OVERRIDE | ||
179 | { | ||
180 | return "hidden"; | ||
181 | } | ||
182 | |||
183 | bool inlineNestedMessages() const Q_DECL_OVERRIDE | ||
184 | { | ||
185 | return false; | ||
186 | } | ||
187 | Display defaultDisplay(KMime::Content *node) const Q_DECL_OVERRIDE | ||
188 | { | ||
189 | if (node->contentType()->isText() && | ||
190 | node->contentDisposition()->filename().trimmed().isEmpty() && | ||
191 | node->contentType()->name().trimmed().isEmpty()) | ||
192 | // text/* w/o filename parameter: | ||
193 | { | ||
194 | return Inline; | ||
195 | } | ||
196 | if (!node->parent()) { | ||
197 | return Inline; | ||
198 | } | ||
199 | |||
200 | if (node->parent() && node->parent()->contentType()->isMultipart() && | ||
201 | node->parent()->contentType()->subType() == "related") { | ||
202 | return Inline; | ||
203 | } | ||
204 | |||
205 | return None; | ||
206 | } | ||
207 | }; | ||
208 | |||
209 | class HeaderOnlyAttachmentStrategy : public AttachmentStrategy | ||
210 | { | ||
211 | friend class AttachmentStrategy; | ||
212 | protected: | ||
213 | HeaderOnlyAttachmentStrategy() : AttachmentStrategy() {} | ||
214 | virtual ~HeaderOnlyAttachmentStrategy() {} | ||
215 | |||
216 | public: | ||
217 | const char *name() const Q_DECL_OVERRIDE | ||
218 | { | ||
219 | return "headerOnly"; | ||
220 | } | ||
221 | |||
222 | bool inlineNestedMessages() const Q_DECL_OVERRIDE | ||
223 | { | ||
224 | return true; | ||
225 | } | ||
226 | |||
227 | Display defaultDisplay(KMime::Content *node) const Q_DECL_OVERRIDE | ||
228 | { | ||
229 | if (NodeHelper::isInEncapsulatedMessage(node)) { | ||
230 | return smartDisplay(node); | ||
231 | } | ||
232 | |||
233 | if (!Util::labelForContent(node).isEmpty() && QIcon::hasThemeIcon(Util::iconNameForContent(node)) && ! Util::isTypeBlacklisted(node)) { | ||
234 | return None; | ||
235 | } | ||
236 | return smartDisplay(node); | ||
237 | } | ||
238 | |||
239 | bool requiresAttachmentListInHeader() const Q_DECL_OVERRIDE | ||
240 | { | ||
241 | return true; | ||
242 | } | ||
243 | }; | ||
244 | |||
245 | // | ||
246 | // AttachmentStrategy abstract base: | ||
247 | // | ||
248 | |||
249 | AttachmentStrategy::AttachmentStrategy() | ||
250 | { | ||
251 | |||
252 | } | ||
253 | |||
254 | AttachmentStrategy::~AttachmentStrategy() | ||
255 | { | ||
256 | |||
257 | } | ||
258 | |||
259 | const AttachmentStrategy *AttachmentStrategy::create(Type type) | ||
260 | { | ||
261 | switch (type) { | ||
262 | case Iconic: return iconic(); | ||
263 | case Smart: return smart(); | ||
264 | case Inlined: return inlined(); | ||
265 | case Hidden: return hidden(); | ||
266 | case HeaderOnly: return headerOnly(); | ||
267 | } | ||
268 | qCCritical(MIMETREEPARSER_LOG) << "Unknown attachment startegy ( type ==" | ||
269 | << (int)type << ") requested!"; | ||
270 | return nullptr; // make compiler happy | ||
271 | } | ||
272 | |||
273 | const AttachmentStrategy *AttachmentStrategy::create(const QString &type) | ||
274 | { | ||
275 | const QString lowerType = type.toLower(); | ||
276 | if (lowerType == QLatin1String("iconic")) { | ||
277 | return iconic(); | ||
278 | } | ||
279 | //if ( lowerType == "smart" ) return smart(); // not needed, see below | ||
280 | if (lowerType == QLatin1String("inlined")) { | ||
281 | return inlined(); | ||
282 | } | ||
283 | if (lowerType == QLatin1String("hidden")) { | ||
284 | return hidden(); | ||
285 | } | ||
286 | if (lowerType == QLatin1String("headeronly")) { | ||
287 | return headerOnly(); | ||
288 | } | ||
289 | // don't kFatal here, b/c the strings are user-provided | ||
290 | // (KConfig), so fail gracefully to the default: | ||
291 | return smart(); | ||
292 | } | ||
293 | |||
294 | static const AttachmentStrategy *iconicStrategy = nullptr; | ||
295 | static const AttachmentStrategy *smartStrategy = nullptr; | ||
296 | static const AttachmentStrategy *inlinedStrategy = nullptr; | ||
297 | static const AttachmentStrategy *hiddenStrategy = nullptr; | ||
298 | static const AttachmentStrategy *headerOnlyStrategy = nullptr; | ||
299 | |||
300 | const AttachmentStrategy *AttachmentStrategy::iconic() | ||
301 | { | ||
302 | if (!iconicStrategy) { | ||
303 | iconicStrategy = new IconicAttachmentStrategy(); | ||
304 | } | ||
305 | return iconicStrategy; | ||
306 | } | ||
307 | |||
308 | const AttachmentStrategy *AttachmentStrategy::smart() | ||
309 | { | ||
310 | if (!smartStrategy) { | ||
311 | smartStrategy = new SmartAttachmentStrategy(); | ||
312 | } | ||
313 | return smartStrategy; | ||
314 | } | ||
315 | |||
316 | const AttachmentStrategy *AttachmentStrategy::inlined() | ||
317 | { | ||
318 | if (!inlinedStrategy) { | ||
319 | inlinedStrategy = new InlinedAttachmentStrategy(); | ||
320 | } | ||
321 | return inlinedStrategy; | ||
322 | } | ||
323 | |||
324 | const AttachmentStrategy *AttachmentStrategy::hidden() | ||
325 | { | ||
326 | if (!hiddenStrategy) { | ||
327 | hiddenStrategy = new HiddenAttachmentStrategy(); | ||
328 | } | ||
329 | return hiddenStrategy; | ||
330 | } | ||
331 | |||
332 | const AttachmentStrategy *AttachmentStrategy::headerOnly() | ||
333 | { | ||
334 | if (!headerOnlyStrategy) { | ||
335 | headerOnlyStrategy = new HeaderOnlyAttachmentStrategy(); | ||
336 | } | ||
337 | return headerOnlyStrategy; | ||
338 | } | ||
339 | |||
340 | bool AttachmentStrategy::requiresAttachmentListInHeader() const | ||
341 | { | ||
342 | return false; | ||
343 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/attachmentstrategy.h b/framework/src/domain/mime/mimetreeparser/otp/attachmentstrategy.h new file mode 100644 index 00000000..a0b5dc81 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/attachmentstrategy.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* -*- c++ -*- | ||
2 | attachmentstrategy.h | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
7 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
8 | |||
9 | KMail is free software; you can redistribute it and/or modify it | ||
10 | under the terms of the GNU General Public License, version 2, as | ||
11 | published by the Free Software Foundation. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #ifndef __MIMETREEPARSER_ATTACHMENTSTRATEGY_H__ | ||
35 | #define __MIMETREEPARSER_ATTACHMENTSTRATEGY_H__ | ||
36 | |||
37 | class QString; | ||
38 | namespace KMime | ||
39 | { | ||
40 | class Content; | ||
41 | } | ||
42 | |||
43 | namespace MimeTreeParser | ||
44 | { | ||
45 | |||
46 | class AttachmentStrategy | ||
47 | { | ||
48 | protected: | ||
49 | AttachmentStrategy(); | ||
50 | virtual ~AttachmentStrategy(); | ||
51 | |||
52 | public: | ||
53 | // | ||
54 | // Factory methods: | ||
55 | // | ||
56 | enum Type { Iconic, Smart, Inlined, Hidden, HeaderOnly }; | ||
57 | |||
58 | static const AttachmentStrategy *create(Type type); | ||
59 | static const AttachmentStrategy *create(const QString &type); | ||
60 | |||
61 | static const AttachmentStrategy *iconic(); | ||
62 | static const AttachmentStrategy *smart(); | ||
63 | static const AttachmentStrategy *inlined(); | ||
64 | static const AttachmentStrategy *hidden(); | ||
65 | static const AttachmentStrategy *headerOnly(); | ||
66 | |||
67 | // | ||
68 | // Navigation methods: | ||
69 | // | ||
70 | |||
71 | virtual const char *name() const = 0; | ||
72 | |||
73 | // | ||
74 | // Bahavioural: | ||
75 | // | ||
76 | |||
77 | enum Display { None, AsIcon, Inline }; | ||
78 | |||
79 | virtual bool inlineNestedMessages() const = 0; | ||
80 | virtual Display defaultDisplay(KMime::Content *node) const = 0; | ||
81 | virtual bool requiresAttachmentListInHeader() const; | ||
82 | }; | ||
83 | |||
84 | } | ||
85 | |||
86 | #endif // __MIMETREEPARSER_ATTACHMENTSTRATEGY_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/attachmenttemporaryfilesdirs.cpp b/framework/src/domain/mime/mimetreeparser/otp/attachmenttemporaryfilesdirs.cpp new file mode 100644 index 00000000..364bc422 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/attachmenttemporaryfilesdirs.cpp | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | Copyright (c) 2013-2017 Montel Laurent <montel@kde.org> | ||
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 | |||
21 | #include "attachmenttemporaryfilesdirs.h" | ||
22 | |||
23 | #include <QDir> | ||
24 | #include <QFile> | ||
25 | #include <QTimer> | ||
26 | |||
27 | using namespace MimeTreeParser; | ||
28 | |||
29 | class MimeTreeParser::AttachmentTemporaryFilesDirsPrivate | ||
30 | { | ||
31 | public: | ||
32 | AttachmentTemporaryFilesDirsPrivate() | ||
33 | : mDelayRemoveAll(10000) | ||
34 | { | ||
35 | |||
36 | } | ||
37 | QStringList mTempFiles; | ||
38 | QStringList mTempDirs; | ||
39 | int mDelayRemoveAll; | ||
40 | }; | ||
41 | |||
42 | AttachmentTemporaryFilesDirs::AttachmentTemporaryFilesDirs(QObject *parent) | ||
43 | : QObject(parent), | ||
44 | d(new AttachmentTemporaryFilesDirsPrivate) | ||
45 | { | ||
46 | |||
47 | } | ||
48 | |||
49 | AttachmentTemporaryFilesDirs::~AttachmentTemporaryFilesDirs() | ||
50 | { | ||
51 | delete d; | ||
52 | } | ||
53 | |||
54 | void AttachmentTemporaryFilesDirs::setDelayRemoveAllInMs(int ms) | ||
55 | { | ||
56 | d->mDelayRemoveAll = (ms < 0) ? 0 : ms; | ||
57 | } | ||
58 | |||
59 | void AttachmentTemporaryFilesDirs::removeTempFiles() | ||
60 | { | ||
61 | QTimer::singleShot(d->mDelayRemoveAll, this, &AttachmentTemporaryFilesDirs::slotRemoveTempFiles); | ||
62 | } | ||
63 | |||
64 | void AttachmentTemporaryFilesDirs::forceCleanTempFiles() | ||
65 | { | ||
66 | QStringList::ConstIterator end = d->mTempFiles.constEnd(); | ||
67 | for (QStringList::ConstIterator it = d->mTempFiles.constBegin(); it != end; ++it) { | ||
68 | QFile::remove(*it); | ||
69 | } | ||
70 | d->mTempFiles.clear(); | ||
71 | end = d->mTempDirs.constEnd(); | ||
72 | for (QStringList::ConstIterator it = d->mTempDirs.constBegin(); it != end; ++it) { | ||
73 | QDir(*it).rmdir(*it); | ||
74 | } | ||
75 | d->mTempDirs.clear(); | ||
76 | } | ||
77 | |||
78 | void AttachmentTemporaryFilesDirs::slotRemoveTempFiles() | ||
79 | { | ||
80 | forceCleanTempFiles(); | ||
81 | //Delete it after cleaning | ||
82 | deleteLater(); | ||
83 | } | ||
84 | |||
85 | void AttachmentTemporaryFilesDirs::addTempFile(const QString &file) | ||
86 | { | ||
87 | if (!d->mTempFiles.contains(file)) { | ||
88 | d->mTempFiles.append(file); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | void AttachmentTemporaryFilesDirs::addTempDir(const QString &dir) | ||
93 | { | ||
94 | if (!d->mTempDirs.contains(dir)) { | ||
95 | d->mTempDirs.append(dir); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | QStringList AttachmentTemporaryFilesDirs::temporaryFiles() const | ||
100 | { | ||
101 | return d->mTempFiles; | ||
102 | } | ||
103 | |||
104 | QStringList AttachmentTemporaryFilesDirs::temporaryDirs() const | ||
105 | { | ||
106 | return d->mTempDirs; | ||
107 | } | ||
108 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/attachmenttemporaryfilesdirs.h b/framework/src/domain/mime/mimetreeparser/otp/attachmenttemporaryfilesdirs.h new file mode 100644 index 00000000..bf65fcdb --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/attachmenttemporaryfilesdirs.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | Copyright (c) 2013-2016 Montel Laurent <montel@kde.org> | ||
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 | |||
21 | #ifndef ATTACHMENTTEMPORARYFILESDIRS_H | ||
22 | #define ATTACHMENTTEMPORARYFILESDIRS_H | ||
23 | |||
24 | #include <QObject> | ||
25 | #include <QStringList> | ||
26 | |||
27 | namespace MimeTreeParser | ||
28 | { | ||
29 | class AttachmentTemporaryFilesDirsPrivate; | ||
30 | |||
31 | class AttachmentTemporaryFilesDirs : public QObject | ||
32 | { | ||
33 | Q_OBJECT | ||
34 | public: | ||
35 | explicit AttachmentTemporaryFilesDirs(QObject *parent = nullptr); | ||
36 | ~AttachmentTemporaryFilesDirs(); | ||
37 | |||
38 | void addTempFile(const QString &file); | ||
39 | void addTempDir(const QString &dir); | ||
40 | QStringList temporaryFiles() const; | ||
41 | void removeTempFiles(); | ||
42 | void forceCleanTempFiles(); | ||
43 | |||
44 | QStringList temporaryDirs() const; | ||
45 | |||
46 | void setDelayRemoveAllInMs(int ms); | ||
47 | |||
48 | private Q_SLOTS: | ||
49 | void slotRemoveTempFiles(); | ||
50 | |||
51 | private: | ||
52 | AttachmentTemporaryFilesDirsPrivate *const d; | ||
53 | }; | ||
54 | |||
55 | } | ||
56 | |||
57 | #endif // ATTACHMENTTEMPORARYFILESDIRS_H | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/CMakeLists.txt b/framework/src/domain/mime/mimetreeparser/otp/autotests/CMakeLists.txt new file mode 100644 index 00000000..789ee795 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/CMakeLists.txt | |||
@@ -0,0 +1,46 @@ | |||
1 | include_directories(../) | ||
2 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) | ||
3 | |||
4 | set(AUTOMOC ON) | ||
5 | |||
6 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) | ||
7 | add_definitions( -DMAIL_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" ) | ||
8 | |||
9 | include(${CMAKE_CURRENT_SOURCE_DIR}/kdepim_add_gpg_crypto_test.cmake) | ||
10 | |||
11 | # convenience macro to add qtest unit tests | ||
12 | macro(add_mimetreeparser_unittest _source) | ||
13 | get_filename_component(_name ${_source} NAME_WE) | ||
14 | ecm_add_test(${_source} util.cpp setupenv.cpp | ||
15 | TEST_NAME ${_name} | ||
16 | NAME_PREFIX "mimetreeparser-" | ||
17 | LINK_LIBRARIES kube_otp Qt5::Test KF5::Mime Gpgmepp | ||
18 | ) | ||
19 | endmacro () | ||
20 | |||
21 | macro(add_mimetreeparser_class_unittest _source _additionalSource) | ||
22 | get_filename_component(_name ${_source} NAME_WE) | ||
23 | ecm_add_test(${_source} ${_additionalSource} | ||
24 | TEST_NAME ${_name} | ||
25 | NAME_PREFIX "mimetreeparser-" | ||
26 | LINK_LIBRARIES kube_otp Qt5::Test KF5::Mime Gpgmepp | ||
27 | ) | ||
28 | endmacro () | ||
29 | |||
30 | macro(add_mimetreeparser_crypto_unittest _source) | ||
31 | set(_test ${_source} util.cpp) | ||
32 | get_filename_component(_name ${_source} NAME_WE) | ||
33 | add_executable( ${_name} ${_test} setupenv.cpp) | ||
34 | ecm_mark_as_test(mimetreeparser-${_name}) | ||
35 | target_link_libraries( ${_name} | ||
36 | kube_otp | ||
37 | Qt5::Test | ||
38 | KF5::Mime | ||
39 | Gpgmepp | ||
40 | ) | ||
41 | add_gpg_crypto_test(${_name} mimetreeparser-${_name}) | ||
42 | endmacro () | ||
43 | |||
44 | add_mimetreeparser_crypto_unittest(attachmenttest.cpp) | ||
45 | add_mimetreeparser_unittest(nodehelpertest.cpp) | ||
46 | add_mimetreeparser_class_unittest(cryptohelpertest.cpp "../cryptohelper.cpp") | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/attachmenttest.cpp b/framework/src/domain/mime/mimetreeparser/otp/autotests/attachmenttest.cpp new file mode 100644 index 00000000..44e40a45 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/attachmenttest.cpp | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | Copyright (c) 2015 Volker Krause <vkrause@kde.org> | ||
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 | #include "objecttreeparser.h" | ||
20 | #include "util.h" | ||
21 | |||
22 | #include "setupenv.h" | ||
23 | |||
24 | #include <qtest.h> | ||
25 | |||
26 | using namespace MimeTreeParser; | ||
27 | |||
28 | class AttachmentTest : public QObject | ||
29 | { | ||
30 | Q_OBJECT | ||
31 | private Q_SLOTS: | ||
32 | void initTestCase(); | ||
33 | void testEncryptedAttachment_data(); | ||
34 | void testEncryptedAttachment(); | ||
35 | }; | ||
36 | |||
37 | QTEST_MAIN(AttachmentTest) | ||
38 | |||
39 | void AttachmentTest::initTestCase() | ||
40 | { | ||
41 | MimeTreeParser::Test::setupEnv(); | ||
42 | } | ||
43 | |||
44 | void AttachmentTest::testEncryptedAttachment_data() | ||
45 | { | ||
46 | QTest::addColumn<QString>("mbox"); | ||
47 | QTest::newRow("encrypted") << "openpgp-encrypted-two-attachments.mbox"; | ||
48 | QTest::newRow("signed") << "openpgp-signed-two-attachments.mbox"; | ||
49 | QTest::newRow("signed+encrypted") << "openpgp-signed-encrypted-two-attachments.mbox"; | ||
50 | QTest::newRow("encrypted+partial signed") << "openpgp-encrypted-partially-signed-attachments.mbox"; | ||
51 | } | ||
52 | |||
53 | void AttachmentTest::testEncryptedAttachment() | ||
54 | { | ||
55 | QFETCH(QString, mbox); | ||
56 | auto msg = readAndParseMail(mbox); | ||
57 | NodeHelper nodeHelper; | ||
58 | Test::TestObjectTreeSource testSource(nullptr); | ||
59 | testSource.setAllowDecryption(true); | ||
60 | ObjectTreeParser otp(&testSource, &nodeHelper); | ||
61 | otp.parseObjectTree(msg.data()); | ||
62 | |||
63 | auto attachments = msg->attachments(); | ||
64 | auto encAtts = nodeHelper.attachmentsOfExtraContents(); | ||
65 | QCOMPARE(attachments.size() + encAtts.size(), 2); | ||
66 | } | ||
67 | |||
68 | #include "attachmenttest.moc" | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/cryptohelpertest.cpp b/framework/src/domain/mime/mimetreeparser/otp/autotests/cryptohelpertest.cpp new file mode 100644 index 00000000..251e657d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/cryptohelpertest.cpp | |||
@@ -0,0 +1,144 @@ | |||
1 | /* Copyright 2015 Sandro Knauß <knauss@kolabsys.com> | ||
2 | |||
3 | This program is free software; you can redistribute it and/or | ||
4 | modify it under the terms of the GNU General Public License as | ||
5 | published by the Free Software Foundation; either version 2 of | ||
6 | the License or (at your option) version 3 or any later version | ||
7 | accepted by the membership of KDE e.V. (or its successor approved | ||
8 | by the membership of KDE e.V.), which shall act as a proxy | ||
9 | defined in Section 14 of version 3 of the license. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #include "cryptohelpertest.h" | ||
20 | |||
21 | #include "cryptohelper.h" | ||
22 | |||
23 | #include <QTest> | ||
24 | |||
25 | using namespace MimeTreeParser; | ||
26 | |||
27 | void CryptoHelperTest::testPMFDEmpty() | ||
28 | { | ||
29 | QCOMPARE(prepareMessageForDecryption("").count(), 0); | ||
30 | } | ||
31 | |||
32 | void CryptoHelperTest::testPMFDWithNoPGPBlock() | ||
33 | { | ||
34 | const QByteArray text = "testblabla"; | ||
35 | const QList<Block> blocks = prepareMessageForDecryption(text); | ||
36 | QCOMPARE(blocks.count(), 1); | ||
37 | QCOMPARE(blocks[0].text(), text); | ||
38 | QCOMPARE(blocks[0].type(), NoPgpBlock); | ||
39 | } | ||
40 | |||
41 | void CryptoHelperTest::testPGPBlockType() | ||
42 | { | ||
43 | const QString blockText = QStringLiteral("text"); | ||
44 | const QString preString = QStringLiteral("before\n"); | ||
45 | for (int i = 1; i <= PrivateKeyBlock; ++i) { | ||
46 | QString name; | ||
47 | switch (i) { | ||
48 | case PgpMessageBlock: | ||
49 | name = QStringLiteral("MESSAGE"); | ||
50 | break; | ||
51 | case MultiPgpMessageBlock: | ||
52 | name = QStringLiteral("MESSAGE PART"); | ||
53 | break; | ||
54 | case SignatureBlock: | ||
55 | name = QStringLiteral("SIGNATURE"); | ||
56 | break; | ||
57 | case ClearsignedBlock: | ||
58 | name = QStringLiteral("SIGNED MESSAGE"); | ||
59 | break; | ||
60 | case PublicKeyBlock: | ||
61 | name = QStringLiteral("PUBLIC KEY BLOCK"); | ||
62 | break; | ||
63 | case PrivateKeyBlock: | ||
64 | name = QStringLiteral("PRIVATE KEY BLOCK"); | ||
65 | break; | ||
66 | } | ||
67 | QString text = QLatin1String("-----BEGIN PGP ") + name + QLatin1String("\n") + blockText; | ||
68 | QList<Block> blocks = prepareMessageForDecryption(preString.toLatin1() + text.toLatin1()); | ||
69 | QCOMPARE(blocks.count(), 1); | ||
70 | QCOMPARE(blocks[0].type(), UnknownBlock); | ||
71 | |||
72 | text += QLatin1String("\n-----END PGP ") + name + QLatin1String("\n"); | ||
73 | blocks = prepareMessageForDecryption(preString.toLatin1() + text.toLatin1()); | ||
74 | QCOMPARE(blocks.count(), 2); | ||
75 | QCOMPARE(blocks[1].text(), text.toLatin1()); | ||
76 | QCOMPARE(blocks[1].type(), static_cast<PGPBlockType>(i)); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | void CryptoHelperTest::testDeterminePGPBlockType() | ||
81 | { | ||
82 | const QString blockText = QStringLiteral("text"); | ||
83 | for (int i = 1; i <= PrivateKeyBlock; ++i) { | ||
84 | QString name; | ||
85 | switch (i) { | ||
86 | |||
87 | case PgpMessageBlock: | ||
88 | name = QStringLiteral("MESSAGE"); | ||
89 | break; | ||
90 | case MultiPgpMessageBlock: | ||
91 | name = QStringLiteral("MESSAGE PART"); | ||
92 | break; | ||
93 | case SignatureBlock: | ||
94 | name = QStringLiteral("SIGNATURE"); | ||
95 | break; | ||
96 | case ClearsignedBlock: | ||
97 | name = QStringLiteral("SIGNED MESSAGE"); | ||
98 | break; | ||
99 | case PublicKeyBlock: | ||
100 | name = QStringLiteral("PUBLIC KEY BLOCK"); | ||
101 | break; | ||
102 | case PrivateKeyBlock: | ||
103 | name = QStringLiteral("PRIVATE KEY BLOCK"); | ||
104 | break; | ||
105 | } | ||
106 | const QString text = QLatin1String("-----BEGIN PGP ") + name + QLatin1String("\n") + blockText + QLatin1String("\n"); | ||
107 | const Block block = Block(text.toLatin1()); | ||
108 | QCOMPARE(block.text(), text.toLatin1()); | ||
109 | QCOMPARE(block.type(), static_cast<PGPBlockType>(i)); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | void CryptoHelperTest::testEmbededPGPBlock() | ||
114 | { | ||
115 | const QByteArray text = QByteArray("before\n-----BEGIN PGP MESSAGE-----\ncrypted - you see :)\n-----END PGP MESSAGE-----\nafter"); | ||
116 | const QList<Block> blocks = prepareMessageForDecryption(text); | ||
117 | QCOMPARE(blocks.count(), 3); | ||
118 | QCOMPARE(blocks[0].text(), QByteArray("before\n")); | ||
119 | QCOMPARE(blocks[1].text(), QByteArray("-----BEGIN PGP MESSAGE-----\ncrypted - you see :)\n-----END PGP MESSAGE-----\n")); | ||
120 | QCOMPARE(blocks[2].text(), QByteArray("after")); | ||
121 | } | ||
122 | |||
123 | void CryptoHelperTest::testClearSignedMessage() | ||
124 | { | ||
125 | const QByteArray text = QByteArray("before\n-----BEGIN PGP SIGNED MESSAGE-----\nsigned content\n-----BEGIN PGP SIGNATURE-----\nfancy signature\n-----END PGP SIGNATURE-----\nafter"); | ||
126 | const QList<Block> blocks = prepareMessageForDecryption(text); | ||
127 | QCOMPARE(blocks.count(), 3); | ||
128 | QCOMPARE(blocks[0].text(), QByteArray("before\n")); | ||
129 | QCOMPARE(blocks[1].text(), QByteArray("-----BEGIN PGP SIGNED MESSAGE-----\nsigned content\n-----BEGIN PGP SIGNATURE-----\nfancy signature\n-----END PGP SIGNATURE-----\n")); | ||
130 | QCOMPARE(blocks[2].text(), QByteArray("after")); | ||
131 | } | ||
132 | |||
133 | void CryptoHelperTest::testMultipleBlockMessage() | ||
134 | { | ||
135 | const QByteArray text = QByteArray("before\n-----BEGIN PGP SIGNED MESSAGE-----\nsigned content\n-----BEGIN PGP SIGNATURE-----\nfancy signature\n-----END PGP SIGNATURE-----\nafter\n-----BEGIN PGP MESSAGE-----\ncrypted - you see :)\n-----END PGP MESSAGE-----\n"); | ||
136 | const QList<Block> blocks = prepareMessageForDecryption(text); | ||
137 | QCOMPARE(blocks.count(), 4); | ||
138 | QCOMPARE(blocks[0].text(), QByteArray("before\n")); | ||
139 | QCOMPARE(blocks[1].text(), QByteArray("-----BEGIN PGP SIGNED MESSAGE-----\nsigned content\n-----BEGIN PGP SIGNATURE-----\nfancy signature\n-----END PGP SIGNATURE-----\n")); | ||
140 | QCOMPARE(blocks[2].text(), QByteArray("after\n")); | ||
141 | QCOMPARE(blocks[3].text(), QByteArray("-----BEGIN PGP MESSAGE-----\ncrypted - you see :)\n-----END PGP MESSAGE-----\n")); | ||
142 | } | ||
143 | |||
144 | QTEST_APPLESS_MAIN(CryptoHelperTest) | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/cryptohelpertest.h b/framework/src/domain/mime/mimetreeparser/otp/autotests/cryptohelpertest.h new file mode 100644 index 00000000..71ae086f --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/cryptohelpertest.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* Copyright 2009 Thomas McGuire <mcguire@kde.org> | ||
2 | |||
3 | This program is free software; you can redistribute it and/or | ||
4 | modify it under the terms of the GNU General Public License as | ||
5 | published by the Free Software Foundation; either version 2 of | ||
6 | the License or (at your option) version 3 or any later version | ||
7 | accepted by the membership of KDE e.V. (or its successor approved | ||
8 | by the membership of KDE e.V.), which shall act as a proxy | ||
9 | defined in Section 14 of version 3 of the license. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef CRYPTOHELPERTEST_H | ||
20 | #define CRYPTOHELPERTEST_H | ||
21 | |||
22 | #include <QObject> | ||
23 | |||
24 | namespace MimeTreeParser | ||
25 | { | ||
26 | |||
27 | class CryptoHelperTest : public QObject | ||
28 | { | ||
29 | Q_OBJECT | ||
30 | |||
31 | private Q_SLOTS: | ||
32 | void testPMFDEmpty(); | ||
33 | void testPMFDWithNoPGPBlock(); | ||
34 | void testPGPBlockType(); | ||
35 | void testDeterminePGPBlockType(); | ||
36 | void testEmbededPGPBlock(); | ||
37 | void testClearSignedMessage(); | ||
38 | void testMultipleBlockMessage(); | ||
39 | }; | ||
40 | |||
41 | } | ||
42 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative-notext.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative-notext.mbox new file mode 100644 index 00000000..86026437 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative-notext.mbox | |||
@@ -0,0 +1,22 @@ | |||
1 | Return-Path: <konqi@example.org> | ||
2 | Date: Wed, 8 Jun 2016 20:34:44 -0700 | ||
3 | From: Konqi <konqi@example.org> | ||
4 | To: konqi@kde.org | ||
5 | Subject: A random subject with a empty text alternative contenttype | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: multipart/alternative; | ||
8 | boundary="----=_Part_12345678_12345678" | ||
9 | |||
10 | |||
11 | ------=_Part_12345678_12345678 | ||
12 | Content-Transfer-Encoding: 7Bit | ||
13 | Content-Type: text/html; charset="windows-1252" | ||
14 | |||
15 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> | ||
16 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> | ||
17 | p, li { white-space: pre-wrap; } | ||
18 | </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> | ||
19 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p></body></html> | ||
20 | |||
21 | |||
22 | ------=_Part_12345678_12345678-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative-notext.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative-notext.mbox.html new file mode 100644 index 00000000..41db4eab --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative-notext.mbox.html | |||
@@ -0,0 +1,17 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <div style="position: relative"> | ||
11 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p> | ||
12 | </div> | ||
13 | </div> | ||
14 | </div> | ||
15 | </div> | ||
16 | </body> | ||
17 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative-notext.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative-notext.mbox.tree new file mode 100644 index 00000000..0de07281 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative-notext.mbox.tree | |||
@@ -0,0 +1,2 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::AlternativeMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative.mbox new file mode 100644 index 00000000..a2c58591 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative.mbox | |||
@@ -0,0 +1,34 @@ | |||
1 | Return-Path: <konqi@example.org> | ||
2 | Date: Wed, 8 Jun 2016 20:34:44 -0700 | ||
3 | From: Konqi <konqi@example.org> | ||
4 | To: konqi@kde.org | ||
5 | Subject: A random subject with alternative contenttype | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: multipart/alternative; | ||
8 | boundary="----=_Part_12345678_12345678" | ||
9 | |||
10 | |||
11 | ------=_Part_12345678_12345678 | ||
12 | Content-Type: text/plain; charset=utf-8 | ||
13 | Content-Transfer-Encoding: quoted-printable | ||
14 | |||
15 | If you can see this text it means that your email client couldn't display o= | ||
16 | ur newsletter properly. | ||
17 | Please visit this link to view the newsletter on our website: http://www.go= | ||
18 | g.com/newsletter/ | ||
19 | |||
20 | =2D GOG.com Team | ||
21 | |||
22 | |||
23 | ------=_Part_12345678_12345678 | ||
24 | Content-Transfer-Encoding: 7Bit | ||
25 | Content-Type: text/html; charset="windows-1252" | ||
26 | |||
27 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> | ||
28 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> | ||
29 | p, li { white-space: pre-wrap; } | ||
30 | </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> | ||
31 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p></body></html> | ||
32 | |||
33 | |||
34 | ------=_Part_12345678_12345678-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative.mbox.html new file mode 100644 index 00000000..2fe886f1 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative.mbox.html | |||
@@ -0,0 +1,17 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att2"/> | ||
9 | <div id="attachmentDiv2"> | ||
10 | <div style="position: relative"> | ||
11 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p> | ||
12 | </div> | ||
13 | </div> | ||
14 | </div> | ||
15 | </div> | ||
16 | </body> | ||
17 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative.mbox.tree new file mode 100644 index 00000000..0de07281 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/alternative.mbox.tree | |||
@@ -0,0 +1,2 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::AlternativeMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/forward-openpgp-signed-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/forward-openpgp-signed-encrypted.mbox.html new file mode 100644 index 00000000..9a81f103 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/forward-openpgp-signed-encrypted.mbox.html | |||
@@ -0,0 +1,84 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <div class="noquote"> | ||
11 | <div dir="ltr">bla bla bla</div> | ||
12 | </div> | ||
13 | </div> | ||
14 | <a name="att2"/> | ||
15 | <div id="attachmentDiv2"> | ||
16 | <table cellspacing="1" cellpadding="1" class="rfc822"> | ||
17 | <tr class="rfc822H"> | ||
18 | <td dir="ltr"> | ||
19 | <a href="attachment:2.1?place=body">Encapsulated message</a> | ||
20 | </td> | ||
21 | </tr> | ||
22 | <tr class="rfc822B"> | ||
23 | <td> | ||
24 | <a name="att2.1"/> | ||
25 | <div id="attachmentDiv2.1"> | ||
26 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
27 | <tr class="encrH"> | ||
28 | <td dir="ltr">Encrypted message</td> | ||
29 | </tr> | ||
30 | <tr class="encrB"> | ||
31 | <td> | ||
32 | <div style="position: relative; word-wrap: break-word"> | ||
33 | <a name="att"/> | ||
34 | <div id="attachmentDiv"> | ||
35 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
36 | <tr class="signOkKeyOkH"> | ||
37 | <td dir="ltr"> | ||
38 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
39 | <tr> | ||
40 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
41 | <td align="right" valign="top" nowrap="nowrap"> | ||
42 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr> | ||
46 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="signOkKeyOkB"> | ||
52 | <td> | ||
53 | <a name="att1"/> | ||
54 | <div id="attachmentDiv1"> | ||
55 | <div class="noquote"> | ||
56 | <div dir="ltr">encrypted message text</div> | ||
57 | </div> | ||
58 | </div> | ||
59 | </td> | ||
60 | </tr> | ||
61 | <tr class="signOkKeyOkH"> | ||
62 | <td dir="ltr">End of signed message</td> | ||
63 | </tr> | ||
64 | </table> | ||
65 | </div> | ||
66 | </div> | ||
67 | </td> | ||
68 | </tr> | ||
69 | <tr class="encrH"> | ||
70 | <td dir="ltr">End of encrypted message</td> | ||
71 | </tr> | ||
72 | </table> | ||
73 | </div> | ||
74 | </td> | ||
75 | </tr> | ||
76 | <tr class="rfc822H"> | ||
77 | <td dir="ltr">End of encapsulated message</td> | ||
78 | </tr> | ||
79 | </table> | ||
80 | </div> | ||
81 | </div> | ||
82 | </div> | ||
83 | </body> | ||
84 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encoded.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encoded.mbox.html new file mode 100644 index 00000000..65d5f95e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encoded.mbox.html | |||
@@ -0,0 +1,38 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
9 | <tr class="signWarnH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td rowspan="2">Message was signed on 12/21/15 3:46 PM with unknown key <a href="kmail:showCertificate#gpg ### OpenPGP ### E68031D299A6527C">0xE68031D299A6527C</a>.<br/>The validity of the signature cannot be verified.<br/>Status:<i>No public key to verify the signature</i></td> | ||
14 | <td align="right" valign="top" nowrap="nowrap"> | ||
15 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | <tr> | ||
19 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
20 | </tr> | ||
21 | </table> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr class="signWarnB"> | ||
25 | <td> | ||
26 | <div class="noquote"> | ||
27 | <div dir="ltr">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</div> | ||
28 | </div> | ||
29 | </td> | ||
30 | </tr> | ||
31 | <tr class="signWarnH"> | ||
32 | <td dir="ltr">End of signed message</td> | ||
33 | </tr> | ||
34 | </table> | ||
35 | </div> | ||
36 | </div> | ||
37 | </body> | ||
38 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted+signed.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted+signed.mbox.html new file mode 100644 index 00000000..96361c30 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted+signed.mbox.html | |||
@@ -0,0 +1,55 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
15 | <tr class="signOkKeyOkH"> | ||
16 | <td dir="ltr"> | ||
17 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
18 | <tr> | ||
19 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
20 | <td align="right" valign="top" nowrap="nowrap"> | ||
21 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr> | ||
25 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <div style="position: relative; word-wrap: break-word"> | ||
33 | <a name="att"/> | ||
34 | <div id="attachmentDiv"> | ||
35 | <div class="noquote"> | ||
36 | <div dir="ltr">encrypted message text</div> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </td> | ||
41 | </tr> | ||
42 | <tr class="signOkKeyOkH"> | ||
43 | <td dir="ltr">End of signed message</td> | ||
44 | </tr> | ||
45 | </table> | ||
46 | </td> | ||
47 | </tr> | ||
48 | <tr class="encrH"> | ||
49 | <td dir="ltr">End of encrypted message</td> | ||
50 | </tr> | ||
51 | </table> | ||
52 | </div> | ||
53 | </div> | ||
54 | </body> | ||
55 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..cc6bf03e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,80 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
25 | <td align="right" valign="top" nowrap="nowrap"> | ||
26 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | <tr> | ||
30 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
31 | </tr> | ||
32 | </table> | ||
33 | </td> | ||
34 | </tr> | ||
35 | <tr class="signOkKeyOkB"> | ||
36 | <td> | ||
37 | <a name="att1"/> | ||
38 | <div id="attachmentDiv1"> | ||
39 | <a name="att1.1"/> | ||
40 | <div id="attachmentDiv1.1"> | ||
41 | <div class="noquote"> | ||
42 | <div dir="ltr">test text</div> | ||
43 | </div> | ||
44 | </div> | ||
45 | <a name="att1.2"/> | ||
46 | <div id="attachmentDiv1.2"> | ||
47 | <hr/> | ||
48 | <div> | ||
49 | <a href="attachment:1:e0:1.2?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>file.txt</a> | ||
50 | </div> | ||
51 | <div/> | ||
52 | </div> | ||
53 | </div> | ||
54 | </td> | ||
55 | </tr> | ||
56 | <tr class="signOkKeyOkH"> | ||
57 | <td dir="ltr">End of signed message</td> | ||
58 | </tr> | ||
59 | </table> | ||
60 | </div> | ||
61 | </div> | ||
62 | </td> | ||
63 | </tr> | ||
64 | <tr class="encrH"> | ||
65 | <td dir="ltr">End of encrypted message</td> | ||
66 | </tr> | ||
67 | </table> | ||
68 | </div> | ||
69 | <a name="att2"/> | ||
70 | <div id="attachmentDiv2"> | ||
71 | <hr/> | ||
72 | <div> | ||
73 | <a href="attachment:2?place=body"><img align="center" height="48" width="48" src="file:image-png.svg" border="0" style="max-width: 100%" alt=""/>image.png</a> | ||
74 | </div> | ||
75 | <div/> | ||
76 | </div> | ||
77 | </div> | ||
78 | </div> | ||
79 | </body> | ||
80 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-attachment.mbox.html new file mode 100644 index 00000000..61bf5d28 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,69 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
23 | <td align="right" valign="top" nowrap="nowrap"> | ||
24 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr> | ||
28 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
29 | </tr> | ||
30 | </table> | ||
31 | </td> | ||
32 | </tr> | ||
33 | <tr class="signOkKeyOkB"> | ||
34 | <td> | ||
35 | <a name="att1"/> | ||
36 | <div id="attachmentDiv1"> | ||
37 | <a name="att1.1"/> | ||
38 | <div id="attachmentDiv1.1"> | ||
39 | <div class="noquote"> | ||
40 | <div dir="ltr">test text</div> | ||
41 | </div> | ||
42 | </div> | ||
43 | <a name="att1.2"/> | ||
44 | <div id="attachmentDiv1.2"> | ||
45 | <hr/> | ||
46 | <div> | ||
47 | <a href="attachment:e0:1.2?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>file.txt</a> | ||
48 | </div> | ||
49 | <div/> | ||
50 | </div> | ||
51 | </div> | ||
52 | </td> | ||
53 | </tr> | ||
54 | <tr class="signOkKeyOkH"> | ||
55 | <td dir="ltr">End of signed message</td> | ||
56 | </tr> | ||
57 | </table> | ||
58 | </div> | ||
59 | </div> | ||
60 | </td> | ||
61 | </tr> | ||
62 | <tr class="encrH"> | ||
63 | <td dir="ltr">End of encrypted message</td> | ||
64 | </tr> | ||
65 | </table> | ||
66 | </div> | ||
67 | </div> | ||
68 | </body> | ||
69 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..8d8bde0d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,72 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
25 | <td align="right" valign="top" nowrap="nowrap"> | ||
26 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | <tr> | ||
30 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
31 | </tr> | ||
32 | </table> | ||
33 | </td> | ||
34 | </tr> | ||
35 | <tr class="signOkKeyOkB"> | ||
36 | <td> | ||
37 | <a name="att1"/> | ||
38 | <div id="attachmentDiv1"> | ||
39 | <a name="att1.1"/> | ||
40 | <div id="attachmentDiv1.1"> | ||
41 | <div class="noquote"> | ||
42 | <div dir="ltr">test text</div> | ||
43 | </div> | ||
44 | </div> | ||
45 | </div> | ||
46 | </td> | ||
47 | </tr> | ||
48 | <tr class="signOkKeyOkH"> | ||
49 | <td dir="ltr">End of signed message</td> | ||
50 | </tr> | ||
51 | </table> | ||
52 | </div> | ||
53 | </div> | ||
54 | </td> | ||
55 | </tr> | ||
56 | <tr class="encrH"> | ||
57 | <td dir="ltr">End of encrypted message</td> | ||
58 | </tr> | ||
59 | </table> | ||
60 | </div> | ||
61 | <a name="att2"/> | ||
62 | <div id="attachmentDiv2"> | ||
63 | <hr/> | ||
64 | <div> | ||
65 | <a href="attachment:2?place=body"><img align="center" height="48" width="48" src="file:image-png.svg" border="0" style="max-width: 100%" alt=""/>image.png</a> | ||
66 | </div> | ||
67 | <div/> | ||
68 | </div> | ||
69 | </div> | ||
70 | </div> | ||
71 | </body> | ||
72 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-partially-signed-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-partially-signed-attachments.mbox.html new file mode 100644 index 00000000..1716b841 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-encrypted-partially-signed-attachments.mbox.html | |||
@@ -0,0 +1,102 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
25 | <td align="right" valign="top" nowrap="nowrap"> | ||
26 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | <tr> | ||
30 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
31 | </tr> | ||
32 | </table> | ||
33 | </td> | ||
34 | </tr> | ||
35 | <tr class="signOkKeyOkB"> | ||
36 | <td> | ||
37 | <a name="att1"/> | ||
38 | <div id="attachmentDiv1"> | ||
39 | <a name="att1.1"/> | ||
40 | <div id="attachmentDiv1.1"> | ||
41 | <div class="noquote"> | ||
42 | <div dir="ltr">This is the main body.</div> | ||
43 | </div> | ||
44 | </div> | ||
45 | <a name="att1.2"/> | ||
46 | <div id="attachmentDiv1.2"> | ||
47 | <table cellspacing="1" class="textAtm"> | ||
48 | <tr class="textAtmH"> | ||
49 | <td dir="ltr">attachment1.txt</td> | ||
50 | </tr> | ||
51 | <tr class="textAtmB"> | ||
52 | <td> | ||
53 | <div class="noquote"> | ||
54 | <div dir="ltr">This is a signed attachment.</div> | ||
55 | </div> | ||
56 | </td> | ||
57 | </tr> | ||
58 | </table> | ||
59 | </div> | ||
60 | </div> | ||
61 | </td> | ||
62 | </tr> | ||
63 | <tr class="signOkKeyOkH"> | ||
64 | <td dir="ltr">End of signed message</td> | ||
65 | </tr> | ||
66 | </table> | ||
67 | </div> | ||
68 | </div> | ||
69 | </td> | ||
70 | </tr> | ||
71 | <tr class="encrH"> | ||
72 | <td dir="ltr">End of encrypted message</td> | ||
73 | </tr> | ||
74 | </table> | ||
75 | </div> | ||
76 | <a name="att2"/> | ||
77 | <div id="attachmentDiv2"> | ||
78 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
79 | <tr class="encrH"> | ||
80 | <td dir="ltr">Encrypted message</td> | ||
81 | </tr> | ||
82 | <tr class="encrB"> | ||
83 | <td> | ||
84 | <div style="position: relative; word-wrap: break-word"> | ||
85 | <a name="att"/> | ||
86 | <div id="attachmentDiv"> | ||
87 | <div class="noquote"> | ||
88 | <div dir="ltr">This is an unsigned attachment.</div> | ||
89 | </div> | ||
90 | </div> | ||
91 | </div> | ||
92 | </td> | ||
93 | </tr> | ||
94 | <tr class="encrH"> | ||
95 | <td dir="ltr">End of encrypted message</td> | ||
96 | </tr> | ||
97 | </table> | ||
98 | </div> | ||
99 | </div> | ||
100 | </div> | ||
101 | </body> | ||
102 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-inline-charset-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-inline-charset-encrypted.mbox.html new file mode 100644 index 00000000..c2fa2fee --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-inline-charset-encrypted.mbox.html | |||
@@ -0,0 +1,50 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
15 | <tr class="signOkKeyOkH"> | ||
16 | <td dir="ltr"> | ||
17 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
18 | <tr> | ||
19 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
20 | <td align="right" valign="top" nowrap="nowrap"> | ||
21 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr> | ||
25 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <div class="noquote"> | ||
33 | <div dir="ltr">asdasd asd asd asdf sadf sdaf sadf öäü</div> | ||
34 | </div> | ||
35 | </td> | ||
36 | </tr> | ||
37 | <tr class="signOkKeyOkH"> | ||
38 | <td dir="ltr">End of signed message</td> | ||
39 | </tr> | ||
40 | </table> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="encrH"> | ||
44 | <td dir="ltr">End of encrypted message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </body> | ||
50 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-inline-signed.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-inline-signed.mbox.html new file mode 100644 index 00000000..00a9dc5b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-inline-signed.mbox.html | |||
@@ -0,0 +1,38 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
14 | <td align="right" valign="top" nowrap="nowrap"> | ||
15 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | <tr> | ||
19 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
20 | </tr> | ||
21 | </table> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr class="signOkKeyOkB"> | ||
25 | <td> | ||
26 | <div class="noquote"> | ||
27 | <div dir="ltr">ohno öäü</div> | ||
28 | </div> | ||
29 | </td> | ||
30 | </tr> | ||
31 | <tr class="signOkKeyOkH"> | ||
32 | <td dir="ltr">End of signed message</td> | ||
33 | </tr> | ||
34 | </table> | ||
35 | </div> | ||
36 | </div> | ||
37 | </body> | ||
38 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-base64-mailman-footer.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-base64-mailman-footer.mbox.html new file mode 100644 index 00000000..c10cecd8 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-base64-mailman-footer.mbox.html | |||
@@ -0,0 +1,81 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
11 | <tr class="signWarnH"> | ||
12 | <td dir="ltr"> | ||
13 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
14 | <tr> | ||
15 | <td rowspan="2">Message was signed on 8/22/15 9:31 AM with unknown key <a href="kmail:showCertificate#gpg ### OpenPGP ### 7F96CCD64D12D247">0x7F96CCD64D12D247</a>.<br/>The validity of the signature cannot be verified.<br/>Status:<i>No public key to verify the signature</i></td> | ||
16 | <td align="right" valign="top" nowrap="nowrap"> | ||
17 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
18 | </td> | ||
19 | </tr> | ||
20 | <tr> | ||
21 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
22 | </tr> | ||
23 | </table> | ||
24 | </td> | ||
25 | </tr> | ||
26 | <tr class="signWarnB"> | ||
27 | <td> | ||
28 | <a name="att1.1"/> | ||
29 | <div id="attachmentDiv1.1"> | ||
30 | <div class="noquote"> | ||
31 | <div dir="ltr">Hi,</div> | ||
32 | <br/> | ||
33 | <div dir="ltr">I've talked to Ben, the current Phabricator test setup would actually be </div> | ||
34 | <div dir="ltr">usable for "production" use for task/project management for us, without </div> | ||
35 | <div dir="ltr">causing the sysadmins unreasonable trouble when migrating to the full </div> | ||
36 | <div dir="ltr">production deployment of Phabricator eventually.</div> | ||
37 | <br/> | ||
38 | <div dir="ltr">Phabricator project layout it orthogonal to repo layout, so we can structure </div> | ||
39 | <div dir="ltr">this however we want. Among other teams I see at least the following layouts:</div> | ||
40 | <div dir="ltr">- single project for everything</div> | ||
41 | <div dir="ltr">- a project per release</div> | ||
42 | <div dir="ltr">- a project per component/module (ie. close to the repo layout)</div> | ||
43 | <br/> | ||
44 | <div dir="ltr">How do we want to structure this?</div> | ||
45 | <br/> | ||
46 | <div dir="ltr">I would start with a single project to not fragment this too much, as we have </div> | ||
47 | <div dir="ltr">a relatively small team actually looking into this, so everyone is looking at </div> | ||
48 | <div dir="ltr">most sub-projects anyway. And should we eventually hit scaling limits, we can </div> | ||
49 | <div dir="ltr">always expand this I think.</div> | ||
50 | <br/> | ||
51 | <div dir="ltr">We of course should also talk about what we actually want to put in there. My </div> | ||
52 | <div dir="ltr">current motivation is having a place to collect the tasks for getting more of </div> | ||
53 | <div dir="ltr">the former pimlibs into KF5, and anything else I run into on the way there </div> | ||
54 | <div dir="ltr">that we eventually should clean up/improve.</div> | ||
55 | <br/> | ||
56 | <div dir="ltr">regards,</div> | ||
57 | <div dir="ltr">Volker</div> | ||
58 | </div> | ||
59 | </div> | ||
60 | </td> | ||
61 | </tr> | ||
62 | <tr class="signWarnH"> | ||
63 | <td dir="ltr">End of signed message</td> | ||
64 | </tr> | ||
65 | </table> | ||
66 | </div> | ||
67 | <a name="att2"/> | ||
68 | <div id="attachmentDiv2"> | ||
69 | <div class="noquote"> | ||
70 | <div dir="ltr">_______________________________________________</div> | ||
71 | <div dir="ltr">KDE PIM mailing list <a href="mailto:kde-pim@kde.org">kde-pim@kde.org</a></div> | ||
72 | <div dir="ltr"> | ||
73 | <a href="https://mail.kde.org/mailman/listinfo/kde-pim">https://mail.kde.org/mailman/listinfo/kde-pim</a> | ||
74 | </div> | ||
75 | <div dir="ltr">KDE PIM home page at <a href="http://pim.kde.org/">http://pim.kde.org/</a></div> | ||
76 | </div> | ||
77 | </div> | ||
78 | </div> | ||
79 | </div> | ||
80 | </body> | ||
81 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-encrypted-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-encrypted-two-attachments.mbox.html new file mode 100644 index 00000000..2c02a22c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-encrypted-two-attachments.mbox.html | |||
@@ -0,0 +1,91 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
23 | <td align="right" valign="top" nowrap="nowrap"> | ||
24 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr> | ||
28 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
29 | </tr> | ||
30 | </table> | ||
31 | </td> | ||
32 | </tr> | ||
33 | <tr class="signOkKeyOkB"> | ||
34 | <td> | ||
35 | <a name="att1"/> | ||
36 | <div id="attachmentDiv1"> | ||
37 | <a name="att1.1"/> | ||
38 | <div id="attachmentDiv1.1"> | ||
39 | <div class="noquote"> | ||
40 | <div dir="ltr">this is the main body</div> | ||
41 | </div> | ||
42 | </div> | ||
43 | <a name="att1.2"/> | ||
44 | <div id="attachmentDiv1.2"> | ||
45 | <table cellspacing="1" class="textAtm"> | ||
46 | <tr class="textAtmH"> | ||
47 | <td dir="ltr">attachment1.txt</td> | ||
48 | </tr> | ||
49 | <tr class="textAtmB"> | ||
50 | <td> | ||
51 | <div class="noquote"> | ||
52 | <div dir="ltr">this is one attachment</div> | ||
53 | </div> | ||
54 | </td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | <a name="att1.3"/> | ||
59 | <div id="attachmentDiv1.3"> | ||
60 | <table cellspacing="1" class="textAtm"> | ||
61 | <tr class="textAtmH"> | ||
62 | <td dir="ltr">attachment2.txt</td> | ||
63 | </tr> | ||
64 | <tr class="textAtmB"> | ||
65 | <td> | ||
66 | <div class="noquote"> | ||
67 | <div dir="ltr">this is the second attachment</div> | ||
68 | </div> | ||
69 | </td> | ||
70 | </tr> | ||
71 | </table> | ||
72 | </div> | ||
73 | </div> | ||
74 | </td> | ||
75 | </tr> | ||
76 | <tr class="signOkKeyOkH"> | ||
77 | <td dir="ltr">End of signed message</td> | ||
78 | </tr> | ||
79 | </table> | ||
80 | </div> | ||
81 | </div> | ||
82 | </td> | ||
83 | </tr> | ||
84 | <tr class="encrH"> | ||
85 | <td dir="ltr">End of encrypted message</td> | ||
86 | </tr> | ||
87 | </table> | ||
88 | </div> | ||
89 | </div> | ||
90 | </body> | ||
91 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-encrypted.mbox.html new file mode 100644 index 00000000..d3a7a0ce --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-encrypted.mbox.html | |||
@@ -0,0 +1,58 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
23 | <td align="right" valign="top" nowrap="nowrap"> | ||
24 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr> | ||
28 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
29 | </tr> | ||
30 | </table> | ||
31 | </td> | ||
32 | </tr> | ||
33 | <tr class="signOkKeyOkB"> | ||
34 | <td> | ||
35 | <a name="att1"/> | ||
36 | <div id="attachmentDiv1"> | ||
37 | <div class="noquote"> | ||
38 | <div dir="ltr">encrypted message text</div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signOkKeyOkH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="encrH"> | ||
52 | <td dir="ltr">End of encrypted message</td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </body> | ||
58 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-mailinglist+old.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-mailinglist+old.mbox.html new file mode 100644 index 00000000..e7da94db --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-mailinglist+old.mbox.html | |||
@@ -0,0 +1,97 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <div style="position: relative; word-wrap: break-word"> | ||
9 | <a name="att"/> | ||
10 | <div id="attachmentDiv"> | ||
11 | <div class="noquote"> | ||
12 | <div dir="ltr">Oh man a header :)</div> | ||
13 | <br/> | ||
14 | </div> | ||
15 | </div> | ||
16 | </div> | ||
17 | <div style="position: relative; word-wrap: break-word"> | ||
18 | <a name="att"/> | ||
19 | <div id="attachmentDiv"> | ||
20 | <table cellspacing="1" cellpadding="1" class="rfc822"> | ||
21 | <tr class="rfc822H"> | ||
22 | <td dir="ltr"> | ||
23 | <a href="attachment:e1:1?place=body">Encapsulated message</a> | ||
24 | </td> | ||
25 | </tr> | ||
26 | <tr class="rfc822B"> | ||
27 | <td> | ||
28 | <a name="att1"/> | ||
29 | <div id="attachmentDiv1"> | ||
30 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
31 | <tr class="signWarnH"> | ||
32 | <td dir="ltr"> | ||
33 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
34 | <tr> | ||
35 | <td rowspan="2">Message was signed on 4/8/13 9:51 AM with unknown key <a href="kmail:showCertificate#gpg ### OpenPGP ### D6B72EB1A7F1DB43">0xD6B72EB1A7F1DB43</a>.<br/>The validity of the signature cannot be verified.<br/>Status:<i>No public key to verify the signature</i></td> | ||
36 | <td align="right" valign="top" nowrap="nowrap"> | ||
37 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
38 | </td> | ||
39 | </tr> | ||
40 | <tr> | ||
41 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
42 | </tr> | ||
43 | </table> | ||
44 | </td> | ||
45 | </tr> | ||
46 | <tr class="signWarnB"> | ||
47 | <td> | ||
48 | <a name="att1.1"/> | ||
49 | <div id="attachmentDiv1.1"> | ||
50 | <div class="noquote"> | ||
51 | <div dir="ltr">hi..</div> | ||
52 | <br/> | ||
53 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
54 | <div dir="ltr">activities_optional</div> | ||
55 | <br/> | ||
56 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
57 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
58 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
59 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
60 | <br/> | ||
61 | <div dir="ltr">-- </div> | ||
62 | <div dir="ltr">Aaron J. Seigo</div> | ||
63 | </div> | ||
64 | </div> | ||
65 | </td> | ||
66 | </tr> | ||
67 | <tr class="signWarnH"> | ||
68 | <td dir="ltr">End of signed message</td> | ||
69 | </tr> | ||
70 | </table> | ||
71 | </div> | ||
72 | </td> | ||
73 | </tr> | ||
74 | <tr class="rfc822H"> | ||
75 | <td dir="ltr">End of encapsulated message</td> | ||
76 | </tr> | ||
77 | </table> | ||
78 | </div> | ||
79 | </div> | ||
80 | <div style="position: relative; word-wrap: break-word"> | ||
81 | <a name="att"/> | ||
82 | <div id="attachmentDiv"> | ||
83 | <div class="noquote"> | ||
84 | <div dir="ltr">Plasma-devel mailing list</div> | ||
85 | <div dir="ltr"> | ||
86 | <a href="mailto:Plasma-devel@kde.org">Plasma-devel@kde.org</a> | ||
87 | </div> | ||
88 | <div dir="ltr"> | ||
89 | <a href="https://mail.kde.org/mailman/listinfo/plasma-devel">https://mail.kde.org/mailman/listinfo/plasma-devel</a> | ||
90 | </div> | ||
91 | </div> | ||
92 | </div> | ||
93 | </div> | ||
94 | </div> | ||
95 | </div> | ||
96 | </body> | ||
97 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-mailinglist.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-mailinglist.mbox.html new file mode 100644 index 00000000..f5b20b6d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-mailinglist.mbox.html | |||
@@ -0,0 +1,68 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
11 | <tr class="signWarnH"> | ||
12 | <td dir="ltr"> | ||
13 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
14 | <tr> | ||
15 | <td rowspan="2">Message was signed on 4/8/13 9:51 AM with unknown key <a href="kmail:showCertificate#gpg ### OpenPGP ### D6B72EB1A7F1DB43">0xD6B72EB1A7F1DB43</a>.<br/>The validity of the signature cannot be verified.<br/>Status:<i>No public key to verify the signature</i></td> | ||
16 | <td align="right" valign="top" nowrap="nowrap"> | ||
17 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
18 | </td> | ||
19 | </tr> | ||
20 | <tr> | ||
21 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
22 | </tr> | ||
23 | </table> | ||
24 | </td> | ||
25 | </tr> | ||
26 | <tr class="signWarnB"> | ||
27 | <td> | ||
28 | <a name="att1.1"/> | ||
29 | <div id="attachmentDiv1.1"> | ||
30 | <div class="noquote"> | ||
31 | <div dir="ltr">hi..</div> | ||
32 | <br/> | ||
33 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
34 | <div dir="ltr">activities_optional</div> | ||
35 | <br/> | ||
36 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
37 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
38 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
39 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
40 | <br/> | ||
41 | <div dir="ltr">-- </div> | ||
42 | <div dir="ltr">Aaron J. Seigo</div> | ||
43 | </div> | ||
44 | </div> | ||
45 | </td> | ||
46 | </tr> | ||
47 | <tr class="signWarnH"> | ||
48 | <td dir="ltr">End of signed message</td> | ||
49 | </tr> | ||
50 | </table> | ||
51 | </div> | ||
52 | <a name="att2"/> | ||
53 | <div id="attachmentDiv2"> | ||
54 | <div class="noquote"> | ||
55 | <div dir="ltr">_______________________________________________</div> | ||
56 | <div dir="ltr">Plasma-devel mailing list</div> | ||
57 | <div dir="ltr"> | ||
58 | <a href="mailto:Plasma-devel@kde.org">Plasma-devel@kde.org</a> | ||
59 | </div> | ||
60 | <div dir="ltr"> | ||
61 | <a href="https://mail.kde.org/mailman/listinfo/plasma-devel">https://mail.kde.org/mailman/listinfo/plasma-devel</a> | ||
62 | </div> | ||
63 | </div> | ||
64 | </div> | ||
65 | </div> | ||
66 | </div> | ||
67 | </body> | ||
68 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-two-attachments.mbox.html new file mode 100644 index 00000000..1432aa44 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/openpgp-signed-two-attachments.mbox.html | |||
@@ -0,0 +1,74 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
14 | <td align="right" valign="top" nowrap="nowrap"> | ||
15 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | <tr> | ||
19 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
20 | </tr> | ||
21 | </table> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr class="signOkKeyOkB"> | ||
25 | <td> | ||
26 | <a name="att1"/> | ||
27 | <div id="attachmentDiv1"> | ||
28 | <a name="att1.1"/> | ||
29 | <div id="attachmentDiv1.1"> | ||
30 | <div class="noquote"> | ||
31 | <div dir="ltr">this is the main body text</div> | ||
32 | </div> | ||
33 | </div> | ||
34 | <a name="att1.2"/> | ||
35 | <div id="attachmentDiv1.2"> | ||
36 | <table cellspacing="1" class="textAtm"> | ||
37 | <tr class="textAtmH"> | ||
38 | <td dir="ltr">attachment1.txt</td> | ||
39 | </tr> | ||
40 | <tr class="textAtmB"> | ||
41 | <td> | ||
42 | <div class="noquote"> | ||
43 | <div dir="ltr">this is attachment one</div> | ||
44 | </div> | ||
45 | </td> | ||
46 | </tr> | ||
47 | </table> | ||
48 | </div> | ||
49 | <a name="att1.3"/> | ||
50 | <div id="attachmentDiv1.3"> | ||
51 | <table cellspacing="1" class="textAtm"> | ||
52 | <tr class="textAtmH"> | ||
53 | <td dir="ltr">attachment2.txt</td> | ||
54 | </tr> | ||
55 | <tr class="textAtmB"> | ||
56 | <td> | ||
57 | <div class="noquote"> | ||
58 | <div dir="ltr">this is attachment two</div> | ||
59 | </div> | ||
60 | </td> | ||
61 | </tr> | ||
62 | </table> | ||
63 | </div> | ||
64 | </div> | ||
65 | </td> | ||
66 | </tr> | ||
67 | <tr class="signOkKeyOkH"> | ||
68 | <td dir="ltr">End of signed message</td> | ||
69 | </tr> | ||
70 | </table> | ||
71 | </div> | ||
72 | </div> | ||
73 | </body> | ||
74 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/signed-forward-openpgp-signed-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/signed-forward-openpgp-signed-encrypted.mbox.html new file mode 100644 index 00000000..b960f318 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/signed-forward-openpgp-signed-encrypted.mbox.html | |||
@@ -0,0 +1,111 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
14 | <td align="right" valign="top" nowrap="nowrap"> | ||
15 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | <tr> | ||
19 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
20 | </tr> | ||
21 | </table> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr class="signOkKeyOkB"> | ||
25 | <td> | ||
26 | <a name="att1"/> | ||
27 | <div id="attachmentDiv1"> | ||
28 | <a name="att1.1"/> | ||
29 | <div id="attachmentDiv1.1"> | ||
30 | <div class="noquote"> | ||
31 | <div dir="ltr">bla bla bla</div> | ||
32 | </div> | ||
33 | </div> | ||
34 | <a name="att1.2"/> | ||
35 | <div id="attachmentDiv1.2"> | ||
36 | <table cellspacing="1" cellpadding="1" class="rfc822"> | ||
37 | <tr class="rfc822H"> | ||
38 | <td dir="ltr"> | ||
39 | <a href="attachment:1.2.1?place=body">Encapsulated message</a> | ||
40 | </td> | ||
41 | </tr> | ||
42 | <tr class="rfc822B"> | ||
43 | <td> | ||
44 | <a name="att1.2.1"/> | ||
45 | <div id="attachmentDiv1.2.1"> | ||
46 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
47 | <tr class="encrH"> | ||
48 | <td dir="ltr">Encrypted message</td> | ||
49 | </tr> | ||
50 | <tr class="encrB"> | ||
51 | <td> | ||
52 | <div style="position: relative; word-wrap: break-word"> | ||
53 | <a name="att"/> | ||
54 | <div id="attachmentDiv"> | ||
55 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
56 | <tr class="signOkKeyOkH"> | ||
57 | <td dir="ltr"> | ||
58 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
59 | <tr> | ||
60 | <td rowspan="2">Message was signed by <a href="mailto:test@kolab.org">test@kolab.org</a> (Key ID: <a href="kmail:showCertificate#gpg ### OpenPGP ### 8D9860C58F246DE6">0x8D9860C58F246DE6</a>).<br/>The signature is valid and the key is fully trusted.</td> | ||
61 | <td align="right" valign="top" nowrap="nowrap"> | ||
62 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
63 | </td> | ||
64 | </tr> | ||
65 | <tr> | ||
66 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
67 | </tr> | ||
68 | </table> | ||
69 | </td> | ||
70 | </tr> | ||
71 | <tr class="signOkKeyOkB"> | ||
72 | <td> | ||
73 | <a name="att1"/> | ||
74 | <div id="attachmentDiv1"> | ||
75 | <div class="noquote"> | ||
76 | <div dir="ltr">encrypted message text</div> | ||
77 | </div> | ||
78 | </div> | ||
79 | </td> | ||
80 | </tr> | ||
81 | <tr class="signOkKeyOkH"> | ||
82 | <td dir="ltr">End of signed message</td> | ||
83 | </tr> | ||
84 | </table> | ||
85 | </div> | ||
86 | </div> | ||
87 | </td> | ||
88 | </tr> | ||
89 | <tr class="encrH"> | ||
90 | <td dir="ltr">End of encrypted message</td> | ||
91 | </tr> | ||
92 | </table> | ||
93 | </div> | ||
94 | </td> | ||
95 | </tr> | ||
96 | <tr class="rfc822H"> | ||
97 | <td dir="ltr">End of encapsulated message</td> | ||
98 | </tr> | ||
99 | </table> | ||
100 | </div> | ||
101 | </div> | ||
102 | </td> | ||
103 | </tr> | ||
104 | <tr class="signOkKeyOkH"> | ||
105 | <td dir="ltr">End of signed message</td> | ||
106 | </tr> | ||
107 | </table> | ||
108 | </div> | ||
109 | </div> | ||
110 | </body> | ||
111 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/smime-opaque-enc+sign.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/smime-opaque-enc+sign.mbox.html new file mode 100644 index 00000000..d6345a7c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/smime-opaque-enc+sign.mbox.html | |||
@@ -0,0 +1,60 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td rowspan="2">Message was signed by <a href="mailto:test%40example.com">test@example.com</a> on 1/10/13 3:48 PM with key <a href="kmail:showCertificate#gpgsm ### SMIME ### 4CC658E3212B49DC">0x4CC658E3212B49DC</a><br/> <br/>Status:<i>Good signature.</i><br/> <br/><u>Warning:</u> Sender's mail address is not stored in the <a href="kmail:showCertificate#gpgsm ### SMIME ### 4CC658E3212B49DC">certificate</a> used for signing.<br/>sender: <br/>stored: test@example.com</td> | ||
23 | <td align="right" valign="top" nowrap="nowrap"> | ||
24 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr> | ||
28 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
29 | </tr> | ||
30 | </table> | ||
31 | </td> | ||
32 | </tr> | ||
33 | <tr class="signOkKeyOkB"> | ||
34 | <td> | ||
35 | <div style="position: relative; word-wrap: break-word"> | ||
36 | <a name="att"/> | ||
37 | <div id="attachmentDiv"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">Encrypted and signed mail.</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="signOkKeyOkH"> | ||
46 | <td dir="ltr">End of signed message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="encrH"> | ||
54 | <td dir="ltr">End of encrypted message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | </div> | ||
59 | </body> | ||
60 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/smime-opaque-sign.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/smime-opaque-sign.mbox.html new file mode 100644 index 00000000..248b93ff --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/smime-opaque-sign.mbox.html | |||
@@ -0,0 +1,43 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td rowspan="2">Message was signed by <a href="mailto:test%40example.com">test@example.com</a> on 1/10/13 3:48 PM with key <a href="kmail:showCertificate#gpgsm ### SMIME ### 4CC658E3212B49DC">0x4CC658E3212B49DC</a><br/> <br/>Status:<i>Good signature.</i></td> | ||
14 | <td align="right" valign="top" nowrap="nowrap"> | ||
15 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | <tr> | ||
19 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
20 | </tr> | ||
21 | </table> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr class="signOkKeyOkB"> | ||
25 | <td> | ||
26 | <div style="position: relative; word-wrap: break-word"> | ||
27 | <a name="att"/> | ||
28 | <div id="attachmentDiv"> | ||
29 | <div class="noquote"> | ||
30 | <div dir="ltr">A simple signed only test.</div> | ||
31 | </div> | ||
32 | </div> | ||
33 | </div> | ||
34 | </td> | ||
35 | </tr> | ||
36 | <tr class="signOkKeyOkH"> | ||
37 | <td dir="ltr">End of signed message</td> | ||
38 | </tr> | ||
39 | </table> | ||
40 | </div> | ||
41 | </div> | ||
42 | </body> | ||
43 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/smime-signed-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/smime-signed-encrypted.mbox.html new file mode 100644 index 00000000..6e811632 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/details/smime-signed-encrypted.mbox.html | |||
@@ -0,0 +1,58 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td rowspan="2">Message was signed by <a href="mailto:test%40example.com">test@example.com</a> on 9/8/10 3:51 PM with key <a href="kmail:showCertificate#gpgsm ### SMIME ### 4CC658E3212B49DC">0x4CC658E3212B49DC</a><br/> <br/>Status:<i>Good signature.</i><br/> <br/><u>Warning:</u> Sender's mail address is not stored in the <a href="kmail:showCertificate#gpgsm ### SMIME ### 4CC658E3212B49DC">certificate</a> used for signing.<br/>sender: <br/>stored: test@example.com</td> | ||
23 | <td align="right" valign="top" nowrap="nowrap"> | ||
24 | <a href="kmail:hideSignatureDetails">Hide Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr> | ||
28 | <td align="right" valign="bottom" nowrap="nowrap"/> | ||
29 | </tr> | ||
30 | </table> | ||
31 | </td> | ||
32 | </tr> | ||
33 | <tr class="signOkKeyOkB"> | ||
34 | <td> | ||
35 | <a name="att1"/> | ||
36 | <div id="attachmentDiv1"> | ||
37 | <div class="noquote"> | ||
38 | <div dir="ltr">encrypted message text</div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signOkKeyOkH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="encrH"> | ||
52 | <td dir="ltr">End of encrypted message</td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </body> | ||
58 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/encapsulated-with-attachment.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/encapsulated-with-attachment.mbox new file mode 100644 index 00000000..885b9d1b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/encapsulated-with-attachment.mbox | |||
@@ -0,0 +1,53 @@ | |||
1 | From: Thomas McGuire <dontspamme@gmx.net> | ||
2 | Subject: Fwd: Test with attachment | ||
3 | Date: Wed, 5 Aug 2009 10:58:27 +0200 | ||
4 | MIME-Version: 1.0 | ||
5 | Content-Type: Multipart/Mixed; | ||
6 | boundary="Boundary-00=_zmUeKB+A8hGfCVZ" | ||
7 | |||
8 | |||
9 | --Boundary-00=_zmUeKB+A8hGfCVZ | ||
10 | Content-Type: text/plain; | ||
11 | charset="iso-8859-15" | ||
12 | Content-Transfer-Encoding: 7bit | ||
13 | Content-Disposition: inline | ||
14 | |||
15 | This is the first encapsulating message. | ||
16 | |||
17 | --Boundary-00=_zmUeKB+A8hGfCVZ | ||
18 | Content-Type: message/rfc822; | ||
19 | name="forwarded message" | ||
20 | Content-Transfer-Encoding: 7bit | ||
21 | Content-Description: Thomas McGuire <dontspamme@gmx.net>: Test with attachment | ||
22 | Content-Disposition: inline | ||
23 | |||
24 | From: Thomas McGuire <dontspamme@gmx.net> | ||
25 | Subject: Test with attachment | ||
26 | Date: Wed, 5 Aug 2009 10:57:58 +0200 | ||
27 | MIME-Version: 1.0 | ||
28 | Content-Type: Multipart/Mixed; | ||
29 | boundary="Boundary-00=_WmUeKQpGb0DHyx1" | ||
30 | |||
31 | --Boundary-00=_WmUeKQpGb0DHyx1 | ||
32 | Content-Type: text/plain; | ||
33 | charset="us-ascii" | ||
34 | Content-Transfer-Encoding: 7bit | ||
35 | Content-Disposition: inline | ||
36 | |||
37 | |||
38 | |||
39 | |||
40 | This is the second encapsulated message. | ||
41 | |||
42 | --Boundary-00=_WmUeKQpGb0DHyx1 | ||
43 | Content-Type: text/plain; | ||
44 | name="attachment.txt" | ||
45 | Content-Transfer-Encoding: 7bit | ||
46 | Content-Disposition: attachment; | ||
47 | filename="attachment.txt" | ||
48 | |||
49 | This is an attachment. | ||
50 | |||
51 | --Boundary-00=_WmUeKQpGb0DHyx1-- | ||
52 | |||
53 | --Boundary-00=_zmUeKB+A8hGfCVZ-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/encapsulated-with-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/encapsulated-with-attachment.mbox.html new file mode 100644 index 00000000..aa3d1090 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/encapsulated-with-attachment.mbox.html | |||
@@ -0,0 +1,51 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <div class="noquote"> | ||
11 | <div dir="ltr">This is the first encapsulating message.</div> | ||
12 | </div> | ||
13 | </div> | ||
14 | <a name="att2"/> | ||
15 | <div id="attachmentDiv2"> | ||
16 | <table cellspacing="1" cellpadding="1" class="rfc822"> | ||
17 | <tr class="rfc822H"> | ||
18 | <td dir="ltr"> | ||
19 | <a href="attachment:2.1?place=body">Encapsulated message</a> | ||
20 | </td> | ||
21 | </tr> | ||
22 | <tr class="rfc822B"> | ||
23 | <td> | ||
24 | <a name="att2.1"/> | ||
25 | <div id="attachmentDiv2.1"> | ||
26 | <a name="att2.1.1"/> | ||
27 | <div id="attachmentDiv2.1.1"> | ||
28 | <div class="noquote"> | ||
29 | <div dir="ltr">This is the second encapsulated message.</div> | ||
30 | </div> | ||
31 | </div> | ||
32 | <a name="att2.1.2"/> | ||
33 | <div id="attachmentDiv2.1.2"> | ||
34 | <hr/> | ||
35 | <div> | ||
36 | <a href="attachment:2.1.2?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>attachment.txt</a> | ||
37 | </div> | ||
38 | <div/> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="rfc822H"> | ||
44 | <td dir="ltr">End of encapsulated message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </div> | ||
50 | </body> | ||
51 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/encapsulated-with-attachment.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/encapsulated-with-attachment.mbox.tree new file mode 100644 index 00000000..050414a2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/encapsulated-with-attachment.mbox.tree | |||
@@ -0,0 +1,10 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::TextMessagePart | ||
4 | * MimeTreeParser::MessagePart | ||
5 | * MimeTreeParser::EncapsulatedRfc822MessagePart | ||
6 | * MimeTreeParser::MimeMessagePart | ||
7 | * MimeTreeParser::AttachmentMessagePart | ||
8 | * MimeTreeParser::MessagePart | ||
9 | * MimeTreeParser::AttachmentMessagePart | ||
10 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/forward-openpgp-signed-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/forward-openpgp-signed-encrypted.mbox new file mode 100644 index 00000000..1c166940 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/forward-openpgp-signed-encrypted.mbox | |||
@@ -0,0 +1,69 @@ | |||
1 | From test@kolab.org Wed, 08 Sep 2010 17:52:37 +0200 | ||
2 | From: OpenPGP Test <test@kolab.org> | ||
3 | Subject: Fwd: OpenPGP signed and encrypted | ||
4 | Date: Wed, 08 Sep 2010 17:52:37 +0200 | ||
5 | User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: multipart/mixed; boundary="nextPart2148910.9CGjQOYhYJ" | ||
8 | Content-Transfer-Encoding: 7Bit | ||
9 | |||
10 | |||
11 | --nextPart2148910.9CGjQOYhYJ | ||
12 | Content-Transfer-Encoding: 7Bit | ||
13 | Content-Type: text/plain; charset="us-ascii" | ||
14 | |||
15 | bla bla bla | ||
16 | --nextPart2148910.9CGjQOYhYJ | ||
17 | Content-Type: message/rfc822 | ||
18 | Content-Disposition: inline; filename="forwarded message" | ||
19 | Content-Description: OpenPGP Test <test@kolab.org>: OpenPGP signed and encrypted | ||
20 | |||
21 | From: OpenPGP Test <test@kolab.org> | ||
22 | To: test@kolab.org | ||
23 | Subject: OpenPGP signed and encrypted | ||
24 | Date: Tue, 07 Sep 2010 18:08:44 +0200 | ||
25 | User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) | ||
26 | MIME-Version: 1.0 | ||
27 | Content-Type: multipart/encrypted; boundary="nextPart25203163.0xtB501Z4V"; protocol="application/pgp-encrypted" | ||
28 | Content-Transfer-Encoding: 7Bit | ||
29 | |||
30 | |||
31 | --nextPart25203163.0xtB501Z4V | ||
32 | Content-Type: application/pgp-encrypted | ||
33 | Content-Disposition: attachment | ||
34 | |||
35 | Version: 1 | ||
36 | --nextPart25203163.0xtB501Z4V | ||
37 | Content-Type: application/octet-stream | ||
38 | Content-Disposition: inline; filename="msg.asc" | ||
39 | |||
40 | -----BEGIN PGP MESSAGE----- | ||
41 | Version: GnuPG v2.0.15 (GNU/Linux) | ||
42 | |||
43 | hQEMAwzOQ1qnzNo7AQf7BFYWaGiCTGtXY59bSh3LCXNnWZejblYALxIUNXOFEXbm | ||
44 | y/YA95FmQsy3U5HRCAJV/DY1PEaJz1RTm9bcdIpDC3Ab2YzSwmOwV5fcoUOB2df4 | ||
45 | KjX19Q+2F3JxpPQ0N1gHf4dKfIu19LH+CKeFzUN13aJs5J4A5wlj+NjJikxzmxDS | ||
46 | kDtNYndynPmo9DJQcsUFw3gpvx5HaHvx1cT4mAB2M5cd2l+vN1jYbaWb0x5Zq41z | ||
47 | mRNI89aPieC3rcM2289m68fGloNbYvi8mZJu5RrI4Tbi/D7Rjm1y63lHgVV6AN88 | ||
48 | XAzRiedOeF99LoTBulrJdtT8AAgCs8nCetcWpIffdtLpAZiZkzHmYOU7nqGxqpRk | ||
49 | OVeUTrCn9DW2SMmHjaP4IiKnMvzEycu5F4a72+V1LeMIhMSjTRTq+ZE2PTaqH59z | ||
50 | QsMn7Nb6GlOICbTptRKNNtyJKO7xXlpT7YtvNKnCyEOkH2XrYH7GvpYCiuQ0/o+7 | ||
51 | SxV436ZejiYIg6DQDXJCoa2DXimGp0C10Jh0HwX0BixpoNtwEjkGRYcX6P/JzkH0 | ||
52 | oBood4Ly+Tiu6iVDisrK3AVGYpIzCrKkE9qULTw4R/jFKR2tcCqGb7Fxtk2LV7Md | ||
53 | 3S+DyOKrvKQ5GNwbp9OE97pwk+Lr1JS3UAvj5f6BR+1PVNcC0i0wWkgwDjPh1eGD | ||
54 | enMQmorE6+N0uHtH2F4fOxo/TbbA3+zhI25kVW3bO03xyUl/cmQZeb52nvfOvtOo | ||
55 | gSb2j6bPkzljDMPEzrtJjbFtGHJbPfUQYJgZv9OE2EQIqpg6goIw279alBq6GLIX | ||
56 | pkO+dRmztzjcDyhcLxMuQ4cTizel/0J/bU7U6lvwHSyZVbT4Ev+opG5K70Hbqbwr | ||
57 | NZcgdWXbSeesxGM/oQaMeSurOevxVl+/zrTVAek61aRRd1baAYqgi2pf2V7y4oK3 | ||
58 | qkdxzmoFpRdNlfrQW65NZWnHOi9rC9XxANIwnVn3kRcDf+t2K4PrFluI157lXM/o | ||
59 | wX91j88fazysbJlQ6TjsApO9ETiPOFEBqouxCTtCZzlUgyVG8jpIjdHWFnagHeXH | ||
60 | +lXNdYjxnTWTjTxMOZC9ySMpXkjWdFI1ecxVwu6Ik6RX51rvBJAAXWP75yUjPKJ4 | ||
61 | rRi5oQl/VLl0QznO7lvgMPtUwgDVNWO/r7Kn9B387h9fAJZ/kWFAEDW2yhAzABqO | ||
62 | rCNKDzBPgfAwCnikCpMoCbOL7SU8BdbzQHD8/Lkv4m0pzliHQ/KkGF710koBzTmF | ||
63 | N7+wk9pwIuvcrEBQj567 | ||
64 | =GV0c | ||
65 | -----END PGP MESSAGE----- | ||
66 | |||
67 | --nextPart25203163.0xtB501Z4V-- | ||
68 | |||
69 | --nextPart2148910.9CGjQOYhYJ-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/forward-openpgp-signed-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/forward-openpgp-signed-encrypted.mbox.html new file mode 100644 index 00000000..7632ec39 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/forward-openpgp-signed-encrypted.mbox.html | |||
@@ -0,0 +1,81 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <div class="noquote"> | ||
11 | <div dir="ltr">bla bla bla</div> | ||
12 | </div> | ||
13 | </div> | ||
14 | <a name="att2"/> | ||
15 | <div id="attachmentDiv2"> | ||
16 | <table cellspacing="1" cellpadding="1" class="rfc822"> | ||
17 | <tr class="rfc822H"> | ||
18 | <td dir="ltr"> | ||
19 | <a href="attachment:2.1?place=body">Encapsulated message</a> | ||
20 | </td> | ||
21 | </tr> | ||
22 | <tr class="rfc822B"> | ||
23 | <td> | ||
24 | <a name="att2.1"/> | ||
25 | <div id="attachmentDiv2.1"> | ||
26 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
27 | <tr class="encrH"> | ||
28 | <td dir="ltr">Encrypted message</td> | ||
29 | </tr> | ||
30 | <tr class="encrB"> | ||
31 | <td> | ||
32 | <div style="position: relative; word-wrap: break-word"> | ||
33 | <a name="att"/> | ||
34 | <div id="attachmentDiv"> | ||
35 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
36 | <tr class="signOkKeyOkH"> | ||
37 | <td dir="ltr"> | ||
38 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
39 | <tr> | ||
40 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
41 | <td align="right"> | ||
42 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
43 | </td> | ||
44 | </tr> | ||
45 | </table> | ||
46 | </td> | ||
47 | </tr> | ||
48 | <tr class="signOkKeyOkB"> | ||
49 | <td> | ||
50 | <a name="att1"/> | ||
51 | <div id="attachmentDiv1"> | ||
52 | <div class="noquote"> | ||
53 | <div dir="ltr">encrypted message text</div> | ||
54 | </div> | ||
55 | </div> | ||
56 | </td> | ||
57 | </tr> | ||
58 | <tr class="signOkKeyOkH"> | ||
59 | <td dir="ltr">End of signed message</td> | ||
60 | </tr> | ||
61 | </table> | ||
62 | </div> | ||
63 | </div> | ||
64 | </td> | ||
65 | </tr> | ||
66 | <tr class="encrH"> | ||
67 | <td dir="ltr">End of encrypted message</td> | ||
68 | </tr> | ||
69 | </table> | ||
70 | </div> | ||
71 | </td> | ||
72 | </tr> | ||
73 | <tr class="rfc822H"> | ||
74 | <td dir="ltr">End of encapsulated message</td> | ||
75 | </tr> | ||
76 | </table> | ||
77 | </div> | ||
78 | </div> | ||
79 | </div> | ||
80 | </body> | ||
81 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/forward-openpgp-signed-encrypted.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/forward-openpgp-signed-encrypted.mbox.tree new file mode 100644 index 00000000..324156db --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/forward-openpgp-signed-encrypted.mbox.tree | |||
@@ -0,0 +1,9 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::TextMessagePart | ||
4 | * MimeTreeParser::MessagePart | ||
5 | * MimeTreeParser::EncapsulatedRfc822MessagePart | ||
6 | * MimeTreeParser::EncryptedMessagePart | ||
7 | * MimeTreeParser::SignedMessagePart | ||
8 | * MimeTreeParser::TextMessagePart | ||
9 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..73c4d2d7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,61 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">test text</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="signOkKeyOkH"> | ||
46 | <td dir="ltr">End of signed message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="encrH"> | ||
54 | <td dir="ltr">End of encrypted message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | </div> | ||
59 | </div> | ||
60 | </body> | ||
61 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-attachment.mbox.html new file mode 100644 index 00000000..d5e4550e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,58 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <a name="att1.1"/> | ||
35 | <div id="attachmentDiv1.1"> | ||
36 | <div class="noquote"> | ||
37 | <div dir="ltr">test text</div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signOkKeyOkH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="encrH"> | ||
52 | <td dir="ltr">End of encrypted message</td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </body> | ||
58 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..73c4d2d7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,61 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">test text</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="signOkKeyOkH"> | ||
46 | <td dir="ltr">End of signed message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="encrH"> | ||
54 | <td dir="ltr">End of encrypted message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | </div> | ||
59 | </div> | ||
60 | </body> | ||
61 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-partially-signed-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-partially-signed-attachments.mbox.html new file mode 100644 index 00000000..ebad7354 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-partially-signed-attachments.mbox.html | |||
@@ -0,0 +1,84 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">This is the main body.</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="signOkKeyOkH"> | ||
46 | <td dir="ltr">End of signed message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="encrH"> | ||
54 | <td dir="ltr">End of encrypted message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | <a name="att2"/> | ||
59 | <div id="attachmentDiv2"> | ||
60 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
61 | <tr class="encrH"> | ||
62 | <td dir="ltr">Encrypted message</td> | ||
63 | </tr> | ||
64 | <tr class="encrB"> | ||
65 | <td> | ||
66 | <div style="position: relative; word-wrap: break-word"> | ||
67 | <a name="att"/> | ||
68 | <div id="attachmentDiv"> | ||
69 | <div class="noquote"> | ||
70 | <div dir="ltr">This is an unsigned attachment.</div> | ||
71 | </div> | ||
72 | </div> | ||
73 | </div> | ||
74 | </td> | ||
75 | </tr> | ||
76 | <tr class="encrH"> | ||
77 | <td dir="ltr">End of encrypted message</td> | ||
78 | </tr> | ||
79 | </table> | ||
80 | </div> | ||
81 | </div> | ||
82 | </div> | ||
83 | </body> | ||
84 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-two-attachments.mbox.html new file mode 100644 index 00000000..4cdeaa63 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-encrypted-two-attachments.mbox.html | |||
@@ -0,0 +1,34 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <a name="att1"/> | ||
18 | <div id="attachmentDiv1"> | ||
19 | <div class="noquote"> | ||
20 | <div dir="ltr">this is the main body part</div> | ||
21 | </div> | ||
22 | </div> | ||
23 | </div> | ||
24 | </div> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr class="encrH"> | ||
28 | <td dir="ltr">End of encrypted message</td> | ||
29 | </tr> | ||
30 | </table> | ||
31 | </div> | ||
32 | </div> | ||
33 | </body> | ||
34 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-apple.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-apple.mbox.html new file mode 100644 index 00000000..330b02a1 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-apple.mbox.html | |||
@@ -0,0 +1,50 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
9 | <tr class="signWarnH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Not enough information to check signature validity.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signWarnB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.2"/> | ||
26 | <div id="attachmentDiv1.2"> | ||
27 | <a name="att1.2.1"/> | ||
28 | <div id="attachmentDiv1.2.1"> | ||
29 | <div style="position: relative"> | ||
30 | <div class="">pre attachment</div> | ||
31 | </div> | ||
32 | </div> | ||
33 | <a name="att1.2.3"/> | ||
34 | <div id="attachmentDiv1.2.3"> | ||
35 | <div style="position: relative"> | ||
36 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signWarnH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </body> | ||
50 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-encrypted-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-encrypted-two-attachments.mbox.html new file mode 100644 index 00000000..83b7a66c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-encrypted-two-attachments.mbox.html | |||
@@ -0,0 +1,58 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <a name="att1.1"/> | ||
35 | <div id="attachmentDiv1.1"> | ||
36 | <div class="noquote"> | ||
37 | <div dir="ltr">this is the main body</div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signOkKeyOkH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="encrH"> | ||
52 | <td dir="ltr">End of encrypted message</td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </body> | ||
58 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-mailinglist+additional-children.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-mailinglist+additional-children.mbox.html new file mode 100644 index 00000000..25b1ad04 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-mailinglist+additional-children.mbox.html | |||
@@ -0,0 +1,52 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <a name="att1.1"/> | ||
11 | <div id="attachmentDiv1.1"> | ||
12 | <div class="noquote"> | ||
13 | <div dir="ltr">hi..</div> | ||
14 | <br/> | ||
15 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
16 | <div dir="ltr">activities_optional</div> | ||
17 | <br/> | ||
18 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
19 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
20 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
21 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
22 | <br/> | ||
23 | <div dir="ltr">-- </div> | ||
24 | <div dir="ltr">Aaron J. Seigo</div> | ||
25 | </div> | ||
26 | </div> | ||
27 | <a name="att1.2"/> | ||
28 | <div id="attachmentDiv1.2"> | ||
29 | <hr/> | ||
30 | <div> | ||
31 | <a href="attachment:1.2?place=body"><img align="center" height="48" width="48" src="file:application-pgp-signature.svg" border="0" style="max-width: 100%" alt=""/>signature.asc</a> | ||
32 | </div> | ||
33 | <div>This is a digitally signed message part.</div> | ||
34 | </div> | ||
35 | </div> | ||
36 | <a name="att2"/> | ||
37 | <div id="attachmentDiv2"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">_______________________________________________</div> | ||
40 | <div dir="ltr">Plasma-devel mailing list</div> | ||
41 | <div dir="ltr"> | ||
42 | <a href="mailto:Plasma-devel@kde.org">Plasma-devel@kde.org</a> | ||
43 | </div> | ||
44 | <div dir="ltr"> | ||
45 | <a href="https://mail.kde.org/mailman/listinfo/plasma-devel">https://mail.kde.org/mailman/listinfo/plasma-devel</a> | ||
46 | </div> | ||
47 | </div> | ||
48 | </div> | ||
49 | </div> | ||
50 | </div> | ||
51 | </body> | ||
52 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-no-protocol.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-no-protocol.mbox.html new file mode 100644 index 00000000..bdac52b6 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-no-protocol.mbox.html | |||
@@ -0,0 +1,28 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <div class="noquote"> | ||
11 | <div dir="ltr">hi..</div> | ||
12 | <br/> | ||
13 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
14 | <div dir="ltr">activities_optional</div> | ||
15 | <br/> | ||
16 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
17 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
18 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
19 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
20 | <br/> | ||
21 | <div dir="ltr">-- </div> | ||
22 | <div dir="ltr">Aaron J. Seigo</div> | ||
23 | </div> | ||
24 | </div> | ||
25 | </div> | ||
26 | </div> | ||
27 | </body> | ||
28 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-two-attachments.mbox.html new file mode 100644 index 00000000..027097f7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/openpgp-signed-two-attachments.mbox.html | |||
@@ -0,0 +1,41 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signOkKeyOkB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.1"/> | ||
26 | <div id="attachmentDiv1.1"> | ||
27 | <div class="noquote"> | ||
28 | <div dir="ltr">this is the main body text</div> | ||
29 | </div> | ||
30 | </div> | ||
31 | </div> | ||
32 | </td> | ||
33 | </tr> | ||
34 | <tr class="signOkKeyOkH"> | ||
35 | <td dir="ltr">End of signed message</td> | ||
36 | </tr> | ||
37 | </table> | ||
38 | </div> | ||
39 | </div> | ||
40 | </body> | ||
41 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/smime-signed-apple.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/smime-signed-apple.mbox.html new file mode 100644 index 00000000..9554bb39 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/headeronly/smime-signed-apple.mbox.html | |||
@@ -0,0 +1,50 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signErr"> | ||
9 | <tr class="signErrH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Invalid signature.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signErrB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.2"/> | ||
26 | <div id="attachmentDiv1.2"> | ||
27 | <a name="att1.2.1"/> | ||
28 | <div id="attachmentDiv1.2.1"> | ||
29 | <div style="position: relative">Olá Konqui,<div class="">Here is the pdf you asked for!</div><div class="">Cheers,</div><div class="">Quaack</div></div> | ||
30 | </div> | ||
31 | <a name="att1.2.3"/> | ||
32 | <div id="attachmentDiv1.2.3"> | ||
33 | <div style="position: relative"> | ||
34 | <blockquote type="cite" class=""> | ||
35 | <div class="">On 20 Jan 2017, at 10:35, Konqui <<a href="mailto:Konqui@kdab.com">Konqui</a></div> | ||
36 | </blockquote> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signErrH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </body> | ||
50 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/encapsulated-with-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/encapsulated-with-attachment.mbox.html new file mode 100644 index 00000000..42f5ecd7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/encapsulated-with-attachment.mbox.html | |||
@@ -0,0 +1,43 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <div class="noquote"> | ||
11 | <div dir="ltr">This is the first encapsulating message.</div> | ||
12 | </div> | ||
13 | </div> | ||
14 | <a name="att2"/> | ||
15 | <div id="attachmentDiv2"> | ||
16 | <table cellspacing="1" cellpadding="1" class="rfc822"> | ||
17 | <tr class="rfc822H"> | ||
18 | <td dir="ltr"> | ||
19 | <a href="attachment:2.1?place=body">Encapsulated message</a> | ||
20 | </td> | ||
21 | </tr> | ||
22 | <tr class="rfc822B"> | ||
23 | <td> | ||
24 | <a name="att2.1"/> | ||
25 | <div id="attachmentDiv2.1"> | ||
26 | <a name="att2.1.1"/> | ||
27 | <div id="attachmentDiv2.1.1"> | ||
28 | <div class="noquote"> | ||
29 | <div dir="ltr">This is the second encapsulated message.</div> | ||
30 | </div> | ||
31 | </div> | ||
32 | </div> | ||
33 | </td> | ||
34 | </tr> | ||
35 | <tr class="rfc822H"> | ||
36 | <td dir="ltr">End of encapsulated message</td> | ||
37 | </tr> | ||
38 | </table> | ||
39 | </div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </body> | ||
43 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..73c4d2d7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,61 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">test text</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="signOkKeyOkH"> | ||
46 | <td dir="ltr">End of signed message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="encrH"> | ||
54 | <td dir="ltr">End of encrypted message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | </div> | ||
59 | </div> | ||
60 | </body> | ||
61 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-attachment.mbox.html new file mode 100644 index 00000000..d5e4550e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,58 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <a name="att1.1"/> | ||
35 | <div id="attachmentDiv1.1"> | ||
36 | <div class="noquote"> | ||
37 | <div dir="ltr">test text</div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signOkKeyOkH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="encrH"> | ||
52 | <td dir="ltr">End of encrypted message</td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </body> | ||
58 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-noData.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-noData.mbox.html new file mode 100644 index 00000000..166812fe --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-noData.mbox.html | |||
@@ -0,0 +1,10 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"/> | ||
8 | </div> | ||
9 | </body> | ||
10 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..73c4d2d7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,61 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">test text</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="signOkKeyOkH"> | ||
46 | <td dir="ltr">End of signed message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="encrH"> | ||
54 | <td dir="ltr">End of encrypted message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | </div> | ||
59 | </div> | ||
60 | </body> | ||
61 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-partially-signed-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-partially-signed-attachments.mbox.html new file mode 100644 index 00000000..ebad7354 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-partially-signed-attachments.mbox.html | |||
@@ -0,0 +1,84 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">This is the main body.</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="signOkKeyOkH"> | ||
46 | <td dir="ltr">End of signed message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="encrH"> | ||
54 | <td dir="ltr">End of encrypted message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | <a name="att2"/> | ||
59 | <div id="attachmentDiv2"> | ||
60 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
61 | <tr class="encrH"> | ||
62 | <td dir="ltr">Encrypted message</td> | ||
63 | </tr> | ||
64 | <tr class="encrB"> | ||
65 | <td> | ||
66 | <div style="position: relative; word-wrap: break-word"> | ||
67 | <a name="att"/> | ||
68 | <div id="attachmentDiv"> | ||
69 | <div class="noquote"> | ||
70 | <div dir="ltr">This is an unsigned attachment.</div> | ||
71 | </div> | ||
72 | </div> | ||
73 | </div> | ||
74 | </td> | ||
75 | </tr> | ||
76 | <tr class="encrH"> | ||
77 | <td dir="ltr">End of encrypted message</td> | ||
78 | </tr> | ||
79 | </table> | ||
80 | </div> | ||
81 | </div> | ||
82 | </div> | ||
83 | </body> | ||
84 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-two-attachments.mbox.html new file mode 100644 index 00000000..4cdeaa63 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-encrypted-two-attachments.mbox.html | |||
@@ -0,0 +1,34 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <a name="att1"/> | ||
18 | <div id="attachmentDiv1"> | ||
19 | <div class="noquote"> | ||
20 | <div dir="ltr">this is the main body part</div> | ||
21 | </div> | ||
22 | </div> | ||
23 | </div> | ||
24 | </div> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr class="encrH"> | ||
28 | <td dir="ltr">End of encrypted message</td> | ||
29 | </tr> | ||
30 | </table> | ||
31 | </div> | ||
32 | </div> | ||
33 | </body> | ||
34 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-apple.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-apple.mbox.html new file mode 100644 index 00000000..330b02a1 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-apple.mbox.html | |||
@@ -0,0 +1,50 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
9 | <tr class="signWarnH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Not enough information to check signature validity.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signWarnB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.2"/> | ||
26 | <div id="attachmentDiv1.2"> | ||
27 | <a name="att1.2.1"/> | ||
28 | <div id="attachmentDiv1.2.1"> | ||
29 | <div style="position: relative"> | ||
30 | <div class="">pre attachment</div> | ||
31 | </div> | ||
32 | </div> | ||
33 | <a name="att1.2.3"/> | ||
34 | <div id="attachmentDiv1.2.3"> | ||
35 | <div style="position: relative"> | ||
36 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signWarnH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </body> | ||
50 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-encrypted-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-encrypted-two-attachments.mbox.html new file mode 100644 index 00000000..83b7a66c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-encrypted-two-attachments.mbox.html | |||
@@ -0,0 +1,58 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <a name="att1.1"/> | ||
35 | <div id="attachmentDiv1.1"> | ||
36 | <div class="noquote"> | ||
37 | <div dir="ltr">this is the main body</div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signOkKeyOkH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="encrH"> | ||
52 | <td dir="ltr">End of encrypted message</td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </body> | ||
58 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-mailinglist+additional-children.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-mailinglist+additional-children.mbox.html new file mode 100644 index 00000000..1f0da385 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-mailinglist+additional-children.mbox.html | |||
@@ -0,0 +1,44 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <a name="att1.1"/> | ||
11 | <div id="attachmentDiv1.1"> | ||
12 | <div class="noquote"> | ||
13 | <div dir="ltr">hi..</div> | ||
14 | <br/> | ||
15 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
16 | <div dir="ltr">activities_optional</div> | ||
17 | <br/> | ||
18 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
19 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
20 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
21 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
22 | <br/> | ||
23 | <div dir="ltr">-- </div> | ||
24 | <div dir="ltr">Aaron J. Seigo</div> | ||
25 | </div> | ||
26 | </div> | ||
27 | </div> | ||
28 | <a name="att2"/> | ||
29 | <div id="attachmentDiv2"> | ||
30 | <div class="noquote"> | ||
31 | <div dir="ltr">_______________________________________________</div> | ||
32 | <div dir="ltr">Plasma-devel mailing list</div> | ||
33 | <div dir="ltr"> | ||
34 | <a href="mailto:Plasma-devel@kde.org">Plasma-devel@kde.org</a> | ||
35 | </div> | ||
36 | <div dir="ltr"> | ||
37 | <a href="https://mail.kde.org/mailman/listinfo/plasma-devel">https://mail.kde.org/mailman/listinfo/plasma-devel</a> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </body> | ||
44 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-no-protocol.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-no-protocol.mbox.html new file mode 100644 index 00000000..bdac52b6 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-no-protocol.mbox.html | |||
@@ -0,0 +1,28 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <div class="noquote"> | ||
11 | <div dir="ltr">hi..</div> | ||
12 | <br/> | ||
13 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
14 | <div dir="ltr">activities_optional</div> | ||
15 | <br/> | ||
16 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
17 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
18 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
19 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
20 | <br/> | ||
21 | <div dir="ltr">-- </div> | ||
22 | <div dir="ltr">Aaron J. Seigo</div> | ||
23 | </div> | ||
24 | </div> | ||
25 | </div> | ||
26 | </div> | ||
27 | </body> | ||
28 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-two-attachments.mbox.html new file mode 100644 index 00000000..027097f7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/openpgp-signed-two-attachments.mbox.html | |||
@@ -0,0 +1,41 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signOkKeyOkB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.1"/> | ||
26 | <div id="attachmentDiv1.1"> | ||
27 | <div class="noquote"> | ||
28 | <div dir="ltr">this is the main body text</div> | ||
29 | </div> | ||
30 | </div> | ||
31 | </div> | ||
32 | </td> | ||
33 | </tr> | ||
34 | <tr class="signOkKeyOkH"> | ||
35 | <td dir="ltr">End of signed message</td> | ||
36 | </tr> | ||
37 | </table> | ||
38 | </div> | ||
39 | </div> | ||
40 | </body> | ||
41 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/smime-signed-apple.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/smime-signed-apple.mbox.html new file mode 100644 index 00000000..9554bb39 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/hidden/smime-signed-apple.mbox.html | |||
@@ -0,0 +1,50 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signErr"> | ||
9 | <tr class="signErrH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Invalid signature.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signErrB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.2"/> | ||
26 | <div id="attachmentDiv1.2"> | ||
27 | <a name="att1.2.1"/> | ||
28 | <div id="attachmentDiv1.2.1"> | ||
29 | <div style="position: relative">Olá Konqui,<div class="">Here is the pdf you asked for!</div><div class="">Cheers,</div><div class="">Quaack</div></div> | ||
30 | </div> | ||
31 | <a name="att1.2.3"/> | ||
32 | <div id="attachmentDiv1.2.3"> | ||
33 | <div style="position: relative"> | ||
34 | <blockquote type="cite" class=""> | ||
35 | <div class="">On 20 Jan 2017, at 10:35, Konqui <<a href="mailto:Konqui@kdab.com">Konqui</a></div> | ||
36 | </blockquote> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signErrH"> | ||
44 | <td dir="ltr">End of signed message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </body> | ||
50 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/html.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/html.mbox new file mode 100644 index 00000000..eebd4283 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/html.mbox | |||
@@ -0,0 +1,31 @@ | |||
1 | From foo@example.com Thu, 26 May 2011 01:16:54 +0100 | ||
2 | From: Thomas McGuire <foo@example.com> | ||
3 | Subject: HTML test | ||
4 | Date: Thu, 26 May 2011 01:16:54 +0100 | ||
5 | Message-ID: <1501334.pROlBb7MZF@herrwackelpudding.localhost> | ||
6 | X-KMail-Transport: GMX | ||
7 | X-KMail-Fcc: 28 | ||
8 | X-KMail-Drafts: 7 | ||
9 | X-KMail-Templates: 9 | ||
10 | User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) | ||
11 | MIME-Version: 1.0 | ||
12 | Content-Type: multipart/alternative; boundary="nextPart8606278.tpV19BTJKu" | ||
13 | Content-Transfer-Encoding: 7Bit | ||
14 | |||
15 | |||
16 | --nextPart8606278.tpV19BTJKu | ||
17 | Content-Transfer-Encoding: 7Bit | ||
18 | Content-Type: text/plain; charset="windows-1252" | ||
19 | |||
20 | Some HTML text | ||
21 | --nextPart8606278.tpV19BTJKu | ||
22 | Content-Transfer-Encoding: 7Bit | ||
23 | Content-Type: text/html; charset="windows-1252" | ||
24 | |||
25 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> | ||
26 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> | ||
27 | p, li { white-space: pre-wrap; } | ||
28 | </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> | ||
29 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p></body></html> | ||
30 | --nextPart8606278.tpV19BTJKu-- | ||
31 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/html.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/html.mbox.html new file mode 100644 index 00000000..2fe886f1 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/html.mbox.html | |||
@@ -0,0 +1,17 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att2"/> | ||
9 | <div id="attachmentDiv2"> | ||
10 | <div style="position: relative"> | ||
11 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p> | ||
12 | </div> | ||
13 | </div> | ||
14 | </div> | ||
15 | </div> | ||
16 | </body> | ||
17 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/html.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/html.mbox.tree new file mode 100644 index 00000000..0de07281 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/html.mbox.tree | |||
@@ -0,0 +1,2 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::AlternativeMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonly.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonly.mbox new file mode 100644 index 00000000..e45b1c4d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonly.mbox | |||
@@ -0,0 +1,21 @@ | |||
1 | From foo@example.com Thu, 26 May 2011 01:16:54 +0100 | ||
2 | From: Thomas McGuire <foo@example.com> | ||
3 | Subject: HTML test | ||
4 | Date: Thu, 26 May 2011 01:16:54 +0100 | ||
5 | Message-ID: <1501334.pROlBb7MZF@herrwackelpudding.localhost> | ||
6 | X-KMail-Transport: GMX | ||
7 | X-KMail-Fcc: 28 | ||
8 | X-KMail-Drafts: 7 | ||
9 | X-KMail-Templates: 9 | ||
10 | User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) | ||
11 | MIME-Version: 1.0 | ||
12 | Content-Type: text/html | ||
13 | Content-Transfer-Encoding: 7Bit | ||
14 | |||
15 | <html> | ||
16 | <head> | ||
17 | </head> | ||
18 | <body> | ||
19 | <b>SOME</b> HTML text. | ||
20 | </body> | ||
21 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonly.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonly.mbox.html new file mode 100644 index 00000000..1143f2cf --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonly.mbox.html | |||
@@ -0,0 +1,12 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <div style="position: relative"><b>SOME</b> HTML text.</div> | ||
9 | </div> | ||
10 | </div> | ||
11 | </body> | ||
12 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonly.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonly.mbox.tree new file mode 100644 index 00000000..a4c3191b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonly.mbox.tree | |||
@@ -0,0 +1,2 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::HtmlMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonlyexternal.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonlyexternal.mbox new file mode 100644 index 00000000..4eb3e2c3 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/htmlonlyexternal.mbox | |||
@@ -0,0 +1,21 @@ | |||
1 | From foo@example.com Thu, 26 May 2011 01:16:54 +0100 | ||
2 | From: Thomas McGuire <foo@example.com> | ||
3 | Subject: HTML test | ||
4 | Date: Thu, 26 May 2011 01:16:54 +0100 | ||
5 | Message-ID: <1501334.pROlBb7MZF@herrwackelpudding.localhost> | ||
6 | X-KMail-Transport: GMX | ||
7 | X-KMail-Fcc: 28 | ||
8 | X-KMail-Drafts: 7 | ||
9 | X-KMail-Templates: 9 | ||
10 | User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) | ||
11 | MIME-Version: 1.0 | ||
12 | Content-Type: text/html | ||
13 | Content-Transfer-Encoding: 7Bit | ||
14 | |||
15 | <html> | ||
16 | <head> | ||
17 | </head> | ||
18 | <body> | ||
19 | <b>SOME</b> HTML text. <img src="http://example.org/test.img" > | ||
20 | </body> | ||
21 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-encrypted-partially-signed-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-encrypted-partially-signed-attachments.mbox.html new file mode 100644 index 00000000..b6f734c2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-encrypted-partially-signed-attachments.mbox.html | |||
@@ -0,0 +1,92 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">This is the main body.</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | <a name="att1.2"/> | ||
43 | <div id="attachmentDiv1.2"> | ||
44 | <hr/> | ||
45 | <div> | ||
46 | <a href="attachment:1:e0:1.2?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>attachment1.txt</a> | ||
47 | </div> | ||
48 | <div/> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="signOkKeyOkH"> | ||
54 | <td dir="ltr">End of signed message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | </div> | ||
59 | </td> | ||
60 | </tr> | ||
61 | <tr class="encrH"> | ||
62 | <td dir="ltr">End of encrypted message</td> | ||
63 | </tr> | ||
64 | </table> | ||
65 | </div> | ||
66 | <a name="att2"/> | ||
67 | <div id="attachmentDiv2"> | ||
68 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
69 | <tr class="encrH"> | ||
70 | <td dir="ltr">Encrypted message</td> | ||
71 | </tr> | ||
72 | <tr class="encrB"> | ||
73 | <td> | ||
74 | <div style="position: relative; word-wrap: break-word"> | ||
75 | <a name="att"/> | ||
76 | <div id="attachmentDiv"> | ||
77 | <div class="noquote"> | ||
78 | <div dir="ltr">This is an unsigned attachment.</div> | ||
79 | </div> | ||
80 | </div> | ||
81 | </div> | ||
82 | </td> | ||
83 | </tr> | ||
84 | <tr class="encrH"> | ||
85 | <td dir="ltr">End of encrypted message</td> | ||
86 | </tr> | ||
87 | </table> | ||
88 | </div> | ||
89 | </div> | ||
90 | </div> | ||
91 | </body> | ||
92 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-encrypted-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-encrypted-two-attachments.mbox.html new file mode 100644 index 00000000..7f0b7abd --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-encrypted-two-attachments.mbox.html | |||
@@ -0,0 +1,50 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <a name="att1"/> | ||
18 | <div id="attachmentDiv1"> | ||
19 | <div class="noquote"> | ||
20 | <div dir="ltr">this is the main body part</div> | ||
21 | </div> | ||
22 | </div> | ||
23 | <a name="att2"/> | ||
24 | <div id="attachmentDiv2"> | ||
25 | <hr/> | ||
26 | <div> | ||
27 | <a href="attachment:e0:2?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>attachment1.txt</a> | ||
28 | </div> | ||
29 | <div/> | ||
30 | </div> | ||
31 | <a name="att3"/> | ||
32 | <div id="attachmentDiv3"> | ||
33 | <hr/> | ||
34 | <div> | ||
35 | <a href="attachment:e0:3?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>attachment2.txt</a> | ||
36 | </div> | ||
37 | <div/> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="encrH"> | ||
44 | <td dir="ltr">End of encrypted message</td> | ||
45 | </tr> | ||
46 | </table> | ||
47 | </div> | ||
48 | </div> | ||
49 | </body> | ||
50 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-signed-encrypted-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-signed-encrypted-two-attachments.mbox.html new file mode 100644 index 00000000..8d6b5814 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-signed-encrypted-two-attachments.mbox.html | |||
@@ -0,0 +1,74 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <a name="att1.1"/> | ||
35 | <div id="attachmentDiv1.1"> | ||
36 | <div class="noquote"> | ||
37 | <div dir="ltr">this is the main body</div> | ||
38 | </div> | ||
39 | </div> | ||
40 | <a name="att1.2"/> | ||
41 | <div id="attachmentDiv1.2"> | ||
42 | <hr/> | ||
43 | <div> | ||
44 | <a href="attachment:e0:1.2?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>attachment1.txt</a> | ||
45 | </div> | ||
46 | <div/> | ||
47 | </div> | ||
48 | <a name="att1.3"/> | ||
49 | <div id="attachmentDiv1.3"> | ||
50 | <hr/> | ||
51 | <div> | ||
52 | <a href="attachment:e0:1.3?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>attachment2.txt</a> | ||
53 | </div> | ||
54 | <div/> | ||
55 | </div> | ||
56 | </div> | ||
57 | </td> | ||
58 | </tr> | ||
59 | <tr class="signOkKeyOkH"> | ||
60 | <td dir="ltr">End of signed message</td> | ||
61 | </tr> | ||
62 | </table> | ||
63 | </div> | ||
64 | </div> | ||
65 | </td> | ||
66 | </tr> | ||
67 | <tr class="encrH"> | ||
68 | <td dir="ltr">End of encrypted message</td> | ||
69 | </tr> | ||
70 | </table> | ||
71 | </div> | ||
72 | </div> | ||
73 | </body> | ||
74 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-signed-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-signed-two-attachments.mbox.html new file mode 100644 index 00000000..73dbc5f4 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/iconic/openpgp-signed-two-attachments.mbox.html | |||
@@ -0,0 +1,57 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signOkKeyOkB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.1"/> | ||
26 | <div id="attachmentDiv1.1"> | ||
27 | <div class="noquote"> | ||
28 | <div dir="ltr">this is the main body text</div> | ||
29 | </div> | ||
30 | </div> | ||
31 | <a name="att1.2"/> | ||
32 | <div id="attachmentDiv1.2"> | ||
33 | <hr/> | ||
34 | <div> | ||
35 | <a href="attachment:1.2?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>attachment1.txt</a> | ||
36 | </div> | ||
37 | <div/> | ||
38 | </div> | ||
39 | <a name="att1.3"/> | ||
40 | <div id="attachmentDiv1.3"> | ||
41 | <hr/> | ||
42 | <div> | ||
43 | <a href="attachment:1.3?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>attachment2.txt</a> | ||
44 | </div> | ||
45 | <div/> | ||
46 | </div> | ||
47 | </div> | ||
48 | </td> | ||
49 | </tr> | ||
50 | <tr class="signOkKeyOkH"> | ||
51 | <td dir="ltr">End of signed message</td> | ||
52 | </tr> | ||
53 | </table> | ||
54 | </div> | ||
55 | </div> | ||
56 | </body> | ||
57 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/encapsulated-with-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/encapsulated-with-attachment.mbox.html new file mode 100644 index 00000000..26d3dd60 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/encapsulated-with-attachment.mbox.html | |||
@@ -0,0 +1,58 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <div class="noquote"> | ||
11 | <div dir="ltr">This is the first encapsulating message.</div> | ||
12 | </div> | ||
13 | </div> | ||
14 | <a name="att2"/> | ||
15 | <div id="attachmentDiv2"> | ||
16 | <table cellspacing="1" cellpadding="1" class="rfc822"> | ||
17 | <tr class="rfc822H"> | ||
18 | <td dir="ltr"> | ||
19 | <a href="attachment:2.1?place=body">Encapsulated message</a> | ||
20 | </td> | ||
21 | </tr> | ||
22 | <tr class="rfc822B"> | ||
23 | <td> | ||
24 | <a name="att2.1"/> | ||
25 | <div id="attachmentDiv2.1"> | ||
26 | <a name="att2.1.1"/> | ||
27 | <div id="attachmentDiv2.1.1"> | ||
28 | <div class="noquote"> | ||
29 | <div dir="ltr">This is the second encapsulated message.</div> | ||
30 | </div> | ||
31 | </div> | ||
32 | <a name="att2.1.2"/> | ||
33 | <div id="attachmentDiv2.1.2"> | ||
34 | <table cellspacing="1" class="textAtm"> | ||
35 | <tr class="textAtmH"> | ||
36 | <td dir="ltr">attachment.txt</td> | ||
37 | </tr> | ||
38 | <tr class="textAtmB"> | ||
39 | <td> | ||
40 | <div class="noquote"> | ||
41 | <div dir="ltr">This is an attachment.</div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | </table> | ||
46 | </div> | ||
47 | </div> | ||
48 | </td> | ||
49 | </tr> | ||
50 | <tr class="rfc822H"> | ||
51 | <td dir="ltr">End of encapsulated message</td> | ||
52 | </tr> | ||
53 | </table> | ||
54 | </div> | ||
55 | </div> | ||
56 | </div> | ||
57 | </body> | ||
58 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..49e503f1 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,90 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">test text</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | <a name="att1.2"/> | ||
43 | <div id="attachmentDiv1.2"> | ||
44 | <table cellspacing="1" class="textAtm"> | ||
45 | <tr class="textAtmH"> | ||
46 | <td dir="ltr">file.txt</td> | ||
47 | </tr> | ||
48 | <tr class="textAtmB"> | ||
49 | <td> | ||
50 | <div class="noquote"> | ||
51 | <div dir="ltr">some plain ascii text...</div> | ||
52 | <br/> | ||
53 | </div> | ||
54 | </td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | </div> | ||
59 | </td> | ||
60 | </tr> | ||
61 | <tr class="signOkKeyOkH"> | ||
62 | <td dir="ltr">End of signed message</td> | ||
63 | </tr> | ||
64 | </table> | ||
65 | </div> | ||
66 | </div> | ||
67 | </td> | ||
68 | </tr> | ||
69 | <tr class="encrH"> | ||
70 | <td dir="ltr">End of encrypted message</td> | ||
71 | </tr> | ||
72 | </table> | ||
73 | </div> | ||
74 | <a name="att2"/> | ||
75 | <div id="attachmentDiv2"> | ||
76 | <hr/> | ||
77 | <div> | ||
78 | <a href="attachment:2?place=body"> | ||
79 | <img align="center" src="file:image.png" border="0" style="max-width: 100%"/> | ||
80 | </a> | ||
81 | </div> | ||
82 | <div> | ||
83 | <a href="attachment:2?place=body">image.png</a> | ||
84 | </div> | ||
85 | <div/> | ||
86 | </div> | ||
87 | </div> | ||
88 | </div> | ||
89 | </body> | ||
90 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-encrypted-attachment.mbox.html new file mode 100644 index 00000000..67897491 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,74 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <a name="att1.1"/> | ||
35 | <div id="attachmentDiv1.1"> | ||
36 | <div class="noquote"> | ||
37 | <div dir="ltr">test text</div> | ||
38 | </div> | ||
39 | </div> | ||
40 | <a name="att1.2"/> | ||
41 | <div id="attachmentDiv1.2"> | ||
42 | <table cellspacing="1" class="textAtm"> | ||
43 | <tr class="textAtmH"> | ||
44 | <td dir="ltr">file.txt</td> | ||
45 | </tr> | ||
46 | <tr class="textAtmB"> | ||
47 | <td> | ||
48 | <div class="noquote"> | ||
49 | <div dir="ltr">some plain ascii text...</div> | ||
50 | <br/> | ||
51 | </div> | ||
52 | </td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </td> | ||
58 | </tr> | ||
59 | <tr class="signOkKeyOkH"> | ||
60 | <td dir="ltr">End of signed message</td> | ||
61 | </tr> | ||
62 | </table> | ||
63 | </div> | ||
64 | </div> | ||
65 | </td> | ||
66 | </tr> | ||
67 | <tr class="encrH"> | ||
68 | <td dir="ltr">End of encrypted message</td> | ||
69 | </tr> | ||
70 | </table> | ||
71 | </div> | ||
72 | </div> | ||
73 | </body> | ||
74 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-encrypted-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-encrypted-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..6091ee5a --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-encrypted-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,74 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">test text</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="signOkKeyOkH"> | ||
46 | <td dir="ltr">End of signed message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="encrH"> | ||
54 | <td dir="ltr">End of encrypted message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | <a name="att2"/> | ||
59 | <div id="attachmentDiv2"> | ||
60 | <hr/> | ||
61 | <div> | ||
62 | <a href="attachment:2?place=body"> | ||
63 | <img align="center" src="file:image.png" border="0" style="max-width: 100%"/> | ||
64 | </a> | ||
65 | </div> | ||
66 | <div> | ||
67 | <a href="attachment:2?place=body">image.png</a> | ||
68 | </div> | ||
69 | <div/> | ||
70 | </div> | ||
71 | </div> | ||
72 | </div> | ||
73 | </body> | ||
74 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-signed-apple.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-signed-apple.mbox.html new file mode 100644 index 00000000..092d5e1c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-signed-apple.mbox.html | |||
@@ -0,0 +1,63 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
9 | <tr class="signWarnH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Not enough information to check signature validity.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signWarnB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.2"/> | ||
26 | <div id="attachmentDiv1.2"> | ||
27 | <a name="att1.2.1"/> | ||
28 | <div id="attachmentDiv1.2.1"> | ||
29 | <div style="position: relative"> | ||
30 | <div class="">pre attachment</div> | ||
31 | </div> | ||
32 | </div> | ||
33 | <a name="att1.2.2"/> | ||
34 | <div id="attachmentDiv1.2.2"> | ||
35 | <hr/> | ||
36 | <div> | ||
37 | <a href="attachment:1.2.2?place=body"> | ||
38 | <img align="center" src="file:image.png" border="0" style="max-width: 100%"/> | ||
39 | </a> | ||
40 | </div> | ||
41 | <div> | ||
42 | <a href="attachment:1.2.2?place=body">image.png</a> | ||
43 | </div> | ||
44 | <div/> | ||
45 | </div> | ||
46 | <a name="att1.2.3"/> | ||
47 | <div id="attachmentDiv1.2.3"> | ||
48 | <div style="position: relative"> | ||
49 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p> | ||
50 | </div> | ||
51 | </div> | ||
52 | </div> | ||
53 | </div> | ||
54 | </td> | ||
55 | </tr> | ||
56 | <tr class="signWarnH"> | ||
57 | <td dir="ltr">End of signed message</td> | ||
58 | </tr> | ||
59 | </table> | ||
60 | </div> | ||
61 | </div> | ||
62 | </body> | ||
63 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-signed-mailinglist+additional-children.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-signed-mailinglist+additional-children.mbox.html new file mode 100644 index 00000000..cc49cbcc --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/openpgp-signed-mailinglist+additional-children.mbox.html | |||
@@ -0,0 +1,67 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <a name="att1.1"/> | ||
11 | <div id="attachmentDiv1.1"> | ||
12 | <div class="noquote"> | ||
13 | <div dir="ltr">hi..</div> | ||
14 | <br/> | ||
15 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
16 | <div dir="ltr">activities_optional</div> | ||
17 | <br/> | ||
18 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
19 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
20 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
21 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
22 | <br/> | ||
23 | <div dir="ltr">-- </div> | ||
24 | <div dir="ltr">Aaron J. Seigo</div> | ||
25 | </div> | ||
26 | </div> | ||
27 | <a name="att1.2"/> | ||
28 | <div id="attachmentDiv1.2"> | ||
29 | <hr/> | ||
30 | <div> | ||
31 | <a href="attachment:1.2?place=body"><img align="center" height="48" width="48" src="file:application-pgp-signature.svg" border="0" style="max-width: 100%" alt=""/>signature.asc</a> | ||
32 | </div> | ||
33 | <div>This is a digitally signed message part.</div> | ||
34 | </div> | ||
35 | <a name="att1.3"/> | ||
36 | <div id="attachmentDiv1.3"> | ||
37 | <table cellspacing="1" class="textAtm"> | ||
38 | <tr class="textAtmH"> | ||
39 | <td dir="ltr">broken.attachment</td> | ||
40 | </tr> | ||
41 | <tr class="textAtmB"> | ||
42 | <td> | ||
43 | <div class="noquote"> | ||
44 | <div dir="ltr">Let's break a signed message - This messageblock should not be here :D</div> | ||
45 | </div> | ||
46 | </td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | <a name="att2"/> | ||
52 | <div id="attachmentDiv2"> | ||
53 | <div class="noquote"> | ||
54 | <div dir="ltr">_______________________________________________</div> | ||
55 | <div dir="ltr">Plasma-devel mailing list</div> | ||
56 | <div dir="ltr"> | ||
57 | <a href="mailto:Plasma-devel@kde.org">Plasma-devel@kde.org</a> | ||
58 | </div> | ||
59 | <div dir="ltr"> | ||
60 | <a href="https://mail.kde.org/mailman/listinfo/plasma-devel">https://mail.kde.org/mailman/listinfo/plasma-devel</a> | ||
61 | </div> | ||
62 | </div> | ||
63 | </div> | ||
64 | </div> | ||
65 | </div> | ||
66 | </body> | ||
67 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/smime-signed-apple.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/smime-signed-apple.mbox.html new file mode 100644 index 00000000..d3f3eeb3 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlined/smime-signed-apple.mbox.html | |||
@@ -0,0 +1,63 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signErr"> | ||
9 | <tr class="signErrH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Invalid signature.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signErrB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.2"/> | ||
26 | <div id="attachmentDiv1.2"> | ||
27 | <a name="att1.2.1"/> | ||
28 | <div id="attachmentDiv1.2.1"> | ||
29 | <div style="position: relative">Olá Konqui,<div class="">Here is the pdf you asked for!</div><div class="">Cheers,</div><div class="">Quaack</div></div> | ||
30 | </div> | ||
31 | <a name="att1.2.2"/> | ||
32 | <div id="attachmentDiv1.2.2"> | ||
33 | <hr/> | ||
34 | <div> | ||
35 | <a href="attachment:1.2.2?place=body"> | ||
36 | <img align="center" src="file:image.png" border="0" style="max-width: 100%"/> | ||
37 | </a> | ||
38 | </div> | ||
39 | <div> | ||
40 | <a href="attachment:1.2.2?place=body">image.png</a> | ||
41 | </div> | ||
42 | <div/> | ||
43 | </div> | ||
44 | <a name="att1.2.3"/> | ||
45 | <div id="attachmentDiv1.2.3"> | ||
46 | <div style="position: relative"> | ||
47 | <blockquote type="cite" class=""> | ||
48 | <div class="">On 20 Jan 2017, at 10:35, Konqui <<a href="mailto:Konqui@kdab.com">Konqui</a></div> | ||
49 | </blockquote> | ||
50 | </div> | ||
51 | </div> | ||
52 | </div> | ||
53 | </div> | ||
54 | </td> | ||
55 | </tr> | ||
56 | <tr class="signErrH"> | ||
57 | <td dir="ltr">End of signed message</td> | ||
58 | </tr> | ||
59 | </table> | ||
60 | </div> | ||
61 | </div> | ||
62 | </body> | ||
63 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-appendix.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-appendix.mbox new file mode 100644 index 00000000..c05a7e69 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-appendix.mbox | |||
@@ -0,0 +1,33 @@ | |||
1 | From test@kolab.org Wed, 25 May 2011 23:49:40 +0100 | ||
2 | From: OpenPGP Test <test@kolab.org> | ||
3 | To: test@kolab.org | ||
4 | Subject: inlinepgpencrypted | ||
5 | Date: Wed, 25 May 2011 23:49:40 +0100 | ||
6 | Message-ID: <1786696.yKXrOjjflF@herrwackelpudding.localhost> | ||
7 | X-KMail-Transport: GMX | ||
8 | X-KMail-Fcc: 28 | ||
9 | X-KMail-Drafts: 7 | ||
10 | X-KMail-Templates: 9 | ||
11 | User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) | ||
12 | MIME-Version: 1.0 | ||
13 | Content-Transfer-Encoding: 7Bit | ||
14 | Content-Type: text/plain; charset="us-ascii" | ||
15 | |||
16 | -----BEGIN PGP MESSAGE----- | ||
17 | Version: GnuPG v2.0.15 (GNU/Linux) | ||
18 | |||
19 | hQEMAwzOQ1qnzNo7AQf/a3aNTLpQBfcUr+4AKsZQLj4h6z7e7a5AaCW8AG0wrbxN | ||
20 | kBYB7E5jdZh45DX/99gvoZslthWryUCX2kKZ3LtIllxKVjqNuK5hSt+SAuKkwiMR | ||
21 | Xcbf1KFKENKupgGSO9B2NJRbjoExdJ+fC3mGXnO3dT7xJJAo3oLE8Nivu+Bj1peY | ||
22 | E1wCf+vcTwVHFrA7SV8eMRb9Z9wBXmU8Q8e9ekJ7ZsRX3tMeBs6jvscVvfMf6DYY | ||
23 | N14snZBZuGNKT9a3DPny7IC1S0lHcaam34ogWwMi3FxPGJt/Lg52kARlkF5TDhcP | ||
24 | N6H0EB/iqDRjOOUoEVm8um5XOSR1FpEiAdD0DON3y9JPATnrYq7sgYZz3BVImYY+ | ||
25 | N/jV8fEiN0a34pcOq8NQedMuOsJHNBS5MtbQH/kJLq0MXBpXekGlHo4MKw0trISc | ||
26 | Rw3pW6/BFfhPJLni29g9tw== | ||
27 | =fRFW | ||
28 | -----END PGP MESSAGE----- | ||
29 | |||
30 | _______________________________________________ | ||
31 | test mailing list | ||
32 | test@lists.kde.org | ||
33 | http://kde.org | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-appendix.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-appendix.mbox.html new file mode 100644 index 00000000..8af2b1c6 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-appendix.mbox.html | |||
@@ -0,0 +1,36 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div class="noquote"> | ||
15 | <div dir="ltr">some random text</div> | ||
16 | </div> | ||
17 | </td> | ||
18 | </tr> | ||
19 | <tr class="encrH"> | ||
20 | <td dir="ltr">End of encrypted message</td> | ||
21 | </tr> | ||
22 | </table> | ||
23 | <div class="noquote"> | ||
24 | <div dir="ltr">_______________________________________________</div> | ||
25 | <div dir="ltr">test mailing list</div> | ||
26 | <div dir="ltr"> | ||
27 | <a href="mailto:test@lists.kde.org">test@lists.kde.org</a> | ||
28 | </div> | ||
29 | <div dir="ltr"> | ||
30 | <a href="http://kde.org">http://kde.org</a> | ||
31 | </div> | ||
32 | </div> | ||
33 | </div> | ||
34 | </div> | ||
35 | </body> | ||
36 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-appendix.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-appendix.mbox.tree new file mode 100644 index 00000000..018f5c33 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-appendix.mbox.tree | |||
@@ -0,0 +1,4 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::TextMessagePart | ||
3 | * MimeTreeParser::EncryptedMessagePart | ||
4 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-error.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-error.mbox new file mode 100644 index 00000000..529b4d3b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-error.mbox | |||
@@ -0,0 +1,55 @@ | |||
1 | From test@kolab.org Wed, 25 May 2011 23:49:40 +0100 | ||
2 | From: OpenPGP Test <test@kolab.org> | ||
3 | To: test@kolab.org | ||
4 | Subject: inlinepgpencrypted - no seckey | ||
5 | Date: Wed, 25 May 2011 23:49:40 +0100 | ||
6 | Message-ID: <1786696.yKXrOjjflF@herrwackelpudding.localhost> | ||
7 | X-KMail-Transport: GMX | ||
8 | X-KMail-Fcc: 28 | ||
9 | X-KMail-Drafts: 7 | ||
10 | X-KMail-Templates: 9 | ||
11 | User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) | ||
12 | MIME-Version: 1.0 | ||
13 | Content-Transfer-Encoding: 7Bit | ||
14 | Content-Type: text/plain; charset="us-ascii" | ||
15 | |||
16 | -----BEGIN PGP MESSAGE----- | ||
17 | Version: GnuPG v2 | ||
18 | |||
19 | hQIMA1U9QmLaS63yAQ/8C8o5D7wQ9LoPHrNCNelku19bwQogTIqxRJSTYzO0b0tr | ||
20 | Pb7Oyxkm1XabYxhg9bxFcNvvAbxcbzmnFJqkVPzCird43N5BDMtwGumiUjNNYVgy | ||
21 | 4tD6hs+h8GsmmQ5/J5cmuUwA+Ee20ubrTMH2qkU75WcyuRAG+IFsA80eEKG5qR8y | ||
22 | i2WXjBiImcmjrEVtSA3L+mUHmhuWxz/46EnCelSAJMfhSG8zuTJnK6OFBSDQNkqE | ||
23 | NRJl0PO4DYDeJiSYeXWEB2GTvc9JXtcHm7wIwzHXHSrBlXvQWEj5B8z9GSOJwO0o | ||
24 | JuV29TVU4iDU8d3flfhMGZEJXUkIIwt66/0CtuJNDmIAnqc4wQO9LtXFXOI/YK7x | ||
25 | twidnLY04kmh1bZfQsUBhwdYqLUzr0AXqE2kRTozod4XgVBmphVt6Ytu11L1UFdb | ||
26 | 1wKBaQG/qmhOmeMJb7eJX6I66p8LzKiqkfNlTnPQURELMbCmiRwoDCC5wnrDj8g/ | ||
27 | K0zvfNRFbGimbTHeQ01OncoVcRIlXK7njM6dTTqnglzwZagHn1Ph0krkdbnzLJkc | ||
28 | j8v1QLWuM1ttMIgW5xu4R4cjSSuLZKtZNmnlQe1e5rllZbwIFlUVH/SRNblAnRi5 | ||
29 | GUPDJWLZJppfFk2H1pjgze4s9oZljEKXzeOa/pfrfcZ8BVmg7UnKnMyygVH1+4aF | ||
30 | BA4D9uaj0SbGMOAQEACfyo8uFl+Yq9XwFbAJmeSP3/AMG2HhfCNgkGkcjE+EykTm | ||
31 | /jn/Emscw1QyjonX1RcOvtFHbI7VsUblCcJngytfikSgM/5U/NniPtrdqohOhjgO | ||
32 | WJ+TxWhO4K64WaBzq5E5Q+7S2ciZTkz3tlZ2jRI0pjTxuvxVUV5fHwlES7ZfHCUg | ||
33 | F4eGGFU7xz3gxC6Wt6OV2EGP7wa1qf430fa5bmLZ1QsJY7l+ApbqOoWqfDmjhN6o | ||
34 | qf6xEtt+xx41lakdWg05VPYzkhDv7FHb2pGWeLRZpG5Rblg3LVi94lGyXstNcFre | ||
35 | cudq5kM2rPB9/LL65qq54KB2BsXgBSuihvRpryHqv7PSSBw+Gx5wOWZ/DZOS2RvV | ||
36 | UsrpN1M8XqJYUX/AExzSajsABQkbLj3Gw1WRyed7Sokrrus9fXJy25FXQ3AjBEQZ | ||
37 | vl8nrsEFWFQIi8s3NWoHz6IU9jyDWzJp2Twi/PKVfe7r7aMeHGRJJWMvVQbIjPEW | ||
38 | C8GqjyVPZmmGw5Eo6V95kwF1ED6UZaEdEYLdgKIoXwL1epil2mEaX0AuugN1vkHr | ||
39 | 35gyHosJC0dWtNRGoSh7nGR4uwEDs6Sf9J87b+QAGbbDgePprH6AAq0qsLxc0SNO | ||
40 | OWFzo8/CeA4KjsYXTCsIOov99TomqI93bP9BrhNBra4RMBxjsfZ5FL2X3cCwKBAA | ||
41 | jPFVgrctgkX3piwu58Zi5OpRbiXOLF6PdPaBjwyD3cFIU+TmdSLU0zGG/uCkwL3U | ||
42 | LSHhHEdf8D5laasulX7Bz72X2DXSKraoHu8tSa2f/gBRrEOSJV86yw6FAxLCn3Lm | ||
43 | NCn/cSKskO/m/J2WGhiHgFSe/4OrFpqx78tWKM+XheAgz6No9vPT9KooEyKqCwlS | ||
44 | lI7QHhLl9eWmT1NPRibfdL9aMzjPfxmE91vaN29NnxQJG2w7KnI7sxXvZljOvuSI | ||
45 | FE9NvGs2uHjRFjO0Vncjuv/fAbdvVvkTCSyLWZLUyOegJa/0KZOU48HtwwBzVxl1 | ||
46 | D9joee2bmQnmxuGomRwelUVbux1GKRhfCtnNuKQNXU7NP3AnNUDAQjrQSD5C1f3e | ||
47 | 9tPOi3wRuXnlYfBcmemKUrdYNVpWBpHh+KnJ1rW/NqwNvUtq0ucYIT5//dKaPiIf | ||
48 | HqizKm0MntFbIv4f29TNfw5Wp1GcTXc6Dmt/KSCjLH+IxPtdAgI5ZlrdOfVxlY1B | ||
49 | abIFKjN0csPfkfX7l8g6ekOYgP/NRHQQs7Zyds59Zj7Roi7+uabV8svXRREm0V34 | ||
50 | 595ro3cEzABOAnErxErC7Lm/VUI348kdOP/3IAckmwv1qts3P2eDA6CcLYE2V+sz | ||
51 | 7mb9UGrUzu8hBxPjbuqIYfi2XOSxGRCvSH0Rmw7XzKfSRwHpusUQjpCbRXyntVqY | ||
52 | Db8+PufLBENx22ipLLEDltP1P9zRuy2KpANd0sggM/HtUC3Bjta7IR9Q3qbVcPDx | ||
53 | 3Qu241eOBdb6 | ||
54 | =J3lb | ||
55 | -----END PGP MESSAGE----- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-error.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-error.mbox.html new file mode 100644 index 00000000..a4427e01 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-error.mbox.html | |||
@@ -0,0 +1,24 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message (decryption not possible)<br/>Reason: Crypto plug-in "OpenPGP" could not decrypt the data.<br/>Error: Decryption failed</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="font-size:x-large; text-align:center; padding:20pt;">No secret key found to encrypt the message. It is encrypted for following keys:<br/><a href="kmail:showCertificate#gpg ### OpenPGP ### 553D4262DA4BADF2">0x553D4262DA4BADF2</a><br/><a href="kmail:showCertificate#gpg ### OpenPGP ### F6E6A3D126C630E0">0xF6E6A3D126C630E0</a></div> | ||
15 | </td> | ||
16 | </tr> | ||
17 | <tr class="encrH"> | ||
18 | <td dir="ltr">End of encrypted message</td> | ||
19 | </tr> | ||
20 | </table> | ||
21 | </div> | ||
22 | </div> | ||
23 | </body> | ||
24 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-error.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-error.mbox.tree new file mode 100644 index 00000000..6680b8bc --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted-error.mbox.tree | |||
@@ -0,0 +1,3 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::TextMessagePart | ||
3 | * MimeTreeParser::EncryptedMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox new file mode 100644 index 00000000..b581602c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox | |||
@@ -0,0 +1,29 @@ | |||
1 | From test@kolab.org Wed, 25 May 2011 23:49:40 +0100 | ||
2 | From: OpenPGP Test <test@kolab.org> | ||
3 | To: test@kolab.org | ||
4 | Subject: inlinepgpencrypted | ||
5 | Date: Wed, 25 May 2011 23:49:40 +0100 | ||
6 | Message-ID: <1786696.yKXrOjjflF@herrwackelpudding.localhost> | ||
7 | X-KMail-Transport: GMX | ||
8 | X-KMail-Fcc: 28 | ||
9 | X-KMail-Drafts: 7 | ||
10 | X-KMail-Templates: 9 | ||
11 | User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) | ||
12 | MIME-Version: 1.0 | ||
13 | Content-Transfer-Encoding: 7Bit | ||
14 | Content-Type: text/plain; charset="us-ascii" | ||
15 | |||
16 | -----BEGIN PGP MESSAGE----- | ||
17 | Version: GnuPG v2.0.15 (GNU/Linux) | ||
18 | |||
19 | hQEMAwzOQ1qnzNo7AQf/a3aNTLpQBfcUr+4AKsZQLj4h6z7e7a5AaCW8AG0wrbxN | ||
20 | kBYB7E5jdZh45DX/99gvoZslthWryUCX2kKZ3LtIllxKVjqNuK5hSt+SAuKkwiMR | ||
21 | Xcbf1KFKENKupgGSO9B2NJRbjoExdJ+fC3mGXnO3dT7xJJAo3oLE8Nivu+Bj1peY | ||
22 | E1wCf+vcTwVHFrA7SV8eMRb9Z9wBXmU8Q8e9ekJ7ZsRX3tMeBs6jvscVvfMf6DYY | ||
23 | N14snZBZuGNKT9a3DPny7IC1S0lHcaam34ogWwMi3FxPGJt/Lg52kARlkF5TDhcP | ||
24 | N6H0EB/iqDRjOOUoEVm8um5XOSR1FpEiAdD0DON3y9JPATnrYq7sgYZz3BVImYY+ | ||
25 | N/jV8fEiN0a34pcOq8NQedMuOsJHNBS5MtbQH/kJLq0MXBpXekGlHo4MKw0trISc | ||
26 | Rw3pW6/BFfhPJLni29g9tw== | ||
27 | =fRFW | ||
28 | -----END PGP MESSAGE----- | ||
29 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox.html new file mode 100644 index 00000000..1f695bdf --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox.html | |||
@@ -0,0 +1,26 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div class="noquote"> | ||
15 | <div dir="ltr">some random text</div> | ||
16 | </div> | ||
17 | </td> | ||
18 | </tr> | ||
19 | <tr class="encrH"> | ||
20 | <td dir="ltr">End of encrypted message</td> | ||
21 | </tr> | ||
22 | </table> | ||
23 | </div> | ||
24 | </div> | ||
25 | </body> | ||
26 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox.inProgress.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox.inProgress.html new file mode 100644 index 00000000..e5eb55d0 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox.inProgress.html | |||
@@ -0,0 +1,24 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Please wait while the message is being decrypted...</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="font-size:x-large; text-align:center; padding:20pt;"/> | ||
15 | </td> | ||
16 | </tr> | ||
17 | <tr class="encrH"> | ||
18 | <td dir="ltr">End of encrypted message</td> | ||
19 | </tr> | ||
20 | </table> | ||
21 | </div> | ||
22 | </div> | ||
23 | </body> | ||
24 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox.tree new file mode 100644 index 00000000..6680b8bc --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/inlinepgpencrypted.mbox.tree | |||
@@ -0,0 +1,3 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::TextMessagePart | ||
3 | * MimeTreeParser::EncryptedMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/mailheader.css b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/mailheader.css new file mode 100644 index 00000000..10181957 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/mailheader.css | |||
@@ -0,0 +1,512 @@ | |||
1 | div.header { | ||
2 | margin-bottom: 10pt ! important; | ||
3 | } | ||
4 | |||
5 | table.textAtm { | ||
6 | margin-top: 10pt ! important; | ||
7 | margin-bottom: 10pt ! important; | ||
8 | } | ||
9 | |||
10 | tr.textAtmH, | ||
11 | tr.textAtmB, | ||
12 | tr.rfc822B { | ||
13 | font-weight: normal ! important; | ||
14 | } | ||
15 | |||
16 | tr.signInProgressH, | ||
17 | tr.rfc822H, | ||
18 | tr.encrH, | ||
19 | tr.signOkKeyOkH, | ||
20 | tr.signOkKeyBadH, | ||
21 | tr.signWarnH, | ||
22 | tr.signErrH { | ||
23 | font-weight: bold ! important; | ||
24 | } | ||
25 | |||
26 | tr.textAtmH td, | ||
27 | tr.textAtmB td { | ||
28 | padding: 3px ! important; | ||
29 | } | ||
30 | |||
31 | table.rfc822 { | ||
32 | width: 100% ! important; | ||
33 | border: solid 1px black ! important; | ||
34 | margin-top: 10pt ! important; | ||
35 | margin-bottom: 10pt ! important; | ||
36 | } | ||
37 | |||
38 | table.textAtm, | ||
39 | table.encr, | ||
40 | table.signWarn, | ||
41 | table.signErr, | ||
42 | table.signOkKeyBad, | ||
43 | table.signOkKeyOk, | ||
44 | table.signInProgress, | ||
45 | div.fancy.header table { | ||
46 | width: 100% ! important; | ||
47 | border-width: 0px ! important; | ||
48 | line-height: normal; | ||
49 | } | ||
50 | |||
51 | div.htmlWarn { | ||
52 | margin: 0px 5% ! important; | ||
53 | padding: 10px ! important; | ||
54 | text-align: left ! important; | ||
55 | line-height: normal; | ||
56 | } | ||
57 | |||
58 | div.fancy.header > div { | ||
59 | font-weight: bold ! important; | ||
60 | padding: 4px ! important; | ||
61 | line-height: normal; | ||
62 | } | ||
63 | |||
64 | div.fancy.header table { | ||
65 | padding: 2px ! important; | ||
66 | text-align: left ! important; | ||
67 | border-collapse: separate ! important; | ||
68 | } | ||
69 | |||
70 | div.fancy.header table th { | ||
71 | font-family: "Sans Serif" ! important; | ||
72 | font-size: 0px ! important; | ||
73 | |||
74 | padding: 0px ! important; | ||
75 | white-space: nowrap ! important; | ||
76 | border-spacing: 0px ! important; | ||
77 | text-align: left ! important; | ||
78 | vertical-align: top ! important; | ||
79 | background-color: #d6d2d0 ! important; | ||
80 | color: #221f1e ! important; | ||
81 | border: 1px ! important; | ||
82 | } | ||
83 | |||
84 | div.fancy.header table td { | ||
85 | font-family: "Sans Serif" ! important; | ||
86 | font-size: 0px ! important; | ||
87 | |||
88 | padding: 0px ! important; | ||
89 | border-spacing: 0px ! important; | ||
90 | text-align: left ! important; | ||
91 | vertical-align: top ! important; | ||
92 | width: 100% ! important; | ||
93 | background-color: #d6d2d0 ! important; | ||
94 | color: #221f1e ! important; | ||
95 | border: 1px ! important; | ||
96 | } | ||
97 | |||
98 | div.fancy.header table a:hover { | ||
99 | background-color: transparent ! important; | ||
100 | } | ||
101 | |||
102 | span.pimsmileytext { | ||
103 | position: absolute; | ||
104 | top: 0px; | ||
105 | left: 0px; | ||
106 | visibility: hidden; | ||
107 | } | ||
108 | |||
109 | img.pimsmileyimg { | ||
110 | } | ||
111 | |||
112 | div.quotelevelmark { | ||
113 | position: absolute; | ||
114 | margin-left:-10px; | ||
115 | } | ||
116 | |||
117 | @media screen { | ||
118 | |||
119 | body { | ||
120 | font-family: "Sans Serif" ! important; | ||
121 | font-size: 0px ! important; | ||
122 | color: #1f1c1b ! important; | ||
123 | background-color: #ffffff ! important; | ||
124 | } | ||
125 | |||
126 | a { | ||
127 | color: #0057ae ! important; | ||
128 | text-decoration: none ! important; | ||
129 | } | ||
130 | |||
131 | a.white { | ||
132 | color: white ! important; | ||
133 | } | ||
134 | |||
135 | a.black { | ||
136 | color: black ! important; | ||
137 | } | ||
138 | |||
139 | table.textAtm { background-color: #1f1c1b ! important; } | ||
140 | |||
141 | tr.textAtmH { | ||
142 | background-color: #ffffff ! important; | ||
143 | font-family: "Sans Serif" ! important; | ||
144 | font-size: 0px ! important; | ||
145 | } | ||
146 | |||
147 | tr.textAtmB { | ||
148 | background-color: #ffffff ! important; | ||
149 | } | ||
150 | |||
151 | table.signInProgress, | ||
152 | table.rfc822 { | ||
153 | background-color: #ffffff ! important; | ||
154 | } | ||
155 | |||
156 | tr.signInProgressH, | ||
157 | tr.rfc822H { | ||
158 | font-family: "Sans Serif" ! important; | ||
159 | font-size: 0px ! important; | ||
160 | } | ||
161 | |||
162 | table.encr { | ||
163 | background-color: #0069cc ! important; | ||
164 | } | ||
165 | |||
166 | tr.encrH { | ||
167 | background-color: #0080ff ! important; | ||
168 | color: #ffffff ! important; | ||
169 | font-family: "Sans Serif" ! important; | ||
170 | font-size: 0px ! important; | ||
171 | } | ||
172 | |||
173 | tr.encrB { background-color: #e0f0ff ! important; } | ||
174 | |||
175 | table.signOkKeyOk { | ||
176 | background-color: #33cc33 ! important; | ||
177 | } | ||
178 | |||
179 | tr.signOkKeyOkH { | ||
180 | background-color: #40ff40 ! important; | ||
181 | color: #27ae60 ! important; | ||
182 | font-family: "Sans Serif" ! important; | ||
183 | font-size: 0px ! important; | ||
184 | } | ||
185 | |||
186 | tr.signOkKeyOkB { background-color: #e8ffe8 ! important; } | ||
187 | |||
188 | table.signOkKeyBad { | ||
189 | background-color: #cccc33 ! important; | ||
190 | } | ||
191 | |||
192 | tr.signOkKeyBadH { | ||
193 | background-color: #ffff40 ! important; | ||
194 | color: #f67400 ! important; | ||
195 | font-family: "Sans Serif" ! important; | ||
196 | font-size: 0px ! important; | ||
197 | } | ||
198 | |||
199 | tr.signOkKeyBadB { background-color: #ffffe8 ! important; } | ||
200 | |||
201 | table.signWarn { | ||
202 | background-color: #cccc33 ! important; | ||
203 | } | ||
204 | |||
205 | tr.signWarnH { | ||
206 | background-color: #ffff40 ! important; | ||
207 | color: #f67400 ! important; | ||
208 | font-family: "Sans Serif" ! important; | ||
209 | font-size: 0px ! important; | ||
210 | } | ||
211 | |||
212 | tr.signWarnB { background-color: #ffffe8 ! important; } | ||
213 | |||
214 | table.signErr { | ||
215 | background-color: #cc0000 ! important; | ||
216 | } | ||
217 | |||
218 | tr.signErrH { | ||
219 | background-color: #ff0000 ! important; | ||
220 | color: #da4453 ! important; | ||
221 | font-family: "Sans Serif" ! important; | ||
222 | font-size: 0px ! important; | ||
223 | } | ||
224 | |||
225 | tr.signErrB { background-color: #ffe0e0 ! important; } | ||
226 | |||
227 | div.htmlWarn { | ||
228 | border: 2px solid #ff4040 ! important; | ||
229 | line-height: normal; | ||
230 | } | ||
231 | |||
232 | div.header { | ||
233 | font-family: "Sans Serif" ! important; | ||
234 | font-size: 0px ! important; | ||
235 | } | ||
236 | |||
237 | div.fancy.header > div { | ||
238 | background-color: #43ace8 ! important; | ||
239 | color: #ffffff ! important; | ||
240 | border: solid #221f1e 1px ! important; | ||
241 | line-height: normal; | ||
242 | } | ||
243 | |||
244 | div.fancy.header > div a[href] { color: #ffffff ! important; } | ||
245 | |||
246 | div.fancy.header > div a[href]:hover { text-decoration: underline ! important; } | ||
247 | |||
248 | div.fancy.header > div.spamheader { | ||
249 | background-color: #cdcdcd ! important; | ||
250 | border-top: 0px ! important; | ||
251 | padding: 3px ! important; | ||
252 | color: black ! important; | ||
253 | font-weight: bold ! important; | ||
254 | font-size: smaller ! important; | ||
255 | } | ||
256 | |||
257 | div.fancy.header > table.outer { | ||
258 | background-color: #d6d2d0 ! important; | ||
259 | color: #221f1e ! important; | ||
260 | border-bottom: solid #221f1e 1px ! important; | ||
261 | border-left: solid #221f1e 1px ! important; | ||
262 | border-right: solid #221f1e 1px ! important; | ||
263 | } | ||
264 | |||
265 | div.senderpic{ | ||
266 | padding: 0px ! important; | ||
267 | font-size:0.8em ! important; | ||
268 | border:1px solid #b3aba7 ! important; | ||
269 | background-color:#d6d2d0 ! important; | ||
270 | } | ||
271 | |||
272 | div.senderstatus{ | ||
273 | text-align:center ! important; | ||
274 | } | ||
275 | |||
276 | div.quotelevel1 { | ||
277 | color: #008000 ! important; | ||
278 | font-style: italic ! important; | ||
279 | } | ||
280 | |||
281 | div.quotelevel2 { | ||
282 | color: #007000 ! important; | ||
283 | font-style: italic ! important; | ||
284 | } | ||
285 | |||
286 | div.quotelevel3 { | ||
287 | color: #006000 ! important; | ||
288 | font-style: italic ! important; | ||
289 | } | ||
290 | |||
291 | div.deepquotelevel1 { | ||
292 | color: #008000 ! important; | ||
293 | font-style: italic ! important; | ||
294 | } | ||
295 | |||
296 | div.deepquotelevel2 { | ||
297 | color: #007000 ! important; | ||
298 | font-style: italic ! important; | ||
299 | } | ||
300 | |||
301 | div.deepquotelevel3 { | ||
302 | color: #006000 ! important; | ||
303 | font-style: italic ! important; | ||
304 | } | ||
305 | |||
306 | blockquote { | ||
307 | margin: 4pt 0 4pt 0; | ||
308 | padding: 0 0 0 1em; | ||
309 | border-left: 2px solid #008000; | ||
310 | unicode-bidi: -webkit-plaintext | ||
311 | } | ||
312 | |||
313 | blockquote blockquote { | ||
314 | margin: 4pt 0 4pt 0; | ||
315 | padding: 0 0 0 1em; | ||
316 | border-left: 2px solid #007000; | ||
317 | unicode-bidi: -webkit-plaintext | ||
318 | } | ||
319 | |||
320 | blockquote blockquote blockquote { | ||
321 | margin: 4pt 0 4pt 0; | ||
322 | padding: 0 0 0 1em; | ||
323 | border-left: 2px solid #006000; | ||
324 | unicode-bidi: -webkit-plaintext | ||
325 | } | ||
326 | |||
327 | blockquote blockquote blockquote blockquote { | ||
328 | margin: 4pt 0 4pt 0; | ||
329 | padding: 0 0 0 1em; | ||
330 | border-left: 2px solid #008000; | ||
331 | unicode-bidi: -webkit-plaintext | ||
332 | } | ||
333 | |||
334 | blockquote blockquote blockquote blockquote blockquote { | ||
335 | margin: 4pt 0 4pt 0; | ||
336 | padding: 0 0 0 1em; | ||
337 | border-left: 2px solid #007000; | ||
338 | unicode-bidi: -webkit-plaintext | ||
339 | } | ||
340 | |||
341 | blockquote blockquote blockquote blockquote blockquote blockquote { | ||
342 | margin: 4pt 0 4pt 0; | ||
343 | padding: 0 0 0 1em; | ||
344 | border-left: 2px solid #006000; | ||
345 | unicode-bidi: -webkit-plaintext | ||
346 | } | ||
347 | |||
348 | blockquote blockquote blockquote blockquote blockquote blockquote blockquote { | ||
349 | margin: 4pt 0 4pt 0; | ||
350 | padding: 0 0 0 1em; | ||
351 | border-left: 2px solid #008000; | ||
352 | unicode-bidi: -webkit-plaintext | ||
353 | } | ||
354 | |||
355 | blockquote blockquote blockquote blockquote blockquote blockquote blockquote blockquote { | ||
356 | margin: 4pt 0 4pt 0; | ||
357 | padding: 0 0 0 1em; | ||
358 | border-left: 2px solid #007000; | ||
359 | unicode-bidi: -webkit-plaintext | ||
360 | } | ||
361 | |||
362 | blockquote blockquote blockquote blockquote blockquote blockquote blockquote blockquote blockquote { | ||
363 | margin: 4pt 0 4pt 0; | ||
364 | padding: 0 0 0 1em; | ||
365 | border-left: 2px solid #006000; | ||
366 | unicode-bidi: -webkit-plaintext | ||
367 | } | ||
368 | |||
369 | .quotemarks{ | ||
370 | color:transparent; | ||
371 | font-size:0px; | ||
372 | } | ||
373 | |||
374 | } | ||
375 | @media print { | ||
376 | |||
377 | body { | ||
378 | font-family: "Sans Serif" ! important; | ||
379 | font-size: 9pt ! important; | ||
380 | color: #000000 ! important; | ||
381 | background-color: #ffffff ! important | ||
382 | } | ||
383 | |||
384 | tr.textAtmH, | ||
385 | tr.signInProgressH, | ||
386 | tr.rfc822H, | ||
387 | tr.encrH, | ||
388 | tr.signOkKeyOkH, | ||
389 | tr.signOkKeyBadH, | ||
390 | tr.signWarnH, | ||
391 | tr.signErrH, | ||
392 | div.header { | ||
393 | font-family: "Sans Serif" ! important; | ||
394 | font-size: 9pt ! important; | ||
395 | } | ||
396 | |||
397 | div.fancy.header > div { | ||
398 | background-color: #d6d2d0 ! important; | ||
399 | color: #221f1e ! important; | ||
400 | padding: 4px ! important; | ||
401 | border: solid #221f1e 1px ! important; | ||
402 | line-height: normal; | ||
403 | } | ||
404 | |||
405 | div.fancy.header > div a[href] { color: #221f1e ! important; } | ||
406 | |||
407 | div.fancy.header > table.outer{ | ||
408 | background-color: #d6d2d0 ! important; | ||
409 | color: #221f1e ! important; | ||
410 | border-bottom: solid #221f1e 1px ! important; | ||
411 | border-left: solid #221f1e 1px ! important; | ||
412 | border-right: solid #221f1e 1px ! important; | ||
413 | } | ||
414 | |||
415 | div.spamheader { | ||
416 | display:none ! important; | ||
417 | } | ||
418 | |||
419 | div.htmlWarn { | ||
420 | border: 2px solid #ffffff ! important; | ||
421 | line-height: normal; | ||
422 | } | ||
423 | |||
424 | div.senderpic{ | ||
425 | font-size:0.8em ! important; | ||
426 | border:1px solid black ! important; | ||
427 | background-color:#d6d2d0 ! important; | ||
428 | } | ||
429 | |||
430 | div.senderstatus{ | ||
431 | text-align:center ! important; | ||
432 | } | ||
433 | |||
434 | div.noprint { | ||
435 | display:none ! important; | ||
436 | } | ||
437 | |||
438 | blockquote { | ||
439 | margin: 4pt 0 4pt 0; | ||
440 | padding: 0 0 0 1em; | ||
441 | border-left: 2px solid #008000; | ||
442 | unicode-bidi: -webkit-plaintext | ||
443 | } | ||
444 | |||
445 | blockquote blockquote { | ||
446 | margin: 4pt 0 4pt 0; | ||
447 | padding: 0 0 0 1em; | ||
448 | border-left: 2px solid #007000; | ||
449 | unicode-bidi: -webkit-plaintext | ||
450 | } | ||
451 | |||
452 | blockquote blockquote blockquote { | ||
453 | margin: 4pt 0 4pt 0; | ||
454 | padding: 0 0 0 1em; | ||
455 | border-left: 2px solid #006000; | ||
456 | unicode-bidi: -webkit-plaintext | ||
457 | } | ||
458 | |||
459 | blockquote blockquote blockquote blockquote { | ||
460 | margin: 4pt 0 4pt 0; | ||
461 | padding: 0 0 0 1em; | ||
462 | border-left: 2px solid #008000; | ||
463 | unicode-bidi: -webkit-plaintext | ||
464 | } | ||
465 | |||
466 | blockquote blockquote blockquote blockquote blockquote { | ||
467 | margin: 4pt 0 4pt 0; | ||
468 | padding: 0 0 0 1em; | ||
469 | border-left: 2px solid #007000; | ||
470 | unicode-bidi: -webkit-plaintext | ||
471 | } | ||
472 | |||
473 | blockquote blockquote blockquote blockquote blockquote blockquote { | ||
474 | margin: 4pt 0 4pt 0; | ||
475 | padding: 0 0 0 1em; | ||
476 | border-left: 2px solid #006000; | ||
477 | unicode-bidi: -webkit-plaintext | ||
478 | } | ||
479 | |||
480 | blockquote blockquote blockquote blockquote blockquote blockquote blockquote { | ||
481 | margin: 4pt 0 4pt 0; | ||
482 | padding: 0 0 0 1em; | ||
483 | border-left: 2px solid #008000; | ||
484 | unicode-bidi: -webkit-plaintext | ||
485 | } | ||
486 | |||
487 | blockquote blockquote blockquote blockquote blockquote blockquote blockquote blockquote { | ||
488 | margin: 4pt 0 4pt 0; | ||
489 | padding: 0 0 0 1em; | ||
490 | border-left: 2px solid #007000; | ||
491 | unicode-bidi: -webkit-plaintext | ||
492 | } | ||
493 | |||
494 | blockquote blockquote blockquote blockquote blockquote blockquote blockquote blockquote blockquote { | ||
495 | margin: 4pt 0 4pt 0; | ||
496 | padding: 0 0 0 1em; | ||
497 | border-left: 2px solid #006000; | ||
498 | unicode-bidi: -webkit-plaintext | ||
499 | } | ||
500 | |||
501 | .quotemarks{ | ||
502 | color:transparent; | ||
503 | font-size:0px; | ||
504 | } | ||
505 | |||
506 | .quotemarksemptyline{ | ||
507 | color:transparent; | ||
508 | font-size:0px; | ||
509 | line-height: 12pt; | ||
510 | } | ||
511 | |||
512 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/no-content-type.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/no-content-type.mbox new file mode 100644 index 00000000..ad050d8c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/no-content-type.mbox | |||
@@ -0,0 +1,7 @@ | |||
1 | From: hans@example.com | ||
2 | To: karl@example.com | ||
3 | Subject: Simple Mail Without Content-Type Header | ||
4 | Date: Sat, 15 May 2010 10:52:24 +0200 | ||
5 | MIME-Version: 1.0 | ||
6 | |||
7 | asdfasdf \ No newline at end of file | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/no-content-type.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/no-content-type.mbox.html new file mode 100644 index 00000000..9e3eb752 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/no-content-type.mbox.html | |||
@@ -0,0 +1,14 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <div class="noquote"> | ||
9 | <div dir="ltr">asdfasdf</div> | ||
10 | </div> | ||
11 | </div> | ||
12 | </div> | ||
13 | </body> | ||
14 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/no-content-type.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/no-content-type.mbox.tree new file mode 100644 index 00000000..c003ec97 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/no-content-type.mbox.tree | |||
@@ -0,0 +1,3 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::TextMessagePart | ||
3 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encoded.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encoded.mbox new file mode 100644 index 00000000..168c8dc4 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encoded.mbox | |||
@@ -0,0 +1,33 @@ | |||
1 | Content-Type: text/plain; charset="us-ascii" | ||
2 | Content-Transfer-Encoding: 7bit | ||
3 | |||
4 | -----BEGIN PGP MESSAGE----- | ||
5 | Version: GnuPG v2 | ||
6 | |||
7 | owGdk31MlVUcx5G3jClvI1JH7GiOil0uYJATBW8FK6HkDtBJI93heQ6Xk8/L9Tnn | ||
8 | XExALDfJQaJutl4UzUoCIxDwos0XTLktqJaJkJE5QAU3yMKpkRqdc+GC/dsfz/bs | ||
9 | ec7v+/v+Pr/v2TnbxytgxvUt8T99cCirZEa9zw/5fopuIHX1xsjjr4gXgO2EqUDW | ||
10 | +WdAMAVQRdQEJF0jSKKIMgNAGdsxkbBmA0jB1AxSdQ1JAAIZQxUo/BgjZpCN5Kn6 | ||
11 | SVEVMgPzX69CJCENEqFqYwgo2MYUCKAENjCu4MAOZBgQCNH/9NUoAoVIkw1kTLfl | ||
12 | 6qquKJhMeDYDqwERQRoVf9yOkI2/KTgfGbp4J5R3ViGlvGTKoANTiABk3I4ZrORF | ||
13 | FGsSlhmXmTSJNKyaAKPArhsUAjc1oECOAcOHbXp8samehJOAhsSAAxViSUzKFGpg | ||
14 | CSPCoWm6BiiXFNb/9waeRxqCmuhpM6ADy5P+zGAVBbyAHwYF/CQxATtTHFiDXIP7 | ||
15 | Uu3IEPZMDytieYokUhQOEpENTLCRuEegYYLFERXatMm5+dIoINCGBVIzeJEZMB8L | ||
16 | mzK043xG3OimUQvHwF4IDUT5kqc5FyBmw1yJd1AAFtZkjKh7BN7GAd07nkSK+ayG | ||
17 | 5gEpOEoSUwnUPPQFc13GfOGGTjwfPcFSMQ8aF3OnbRoIDxJUEGGQ43PvyyjUNYm5 | ||
18 | R+L+dQnzGg1SXeCw8wDTiemoG4YIIH/s0OCjY5E/VRfsTLyESO61GVgW++c1qlBd | ||
19 | oQGDUYNre9xPB0NcEnFZJoPppi4o83gU8MxxFCK9Ewvk94bz4Lk2B2z3jvD1mhHg | ||
20 | 5e/nLW60V8CjwZ7LTpKCxjNIzhNRXcER/6RVXUzaGdocqGY3vd+5LO7+qSV3pdFP | ||
21 | +s6tv3Jp8EZg+V9qza9zKhf4b3xn4MfVSYOW+qaihPsHrc3O5hpzXCV77sROqxWw | ||
22 | vbfaOrpClvTszr8+8pVc/ELc0aeOm+856kqfDYNZmUXt33+Y1nLT4nvH0tomz47f | ||
23 | tfzP+dlpQW8vRj3v+qcXyXpef3Hvldy2gfECZ3LMGdMomlsR8fQm42zMcLh3eW1N | ||
24 | Xszwqt5dLXimuVk6vb+/etNN8xgeuhoWeb79myzXg9jUv11xbQ8OR9/wnXP7QGzj | ||
25 | kWN+v+RpX58qa2dbTr2VeMn/aPJrOZ3ZYS0dW7s6dhcu/3lzT1DdhS8zGgIrynIH | ||
26 | tjkf21tmXtZ8pOjj/a7xsahsEGKxLG4h+St9Oj9ace1kn1+vdWl06+nEvhPlOWnh | ||
27 | 5OVrw1nzTv6+pjo3K9Vr3YFZeZmu6K1jA2OW7M96Bs85ChL23ck95Cx5/bfuHeX3 | ||
28 | wktCXYN1/fvWpxxIfyk2/pm0N4bCRyrfS8z13VPNMr6rckbuP1YS2rp0z27X/FEy | ||
29 | FPHm4OHHv7iXsuaPg5dpg6XWN9B/SG/81Bq8tv5WwMjFRVUZId6Rn+sL68uudls3 | ||
30 | z+vMvLwwrdw5t+Pb5ISuppDUVkvmme4nTahhwYX7setmpdxt29ZeO5MFPFK6Pep2 | ||
31 | +nlHdfFa78ZFpSMV/Q1n/wU= | ||
32 | =zzr4 | ||
33 | -----END PGP MESSAGE----- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encoded.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encoded.mbox.html new file mode 100644 index 00000000..585bb4f0 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encoded.mbox.html | |||
@@ -0,0 +1,35 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
9 | <tr class="signWarnH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Not enough information to check signature validity.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signWarnB"> | ||
22 | <td> | ||
23 | <div class="noquote"> | ||
24 | <div dir="ltr">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</div> | ||
25 | </div> | ||
26 | </td> | ||
27 | </tr> | ||
28 | <tr class="signWarnH"> | ||
29 | <td dir="ltr">End of signed message</td> | ||
30 | </tr> | ||
31 | </table> | ||
32 | </div> | ||
33 | </div> | ||
34 | </body> | ||
35 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encoded.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encoded.mbox.tree new file mode 100644 index 00000000..ea8223fd --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encoded.mbox.tree | |||
@@ -0,0 +1,4 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::TextMessagePart | ||
3 | * MimeTreeParser::EncryptedMessagePart | ||
4 | * MimeTreeParser::SignedMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted+signed.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted+signed.mbox new file mode 100644 index 00000000..fbe5ce7f --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted+signed.mbox | |||
@@ -0,0 +1,46 @@ | |||
1 | From test@kolab.org Wed, 08 Sep 2010 17:02:52 +0200 | ||
2 | From: OpenPGP Test <test@kolab.org> | ||
3 | To: test@kolab.org | ||
4 | Subject: OpenPGP encrypted | ||
5 | Date: Wed, 08 Sep 2010 17:02:52 +0200 | ||
6 | User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) | ||
7 | MIME-Version: 1.0 | ||
8 | Content-Type: multipart/encrypted; boundary="nextPart1357031.ppLHckZtsp"; protocol="application/pgp-encrypted" | ||
9 | Content-Transfer-Encoding: 7Bit | ||
10 | |||
11 | |||
12 | --nextPart1357031.ppLHckZtsp | ||
13 | Content-Type: application/pgp-encrypted | ||
14 | Content-Disposition: attachment | ||
15 | |||
16 | Version: 1 | ||
17 | --nextPart1357031.ppLHckZtsp | ||
18 | Content-Type: application/octet-stream | ||
19 | Content-Disposition: inline; filename="msg.asc" | ||
20 | |||
21 | -----BEGIN PGP MESSAGE----- | ||
22 | Version: GnuPG v2 | ||
23 | |||
24 | hQEMAwzOQ1qnzNo7AQgAkQI925mOOybpzcGcjUE7jmfMVoUvJW6Br9Zx9UEtko5H | ||
25 | fdmnrrUhFDyhBdwcg2E6AChipNcJjZhdX17lNAO0kI2IoPJAEkX9lyhjoiVEH/M8 | ||
26 | xmJEKFRejYzefx0S8esKyqqtfAmMKfsA5HmKRY8iDmQnI5d/FKhkcqLTJYo7fQyL | ||
27 | rEEycdr5PU5OJbMtE5+8+kbmG8PywjiCCad68FXakXIEFyWX1A99W/0ScWtqrqDB | ||
28 | kuQSdxJs4aAZWopxGKxDobt/qVyG6W6+PUnLx3eg80KytcWNxLJRV7WEJMj4OYCU | ||
29 | JdHrh4J1DTTRbuRmqx9de3fBDFHNNZpJP43UJYJWtoSMAxiZbYU0+6KtAQQAnRxD | ||
30 | XNwzBSmPk9NG3HYf/RleTAS8/fMp3D973Y3VF5JV72ljWqZO/1o/3RIpD0pl5nSE | ||
31 | nI0wPyncmPvAgQl5EAKTdYonKLuMCTbQ4eT7vkOdfA/HUxgaoE8ppH/OYXDDiqz/ | ||
32 | 2GlNCCHcaQcVWwkHbWWgyhd/VvB7Mt9PVqPgTsHSwQ4BZf/JDwWe3MDAg21Raryf | ||
33 | dN4ZmWUzd3osDIRyy8H2hZL9vgZ3r0auIP6DMyYrPf3yTj9ApZeBiIpgBvqMwvR/ | ||
34 | 8si6r1JaXr48KRCxAkn9fIXe2jMwQE2bk5tYDrTXY868V3DA5iKq1dgXUSn0tzG3 | ||
35 | 0x9pjaOFkwxm0wtlpwnhZREJ9/ieIY7hy6p7CDpq4ZGRh8jQta4tWrjxN0wly+Dh | ||
36 | a9TjzHzgTh9BTh7vjcDLitOQFL5NcCQtK717FQ5Z1DRnkHDVLPoyPnW+5sllOVr9 | ||
37 | UcqNXwrPbrtElFjHULL5Y1pem1+AE6nCAtlvCAc7cil6QDsU508sOXW7BhTWATIU | ||
38 | tGHg/nIC0qVs24LR3MyYrwvfXL2JOkN/IK/g+0bbs6DMYVYaEOjcjqtidxWuLsE5 | ||
39 | aFEwlUFzcTcSauW+AOKwH+YFihRnlh9+4taaZxGZeutb12D5u8eEk+3nyVcsdogY | ||
40 | k/nT6ElN8i/Z2vgcxL6ABvB+g/bZmp/eCJphDNYc00lP8NMC4EEJvTZL438ThJ3j | ||
41 | wz0Qo4PlV0/OMXYxP2iZup2/rCe+pkmc9Gyz3Mkal4/9bBtIgP9cWBR7JZLMrK50 | ||
42 | KO4+NtrZYEY4JXRJlAo= | ||
43 | =1lYB | ||
44 | -----END PGP MESSAGE----- | ||
45 | |||
46 | --nextPart1357031.ppLHckZtsp-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted+signed.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted+signed.mbox.html new file mode 100644 index 00000000..54c58b85 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted+signed.mbox.html | |||
@@ -0,0 +1,52 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
15 | <tr class="signOkKeyOkH"> | ||
16 | <td dir="ltr"> | ||
17 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
18 | <tr> | ||
19 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
20 | <td align="right"> | ||
21 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
22 | </td> | ||
23 | </tr> | ||
24 | </table> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr class="signOkKeyOkB"> | ||
28 | <td> | ||
29 | <div style="position: relative; word-wrap: break-word"> | ||
30 | <a name="att"/> | ||
31 | <div id="attachmentDiv"> | ||
32 | <div class="noquote"> | ||
33 | <div dir="ltr">encrypted message text</div> | ||
34 | </div> | ||
35 | </div> | ||
36 | </div> | ||
37 | </td> | ||
38 | </tr> | ||
39 | <tr class="signOkKeyOkH"> | ||
40 | <td dir="ltr">End of signed message</td> | ||
41 | </tr> | ||
42 | </table> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="encrH"> | ||
46 | <td dir="ltr">End of encrypted message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </body> | ||
52 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted+signed.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted+signed.mbox.tree new file mode 100644 index 00000000..7d5bbeb7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted+signed.mbox.tree | |||
@@ -0,0 +1,5 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::SignedMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-applemail.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-applemail.mbox new file mode 100644 index 00000000..f5d083ff --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-applemail.mbox | |||
@@ -0,0 +1,52 @@ | |||
1 | Received: from konqi | ||
2 | From: "Konqui" <konqi@example.org> | ||
3 | To: "Bird" <bird@example.org> | ||
4 | Subject: gpg problem 1/2 | ||
5 | Date: Tue, 22 Mar 2016 17:09:18 +0100 | ||
6 | Message-ID: <123456@example.org> | ||
7 | Accept-Language: de-DE, en-US | ||
8 | Content-Language: en-US | ||
9 | Content-Type: multipart/mixed; | ||
10 | boundary="_003_55514CDCA78D430384C5F0810DF10C7Adsmpgde_" | ||
11 | MIME-Version: 1.0 | ||
12 | |||
13 | |||
14 | --_003_55514CDCA78D430384C5F0810DF10C7Adsmpgde_ | ||
15 | Content-Type: text/plain; charset="us-ascii" | ||
16 | |||
17 | |||
18 | --_003_55514CDCA78D430384C5F0810DF10C7Adsmpgde_ | ||
19 | Content-Type: application/pgp-encrypted; | ||
20 | name="PGPMIME Versions Identification" | ||
21 | Content-Description: PGP/MIME Versions Identification | ||
22 | Content-Disposition: attachment; filename="PGPMIME Versions Identification"; | ||
23 | size=77; creation-date="Tue, 22 Mar 2016 16:09:18 GMT"; | ||
24 | modification-date="Tue, 22 Mar 2016 16:09:18 GMT" | ||
25 | Content-ID: <D82BB3DF89947646AD6C4C24C8C54BAC@example.org> | ||
26 | Content-Transfer-Encoding: base64 | ||
27 | |||
28 | VmVyc2lvbjogMQ0NCg== | ||
29 | |||
30 | --_003_55514CDCA78D430384C5F0810DF10C7Adsmpgde_ | ||
31 | Content-Type: application/octet-stream; name="encrypted.asc" | ||
32 | Content-Description: OpenPGP encrypted message.asc | ||
33 | Content-Disposition: attachment; filename="encrypted.asc"; size=872; | ||
34 | creation-date="Tue, 22 Mar 2016 16:09:18 GMT"; | ||
35 | modification-date="Tue, 22 Mar 2016 16:09:18 GMT" | ||
36 | Content-ID: <58A712E65AB1824AB726904A6449178F@example.org> | ||
37 | Content-Transfer-Encoding: base64 | ||
38 | |||
39 | LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tClZlcnNpb246IEdudVBHIHYxCkNvbW1lbnQ6IFVz | ||
40 | aW5nIEdudVBHIHdpdGggSWNlZG92ZSAtIGh0dHA6Ly93d3cuZW5pZ21haWwubmV0LwoKaEl3REdK | ||
41 | bHRoVFQ3b3EwQkEvOU50TExYYmlJSlZTNnBPeW53RWVTem5yUUs3a1lWbGE4Uk00My8vSkVDQ2tH | ||
42 | SgphekVhU0J6bmFiQnY2ZXBhRm1RdFZITE1YbENiWm5NbVc5bG95cVBCZk1vQW1zNmtLS0JkRy9q | ||
43 | cWh1czg5aVhFCitzZVhuZ0MyMzNWYS9nWk1iMkR4T3FJb2tWTmZqOXRwUjd4UTh3Uy9qSFREaUxO | ||
44 | YzFHT1FDN2t1NDJ6MmJOTEEKSVFGUkQvcWJCRno4OWhVNHdQNGNZb0F5c09uRURvakZyc3JuQ2lk | ||
45 | VEhKT0pybmRNNlBQVXRIL2pRQ3lmci9FRwoydFNwSndZS3ZtVDZseTN5cWFHTEJ0UlBJeGl2K2RN | ||
46 | ZSs3eXcwdDQwcWJqdnZhVEdhdkVyRUJKRUtYNWVXYlROCi9zamFqSHBVSHFzNlNJaU1oZUg5ZHIr | ||
47 | V2Z6Rk9OdFZiUEVnR1JtT0VSaGxnVGwvbkxvODZBWnBqSnJvSUdLSkoKdFRIQ2NvUUdBV0crTjd3 | ||
48 | ckNFMVJ4UjBra01zNG5Sb3pqMFRMdTZaeVhNcytIMDYzTWV3VFBOeE5BaVFUMU5iaQp1ZEtXbWZM | ||
49 | Qmx4bjA2cCtKRHpVS3hqOFBGd09iZGJ4VHZBQ3piQXZCWTFhSE1RPT0KPW1MbDMKLS0tLS1FTkQg | ||
50 | UEdQIE1FU1NBR0UtLS0tLQoK | ||
51 | |||
52 | --_003_55514CDCA78D430384C5F0810DF10C7Adsmpgde_-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-applemail.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-applemail.mbox.html new file mode 100644 index 00000000..ca8d7fbb --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-applemail.mbox.html | |||
@@ -0,0 +1,39 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"/> | ||
10 | <a name="att2"/> | ||
11 | <div id="attachmentDiv2"> | ||
12 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
13 | <tr class="encrH"> | ||
14 | <td dir="ltr">Encrypted message</td> | ||
15 | </tr> | ||
16 | <tr class="encrB"> | ||
17 | <td> | ||
18 | <div style="position: relative; word-wrap: break-word"> | ||
19 | <a name="att"/> | ||
20 | <div id="attachmentDiv"> | ||
21 | <a name="att1"/> | ||
22 | <div id="attachmentDiv1"> | ||
23 | <div class="noquote"> | ||
24 | <div dir="ltr">test</div> | ||
25 | </div> | ||
26 | </div> | ||
27 | </div> | ||
28 | </div> | ||
29 | </td> | ||
30 | </tr> | ||
31 | <tr class="encrH"> | ||
32 | <td dir="ltr">End of encrypted message</td> | ||
33 | </tr> | ||
34 | </table> | ||
35 | </div> | ||
36 | </div> | ||
37 | </div> | ||
38 | </body> | ||
39 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-applemail.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-applemail.mbox.tree new file mode 100644 index 00000000..8ef3df2d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-applemail.mbox.tree | |||
@@ -0,0 +1,7 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::TextMessagePart | ||
4 | * MimeTreeParser::EncryptedMessagePart | ||
5 | * MimeTreeParser::MimeMessagePart | ||
6 | * MimeTreeParser::TextMessagePart | ||
7 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox new file mode 100644 index 00000000..2d9726ea --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox | |||
@@ -0,0 +1,115 @@ | |||
1 | From test@kolab.org Fri May 01 15:12:47 2015 | ||
2 | From: testkey <test@kolab.org> | ||
3 | To: you@you.com | ||
4 | Subject: enc & non enc attachment | ||
5 | Date: Fri, 01 May 2015 17:12:47 +0200 | ||
6 | Message-ID: <13897561.XENKdJMSlR@tabin.local> | ||
7 | X-KMail-Identity: 1197256126 | ||
8 | User-Agent: KMail/4.13.0.1 (Linux/3.19.1-towo.1-siduction-amd64; KDE/4.14.2; x86_64; git-cd33034; 2015-04-11) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: multipart/mixed; boundary="nextPart1939768.sIoLGH0PD8" | ||
11 | Content-Transfer-Encoding: 7Bit | ||
12 | |||
13 | This is a multi-part message in MIME format. | ||
14 | |||
15 | --nextPart1939768.sIoLGH0PD8 | ||
16 | Content-Type: multipart/encrypted; boundary="nextPart2814166.CHKktCGlQ3"; protocol="application/pgp-encrypted" | ||
17 | |||
18 | |||
19 | --nextPart2814166.CHKktCGlQ3 | ||
20 | Content-Type: application/pgp-encrypted | ||
21 | Content-Disposition: attachment | ||
22 | Content-Transfer-Encoding: 7Bit | ||
23 | |||
24 | Version: 1 | ||
25 | --nextPart2814166.CHKktCGlQ3 | ||
26 | Content-Type: application/octet-stream | ||
27 | Content-Disposition: inline; filename="msg.asc" | ||
28 | Content-Transfer-Encoding: 7Bit | ||
29 | |||
30 | -----BEGIN PGP MESSAGE----- | ||
31 | Version: GnuPG v2 | ||
32 | |||
33 | hIwDGJlthTT7oq0BA/9cXFQ6mN9Vxnc2B9M10odS3/6z1tsIY9oJdsiOjpfxqapX | ||
34 | P7nOzR/jNWdFQanXoG1SjAcY2FeZEN0c3SkxEM6R5QVF1vMh/Xsni1clI+peZyVT | ||
35 | Z4OSU74YCfYLg+cgDnPCF3kyNPVe6Z1pnfWOCZNCG3rpApw6UVLN63ScWC6eQIUB | ||
36 | DAMMzkNap8zaOwEIANKHn1svvj+hBOIZYf8R+q2Bw7cd4xEChiJ7uQLnD98j0Fh1 | ||
37 | 85v7/8JbZx6rEDDenPp1mCciDodb0aCmi0XLuzJz2ANGTVflfq+ZA+v1pwLksWCs | ||
38 | 0YcHLEjOJzjr3KKmvu6wqnun5J2yV69K3OW3qTTGhNvcYZulqQ617pPa48+sFCgh | ||
39 | nM8TMAD0ElVEwmMtrS3AWoJz52Af+R3YzpAnX8NzV317/JG+b6e2ksl3tR7TWp1q | ||
40 | 2FOqC1sXAxuv+DIz4GgRfaK1+xYr2ckkg+H/3HJqa5LmJ7rGCyv+Epfp9u+OvdBG | ||
41 | PBvuCtO3tm0crmnttMw57Gy35BKutRf/8MpBj/nS6QFX0t7XOLeL4Me7/a2H20wz | ||
42 | HZsuRGDXMCh0lL0FYCBAwdbbYvvy0gz/5iaNvoADtaIu+VtbFNrTUN0SwuL+AIFS | ||
43 | +WIiaSbFt4Ng3t9YmqL6pqB7fjxI10S+PK0s7ABqe4pgbzUWWt1yzBcxfk8l/47Q | ||
44 | JrlvcE7HuDOhNOHfZIgUP2Dbeu+pVvHIJbmLsNWpl4s+nHhoxc9HrVhYG/MTZtQ3 | ||
45 | kkUWviegO6mwEZjQvgBxjWib7090sCxkO847b8A93mfQNHnuy2ZEEJ+9xyk7nIWs | ||
46 | 4RsiNR8pYc/SMvdocyAvQMH/qSvmn/IFJ+jHhtT8UJlXJ0bHvXTHjHMqBp6fP69z | ||
47 | Jh1ERadWQdMaTkzQ+asl+kl/x3p6RZP8MEVbZIl/3pcV+xiFCYcFu2TETKMtbW+b | ||
48 | NYOlrltFxFDvyu3WeNNp0g9k0nFpD/T1OXHRBRcbUDWE4QF6NWTm6NO9wy2UYHCi | ||
49 | 7QTSecBWgMaw7cUdwvnW6chIVoov1pm69BI9D0PoV76zCI7KzpiDsTFxdilKwbQf | ||
50 | K/PDnv9Adx3ERh0/F8llBHrj2UGsRs4aHSEBDBJIHDCp8+lqtsRcINQBKEU3qIjt | ||
51 | wf5vizdaVIgQnsD2z8QmBQ7QCCipI0ur6GKl+YWDDOSDLDUs9dK4A6xo/4Q0bsnI | ||
52 | rH63ti5HslGq6uArfFkewH2MWff/8Li3uGEqzpK5NhP5UpbArelK+QaQQP5SdsmW | ||
53 | XFwUqDS4QTCKNJXw/5SQMl8UE10l2Xaav3TkiOYTcBcvPNDovYgnMyRff/tTeFa8 | ||
54 | 83STkvpGtkULkCntp22fydv5rg6DZ7eJrYfC2oZXdM87hHhUALUO6Y/VtVmNdNYw | ||
55 | F3Uim4PDuLIKt+mFqRtFqnWm+5X/AslC31qLkjH+Fbb83TY+mC9gbIn7CZGJRCjn | ||
56 | zzzMX2h15V/VHzNUgx9V/h28T0/z25FxoozZiJxpmhOtqoxMHp+y6nXXfMoIAD1D | ||
57 | 963Pc7u1HS0ny54A7bqc6KKd4W9IF7HkXn3SoBwCyn0IOPoKQTDD8mW3lbBI6+h9 | ||
58 | vP+MAQpfD8s+3VZ9r7OKYCVmUv47ViTRlf428Co6WT7rTHjGM09tqz826fTOXA== | ||
59 | =6Eu9 | ||
60 | -----END PGP MESSAGE----- | ||
61 | |||
62 | --nextPart2814166.CHKktCGlQ3-- | ||
63 | |||
64 | --nextPart1939768.sIoLGH0PD8 | ||
65 | Content-Disposition: attachment; filename="image.png" | ||
66 | Content-Transfer-Encoding: base64 | ||
67 | Content-Type: image/png; name="image.png" | ||
68 | |||
69 | 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 | ||
112 | o/0d59+Lh3Y1HHcAAAAASUVORK5CYII= | ||
113 | |||
114 | --nextPart1939768.sIoLGH0PD8-- | ||
115 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..092a3440 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,77 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">test text</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | <a name="att1.2"/> | ||
43 | <div id="attachmentDiv1.2"> | ||
44 | <hr/> | ||
45 | <div> | ||
46 | <a href="attachment:1:e0:1.2?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>file.txt</a> | ||
47 | </div> | ||
48 | <div/> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="signOkKeyOkH"> | ||
54 | <td dir="ltr">End of signed message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | </div> | ||
59 | </td> | ||
60 | </tr> | ||
61 | <tr class="encrH"> | ||
62 | <td dir="ltr">End of encrypted message</td> | ||
63 | </tr> | ||
64 | </table> | ||
65 | </div> | ||
66 | <a name="att2"/> | ||
67 | <div id="attachmentDiv2"> | ||
68 | <hr/> | ||
69 | <div> | ||
70 | <a href="attachment:2?place=body"><img align="center" height="48" width="48" src="file:image-png.svg" border="0" style="max-width: 100%" alt=""/>image.png</a> | ||
71 | </div> | ||
72 | <div/> | ||
73 | </div> | ||
74 | </div> | ||
75 | </div> | ||
76 | </body> | ||
77 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.tree new file mode 100644 index 00000000..473f0b10 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox.tree | |||
@@ -0,0 +1,11 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::EncryptedMessagePart | ||
4 | * MimeTreeParser::SignedMessagePart | ||
5 | * MimeTreeParser::MimeMessagePart | ||
6 | * MimeTreeParser::TextMessagePart | ||
7 | * MimeTreeParser::MessagePart | ||
8 | * MimeTreeParser::AttachmentMessagePart | ||
9 | * MimeTreeParser::MessagePart | ||
10 | * MimeTreeParser::AttachmentMessagePart | ||
11 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment.mbox new file mode 100644 index 00000000..4204fb0b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment.mbox | |||
@@ -0,0 +1,57 @@ | |||
1 | From test@kolab.org Fri May 01 15:13:18 2015 | ||
2 | From: testkey <test@kolab.org> | ||
3 | To: you@you.com | ||
4 | Subject: enc attachment | ||
5 | Date: Fri, 01 May 2015 17:13:18 +0200 | ||
6 | Message-ID: <2401407.XhOc2XYoOt@tabin.local> | ||
7 | X-KMail-Identity: 1197256126 | ||
8 | User-Agent: KMail/4.13.0.1 (Linux/3.19.1-towo.1-siduction-amd64; KDE/4.14.2; x86_64; git-cd33034; 2015-04-11) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: multipart/encrypted; boundary="nextPart4793536.cjk9hKXLQ5"; protocol="application/pgp-encrypted" | ||
11 | |||
12 | |||
13 | --nextPart4793536.cjk9hKXLQ5 | ||
14 | Content-Type: application/pgp-encrypted | ||
15 | Content-Disposition: attachment | ||
16 | Content-Transfer-Encoding: 7Bit | ||
17 | |||
18 | Version: 1 | ||
19 | --nextPart4793536.cjk9hKXLQ5 | ||
20 | Content-Type: application/octet-stream | ||
21 | Content-Disposition: inline; filename="msg.asc" | ||
22 | Content-Transfer-Encoding: 7Bit | ||
23 | |||
24 | -----BEGIN PGP MESSAGE----- | ||
25 | Version: GnuPG v2 | ||
26 | |||
27 | hIwDGJlthTT7oq0BBACLMnR5Mln6JGCccvqZCgM3qUkFWZ7a33b7Nl2g5lSOLX6q | ||
28 | dlGOr/0jAuqdkRwCDTom3hsrH2vf1kARTSST+5cewngS2CgBTAwwc8JymEagTkKf | ||
29 | VK/tTnM6G7puMVkwuafpuRggyJAUYvjktgUKOUaXtuxX71g0NagAFQGqlvGuq4UB | ||
30 | DAMMzkNap8zaOwEH+wWSs5xdV1x37T11EnUvkhoOMu+uId2U7NEx2JdQ/FGJZdti | ||
31 | mtqfM9GKTtQlGVcn3ISH7Wmrw3x0bsOLuW7oxkU4xIS3tVvibxaaWdmponN5TUai | ||
32 | Dr4LCTEmG7+jLNopF6V4zPmpQ9YxMwQOm8ITml+auNOg9EtHxavwr3Xd1hOYA92N | ||
33 | 1bkOiHzmb9hQtUy1GfRRk91tRqtRPoaamczLxWV9yROFDRNuSSbZ8oBU/K4YgSTL | ||
34 | D+/FhCt6MxV0DQzp+UCSL7ZsMx+ldPnZK44Udd17+U3xQDDUffo6cSg6FAF425Rh | ||
35 | v3ZQP0j7LtSIwDh2Rxc+Is4DuSmfZksL5nLPH5nS6QGJnsVEqVcZgQPktl1Zaeil | ||
36 | x/6WaWruuJm92G2fd9x2/giTLZnk918BVi/n00xR/n4bnSQmmFhXVqAVjGlG6Tr9 | ||
37 | dxej8dSiFdxO8ZjFe5tguQw76xlCu/9MxmSXTP7Mfvm4jqdcjUOINwHOzR/h2T62 | ||
38 | ZlrmqoxMHm4RN0PQ334tSzQXD4gcoUHL+xq62ATt7/jx0p0pIXPmPVUFopCk8k1E | ||
39 | m2ErPLnyfGLd4LNZRL03oP0jCjX6Q/LFWLTjCIdU6+aM6nT26CZy98yZV0SRGyhu | ||
40 | qYxN0aVW+RatmDRWWtouOJllQouQ7ZaqmjHLgyOj32/oT8cYUWWdFswSsnMhJjxb | ||
41 | r6iajUeAZgiN+zqwgf6j1Z8/mMvb+yirP+Rn9ME1fq3XSYHlnIOxKNBa+St8DdaP | ||
42 | /ZvrkwNTpVp1GmaZLBXdqdeLmflJ4U/X7wphZGR3sgjOwj0oYotX1Zb8OrtlP5WC | ||
43 | VXhhrt40e7Ilt2B0x7Xe9DWKByDCqrQUhwxwTS3miiKH9G1VEcHko70O98RjKJQ3 | ||
44 | I4VW6e/Gqv2zAMiiOu1MBTeGfPQItca4bUrVzhKjm27twtZD4wLSQDTQECxrCWHC | ||
45 | BFAdzvsIry0FIXoO6Vh16Hojq+YZ8tpmknGfpg0pnuRvAdDWU+0uuECXDE0UZFWC | ||
46 | 2g3Bs2Dn2BYYyrI6X92swHz8qP3JvdxN0dpsYMkMdHN4yWXJogNSfXzy2udf0A4P | ||
47 | NNZMOonhlwH+DBRfcWS0A/j0/fdDCDzR5Ca5dbX7lL4EscbBeoCP1JJyVoOp6DUc | ||
48 | ICuHJGGrnpNdG9DMa97tqpyGRHTAwI3lJXPKTDEHN9v9XobIyndFgi/tcPLZ7QWz | ||
49 | 9mN94NKLmeYWjrMiRbNQk8BYXR9K17SHb4BkIMdBxRsJjgMEC8qniUH64Nnf8/x4 | ||
50 | yaRCuUo0bkHDE3AqCzZE1R0he66dDkfOIz+mLwcpG8jZWjFm7sXAflBe3jvIc0lm | ||
51 | NyWQ1WnMkP83fWm/+YqrLLf+tTQtievRPeS1Dd/7v9yqUWEmQ0pUOj3MNf9Ej2KI | ||
52 | vu5ap7fHIevcBn42BPwQgSnp4YmXEY0ir5Ccwogusnt7QliNSRmkN6Jap4AF | ||
53 | =AVJ4 | ||
54 | -----END PGP MESSAGE----- | ||
55 | |||
56 | --nextPart4793536.cjk9hKXLQ5-- | ||
57 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment.mbox.html new file mode 100644 index 00000000..2b266b02 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,66 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <a name="att1.1"/> | ||
35 | <div id="attachmentDiv1.1"> | ||
36 | <div class="noquote"> | ||
37 | <div dir="ltr">test text</div> | ||
38 | </div> | ||
39 | </div> | ||
40 | <a name="att1.2"/> | ||
41 | <div id="attachmentDiv1.2"> | ||
42 | <hr/> | ||
43 | <div> | ||
44 | <a href="attachment:e0:1.2?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>file.txt</a> | ||
45 | </div> | ||
46 | <div/> | ||
47 | </div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="signOkKeyOkH"> | ||
52 | <td dir="ltr">End of signed message</td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </td> | ||
58 | </tr> | ||
59 | <tr class="encrH"> | ||
60 | <td dir="ltr">End of encrypted message</td> | ||
61 | </tr> | ||
62 | </table> | ||
63 | </div> | ||
64 | </div> | ||
65 | </body> | ||
66 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment.mbox.tree new file mode 100644 index 00000000..f433fd45 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-attachment.mbox.tree | |||
@@ -0,0 +1,8 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::SignedMessagePart | ||
4 | * MimeTreeParser::MimeMessagePart | ||
5 | * MimeTreeParser::TextMessagePart | ||
6 | * MimeTreeParser::MessagePart | ||
7 | * MimeTreeParser::AttachmentMessagePart | ||
8 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-enigmail1.6.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-enigmail1.6.mbox new file mode 100644 index 00000000..9afd17e3 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-enigmail1.6.mbox | |||
@@ -0,0 +1,48 @@ | |||
1 | From you@you.com Sat, 29 Mar 2014 15:04:21 +0100 | ||
2 | FCC: imap://hefee%40netzguerilla.net@mail.netzguerilla.net/Sent | ||
3 | X-Identity-Key: id1 | ||
4 | X-Account-Key: account4 | ||
5 | Message-ID: <5336D2E5.6010602@you.com> | ||
6 | Date: Sat, 29 Mar 2014 15:04:21 +0100 | ||
7 | From: you <you@you.com> | ||
8 | X-Mozilla-Draft-Info: internal/draft; vcard=0; receipt=0; DSN=0; uuencode=0 | ||
9 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Icedove/24.4.0 | ||
10 | MIME-Version: 1.0 | ||
11 | To: test@kolab.com | ||
12 | Subject: test | ||
13 | X-Enigmail-Version: 1.6 | ||
14 | X-Enigmail-Draft-Status: 515 | ||
15 | X-Enigmail-Draft-Status: 739 | ||
16 | Content-Type: multipart/encrypted; | ||
17 | protocol="application/pgp-encrypted"; | ||
18 | boundary="23VWJ4jAoB40SD17lh6TOBXK3fQSEGNu5" | ||
19 | |||
20 | This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156) | ||
21 | --23VWJ4jAoB40SD17lh6TOBXK3fQSEGNu5 | ||
22 | Content-Type: application/pgp-encrypted | ||
23 | Content-Description: PGP/MIME version identification | ||
24 | |||
25 | Version: 1 | ||
26 | |||
27 | --23VWJ4jAoB40SD17lh6TOBXK3fQSEGNu5 | ||
28 | Content-Type: application/octet-stream; name="encrypted.asc" | ||
29 | Content-Description: OpenPGP encrypted message | ||
30 | Content-Disposition: inline; filename="encrypted.asc" | ||
31 | |||
32 | -----BEGIN PGP MESSAGE----- | ||
33 | Version: GnuPG v1 | ||
34 | Comment: Using GnuPG with Icedove - http://www.enigmail.net/ | ||
35 | |||
36 | hIwDGJlthTT7oq0BA/9NtLLXbiIJVS6pOynwEeSznrQK7kYVla8RM43//JECCkGJ | ||
37 | azEaSBznabBv6epaFmQtVHLMXlCbZnMmW9loyqPBfMoAms6kKKBdG/jqhus89iXE | ||
38 | +seXngC233Va/gZMb2DxOqIokVNfj9tpR7xQ8wS/jHTDiLNc1GOQC7ku42z2bNLA | ||
39 | IQFRD/qbBFz89hU4wP4cYoAysOnEDojFrsrnCidTHJOJrndM6PPUtH/jQCyfr/EG | ||
40 | 2tSpJwYKvmT6ly3yqaGLBtRPIxiv+dMe+7yw0t40qbjvvaTGavErEBJEKX5eWbTN | ||
41 | /sjajHpUHqs6SIiMheH9dr+WfzFONtVbPEgGRmOERhlgTl/nLo86AZpjJroIGKJJ | ||
42 | tTHCcoQGAWG+N7wrCE1RxR0kkMs4nRozj0TLu6ZyXMs+H063MewTPNxNAiQT1Nbi | ||
43 | udKWmfLBlxn06p+JDzUKxj8PFwObdbxTvACzbAvBY1aHMQ== | ||
44 | =mLl3 | ||
45 | -----END PGP MESSAGE----- | ||
46 | |||
47 | --23VWJ4jAoB40SD17lh6TOBXK3fQSEGNu5-- | ||
48 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-enigmail1.6.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-enigmail1.6.mbox.html new file mode 100644 index 00000000..09d904bb --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-enigmail1.6.mbox.html | |||
@@ -0,0 +1,34 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <a name="att1"/> | ||
18 | <div id="attachmentDiv1"> | ||
19 | <div class="noquote"> | ||
20 | <div dir="ltr">test</div> | ||
21 | </div> | ||
22 | </div> | ||
23 | </div> | ||
24 | </div> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr class="encrH"> | ||
28 | <td dir="ltr">End of encrypted message</td> | ||
29 | </tr> | ||
30 | </table> | ||
31 | </div> | ||
32 | </div> | ||
33 | </body> | ||
34 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-enigmail1.6.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-enigmail1.6.mbox.tree new file mode 100644 index 00000000..009ba99a --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-enigmail1.6.mbox.tree | |||
@@ -0,0 +1,5 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::MimeMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-noData.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-noData.mbox new file mode 100644 index 00000000..c4f14226 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-noData.mbox | |||
@@ -0,0 +1,17 @@ | |||
1 | From test@kolab.org Wed, 08 Sep 2010 17:02:52 +0200 | ||
2 | From: OpenPGP Test <test@kolab.org> | ||
3 | To: test@kolab.org | ||
4 | Subject: OpenPGP encrypted | ||
5 | Date: Wed, 08 Sep 2010 17:02:52 +0200 | ||
6 | User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) | ||
7 | MIME-Version: 1.0 | ||
8 | Content-Type: multipart/encrypted; boundary="nextPart1357031.ppLHckZtsp"; protocol="application/pgp-encrypted" | ||
9 | Content-Transfer-Encoding: 7Bit | ||
10 | |||
11 | --nextPart1357031.ppLHckZtsp | ||
12 | Content-Type: application/pgp-encrypted | ||
13 | Content-Disposition: attachment | ||
14 | |||
15 | Version: 1 | ||
16 | |||
17 | --nextPart1357031.ppLHckZtsp-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-noData.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-noData.mbox.html new file mode 100644 index 00000000..52196784 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-noData.mbox.html | |||
@@ -0,0 +1,19 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <hr/> | ||
11 | <div> | ||
12 | <a href="attachment:1?place=body"><img align="center" height="48" width="48" src="file:application-pgp-encrypted.svg" border="0" style="max-width: 100%" alt=""/>Unnamed</a> | ||
13 | </div> | ||
14 | <div/> | ||
15 | </div> | ||
16 | </div> | ||
17 | </div> | ||
18 | </body> | ||
19 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-noData.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-noData.mbox.tree new file mode 100644 index 00000000..79a20c8d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-noData.mbox.tree | |||
@@ -0,0 +1,4 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::AttachmentMessagePart | ||
4 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-non-encrypted-attachment.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-non-encrypted-attachment.mbox new file mode 100644 index 00000000..2957bf3c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-non-encrypted-attachment.mbox | |||
@@ -0,0 +1,114 @@ | |||
1 | From test@kolab.org Fri May 01 15:13:51 2015 | ||
2 | From: testkey <test@kolab.org> | ||
3 | To: you@you.com | ||
4 | Subject: non enc attachment | ||
5 | Date: Fri, 01 May 2015 17:13:51 +0200 | ||
6 | Message-ID: <20157069.RcaNBhWVXx@tabin.local> | ||
7 | X-KMail-Identity: 1197256126 | ||
8 | User-Agent: KMail/4.13.0.1 (Linux/3.19.1-towo.1-siduction-amd64; KDE/4.14.2; x86_64; git-cd33034; 2015-04-11) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: multipart/mixed; boundary="nextPart1612969.Xqz3IcFXZ3" | ||
11 | Content-Transfer-Encoding: 7Bit | ||
12 | |||
13 | This is a multi-part message in MIME format. | ||
14 | |||
15 | --nextPart1612969.Xqz3IcFXZ3 | ||
16 | Content-Type: multipart/encrypted; boundary="nextPart2213427.hvfAsaxZ1O"; protocol="application/pgp-encrypted" | ||
17 | |||
18 | |||
19 | --nextPart2213427.hvfAsaxZ1O | ||
20 | Content-Type: application/pgp-encrypted | ||
21 | Content-Disposition: attachment | ||
22 | Content-Transfer-Encoding: 7Bit | ||
23 | |||
24 | Version: 1 | ||
25 | --nextPart2213427.hvfAsaxZ1O | ||
26 | Content-Type: application/octet-stream | ||
27 | Content-Disposition: inline; filename="msg.asc" | ||
28 | Content-Transfer-Encoding: 7Bit | ||
29 | |||
30 | -----BEGIN PGP MESSAGE----- | ||
31 | Version: GnuPG v2 | ||
32 | |||
33 | hIwDGJlthTT7oq0BBACdvp3PFrRx6vxZhxt06LqyaO7+SWBbVUr7GOa3QaYCCBm+ | ||
34 | /KTUZEfhPuGVcsVpJKZbPsUKVhYfvYpDAsZu3TehmKflobWAV/cCIK2BkQB744pd | ||
35 | oaCtTj7pmCO05Zt5Uo/tXbrgceuW+/huwn2DO2fk4MUBsluH3fMbvccZJnR3yoUB | ||
36 | DAMMzkNap8zaOwEIAOTKI8Bh3NhfuJdWDsjv+UT6E4kf/zg3D95mJ+3gK8kHFXdd | ||
37 | YyEKaMsYx64kSwm1KcjsJ4gWykJlB34YDDfcIrnbgO2QRss9GhgOcUtLr0KNcY+0 | ||
38 | OJ4sbNmI8I3XssMb4rHtDrcXc0ODd0v/C/Lw2VfUdN+bBY4EetG096OPiZ4R41kF | ||
39 | Rj95nhO8tpoJx9VltegCdZI2AxtykOYvUaLFyYqCoKMmQwqGjdaUv1CeMnxUIPsn | ||
40 | A/x6TQ0AjpZ5IfMqO7QmOv3ACFo5/Ur93NauOK6szg/zdih9OxUL0Qid3nZQQwqA | ||
41 | J9ZChTcUgdjQo8EjpWLy0oXR9uLSHcLwRo3OdRzS6QEz7Dus6hmpEal3zTZFj2NR | ||
42 | mK38tpp+eWhzSAFAx8tyImz8SU2N2o7xQHlEdlWYGeIQg0embMnmMv6WJVWhYahb | ||
43 | x5OTfHCGwHFsLhZDmtaNhAVMlYdqxKXoR45H9cmGNPpU5kN5Ckjr6I+I51cfgAOE | ||
44 | 1vF54jYHXd1btfGrwAyKWBfFVQFPWjuIUdsEl8zDjNTmcCCbA77tEGohSqDi+WWL | ||
45 | LyYw5g/uwwZ+5OzeRdjAJ+9xtJ+WXhnDUffG8GgGgZWBQD+S2Ix4lZ2NcAeyLPt/ | ||
46 | cXeDHkPUXj7cjm0hl7SvBKzR6X4EEWO/hh19mxngd4+e19q6Qm4K2QMfTwQQyNED | ||
47 | whBkRXhcXcRxWlb/ICwFDIgxKLJko5HVTknBJDllNdm6l2C4Y9/IY2imqXni8xZX | ||
48 | zQfAkDOBlfouUrHbPuBCRdCLmp7BgbanCaJDvgYGBvXEgjMKpV3bezTfm4Ugwiyk | ||
49 | dJfMu/4XftZy7XqoFuDheNXuQ5JobpvVDaiTQ0EWHpHeX3TZ0xa8i1FO6ANLakUp | ||
50 | aVFWzYl91bxbNHIcPh278neyi+LNWWT6TvkCwcbUYUfuIySOwfSUJAHDIJOx50Ha | ||
51 | If0fNQDtF4o9mDFwXDwVf8e2zx5NjheqgYX/qIWjFE2cCCkUM4UkNrkYBOiwnh9F | ||
52 | RJz4M6wKPhZT34MBlTKgwDbypDp+XYnM2HunzIDXCAigYsD/AuLNeFwsIPiXWJ47 | ||
53 | oXamEJxyqS9G0t/iy7+1mbNiFct7pvHt6QUKZ9aXSXj3MkQuWjjVNvMz6KocTSyL | ||
54 | AeWQNYuvA5NkyZOA5+VU1ma3wn7IAXYkgw+OMvcz9VNevXNg956ZnGbb47Fqppp+ | ||
55 | MjK2ptM1UzIEnHxXtq3KFrXG1AzzhyFnKIjsiDpFTlMGTT9pRGnK8zyYXYPEgpwW | ||
56 | 874A5auLFOvhwPSNMhMai+XSoE3P+zZDqhXMYU8c49O+SeOtISg3Iy5tXuIPlIps | ||
57 | 7k0KA60hPulMYBQLtZ/yDO/gXhkeWaw= | ||
58 | =EJZ6 | ||
59 | -----END PGP MESSAGE----- | ||
60 | |||
61 | --nextPart2213427.hvfAsaxZ1O-- | ||
62 | |||
63 | --nextPart1612969.Xqz3IcFXZ3 | ||
64 | Content-Disposition: attachment; filename="image.png" | ||
65 | Content-Transfer-Encoding: base64 | ||
66 | Content-Type: image/png; name="image.png" | ||
67 | |||
68 | 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 | ||
111 | o/0d59+Lh3Y1HHcAAAAASUVORK5CYII= | ||
112 | |||
113 | --nextPart1612969.Xqz3IcFXZ3-- | ||
114 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-non-encrypted-attachment.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-non-encrypted-attachment.mbox.html new file mode 100644 index 00000000..e20a9568 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-non-encrypted-attachment.mbox.html | |||
@@ -0,0 +1,69 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">test text</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | </td> | ||
44 | </tr> | ||
45 | <tr class="signOkKeyOkH"> | ||
46 | <td dir="ltr">End of signed message</td> | ||
47 | </tr> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | <tr class="encrH"> | ||
54 | <td dir="ltr">End of encrypted message</td> | ||
55 | </tr> | ||
56 | </table> | ||
57 | </div> | ||
58 | <a name="att2"/> | ||
59 | <div id="attachmentDiv2"> | ||
60 | <hr/> | ||
61 | <div> | ||
62 | <a href="attachment:2?place=body"><img align="center" height="48" width="48" src="file:image-png.svg" border="0" style="max-width: 100%" alt=""/>image.png</a> | ||
63 | </div> | ||
64 | <div/> | ||
65 | </div> | ||
66 | </div> | ||
67 | </div> | ||
68 | </body> | ||
69 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-non-encrypted-attachment.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-non-encrypted-attachment.mbox.tree new file mode 100644 index 00000000..c2a6ad01 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-non-encrypted-attachment.mbox.tree | |||
@@ -0,0 +1,9 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::EncryptedMessagePart | ||
4 | * MimeTreeParser::SignedMessagePart | ||
5 | * MimeTreeParser::MimeMessagePart | ||
6 | * MimeTreeParser::TextMessagePart | ||
7 | * MimeTreeParser::MessagePart | ||
8 | * MimeTreeParser::AttachmentMessagePart | ||
9 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-partially-signed-attachments.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-partially-signed-attachments.mbox new file mode 100644 index 00000000..222b5936 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-partially-signed-attachments.mbox | |||
@@ -0,0 +1,91 @@ | |||
1 | From: firstname.lastname@example.com | ||
2 | To: test@kolab.org | ||
3 | Subject: OpenPGP encrypted one signed and one unsigned attachment | ||
4 | Date: Sun, 30 Aug 2015 12:08:40 +0200 | ||
5 | Message-ID: <1737262.ESByPkoaL9@vkpc5> | ||
6 | X-KMail-Identity: 402312391 | ||
7 | X-KMail-Dictionary: en_US | ||
8 | User-Agent: KMail/5.0.42 pre (Linux/3.16.6-2-desktop; KDE/5.14.0; x86_64; ; ) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: multipart/mixed; boundary="nextPart2760349.k2GQmrcl5a" | ||
11 | Content-Transfer-Encoding: 7Bit | ||
12 | |||
13 | This is a multi-part message in MIME format. | ||
14 | |||
15 | --nextPart2760349.k2GQmrcl5a | ||
16 | Content-Type: multipart/encrypted; boundary="nextPart2260160.XvshVD34ka"; protocol="application/pgp-encrypted" | ||
17 | |||
18 | --nextPart2260160.XvshVD34ka | ||
19 | Content-Type: application/pgp-encrypted | ||
20 | Content-Disposition: attachment | ||
21 | Content-Transfer-Encoding: 7Bit | ||
22 | |||
23 | Version: 1 | ||
24 | --nextPart2260160.XvshVD34ka | ||
25 | Content-Type: application/octet-stream | ||
26 | Content-Disposition: inline; filename="msg.asc" | ||
27 | Content-Transfer-Encoding: 7Bit | ||
28 | |||
29 | -----BEGIN PGP MESSAGE----- | ||
30 | Version: GnuPG v2 | ||
31 | |||
32 | hQEMAwzOQ1qnzNo7AQgAooa+Peu1t5aiX4WvssEnRlapkr62/49/Dbz5assvshdr | ||
33 | o9zOC+89Qr5P/ea+tC1MO7ek/DfyL9C4EzOMp/r08GeInLqWMc9qLZO//YaT2JUp | ||
34 | 0IZFbpUQ4C2zjXMRuy/PMrltHuCfsvhvHX1YAHp/xjRsKpQoE3mSDzz5sc8/Hj9n | ||
35 | 2eoKoCEW1rgt2qHtV4DD6lvUPo42LMZclJ9GqfoD7WLoEH9ebRLhXr3D00j6xBfy | ||
36 | //nooAhzQSW8b7GZth4Qc7DKAZMhuEly/kp07nhuPd1fMJDEAB/zh9EYlgnn3STb | ||
37 | MCdtFs6kMC24uA2eDCH330Bn9OzzWnsVU9ae4XiKnNLpAeactSFRKKvGytBQaloq | ||
38 | Gvn1+D0Xmw6OsSmRJ84DzKqG4E6bzE+XhMEMnLlqDvZDsOtU/sCGvMK0MM3y5B7M | ||
39 | ONqWLN3ng3zrGPec5gqfvnWgKpANUrbJkzS8LNjv4hwoKh0tFpghWQiefG0Z9Hw1 | ||
40 | UaYbFwvaFgXcm72oBkynDCleWjQ2vnDE4P38PldqZbAW/Pw1q6Yq8m9MhS1VpbI5 | ||
41 | WBjuRQhgQvMG0LY0gR/3Qor5tX9ASllWnPfWYVuOiSOAe5Hsp7BmELXkWftHii7k | ||
42 | YW0Qim7jleDaY1MGfFr0vrO/PiYxGTb+4IUyUgEBYEpxa9ozUoeftF6JbHPuEZI0 | ||
43 | ENX8aIVJ9FnpssrR5HlpXieF12ec9ZFeV7mAwcucJ3RXuDcQHQTHgEbfnzTsaEpL | ||
44 | Hxs+6euOCJXhKOYVrsAlB4IxK0OQm4XHiZ7WBp5Jp7rlSHltdxFpSnHIfqngyCA4 | ||
45 | L+c/gsUEVbNI++iOOhOKVT47XIf+s/xa1Y4XghGbHIA3/pQphYo4U5dTeLoX0OWI | ||
46 | 64tPxliQTKuJ+NAv9Km2bDgvlvn83jsc94THi5u+fIdDEGp7pgoQNXR69Lkz1bsA | ||
47 | Hh9xqKzVloHu4SsT3OGX+bfTO3jUh8ieU/4tflZMrJ9RkEfE08PzTnopT08FppFx | ||
48 | QWpHv/fwyJf6Cw1IevM5pVLAShg0sbCPF/xsYTjSyWNib1wFtxkmv5MToCFwkxi5 | ||
49 | b1yT23BNlV5RV6wcjmrum7p2fMwPjbt8X6z+pgUtkD7zImBWeYddMjgSjOFuFEjF | ||
50 | gpfVoV3OIvMPZMe2jqWsjnjujHJr2z5IZn3A7WI0b4SIDP0sGwsTBiogKqcBNWpn | ||
51 | O4MKUq9JwC0K/MY7yS1MCLoHfwU18z19Es/flaAgwtXk8IWIcjkkumAwNl+y8Q+I | ||
52 | +8AFGdiXTKld9QVwCKnMS3QivHPuFNL8rfcWKsr1nOhOEhaO+zD94eOOiCbwiXGr | ||
53 | E6WsewNCVQUN4bxAXl2vRi+9WRctLy7bsuIL5dgUz0CMYkQ+dDmrBflD0nyC | ||
54 | =TGNA | ||
55 | -----END PGP MESSAGE----- | ||
56 | |||
57 | --nextPart2260160.XvshVD34ka-- | ||
58 | |||
59 | --nextPart2760349.k2GQmrcl5a | ||
60 | Content-Type: multipart/encrypted; boundary="nextPart22530242.iRl14SoP0Q"; protocol="application/pgp-encrypted" | ||
61 | |||
62 | --nextPart22530242.iRl14SoP0Q | ||
63 | Content-Type: application/pgp-encrypted | ||
64 | Content-Disposition: attachment | ||
65 | Content-Transfer-Encoding: 7Bit | ||
66 | |||
67 | Version: 1 | ||
68 | --nextPart22530242.iRl14SoP0Q | ||
69 | Content-Type: application/octet-stream | ||
70 | Content-Disposition: inline; filename="msg.asc" | ||
71 | Content-Transfer-Encoding: 7Bit | ||
72 | |||
73 | -----BEGIN PGP MESSAGE----- | ||
74 | Version: GnuPG v2 | ||
75 | |||
76 | hQEMAwzOQ1qnzNo7AQgAtA94bBRwgpo64zcyh+4dzt0Pr2pmNjiS4ZX+a/xzYCmD | ||
77 | oS1a26s/LVZH+aJYC13l1kEu+6YjKn+ruQvMfhihOxglHBLjmUO17TPFC05AReSn | ||
78 | amMqPbgS6mOwhlBJHrBa/SVwkxmbMaNBUJ/KxRXFtTW/V4pPWImRvI9mnmpo8fHy | ||
79 | ZLvVAI3hGe7vPG5Vbdi5/Iu/JzqwlglVsP82gYpLlx7HhWGF4gmTGc6YBwFtzEvS | ||
80 | eqFtKRDqN60bo4HnNLOEnMaWlYPTpt3QibLWWIbtpA1Gb0Q/1NvDnn3Lyj8H+0WV | ||
81 | 8H6Ks9/cvAuoAMOad6y4gDJb+K/AS7Ha+08/3lMYG9LAAgGe8Qocxg1W3ha1o0Ph | ||
82 | YSfV2ooebsLiHjwspjYpsX5ijnRj6uNGp5Dt28EIo1ANF+oDiSKEwAMGPBtcnqaO | ||
83 | FWXy39dP3VXE73nsO+dyTidaATFBlYg+IpPTDSFTgsk7XDV973EpdXvOkBEp/vBv | ||
84 | EZknuZFOkS0v5QHk9Y/hhlSLACTIEWQpBiFGOwUVSZFXLEY5zQNTbQdRbz3ZYcE9 | ||
85 | mIFzD9Ujw6tIJIOFazhwr9SxxyeaAygWeg4ifmmdhAsmFYum | ||
86 | =WsAv | ||
87 | -----END PGP MESSAGE----- | ||
88 | |||
89 | --nextPart22530242.iRl14SoP0Q-- | ||
90 | |||
91 | --nextPart2760349.k2GQmrcl5a-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-partially-signed-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-partially-signed-attachments.mbox.html new file mode 100644 index 00000000..c0b9d79e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-partially-signed-attachments.mbox.html | |||
@@ -0,0 +1,99 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
11 | <tr class="encrH"> | ||
12 | <td dir="ltr">Encrypted message</td> | ||
13 | </tr> | ||
14 | <tr class="encrB"> | ||
15 | <td> | ||
16 | <div style="position: relative; word-wrap: break-word"> | ||
17 | <a name="att"/> | ||
18 | <div id="attachmentDiv"> | ||
19 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
20 | <tr class="signOkKeyOkH"> | ||
21 | <td dir="ltr"> | ||
22 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
23 | <tr> | ||
24 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
25 | <td align="right"> | ||
26 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
27 | </td> | ||
28 | </tr> | ||
29 | </table> | ||
30 | </td> | ||
31 | </tr> | ||
32 | <tr class="signOkKeyOkB"> | ||
33 | <td> | ||
34 | <a name="att1"/> | ||
35 | <div id="attachmentDiv1"> | ||
36 | <a name="att1.1"/> | ||
37 | <div id="attachmentDiv1.1"> | ||
38 | <div class="noquote"> | ||
39 | <div dir="ltr">This is the main body.</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | <a name="att1.2"/> | ||
43 | <div id="attachmentDiv1.2"> | ||
44 | <table cellspacing="1" class="textAtm"> | ||
45 | <tr class="textAtmH"> | ||
46 | <td dir="ltr">attachment1.txt</td> | ||
47 | </tr> | ||
48 | <tr class="textAtmB"> | ||
49 | <td> | ||
50 | <div class="noquote"> | ||
51 | <div dir="ltr">This is a signed attachment.</div> | ||
52 | </div> | ||
53 | </td> | ||
54 | </tr> | ||
55 | </table> | ||
56 | </div> | ||
57 | </div> | ||
58 | </td> | ||
59 | </tr> | ||
60 | <tr class="signOkKeyOkH"> | ||
61 | <td dir="ltr">End of signed message</td> | ||
62 | </tr> | ||
63 | </table> | ||
64 | </div> | ||
65 | </div> | ||
66 | </td> | ||
67 | </tr> | ||
68 | <tr class="encrH"> | ||
69 | <td dir="ltr">End of encrypted message</td> | ||
70 | </tr> | ||
71 | </table> | ||
72 | </div> | ||
73 | <a name="att2"/> | ||
74 | <div id="attachmentDiv2"> | ||
75 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
76 | <tr class="encrH"> | ||
77 | <td dir="ltr">Encrypted message</td> | ||
78 | </tr> | ||
79 | <tr class="encrB"> | ||
80 | <td> | ||
81 | <div style="position: relative; word-wrap: break-word"> | ||
82 | <a name="att"/> | ||
83 | <div id="attachmentDiv"> | ||
84 | <div class="noquote"> | ||
85 | <div dir="ltr">This is an unsigned attachment.</div> | ||
86 | </div> | ||
87 | </div> | ||
88 | </div> | ||
89 | </td> | ||
90 | </tr> | ||
91 | <tr class="encrH"> | ||
92 | <td dir="ltr">End of encrypted message</td> | ||
93 | </tr> | ||
94 | </table> | ||
95 | </div> | ||
96 | </div> | ||
97 | </div> | ||
98 | </body> | ||
99 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-partially-signed-attachments.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-partially-signed-attachments.mbox.tree new file mode 100644 index 00000000..5cb83749 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-partially-signed-attachments.mbox.tree | |||
@@ -0,0 +1,12 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::EncryptedMessagePart | ||
4 | * MimeTreeParser::SignedMessagePart | ||
5 | * MimeTreeParser::MimeMessagePart | ||
6 | * MimeTreeParser::TextMessagePart | ||
7 | * MimeTreeParser::MessagePart | ||
8 | * MimeTreeParser::AttachmentMessagePart | ||
9 | * MimeTreeParser::MessagePart | ||
10 | * MimeTreeParser::EncryptedMessagePart | ||
11 | * MimeTreeParser::TextMessagePart | ||
12 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-two-attachments.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-two-attachments.mbox new file mode 100644 index 00000000..c53e0916 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-two-attachments.mbox | |||
@@ -0,0 +1,42 @@ | |||
1 | From: firstname.lastname@example.com | ||
2 | To: test@kolab.org | ||
3 | Subject: OpenPGP encrypted with 2 text attachments | ||
4 | Date: Sun, 30 Aug 2015 12:05:17 +0200 | ||
5 | Message-ID: <1505824.VT0nqpAGu0@vkpc5> | ||
6 | X-KMail-Identity: 402312391 | ||
7 | X-KMail-Dictionary: en_US | ||
8 | User-Agent: KMail/5.0.42 pre (Linux/3.16.6-2-desktop; KDE/5.14.0; x86_64; ; ) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: multipart/encrypted; boundary="nextPart3335835.KxmPgziKxd"; protocol="application/pgp-encrypted" | ||
11 | |||
12 | --nextPart3335835.KxmPgziKxd | ||
13 | Content-Type: application/pgp-encrypted | ||
14 | Content-Disposition: attachment | ||
15 | Content-Transfer-Encoding: 7Bit | ||
16 | |||
17 | Version: 1 | ||
18 | --nextPart3335835.KxmPgziKxd | ||
19 | Content-Type: application/octet-stream | ||
20 | Content-Disposition: inline; filename="msg.asc" | ||
21 | Content-Transfer-Encoding: 7Bit | ||
22 | |||
23 | -----BEGIN PGP MESSAGE----- | ||
24 | Version: GnuPG v2 | ||
25 | |||
26 | hQEMAwzOQ1qnzNo7AQgA6tTJs017mI+xuhjcSTr3F5X/rJghq0oaXbjk1K0W33p+ | ||
27 | jsEyPTbuUIvI2a+5xHJ3BV+gnnO0Xosz57tGTF/eVAySnGiMse5cu2RQR9b/9EkC | ||
28 | uzt3tIChyub3GUODG3yzXqkhSiwIImvedWgnJYTJ7eeBkWdizVT0b0byiG2d7Hjq | ||
29 | hzYzyPJRwuoE36hryDsFycAhPfSsQAirxDJXk4HTsfBCmz7tzJhtt4wKc7z5m8fq | ||
30 | y+jddnDADq5+tykJS6zemJOzgU3AOQyVJbmsx2vTV1CJdpKPHvTTgghpAaSuVbg0 | ||
31 | tR9BX1nPnA/bgX/V7C+3PwuCvB0ZKmv5d8kaGaTwO9LAhQGaWTfhG1cyy+MJhXdR | ||
32 | rH63PMkZh/lrvj7qJYofI5iVoe1CiMaX44BiwKVclGf7bEFdzc2NSRvvTSzisN3T | ||
33 | nSzydEttuEY5jGagQQNT1l1l4I8HAtUgwGtkKZVTAUL6iKHYAqzB77sRs33UJy4k | ||
34 | ZSIWFnSY8l+HLG+MYKsYCGsvJHkxEHnMiS1EZcmpUFhxOGQpiF2rJ4qnL2jbFWbA | ||
35 | 9N1O5N1N/DJ/YKjwgy/jVVj6AOCrBZrxvKKt2mtG/wVX0F/KSKiEd8mgrLIx1udw | ||
36 | tibiDAJmDxUk8K0lAdOHBrzBChvysiT/QxCJFcSY6FE99Rral+BWjeyAIQQWvc2B | ||
37 | cEceZCtzjCOrwvoJwl2uEX+51nmMp+z1EoeyyhmUZZ4y65yOg4P6KGXGcLmIjSbH | ||
38 | IhsSls1jRkSrypf/wcEd6o7KZdeYbfA= | ||
39 | =Sud3 | ||
40 | -----END PGP MESSAGE----- | ||
41 | |||
42 | --nextPart3335835.KxmPgziKxd-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-two-attachments.mbox.html new file mode 100644 index 00000000..cca4c455 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-two-attachments.mbox.html | |||
@@ -0,0 +1,64 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <a name="att1"/> | ||
18 | <div id="attachmentDiv1"> | ||
19 | <div class="noquote"> | ||
20 | <div dir="ltr">this is the main body part</div> | ||
21 | </div> | ||
22 | </div> | ||
23 | <a name="att2"/> | ||
24 | <div id="attachmentDiv2"> | ||
25 | <table cellspacing="1" class="textAtm"> | ||
26 | <tr class="textAtmH"> | ||
27 | <td dir="ltr">attachment1.txt</td> | ||
28 | </tr> | ||
29 | <tr class="textAtmB"> | ||
30 | <td> | ||
31 | <div class="noquote"> | ||
32 | <div dir="ltr">this is the first attachment</div> | ||
33 | </div> | ||
34 | </td> | ||
35 | </tr> | ||
36 | </table> | ||
37 | </div> | ||
38 | <a name="att3"/> | ||
39 | <div id="attachmentDiv3"> | ||
40 | <table cellspacing="1" class="textAtm"> | ||
41 | <tr class="textAtmH"> | ||
42 | <td dir="ltr">attachment2.txt</td> | ||
43 | </tr> | ||
44 | <tr class="textAtmB"> | ||
45 | <td> | ||
46 | <div class="noquote"> | ||
47 | <div dir="ltr">this is the second attachment</div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | </table> | ||
52 | </div> | ||
53 | </div> | ||
54 | </div> | ||
55 | </td> | ||
56 | </tr> | ||
57 | <tr class="encrH"> | ||
58 | <td dir="ltr">End of encrypted message</td> | ||
59 | </tr> | ||
60 | </table> | ||
61 | </div> | ||
62 | </div> | ||
63 | </body> | ||
64 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-two-attachments.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-two-attachments.mbox.tree new file mode 100644 index 00000000..71a67b58 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted-two-attachments.mbox.tree | |||
@@ -0,0 +1,9 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::MimeMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
6 | * MimeTreeParser::AttachmentMessagePart | ||
7 | * MimeTreeParser::MessagePart | ||
8 | * MimeTreeParser::AttachmentMessagePart | ||
9 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox new file mode 100644 index 00000000..5102fa78 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox | |||
@@ -0,0 +1,36 @@ | |||
1 | From test@kolab.org Wed, 08 Sep 2010 17:02:52 +0200 | ||
2 | From: OpenPGP Test <test@kolab.org> | ||
3 | To: test@kolab.org | ||
4 | Subject: OpenPGP encrypted | ||
5 | Date: Wed, 08 Sep 2010 17:02:52 +0200 | ||
6 | User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) | ||
7 | MIME-Version: 1.0 | ||
8 | Content-Type: multipart/encrypted; boundary="nextPart1357031.ppLHckZtsp"; protocol="application/pgp-encrypted" | ||
9 | Content-Transfer-Encoding: 7Bit | ||
10 | |||
11 | |||
12 | --nextPart1357031.ppLHckZtsp | ||
13 | Content-Type: application/pgp-encrypted | ||
14 | Content-Disposition: attachment | ||
15 | |||
16 | Version: 1 | ||
17 | --nextPart1357031.ppLHckZtsp | ||
18 | Content-Type: application/octet-stream | ||
19 | Content-Disposition: inline; filename="msg.asc" | ||
20 | |||
21 | -----BEGIN PGP MESSAGE----- | ||
22 | Version: GnuPG v2.0.15 (GNU/Linux) | ||
23 | |||
24 | hQEMAwzOQ1qnzNo7AQgAtWfDWWI2JUGuptpackiIxpWViEEpGAeruETubiIPwxNb | ||
25 | DNmXrMDhbm/zIbPntIGWJDgUMfABZCUgmlJLWhsceDTt+tXnWGha2VYrN2/WsF6/ | ||
26 | Pqs/TavTvMIJQHDaIH5yDDCaMoq/mGSbcu7go2H8Sw7aBEYlM8jGlqc1HziXnZ1q | ||
27 | 3vDiA+4qWfvbNoSRo1kb9Pcq997yg6WqZXH2hJ7cp+hIQ4uTP1/+qgYHMvfPlzQk | ||
28 | XcDguGbIer88ELhuR5622unGBAB4dqp+5w6n9c6rrCH81qhV4W0nqSEvj1tBj78S | ||
29 | ZTi6VBAo5eS0e3iOJqMpwUZz6hQUpJw2wnNRGvLgI9KZAag0HkgPdMeANowg7vpE | ||
30 | L4nU7B0ybhswA2Y7QT/wwCDZu9N1JGeBmy0dgy4sA38Ki27rn2/lIaP0j14JycwM | ||
31 | RTJ1uwI+ZuQiwXlyYtdFZJWe8nraWARch0oKqhaR7aSsxGWo63eiGEQhkQCBFBb3 | ||
32 | Vg0nNCZRBauEqIESEW5EV2zrJqdfNYcz+f9IP125dnQEKgLZ6FxTt3+v | ||
33 | =mhNl | ||
34 | -----END PGP MESSAGE----- | ||
35 | |||
36 | --nextPart1357031.ppLHckZtsp-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox.html new file mode 100644 index 00000000..ba0976cd --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox.html | |||
@@ -0,0 +1,31 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <div class="noquote"> | ||
18 | <div dir="ltr">encrypted message text</div> | ||
19 | </div> | ||
20 | </div> | ||
21 | </div> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr class="encrH"> | ||
25 | <td dir="ltr">End of encrypted message</td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </div> | ||
29 | </div> | ||
30 | </body> | ||
31 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox.inProgress.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox.inProgress.html new file mode 100644 index 00000000..e5eb55d0 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox.inProgress.html | |||
@@ -0,0 +1,24 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Please wait while the message is being decrypted...</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="font-size:x-large; text-align:center; padding:20pt;"/> | ||
15 | </td> | ||
16 | </tr> | ||
17 | <tr class="encrH"> | ||
18 | <td dir="ltr">End of encrypted message</td> | ||
19 | </tr> | ||
20 | </table> | ||
21 | </div> | ||
22 | </div> | ||
23 | </body> | ||
24 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox.tree new file mode 100644 index 00000000..82f705c2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-encrypted.mbox.tree | |||
@@ -0,0 +1,4 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::TextMessagePart | ||
4 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox new file mode 100644 index 00000000..8bd06910 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox | |||
@@ -0,0 +1,40 @@ | |||
1 | From test@example.com Thu, 17 Oct 2013 02:13:03 +0200 | ||
2 | Return-Path: <test@example.com> | ||
3 | Delivered-To: you@you.com | ||
4 | Received: from localhost (localhost [127.0.0.1]) | ||
5 | by test@example.com (Postfix) with ESMTP id B30D8120030 | ||
6 | for <you@you.com>; Thu, 17 Oct 2013 02:13:05 +0200 (CEST) | ||
7 | From: test <test@example.com> | ||
8 | To: you@you.com | ||
9 | Subject: charset | ||
10 | Date: Thu, 17 Oct 2013 02:13:03 +0200 | ||
11 | Message-ID: <4081645.yGjUJ4o4Se@example.local> | ||
12 | User-Agent: KMail/4.12 pre (Linux/3.11-4.towo-siduction-amd64; KDE/4.11.2; x86_64; git-f7f14e3; 2013-10-15) | ||
13 | MIME-Version: 1.0 | ||
14 | Content-Transfer-Encoding: 7Bit | ||
15 | Content-Type: text/plain; charset="ISO-8859-15" | ||
16 | |||
17 | -----BEGIN PGP MESSAGE----- | ||
18 | Version: GnuPG v2.0.22 (GNU/Linux) | ||
19 | |||
20 | hIwDGJlthTT7oq0BBACbaRZudMigMTetPZNRgkfEXv4QQowR1jborw0dcgKKqMQ1 | ||
21 | 6o67NkpxvmXKGJTfTVCLBX3nk6FKYo6NwlPCyU7X9X0DDk8hvaBdR9wGfrdm5YWX | ||
22 | GKOzcqJY1EypiMsspXeZvjzEW7O8I956c3vBb/2pM3xqYEK1kh8+d9bVH+cjf4UB | ||
23 | DAMMzkNap8zaOwEH/1rPShyYL8meJN+/GGgS8+Nf1BW5pSHdAPCg0dnX4QCLEx7u | ||
24 | GkBU6N4JGYayaCBofibOLacQPhYZdnR5Xb/Pvrx03GrzyzyDp0WyeI9nGNfkani7 | ||
25 | sCRWbzlMPsEvGEvJVnMLNRSk4xhPIWumL4APkw+Mgi6mf+Br8z0RhfnGwyMA53Mr | ||
26 | pG9VQKlq3v7/aaN40pMjAsxiytcHS515jXrb3Ko4pWbTlAr/eytOEfkLRJgSOpQT | ||
27 | BY7lWs+UQJqiG8Yn65vS9LMDNJgX9EOGx77Z4u9wvv4ZieOxzgbHGg5kYCoae7ba | ||
28 | hxZeNjYKscH+E6epbOxM/wlTdr4UTiiW9dMsH0zSwMUB891gToeXq+LDGEPTKVSX | ||
29 | tsJm4HS/kISJBwrCI4EUqWZML6xQ427NkZGmF2z/sD3kmL66GjspIKnb4zHmXacp | ||
30 | 84n2KrI9s7p6AnKnQjsxvB/4/lpXPCIY5GH7KjySEJiMsHECzeN1dJSL6keykBsx | ||
31 | DtmYDA+dhZ6UWbwzx/78+mjNREhyp/UiSAmLzlJh89OH/xelAPvKcIosYwz4cY9N | ||
32 | wjralTmL+Y0aHKeZJOeqPLaXADcPFiZrCNPCH65Ey5GEtDpjLpEbjVbykPV9+YkK | ||
33 | 7JKW6bwMraOl5zmAoR77PWMo3IoYb9q4GuqDr1V2ZGlb7eMH1gj1nfgfVintKC1X | ||
34 | 3jFfy7aK6LIQDVKEwbi0SxVXTKStuliVUy5oX4woDOxmTEotJf1QlKZpn5oF20UP | ||
35 | tumYrp0SPoP8Bo4EVRVaLupduI5cYce1q/kFj9Iho/wk56MoG9PxMMfsH7oKg3AA | ||
36 | CqQ6/kM4oJNdN5xIf1EH5HeaNFkDy1jlLznnhwVAZKPo/9ffpg== | ||
37 | =bPqu | ||
38 | -----END PGP MESSAGE----- | ||
39 | |||
40 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox.html new file mode 100644 index 00000000..344dc237 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox.html | |||
@@ -0,0 +1,47 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
15 | <tr class="signOkKeyOkH"> | ||
16 | <td dir="ltr"> | ||
17 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
18 | <tr> | ||
19 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
20 | <td align="right"> | ||
21 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
22 | </td> | ||
23 | </tr> | ||
24 | </table> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr class="signOkKeyOkB"> | ||
28 | <td> | ||
29 | <div class="noquote"> | ||
30 | <div dir="ltr">asdasd asd asd asdf sadf sdaf sadf öäü</div> | ||
31 | </div> | ||
32 | </td> | ||
33 | </tr> | ||
34 | <tr class="signOkKeyOkH"> | ||
35 | <td dir="ltr">End of signed message</td> | ||
36 | </tr> | ||
37 | </table> | ||
38 | </td> | ||
39 | </tr> | ||
40 | <tr class="encrH"> | ||
41 | <td dir="ltr">End of encrypted message</td> | ||
42 | </tr> | ||
43 | </table> | ||
44 | </div> | ||
45 | </div> | ||
46 | </body> | ||
47 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox.inProgress.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox.inProgress.html new file mode 100644 index 00000000..e5eb55d0 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox.inProgress.html | |||
@@ -0,0 +1,24 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Please wait while the message is being decrypted...</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="font-size:x-large; text-align:center; padding:20pt;"/> | ||
15 | </td> | ||
16 | </tr> | ||
17 | <tr class="encrH"> | ||
18 | <td dir="ltr">End of encrypted message</td> | ||
19 | </tr> | ||
20 | </table> | ||
21 | </div> | ||
22 | </div> | ||
23 | </body> | ||
24 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox.tree new file mode 100644 index 00000000..ea8223fd --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-charset-encrypted.mbox.tree | |||
@@ -0,0 +1,4 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::TextMessagePart | ||
3 | * MimeTreeParser::EncryptedMessagePart | ||
4 | * MimeTreeParser::SignedMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed-broken.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed-broken.mbox new file mode 100644 index 00000000..fc0d2df9 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed-broken.mbox | |||
@@ -0,0 +1,26 @@ | |||
1 | From: test <test@kolab.org> | ||
2 | To: you@you.de | ||
3 | Subject: test | ||
4 | Date: Tue, 25 Aug 2015 16:47:10 +0200 | ||
5 | Message-ID: <1662097.O9NVKTC5pT@11b508545ba2> | ||
6 | X-KMail-Identity: 1428848833 | ||
7 | User-Agent: KMail/4.13.0.3 (Linux/4.1.0-rc5-siduction-amd64; KDE/4.14.3; x86_64; git-7c86098; 2015-08-23) | ||
8 | MIME-Version: 1.0 | ||
9 | Content-Transfer-Encoding: quoted-printable | ||
10 | Content-Type: text/plain; charset="iso-8859-1" | ||
11 | |||
12 | -----BEGIN PGP SIGNED MESSAGE----- | ||
13 | Hash: SHA256 | ||
14 | |||
15 | ohno break it =F6=E4=FC | ||
16 | -----BEGIN PGP SIGNATURE----- | ||
17 | Version: GnuPG v2 | ||
18 | |||
19 | iQEcBAEBCAAGBQJV3H/vAAoJEI2YYMWPJG3mEZQH/2mbCDa60risTUsomEecasc7 | ||
20 | kIc8Ch+OjZwlEQWKEiFbpLCMVjMwf0oGFcpc/dqnIyIqeVvF6Em+v7iqKuyAaihu | ||
21 | 7ZxxC816tDDI7UIpmyWu39McqGB/2hoA/q+QAMgBiaIuMwYJK9Aw08hXzoCds6O7 | ||
22 | Uor2Y6kMSwEiRnTSYvQHdoaZY3F9SFTLPgjvwfSu7scvp7xvH7bAVIqGGfkLjXpP | ||
23 | OFkDhEqUI7ORwD5cvvzEu57XmbGB7Nj5LRCGcTq6IlaGeN6Pw5+hOdd6MQ4iISwy | ||
24 | 870msP9NvktURnfXYC3fYnJaK/eUln7LYCBl/k04Z/3Um6dMYyQGh63oGv/2qxQ=3D | ||
25 | =3D4ctb | ||
26 | -----END PGP SIGNATURE----- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox new file mode 100644 index 00000000..6099a51f --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox | |||
@@ -0,0 +1,26 @@ | |||
1 | From: test <test@kolab.org> | ||
2 | To: you@you.de | ||
3 | Subject: test | ||
4 | Date: Tue, 25 Aug 2015 16:47:10 +0200 | ||
5 | Message-ID: <1662097.O9NVKTC5pT@11b508545ba2> | ||
6 | X-KMail-Identity: 1428848833 | ||
7 | User-Agent: KMail/4.13.0.3 (Linux/4.1.0-rc5-siduction-amd64; KDE/4.14.3; x86_64; git-7c86098; 2015-08-23) | ||
8 | MIME-Version: 1.0 | ||
9 | Content-Transfer-Encoding: quoted-printable | ||
10 | Content-Type: text/plain; charset="iso-8859-1" | ||
11 | |||
12 | -----BEGIN PGP SIGNED MESSAGE----- | ||
13 | Hash: SHA256 | ||
14 | |||
15 | ohno =F6=E4=FC | ||
16 | -----BEGIN PGP SIGNATURE----- | ||
17 | Version: GnuPG v2 | ||
18 | |||
19 | iQEcBAEBCAAGBQJV3H/vAAoJEI2YYMWPJG3mEZQH/2mbCDa60risTUsomEecasc7 | ||
20 | kIc8Ch+OjZwlEQWKEiFbpLCMVjMwf0oGFcpc/dqnIyIqeVvF6Em+v7iqKuyAaihu | ||
21 | 7ZxxC816tDDI7UIpmyWu39McqGB/2hoA/q+QAMgBiaIuMwYJK9Aw08hXzoCds6O7 | ||
22 | Uor2Y6kMSwEiRnTSYvQHdoaZY3F9SFTLPgjvwfSu7scvp7xvH7bAVIqGGfkLjXpP | ||
23 | OFkDhEqUI7ORwD5cvvzEu57XmbGB7Nj5LRCGcTq6IlaGeN6Pw5+hOdd6MQ4iISwy | ||
24 | 870msP9NvktURnfXYC3fYnJaK/eUln7LYCBl/k04Z/3Um6dMYyQGh63oGv/2qxQ=3D | ||
25 | =3D4ctb | ||
26 | -----END PGP SIGNATURE----- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox.html new file mode 100644 index 00000000..d32d0235 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox.html | |||
@@ -0,0 +1,35 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signOkKeyOkB"> | ||
22 | <td> | ||
23 | <div class="noquote"> | ||
24 | <div dir="ltr">ohno öäü</div> | ||
25 | </div> | ||
26 | </td> | ||
27 | </tr> | ||
28 | <tr class="signOkKeyOkH"> | ||
29 | <td dir="ltr">End of signed message</td> | ||
30 | </tr> | ||
31 | </table> | ||
32 | </div> | ||
33 | </div> | ||
34 | </body> | ||
35 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox.inProgress.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox.inProgress.html new file mode 100644 index 00000000..45a999d3 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox.inProgress.html | |||
@@ -0,0 +1,22 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signInProgress"> | ||
9 | <tr class="signInProgressH"> | ||
10 | <td dir="ltr">Please wait while the signature is being verified...</td> | ||
11 | </tr> | ||
12 | <tr class="signInProgressB"> | ||
13 | <td/> | ||
14 | </tr> | ||
15 | <tr class="signInProgressH"> | ||
16 | <td dir="ltr">End of signed message</td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </div> | ||
20 | </div> | ||
21 | </body> | ||
22 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox.tree new file mode 100644 index 00000000..23e99880 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-signed.mbox.tree | |||
@@ -0,0 +1,3 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::TextMessagePart | ||
3 | * MimeTreeParser::SignedMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-wrong-charset-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-wrong-charset-encrypted.mbox new file mode 100644 index 00000000..5ecfc612 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-wrong-charset-encrypted.mbox | |||
@@ -0,0 +1,34 @@ | |||
1 | From t.glaser@tarent.de Mon Aug 18 10:59:01 2014 | ||
2 | Return-Path: <t.glaser@tarent.de> | ||
3 | Received: from tgwrk.ig42.org (tgwrk.ig42.org. | ||
4 | [2a01:238:4200:4342:321e:80ff:fe12:4223]) by mx.google.com with ESMTPSA id | ||
5 | pe6sm40660135wjb.38.2014.08.18.01.59.01 for <t.glaser@tarent.de> | ||
6 | (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 | ||
7 | Aug 2014 01:59:01 -0700 (PDT) | ||
8 | Date: Mon, 18 Aug 2014 10:59:00 +0200 (CEST) | ||
9 | From: Thorsten Glaser <t.glaser@tarent.de> | ||
10 | X-X-Sender: tglase@tglase.lan.tarent.de | ||
11 | To: Thorsten Glaser <t.glaser@tarent.de> | ||
12 | Subject: Test for Mozilla bug#1054187 | ||
13 | Message-ID: <alpine.DEB.2.11.1408181058220.30583@tglase.lan.tarent.de> | ||
14 | User-Agent: Alpine 2.11 (DEB 23 2013-08-11) | ||
15 | MIME-Version: 1.0 | ||
16 | Content-Type: TEXT/PLAIN; charset=US-ASCII | ||
17 | |||
18 | -----BEGIN PGP MESSAGE----- | ||
19 | Version: GnuPG v2 | ||
20 | |||
21 | hIwDTFSKP3rBSXcBBAClcHW9/6kw8i+XkMes47vcmGBCjIC0UysqkVYyNqT2Y6tb | ||
22 | s7pdfZFQPVWbdYoxP0WLzGgNFEWttlojWJmaTNiDVLOP22hFuJL3LUxesC1cWE+6 | ||
23 | foCkENDI2YnkAw4o5HTrmHoBlG7N/Nzzu3+1kfUVANSoAhgWd5WJDsXyvPMoD9LA | ||
24 | 7gHZZmq4bK5OwTHvAvdUOstCGd6Wqj5zkVXT59WOfYxYLcrGZ8I62lBS1/90TlJe | ||
25 | iEolBoaufZT7K2YW7k/+DPYgRIzvWISTccPWpcS7OOyifvK4zOFJeGsVq/DowP52 | ||
26 | Zt1xQj1En5CVUT/MkpvS1rB4BfSuhJETZdtUGveUe0HhcAzbnbIJULdK0p1XAo4O | ||
27 | q84vmOVD0BtKJVy/+rIW7h4aOr8C66HNDKLiUzWtdEaG97GQwhpQZ05JNsulG9tV | ||
28 | wyP6UWmDMY/5YuRoVHOYx8NXORHX4E5P151Tr5Fted9TpXI/gOTHHyPK5AiiDG6U | ||
29 | ja4fgkO6hYnjHxqqooxfGj+pg5atynnbMTALfWoXxmqyKrIB+SKqnsw+sCL3ro2x | ||
30 | j54EGZZ9wM6AYDQ48lJV5beWgQ55r28HxlhPNl/driNkMZHUazAdsubWo5NqJPXl | ||
31 | HrHQ4lv53ZUohbpVvdkmsldWhA5me7yRhQHytTQMMfadmSiYZVsy53siQ/5gEhUv | ||
32 | DQ4ggpUjf8twqR+5TLue5/r/fRXkGfKr5U1w4qcMcFcGwEIbwE+qtIDY0Cw/+xU= | ||
33 | =Ecl0 | ||
34 | -----END PGP MESSAGE----- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-wrong-charset-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-wrong-charset-encrypted.mbox.html new file mode 100644 index 00000000..3ed4e0fb --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-wrong-charset-encrypted.mbox.html | |||
@@ -0,0 +1,47 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
15 | <tr class="signOkKeyOkH"> | ||
16 | <td dir="ltr"> | ||
17 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
18 | <tr> | ||
19 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
20 | <td align="right"> | ||
21 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
22 | </td> | ||
23 | </tr> | ||
24 | </table> | ||
25 | </td> | ||
26 | </tr> | ||
27 | <tr class="signOkKeyOkB"> | ||
28 | <td> | ||
29 | <div class="noquote"> | ||
30 | <div dir="ltr">This is a utf-8 message you see - öäüß@ł€¶ŧ←↓→øþ</div> | ||
31 | </div> | ||
32 | </td> | ||
33 | </tr> | ||
34 | <tr class="signOkKeyOkH"> | ||
35 | <td dir="ltr">End of signed message</td> | ||
36 | </tr> | ||
37 | </table> | ||
38 | </td> | ||
39 | </tr> | ||
40 | <tr class="encrH"> | ||
41 | <td dir="ltr">End of encrypted message</td> | ||
42 | </tr> | ||
43 | </table> | ||
44 | </div> | ||
45 | </div> | ||
46 | </body> | ||
47 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-wrong-charset-encrypted.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-wrong-charset-encrypted.mbox.tree new file mode 100644 index 00000000..ea8223fd --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-inline-wrong-charset-encrypted.mbox.tree | |||
@@ -0,0 +1,4 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::TextMessagePart | ||
3 | * MimeTreeParser::EncryptedMessagePart | ||
4 | * MimeTreeParser::SignedMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox new file mode 100644 index 00000000..ba85df86 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox | |||
@@ -0,0 +1,129 @@ | |||
1 | Return-Path: <sender@example.org> | ||
2 | Sender: sender@example.org | ||
3 | From: Quonk <sender@example.org> | ||
4 | X-Pgp-Agent: GPGMail | ||
5 | Content-Type: multipart/signed; boundary="Apple-Mail=_12345678-1234-1234-1234-12345678"; protocol="application/pgp-signature"; micalg=pgp-sha512 | ||
6 | Subject: PDF | ||
7 | Date: Mon, 16 Jan 2017 15:14:51 +0100 | ||
8 | Message-Id: <199E2891-3080-42B6-ABCD-1230B78EBABC@example.org> | ||
9 | To: Konqi <konqui@example.org> | ||
10 | Mime-Version: 1.0 (Mac OS X Mail 9.3 \(3124\)) | ||
11 | |||
12 | |||
13 | --Apple-Mail=_12345678-1234-1234-1234-12345678 | ||
14 | Content-Type: multipart/alternative; | ||
15 | boundary="Apple-Mail=_23456789-1234-1234-1234-12345678" | ||
16 | |||
17 | |||
18 | --Apple-Mail=_23456789-1234-1234-1234-12345678 | ||
19 | Content-Transfer-Encoding: quoted-printable | ||
20 | Content-Type: text/plain; | ||
21 | charset=utf-8 | ||
22 | |||
23 | |||
24 | |||
25 | =E2=80=A6 | ||
26 | Quonk | ||
27 | Klar=C3=A4lvdalens Datakonsult AB, a KDAB Group company | ||
28 | Sweden (HQ) +46-563-540090, Germany +49-30-521325470 | ||
29 | KDAB - The Qt, C++ and OpenGL Experts | www.kdab.com | ||
30 | |||
31 | |||
32 | --Apple-Mail=_23456789-1234-1234-1234-12345678 | ||
33 | Content-Type: multipart/mixed; | ||
34 | boundary="Apple-Mail=_34567890-1234-1234-1234-12345678" | ||
35 | |||
36 | |||
37 | --Apple-Mail=_34567890-1234-1234-1234-12345678 | ||
38 | Content-Transfer-Encoding: 7bit | ||
39 | Content-Type: text/html; | ||
40 | charset=us-ascii | ||
41 | |||
42 | <html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">pre attachment</div></body></html> | ||
43 | --Apple-Mail=_34567890-1234-1234-1234-12345678 | ||
44 | Content-Disposition: attachment; filename="image.png" | ||
45 | Content-Transfer-Encoding: base64 | ||
46 | Content-Type: image/png; name="image.png" | ||
47 | |||
48 | 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 | ||
91 | o/0d59+Lh3Y1HHcAAAAASUVORK5CYII= | ||
92 | --Apple-Mail=_34567890-1234-1234-1234-12345678 | ||
93 | Content-Transfer-Encoding: quoted-printable | ||
94 | Content-Type: text/html; | ||
95 | charset=utf-8 | ||
96 | |||
97 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> | ||
98 | p, li { white-space: pre-wrap; } | ||
99 | </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> | ||
100 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p> | ||
101 | </body></html> | ||
102 | |||
103 | --Apple-Mail=_34567890-1234-1234-1234-12345678-- | ||
104 | |||
105 | --Apple-Mail=_23456789-1234-1234-1234-12345678-- | ||
106 | |||
107 | --Apple-Mail=_12345678-1234-1234-1234-12345678 | ||
108 | Content-Transfer-Encoding: 7bit | ||
109 | Content-Disposition: attachment; | ||
110 | filename=signature.asc | ||
111 | Content-Type: application/pgp-signature; | ||
112 | name=signature.asc | ||
113 | Content-Description: Message signed with OpenPGP using GPGMail | ||
114 | |||
115 | -----BEGIN PGP SIGNATURE----- | ||
116 | |||
117 | iQEzBAEBCAAdFiEEG6Mjkys/qoJhMseejZhgxY8kbeYFAlh/rcwACgkQjZhgxY8k | ||
118 | beYaoQf+Miuj4cnVumYXMopVMHJs6AK6D+uKO4jXHl/XUK3TOg17kFUZDEN/9JFd | ||
119 | SCN9oD5emzpBl4GSmYBbjvLvXTHTLHviVD6In35+wgMlQL+xfAv91Dx56QslCQMo | ||
120 | UhDYGgFPiEAfCY2UozQD/R3KWOHFB9bNdtOM0hdT84D35W2PZhzTlz2q3hpq3bYw | ||
121 | lNhFVebqURh9OEAZglB3Q9oDE13PJDtRLflKquC5ZU8N4Bj23TCOgxv4FzSyyAn/ | ||
122 | XalEKdwYrkZ8p4rRtd0YvAVevDUC4pQNGTgfsXgldoPEGUBXsdlczLPEj2sjLvNu | ||
123 | HX1GMDrZL/+7DZsURYV5DjhsqWzExQ== | ||
124 | =q0F6 | ||
125 | -----END PGP SIGNATURE----- | ||
126 | |||
127 | --Apple-Mail=_12345678-1234-1234-1234-12345678-- | ||
128 | |||
129 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox.html new file mode 100644 index 00000000..234eaae4 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox.html | |||
@@ -0,0 +1,58 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
9 | <tr class="signWarnH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Not enough information to check signature validity.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signWarnB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.2"/> | ||
26 | <div id="attachmentDiv1.2"> | ||
27 | <a name="att1.2.1"/> | ||
28 | <div id="attachmentDiv1.2.1"> | ||
29 | <div style="position: relative"> | ||
30 | <div class="">pre attachment</div> | ||
31 | </div> | ||
32 | </div> | ||
33 | <a name="att1.2.2"/> | ||
34 | <div id="attachmentDiv1.2.2"> | ||
35 | <hr/> | ||
36 | <div> | ||
37 | <a href="attachment:1.2.2?place=body"><img align="center" height="48" width="48" src="file:image-png.svg" border="0" style="max-width: 100%" alt=""/>image.png</a> | ||
38 | </div> | ||
39 | <div/> | ||
40 | </div> | ||
41 | <a name="att1.2.3"/> | ||
42 | <div id="attachmentDiv1.2.3"> | ||
43 | <div style="position: relative"> | ||
44 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p> | ||
45 | </div> | ||
46 | </div> | ||
47 | </div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="signWarnH"> | ||
52 | <td dir="ltr">End of signed message</td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </body> | ||
58 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox.inProgress.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox.inProgress.html new file mode 100644 index 00000000..b5236fe4 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox.inProgress.html | |||
@@ -0,0 +1,49 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signInProgress"> | ||
9 | <tr class="signInProgressH"> | ||
10 | <td dir="ltr">Please wait while the signature is being verified...</td> | ||
11 | </tr> | ||
12 | <tr class="signInProgressB"> | ||
13 | <td> | ||
14 | <a name="att1"/> | ||
15 | <div id="attachmentDiv1"> | ||
16 | <a name="att1.2"/> | ||
17 | <div id="attachmentDiv1.2"> | ||
18 | <a name="att1.2.1"/> | ||
19 | <div id="attachmentDiv1.2.1"> | ||
20 | <div style="position: relative"> | ||
21 | <div class="">pre attachment</div> | ||
22 | </div> | ||
23 | </div> | ||
24 | <a name="att1.2.2"/> | ||
25 | <div id="attachmentDiv1.2.2"> | ||
26 | <hr/> | ||
27 | <div> | ||
28 | <a href="attachment:1.2.2?place=body"><img align="center" height="48" width="48" src="file:image-png.svg" border="0" style="max-width: 100%" alt=""/>image.png</a> | ||
29 | </div> | ||
30 | <div/> | ||
31 | </div> | ||
32 | <a name="att1.2.3"/> | ||
33 | <div id="attachmentDiv1.2.3"> | ||
34 | <div style="position: relative"> | ||
35 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Some <span style=" font-weight:600;">HTML</span> text</p> | ||
36 | </div> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </td> | ||
41 | </tr> | ||
42 | <tr class="signInProgressH"> | ||
43 | <td dir="ltr">End of signed message</td> | ||
44 | </tr> | ||
45 | </table> | ||
46 | </div> | ||
47 | </div> | ||
48 | </body> | ||
49 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox.tree new file mode 100644 index 00000000..3ade4efe --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-apple.mbox.tree | |||
@@ -0,0 +1,3 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::SignedMessagePart | ||
3 | * MimeTreeParser::AlternativeMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-base64-mailman-footer.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-base64-mailman-footer.mbox new file mode 100644 index 00000000..70bf4ef8 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-base64-mailman-footer.mbox | |||
@@ -0,0 +1,117 @@ | |||
1 | Return-Path: <kde-pim-bounces@kde.org> | ||
2 | X-Sieve: CMU Sieve 2.3 | ||
3 | X-Virus-Scanned: amavisd-new at site | ||
4 | Authentication-Results: linux.site (amavisd-new); dkim=pass (1024-bit key) | ||
5 | header.d=kde.org | ||
6 | Received: from postbox.kde.org (localhost.localdomain [127.0.0.1]) | ||
7 | by postbox.kde.org (Postfix) with ESMTP id 867B8BF274; | ||
8 | Sat, 22 Aug 2015 09:32:21 +0000 (UTC) | ||
9 | DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=kde.org; s=default; | ||
10 | t=1440235945; bh=WhGhdxvdvRs04JdzjAkPcBVPmx7putlUE3ka9dvMIoc=; | ||
11 | h=From:To:Date:Subject:Reply-To:List-Id:List-Unsubscribe:List-Post: | ||
12 | List-Help:List-Subscribe:From; | ||
13 | b=mvxeMMGebkZKq7hekRypkPvt6S8lidA/8vQ3AC5Kft8HDmj8lDUpvOo0VXwCF0OG+ | ||
14 | iAOPKxYtxclf8PgYvgK8NIzr56CwcdlNm3/PpoSe20P3I1DGFpDDMFtW5tOD05SSHz | ||
15 | 5L6PCQyb+KFW1GrXgcm+eHshzJh3U8nHcyd8Vw2E= | ||
16 | X-Original-To: kde-pim@kde.org | ||
17 | Delivered-To: kde-pim@localhost.kde.org | ||
18 | X-Virus-Scanned: amavisd-new at site | ||
19 | From: Volker Krause <vkrause@kde.org> | ||
20 | To: KDEPIM <kde-pim@kde.org> | ||
21 | Date: Sat, 22 Aug 2015 11:31:38 +0200 | ||
22 | Message-ID: <11737387.KAAPH2KlE3@vkpc5> | ||
23 | Organization: KDE | ||
24 | User-Agent: KMail/4.14.3 (Linux/3.16.6-2-desktop; KDE/4.14.7; x86_64; | ||
25 | git-c97b13e; 2014-12-30) | ||
26 | MIME-Version: 1.0 | ||
27 | Subject: [Kde-pim] Phabricator Project Setup | ||
28 | X-BeenThere: kde-pim@kde.org | ||
29 | X-Mailman-Version: 2.1.16 | ||
30 | Precedence: list | ||
31 | Reply-To: KDE PIM <kde-pim@kde.org> | ||
32 | List-Id: KDE PIM <kde-pim.kde.org> | ||
33 | List-Unsubscribe: <https://mail.kde.org/mailman/options/kde-pim>, | ||
34 | <mailto:kde-pim-request@kde.org?subject=unsubscribe> | ||
35 | List-Post: <mailto:kde-pim@kde.org> | ||
36 | List-Help: <mailto:kde-pim-request@kde.org?subject=help> | ||
37 | List-Subscribe: <https://mail.kde.org/mailman/listinfo/kde-pim>, | ||
38 | <mailto:kde-pim-request@kde.org?subject=subscribe> | ||
39 | Content-Type: multipart/mixed; boundary="===============1910646461178264940==" | ||
40 | Errors-To: kde-pim-bounces@kde.org | ||
41 | Sender: "kde-pim" <kde-pim-bounces@kde.org> | ||
42 | |||
43 | |||
44 | --===============1910646461178264940== | ||
45 | Content-Type: multipart/signed; boundary="nextPart2440608.7aDuJBW7cK"; micalg="pgp-sha1"; protocol="application/pgp-signature" | ||
46 | |||
47 | --nextPart2440608.7aDuJBW7cK | ||
48 | Content-Transfer-Encoding: quoted-printable | ||
49 | Content-Type: text/plain; charset="us-ascii" | ||
50 | |||
51 | Hi, | ||
52 | |||
53 | I've talked to Ben, the current Phabricator test setup would actually b= | ||
54 | e=20 | ||
55 | usable for "production" use for task/project management for us, without= | ||
56 | =20 | ||
57 | causing the sysadmins unreasonable trouble when migrating to the full=20= | ||
58 | |||
59 | production deployment of Phabricator eventually. | ||
60 | |||
61 | Phabricator project layout it orthogonal to repo layout, so we can stru= | ||
62 | cture=20 | ||
63 | this however we want. Among other teams I see at least the following la= | ||
64 | youts: | ||
65 | - single project for everything | ||
66 | - a project per release | ||
67 | - a project per component/module (ie. close to the repo layout) | ||
68 | |||
69 | How do we want to structure this? | ||
70 | |||
71 | I would start with a single project to not fragment this too much, as w= | ||
72 | e have=20 | ||
73 | a relatively small team actually looking into this, so everyone is look= | ||
74 | ing at=20 | ||
75 | most sub-projects anyway. And should we eventually hit scaling limits, = | ||
76 | we can=20 | ||
77 | always expand this I think. | ||
78 | |||
79 | We of course should also talk about what we actually want to put in the= | ||
80 | re. My=20 | ||
81 | current motivation is having a place to collect the tasks for getting m= | ||
82 | ore of=20 | ||
83 | the former pimlibs into KF5, and anything else I run into on the way th= | ||
84 | ere=20 | ||
85 | that we eventually should clean up/improve. | ||
86 | |||
87 | regards, | ||
88 | Volker | ||
89 | |||
90 | --nextPart2440608.7aDuJBW7cK | ||
91 | Content-Type: application/pgp-signature; name="signature.asc" | ||
92 | Content-Description: This is a digitally signed message part. | ||
93 | Content-Transfer-Encoding: 7Bit | ||
94 | |||
95 | -----BEGIN PGP SIGNATURE----- | ||
96 | Version: GnuPG v2 | ||
97 | |||
98 | iD8DBQBV2EF9f5bM1k0S0kcRAk9cAJ4vHEh9JkT3Jy3EfxII7nP9HPmxrQCgjeLF | ||
99 | eYXCyN9NRAyC6CHeNnWZN10= | ||
100 | =Y8W4 | ||
101 | -----END PGP SIGNATURE----- | ||
102 | |||
103 | --nextPart2440608.7aDuJBW7cK-- | ||
104 | |||
105 | |||
106 | --===============1910646461178264940== | ||
107 | Content-Type: text/plain; charset="utf-8" | ||
108 | MIME-Version: 1.0 | ||
109 | Content-Transfer-Encoding: base64 | ||
110 | Content-Disposition: inline | ||
111 | |||
112 | X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KS0RFIFBJTSBt | ||
113 | YWlsaW5nIGxpc3Qga2RlLXBpbUBrZGUub3JnCmh0dHBzOi8vbWFpbC5rZGUub3JnL21haWxtYW4v | ||
114 | bGlzdGluZm8va2RlLXBpbQpLREUgUElNIGhvbWUgcGFnZSBhdCBodHRwOi8vcGltLmtkZS5vcmcv | ||
115 | |||
116 | --===============1910646461178264940==-- | ||
117 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-base64-mailman-footer.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-base64-mailman-footer.mbox.html new file mode 100644 index 00000000..50eddaa6 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-base64-mailman-footer.mbox.html | |||
@@ -0,0 +1,78 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
11 | <tr class="signWarnH"> | ||
12 | <td dir="ltr"> | ||
13 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
14 | <tr> | ||
15 | <td>Not enough information to check signature validity.</td> | ||
16 | <td align="right"> | ||
17 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
18 | </td> | ||
19 | </tr> | ||
20 | </table> | ||
21 | </td> | ||
22 | </tr> | ||
23 | <tr class="signWarnB"> | ||
24 | <td> | ||
25 | <a name="att1.1"/> | ||
26 | <div id="attachmentDiv1.1"> | ||
27 | <div class="noquote"> | ||
28 | <div dir="ltr">Hi,</div> | ||
29 | <br/> | ||
30 | <div dir="ltr">I've talked to Ben, the current Phabricator test setup would actually be </div> | ||
31 | <div dir="ltr">usable for "production" use for task/project management for us, without </div> | ||
32 | <div dir="ltr">causing the sysadmins unreasonable trouble when migrating to the full </div> | ||
33 | <div dir="ltr">production deployment of Phabricator eventually.</div> | ||
34 | <br/> | ||
35 | <div dir="ltr">Phabricator project layout it orthogonal to repo layout, so we can structure </div> | ||
36 | <div dir="ltr">this however we want. Among other teams I see at least the following layouts:</div> | ||
37 | <div dir="ltr">- single project for everything</div> | ||
38 | <div dir="ltr">- a project per release</div> | ||
39 | <div dir="ltr">- a project per component/module (ie. close to the repo layout)</div> | ||
40 | <br/> | ||
41 | <div dir="ltr">How do we want to structure this?</div> | ||
42 | <br/> | ||
43 | <div dir="ltr">I would start with a single project to not fragment this too much, as we have </div> | ||
44 | <div dir="ltr">a relatively small team actually looking into this, so everyone is looking at </div> | ||
45 | <div dir="ltr">most sub-projects anyway. And should we eventually hit scaling limits, we can </div> | ||
46 | <div dir="ltr">always expand this I think.</div> | ||
47 | <br/> | ||
48 | <div dir="ltr">We of course should also talk about what we actually want to put in there. My </div> | ||
49 | <div dir="ltr">current motivation is having a place to collect the tasks for getting more of </div> | ||
50 | <div dir="ltr">the former pimlibs into KF5, and anything else I run into on the way there </div> | ||
51 | <div dir="ltr">that we eventually should clean up/improve.</div> | ||
52 | <br/> | ||
53 | <div dir="ltr">regards,</div> | ||
54 | <div dir="ltr">Volker</div> | ||
55 | </div> | ||
56 | </div> | ||
57 | </td> | ||
58 | </tr> | ||
59 | <tr class="signWarnH"> | ||
60 | <td dir="ltr">End of signed message</td> | ||
61 | </tr> | ||
62 | </table> | ||
63 | </div> | ||
64 | <a name="att2"/> | ||
65 | <div id="attachmentDiv2"> | ||
66 | <div class="noquote"> | ||
67 | <div dir="ltr">_______________________________________________</div> | ||
68 | <div dir="ltr">KDE PIM mailing list <a href="mailto:kde-pim@kde.org">kde-pim@kde.org</a></div> | ||
69 | <div dir="ltr"> | ||
70 | <a href="https://mail.kde.org/mailman/listinfo/kde-pim">https://mail.kde.org/mailman/listinfo/kde-pim</a> | ||
71 | </div> | ||
72 | <div dir="ltr">KDE PIM home page at <a href="http://pim.kde.org/">http://pim.kde.org/</a></div> | ||
73 | </div> | ||
74 | </div> | ||
75 | </div> | ||
76 | </div> | ||
77 | </body> | ||
78 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-base64-mailman-footer.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-base64-mailman-footer.mbox.tree new file mode 100644 index 00000000..2753978c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-base64-mailman-footer.mbox.tree | |||
@@ -0,0 +1,7 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::SignedMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
6 | * MimeTreeParser::AttachmentMessagePart | ||
7 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted-two-attachments.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted-two-attachments.mbox new file mode 100644 index 00000000..7939af83 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted-two-attachments.mbox | |||
@@ -0,0 +1,52 @@ | |||
1 | From: firstname.lastname@example.com | ||
2 | To: test@kolab.org | ||
3 | Subject: OpenPGP signed+encrypted with 2 text attachments | ||
4 | Date: Sun, 30 Aug 2015 12:01:20 +0200 | ||
5 | Message-ID: <4368981.7YjI8cQ7Br@vkpc5> | ||
6 | X-KMail-Identity: 402312391 | ||
7 | X-KMail-Dictionary: en_US | ||
8 | User-Agent: KMail/5.0.42 pre (Linux/3.16.6-2-desktop; KDE/5.14.0; x86_64; ; ) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: multipart/encrypted; boundary="nextPart3246504.5GAivIUY6Q"; protocol="application/pgp-encrypted" | ||
11 | |||
12 | --nextPart3246504.5GAivIUY6Q | ||
13 | Content-Type: application/pgp-encrypted | ||
14 | Content-Disposition: attachment | ||
15 | Content-Transfer-Encoding: 7Bit | ||
16 | |||
17 | Version: 1 | ||
18 | --nextPart3246504.5GAivIUY6Q | ||
19 | Content-Type: application/octet-stream | ||
20 | Content-Disposition: inline; filename="msg.asc" | ||
21 | Content-Transfer-Encoding: 7Bit | ||
22 | |||
23 | -----BEGIN PGP MESSAGE----- | ||
24 | Version: GnuPG v2 | ||
25 | |||
26 | hQEMAwzOQ1qnzNo7AQf9Ge9nFjtqLOKSQNhobS+0iCB2GUdLP7LCIWu6gBo9pWa+ | ||
27 | 9wCNLxwmhqWOYv37RAk6v5VXjCYUX3/7UF7e7epSqo7YjS7VsUOow0gszQjJqocK | ||
28 | Gd1T1oyNknza6oaRGgVeWPOZVAPb+Gj+3yS8VZa33Aq2ay7F7eI8dvRUN7Z3TuAh | ||
29 | BOVV+itwHHzanfNG8RoCvokcE1vkANfvI3u7R4Q93U8Q+Qmjh1L5ypPe37N5BtAF | ||
30 | UCPCiD9XySHjm5PyXx8ImrJDeUgFs1YhYox4B6NKsCcmm7R8NdYZYGNo1kzR4yKV | ||
31 | FzMu1NUU/bwtvrpRXLe4dBL1pEkO2PpuMYDUR9+WVNLpAafTDbeIHPi/Z8v48seQ | ||
32 | JxscRehfOB3DG1xrvQTMFJc3UJEBqNMkM9gOxLKOQcCcZp79FMsfWB7EjjlPR1Oh | ||
33 | gyA5NR+4HxNw75Q5FpZ7qziWvIrb1Kzwfbsb9Dimx+MmiNMX9kUEPqkPo4pspwZ9 | ||
34 | pLCfjYUnikcnYyQ0b2ojsjQmLotYlz8mK0GH9L40zfFb1+oYfuu4Y9FPzHdPzNjx | ||
35 | aFRY8cJQy1CNkCITsz53kni5rk3zVsapq0+NeBDEBYoUqX815fo0W+HVF7/j/uhT | ||
36 | lPkJhRnJZPwOr5XgzPk3Yk9GlSRLJiqKF4/G8ya/nKyiNIebKM7DTcldWCmZM95B | ||
37 | BIftaRN4hvVBhl0ElFnZg0xLP1AePFuuplRQTDuW8gpaNKrxwXiF3d4XJdVmjh/p | ||
38 | YmnieIhbogUHFXugc3g9rE8c3oHA8b514ajSHUm9DXc0cXqw/DrsxXZtKXb+IDpF | ||
39 | uv9AiM7bSU7I0h/AlaAL5uU0mL58XhkXXFQtaTbMS+u4Rv/Ie1IsnlWR4QSc4m7x | ||
40 | 91rfC1fIf/U43wwwnR+UjIRyr2vWcgTTpwnsZFDD8eSoJ8WqinazJRlMud6Sv+L6 | ||
41 | gI2wiCYyEYHrFEHy0WuS2nUSMNl5AWm31zB+erfKSLZr4EIFBIy4dJWZKwYhi46Q | ||
42 | pDbw1Svf7xVdHix+5UkkYy3AY70ipf5bxA7FTJ1geJa86VKShDkqVpU6EtT+YQIJ | ||
43 | 7geWCyskT0DTaPp6qc8QpjajmRYssDcjiTke5WiqLQAjm8BIuny0fNm6kNC8KMS7 | ||
44 | eGmaBI2nB92bgrqlAW+LhvW95YB0dfO8beg3jKk8s6OJ4gicGFEFp6hXFfEsEZiv | ||
45 | gi7Q2QCVFvCV11884H8rtZYmMRFGmuVUvm6xh/z1xicmfSy0YUowgkA3jpi7o913 | ||
46 | fqmYOHAwzCxv8Zp7xBf9hLT8DxMXdxqYUnJ+FaEMRcFkJ1MAFBpQ9uDbbqAz5bd5 | ||
47 | F3d6o0JSleOOTDlNH7wpN15HYtaCx9v3mXLN9FY4Y1g4mE8wdU0JZn7sFEmgmAkV | ||
48 | /vj9khHS6eB01GPiCA6sy/u2tSdCQQ== | ||
49 | =1GHi | ||
50 | -----END PGP MESSAGE----- | ||
51 | |||
52 | --nextPart3246504.5GAivIUY6Q-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted-two-attachments.mbox.html new file mode 100644 index 00000000..53856e74 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted-two-attachments.mbox.html | |||
@@ -0,0 +1,88 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <a name="att1.1"/> | ||
35 | <div id="attachmentDiv1.1"> | ||
36 | <div class="noquote"> | ||
37 | <div dir="ltr">this is the main body</div> | ||
38 | </div> | ||
39 | </div> | ||
40 | <a name="att1.2"/> | ||
41 | <div id="attachmentDiv1.2"> | ||
42 | <table cellspacing="1" class="textAtm"> | ||
43 | <tr class="textAtmH"> | ||
44 | <td dir="ltr">attachment1.txt</td> | ||
45 | </tr> | ||
46 | <tr class="textAtmB"> | ||
47 | <td> | ||
48 | <div class="noquote"> | ||
49 | <div dir="ltr">this is one attachment</div> | ||
50 | </div> | ||
51 | </td> | ||
52 | </tr> | ||
53 | </table> | ||
54 | </div> | ||
55 | <a name="att1.3"/> | ||
56 | <div id="attachmentDiv1.3"> | ||
57 | <table cellspacing="1" class="textAtm"> | ||
58 | <tr class="textAtmH"> | ||
59 | <td dir="ltr">attachment2.txt</td> | ||
60 | </tr> | ||
61 | <tr class="textAtmB"> | ||
62 | <td> | ||
63 | <div class="noquote"> | ||
64 | <div dir="ltr">this is the second attachment</div> | ||
65 | </div> | ||
66 | </td> | ||
67 | </tr> | ||
68 | </table> | ||
69 | </div> | ||
70 | </div> | ||
71 | </td> | ||
72 | </tr> | ||
73 | <tr class="signOkKeyOkH"> | ||
74 | <td dir="ltr">End of signed message</td> | ||
75 | </tr> | ||
76 | </table> | ||
77 | </div> | ||
78 | </div> | ||
79 | </td> | ||
80 | </tr> | ||
81 | <tr class="encrH"> | ||
82 | <td dir="ltr">End of encrypted message</td> | ||
83 | </tr> | ||
84 | </table> | ||
85 | </div> | ||
86 | </div> | ||
87 | </body> | ||
88 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted-two-attachments.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted-two-attachments.mbox.tree new file mode 100644 index 00000000..6705a4d7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted-two-attachments.mbox.tree | |||
@@ -0,0 +1,10 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::SignedMessagePart | ||
4 | * MimeTreeParser::MimeMessagePart | ||
5 | * MimeTreeParser::TextMessagePart | ||
6 | * MimeTreeParser::MessagePart | ||
7 | * MimeTreeParser::AttachmentMessagePart | ||
8 | * MimeTreeParser::MessagePart | ||
9 | * MimeTreeParser::AttachmentMessagePart | ||
10 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted.mbox new file mode 100644 index 00000000..6d723d52 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted.mbox | |||
@@ -0,0 +1,47 @@ | |||
1 | From: OpenPGP Test <test@kolab.org> | ||
2 | To: test@kolab.org | ||
3 | Subject: OpenPGP signed and encrypted | ||
4 | Date: Tue, 07 Sep 2010 18:08:44 +0200 | ||
5 | User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: multipart/encrypted; boundary="nextPart25203163.0xtB501Z4V"; protocol="application/pgp-encrypted" | ||
8 | Content-Transfer-Encoding: 7Bit | ||
9 | |||
10 | |||
11 | --nextPart25203163.0xtB501Z4V | ||
12 | Content-Type: application/pgp-encrypted | ||
13 | Content-Disposition: attachment | ||
14 | |||
15 | Version: 1 | ||
16 | --nextPart25203163.0xtB501Z4V | ||
17 | Content-Type: application/octet-stream | ||
18 | Content-Disposition: inline; filename="msg.asc" | ||
19 | |||
20 | -----BEGIN PGP MESSAGE----- | ||
21 | Version: GnuPG v2.0.15 (GNU/Linux) | ||
22 | |||
23 | hQEMAwzOQ1qnzNo7AQf7BFYWaGiCTGtXY59bSh3LCXNnWZejblYALxIUNXOFEXbm | ||
24 | y/YA95FmQsy3U5HRCAJV/DY1PEaJz1RTm9bcdIpDC3Ab2YzSwmOwV5fcoUOB2df4 | ||
25 | KjX19Q+2F3JxpPQ0N1gHf4dKfIu19LH+CKeFzUN13aJs5J4A5wlj+NjJikxzmxDS | ||
26 | kDtNYndynPmo9DJQcsUFw3gpvx5HaHvx1cT4mAB2M5cd2l+vN1jYbaWb0x5Zq41z | ||
27 | mRNI89aPieC3rcM2289m68fGloNbYvi8mZJu5RrI4Tbi/D7Rjm1y63lHgVV6AN88 | ||
28 | XAzRiedOeF99LoTBulrJdtT8AAgCs8nCetcWpIffdtLpAZiZkzHmYOU7nqGxqpRk | ||
29 | OVeUTrCn9DW2SMmHjaP4IiKnMvzEycu5F4a72+V1LeMIhMSjTRTq+ZE2PTaqH59z | ||
30 | QsMn7Nb6GlOICbTptRKNNtyJKO7xXlpT7YtvNKnCyEOkH2XrYH7GvpYCiuQ0/o+7 | ||
31 | SxV436ZejiYIg6DQDXJCoa2DXimGp0C10Jh0HwX0BixpoNtwEjkGRYcX6P/JzkH0 | ||
32 | oBood4Ly+Tiu6iVDisrK3AVGYpIzCrKkE9qULTw4R/jFKR2tcCqGb7Fxtk2LV7Md | ||
33 | 3S+DyOKrvKQ5GNwbp9OE97pwk+Lr1JS3UAvj5f6BR+1PVNcC0i0wWkgwDjPh1eGD | ||
34 | enMQmorE6+N0uHtH2F4fOxo/TbbA3+zhI25kVW3bO03xyUl/cmQZeb52nvfOvtOo | ||
35 | gSb2j6bPkzljDMPEzrtJjbFtGHJbPfUQYJgZv9OE2EQIqpg6goIw279alBq6GLIX | ||
36 | pkO+dRmztzjcDyhcLxMuQ4cTizel/0J/bU7U6lvwHSyZVbT4Ev+opG5K70Hbqbwr | ||
37 | NZcgdWXbSeesxGM/oQaMeSurOevxVl+/zrTVAek61aRRd1baAYqgi2pf2V7y4oK3 | ||
38 | qkdxzmoFpRdNlfrQW65NZWnHOi9rC9XxANIwnVn3kRcDf+t2K4PrFluI157lXM/o | ||
39 | wX91j88fazysbJlQ6TjsApO9ETiPOFEBqouxCTtCZzlUgyVG8jpIjdHWFnagHeXH | ||
40 | +lXNdYjxnTWTjTxMOZC9ySMpXkjWdFI1ecxVwu6Ik6RX51rvBJAAXWP75yUjPKJ4 | ||
41 | rRi5oQl/VLl0QznO7lvgMPtUwgDVNWO/r7Kn9B387h9fAJZ/kWFAEDW2yhAzABqO | ||
42 | rCNKDzBPgfAwCnikCpMoCbOL7SU8BdbzQHD8/Lkv4m0pzliHQ/KkGF710koBzTmF | ||
43 | N7+wk9pwIuvcrEBQj567 | ||
44 | =GV0c | ||
45 | -----END PGP MESSAGE----- | ||
46 | |||
47 | --nextPart25203163.0xtB501Z4V-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted.mbox.html new file mode 100644 index 00000000..86a964b8 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted.mbox.html | |||
@@ -0,0 +1,55 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <div class="noquote"> | ||
35 | <div dir="ltr">encrypted message text</div> | ||
36 | </div> | ||
37 | </div> | ||
38 | </td> | ||
39 | </tr> | ||
40 | <tr class="signOkKeyOkH"> | ||
41 | <td dir="ltr">End of signed message</td> | ||
42 | </tr> | ||
43 | </table> | ||
44 | </div> | ||
45 | </div> | ||
46 | </td> | ||
47 | </tr> | ||
48 | <tr class="encrH"> | ||
49 | <td dir="ltr">End of encrypted message</td> | ||
50 | </tr> | ||
51 | </table> | ||
52 | </div> | ||
53 | </div> | ||
54 | </body> | ||
55 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted.mbox.tree new file mode 100644 index 00000000..7d5bbeb7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-encrypted.mbox.tree | |||
@@ -0,0 +1,5 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::SignedMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+additional-children.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+additional-children.mbox new file mode 100644 index 00000000..dbca8d45 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+additional-children.mbox | |||
@@ -0,0 +1,126 @@ | |||
1 | Return-Path: <plasma-devel-bounces@kde.org> | ||
2 | Delivered-To: einar@heavensinferno.net | ||
3 | Received: from localhost (localhost.localdomain [127.0.0.1]) | ||
4 | by akihabara.dennogumi.org (Postfix) with ESMTP id 15AB75CD846 | ||
5 | for <einar@heavensinferno.net>; Mon, 8 Apr 2013 12:15:03 +0200 (CEST) | ||
6 | Authentication-Results: akihabara.dennogumi.org; dkim=pass | ||
7 | (1024-bit key; insecure key) header.i=@kde.org header.b=vQ0NnJ9g; | ||
8 | dkim-adsp=pass | ||
9 | X-Virus-Scanned: Debian amavisd-new at akihabara.dennogumi.org | ||
10 | X-Spam-Flag: NO | ||
11 | X-Spam-Score: -3.818 | ||
12 | X-Spam-Level: | ||
13 | X-Spam-Status: No, score=-3.818 required=5 tests=[BAYES_50=0.8, | ||
14 | RCVD_IN_DNSWL_MED=-2.3, RP_MATCHES_RCVD=-2.328, T_DKIM_INVALID=0.01] | ||
15 | autolearn=unavailable | ||
16 | Received: from akihabara.dennogumi.org ([127.0.0.1]) | ||
17 | by localhost (akihabara.dennogumi.org [127.0.0.1]) (amavisd-new, port 10024) | ||
18 | with ESMTP id RMAq-XNJ040f for <einar@heavensinferno.net>; | ||
19 | Mon, 8 Apr 2013 12:14:44 +0200 (CEST) | ||
20 | Received: from postbox.kde.org (postbox.kde.org [46.4.96.248]) | ||
21 | by akihabara.dennogumi.org (Postfix) with ESMTP id 321675CD845 | ||
22 | for <einar@heavensinferno.net>; Mon, 8 Apr 2013 12:14:44 +0200 (CEST) | ||
23 | Authentication-Results: akihabara.dennogumi.org; dkim=pass | ||
24 | (1024-bit key; insecure key) header.i=@kde.org header.b=vQ0NnJ9g; | ||
25 | dkim-adsp=pass | ||
26 | Received: from postbox.kde.org (localhost [IPv6:::1]) | ||
27 | by postbox.kde.org (Postfix) with ESMTP id 9F5E1B37F95; | ||
28 | Mon, 8 Apr 2013 10:13:32 +0000 (UTC) | ||
29 | DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=kde.org; s=default; | ||
30 | t=1365416012; bh=ZJtmtbDLoGFwSyJUINdTk4UpuX+xzxcjGp7LSPrKNUs=; | ||
31 | h=From:To:Subject:Date:Message-ID:MIME-Version:Reply-To:List-Id: | ||
32 | List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: | ||
33 | Content-Type:Sender; b=vQ0NnJ9gjeyPLhPbQx6o9UxmILkS9KrhaKG6luAS/GR | ||
34 | 6iR3HKXR3HE0BCkTMD5xmKL5ztFMGcU5e79fz0ch0sd2pnZ0y1WVw7KjCxsv/YtO9HM | ||
35 | OplAHmhwRI5zH8KKQbyvdPULvssI/ISdViAXmHw04hNPsBjsIGkTPgvNbPFuk= | ||
36 | X-Original-To: plasma-devel@kde.org | ||
37 | Delivered-To: plasma-devel@localhost.kde.org | ||
38 | Received: from mail.bddf.ca (unknown [64.141.113.219]) | ||
39 | by postbox.kde.org (Postfix) with ESMTP id 782C6B37BE6 | ||
40 | for <plasma-devel@kde.org>; Mon, 8 Apr 2013 09:51:17 +0000 (UTC) | ||
41 | Received: from freedom.localnet (242.13.24.31.ftth.as8758.net [31.24.13.242]) | ||
42 | (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) | ||
43 | (No client certificate requested) | ||
44 | by mail.bddf.ca (Postfix) with ESMTPSA id 0CB712DC040 | ||
45 | for <plasma-devel@kde.org>; Mon, 8 Apr 2013 03:51:16 -0600 (MDT) | ||
46 | From: "Aaron J. Seigo" <aseigo@kde.org> | ||
47 | To: plasma-devel@kde.org | ||
48 | Subject: activities_optional branch in kde-workspace | ||
49 | Date: Mon, 08 Apr 2013 11:51:11 +0200 | ||
50 | Message-ID: <4143483.eqrJjo7JEn@freedom> | ||
51 | User-Agent: KMail/4.11 pre (Linux/3.6.3-1-desktop; KDE/4.10.60; i686; | ||
52 | git-da50be0; 2013-03-12) | ||
53 | MIME-Version: 1.0 | ||
54 | X-Scanned-By: MIMEDefang 2.71 on 46.4.96.248 | ||
55 | X-BeenThere: plasma-devel@kde.org | ||
56 | X-Mailman-Version: 2.1.14 | ||
57 | Precedence: list | ||
58 | Reply-To: plasma-devel@kde.org | ||
59 | List-Id: <plasma-devel.kde.org> | ||
60 | List-Unsubscribe: <https://mail.kde.org/mailman/options/plasma-devel>, | ||
61 | <mailto:plasma-devel-request@kde.org?subject=unsubscribe> | ||
62 | List-Archive: <http://mail.kde.org/pipermail/plasma-devel> | ||
63 | List-Post: <mailto:plasma-devel@kde.org> | ||
64 | List-Help: <mailto:plasma-devel-request@kde.org?subject=help> | ||
65 | List-Subscribe: <https://mail.kde.org/mailman/listinfo/plasma-devel>, | ||
66 | <mailto:plasma-devel-request@kde.org?subject=subscribe> | ||
67 | Content-Type: multipart/mixed; boundary="===============6664737512143839854==" | ||
68 | Errors-To: plasma-devel-bounces@kde.org | ||
69 | Sender: plasma-devel-bounces@kde.org | ||
70 | |||
71 | |||
72 | --===============6664737512143839854== | ||
73 | Content-Type: multipart/signed; boundary="nextPart1996263.NlFDv9GTkA"; micalg="pgp-sha1"; protocol="application/pgp-signature" | ||
74 | |||
75 | |||
76 | --nextPart1996263.NlFDv9GTkA | ||
77 | Content-Transfer-Encoding: 7Bit | ||
78 | Content-Type: text/plain; charset="us-ascii" | ||
79 | |||
80 | hi.. | ||
81 | |||
82 | i noticed a new branch when i pulled kde-workspace today (finally!): | ||
83 | activities_optional | ||
84 | |||
85 | the lone commit in it was pushed on april 1, so maybe it's an april fools | ||
86 | joke, but if it isn't, it looks like someone is trying to do something that | ||
87 | makes no sense (and has no chance of being merged into master). so if this is | ||
88 | a "for reals" branch, perhaps the motivation behind it can be shared? | ||
89 | |||
90 | -- | ||
91 | Aaron J. Seigo | ||
92 | --nextPart1996263.NlFDv9GTkA | ||
93 | Content-Type: application/pgp-signature; name="signature.asc" | ||
94 | Content-Description: This is a digitally signed message part. | ||
95 | Content-Transfer-Encoding: 7Bit | ||
96 | |||
97 | -----BEGIN PGP SIGNATURE----- | ||
98 | Version: GnuPG v2.0.19 (GNU/Linux) | ||
99 | |||
100 | iEUEABECAAYFAlFikxAACgkQ1rcusafx20MHbwCfeXOgTDwtR81XJwAdcQB40Lt7 | ||
101 | t2IAmJpIZxdU+SSruySeEfbQs3VXq/8= | ||
102 | =BQPF | ||
103 | -----END PGP SIGNATURE----- | ||
104 | --nextPart1996263.NlFDv9GTkA | ||
105 | Content-Type: text/plain; name="broken.attachment" | ||
106 | Content-Transfer-Encoding: 7Bit | ||
107 | |||
108 | Let's break a signed message - This messageblock should not be here :D | ||
109 | |||
110 | --nextPart1996263.NlFDv9GTkA-- | ||
111 | |||
112 | |||
113 | --===============6664737512143839854== | ||
114 | Content-Type: text/plain; charset="us-ascii" | ||
115 | MIME-Version: 1.0 | ||
116 | Content-Transfer-Encoding: 7bit | ||
117 | Content-Disposition: inline | ||
118 | |||
119 | _______________________________________________ | ||
120 | Plasma-devel mailing list | ||
121 | Plasma-devel@kde.org | ||
122 | https://mail.kde.org/mailman/listinfo/plasma-devel | ||
123 | |||
124 | --===============6664737512143839854==-- | ||
125 | |||
126 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+additional-children.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+additional-children.mbox.html new file mode 100644 index 00000000..a95252e4 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+additional-children.mbox.html | |||
@@ -0,0 +1,60 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <a name="att1.1"/> | ||
11 | <div id="attachmentDiv1.1"> | ||
12 | <div class="noquote"> | ||
13 | <div dir="ltr">hi..</div> | ||
14 | <br/> | ||
15 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
16 | <div dir="ltr">activities_optional</div> | ||
17 | <br/> | ||
18 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
19 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
20 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
21 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
22 | <br/> | ||
23 | <div dir="ltr">-- </div> | ||
24 | <div dir="ltr">Aaron J. Seigo</div> | ||
25 | </div> | ||
26 | </div> | ||
27 | <a name="att1.2"/> | ||
28 | <div id="attachmentDiv1.2"> | ||
29 | <hr/> | ||
30 | <div> | ||
31 | <a href="attachment:1.2?place=body"><img align="center" height="48" width="48" src="file:application-pgp-signature.svg" border="0" style="max-width: 100%" alt=""/>signature.asc</a> | ||
32 | </div> | ||
33 | <div>This is a digitally signed message part.</div> | ||
34 | </div> | ||
35 | <a name="att1.3"/> | ||
36 | <div id="attachmentDiv1.3"> | ||
37 | <hr/> | ||
38 | <div> | ||
39 | <a href="attachment:1.3?place=body"><img align="center" height="48" width="48" src="file:text-plain.svg" border="0" style="max-width: 100%" alt=""/>broken.attachment</a> | ||
40 | </div> | ||
41 | <div/> | ||
42 | </div> | ||
43 | </div> | ||
44 | <a name="att2"/> | ||
45 | <div id="attachmentDiv2"> | ||
46 | <div class="noquote"> | ||
47 | <div dir="ltr">_______________________________________________</div> | ||
48 | <div dir="ltr">Plasma-devel mailing list</div> | ||
49 | <div dir="ltr"> | ||
50 | <a href="mailto:Plasma-devel@kde.org">Plasma-devel@kde.org</a> | ||
51 | </div> | ||
52 | <div dir="ltr"> | ||
53 | <a href="https://mail.kde.org/mailman/listinfo/plasma-devel">https://mail.kde.org/mailman/listinfo/plasma-devel</a> | ||
54 | </div> | ||
55 | </div> | ||
56 | </div> | ||
57 | </div> | ||
58 | </div> | ||
59 | </body> | ||
60 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+additional-children.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+additional-children.mbox.tree new file mode 100644 index 00000000..906e6274 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+additional-children.mbox.tree | |||
@@ -0,0 +1,10 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::MimeMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
6 | * MimeTreeParser::AttachmentMessagePart | ||
7 | * MimeTreeParser::AttachmentMessagePart | ||
8 | * MimeTreeParser::MessagePart | ||
9 | * MimeTreeParser::AttachmentMessagePart | ||
10 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+old.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+old.mbox new file mode 100644 index 00000000..362dff3e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+old.mbox | |||
@@ -0,0 +1,67 @@ | |||
1 | Return-Path: <plasma-devel-bounces@kde.org> | ||
2 | Delivered-To: einar@heavensinferno.net | ||
3 | From: "Aaron J. Seigo" <aseigo@kde.org> | ||
4 | To: plasma-devel@kde.org | ||
5 | Subject: activities_optional branch in kde-workspace | ||
6 | Date: Mon, 08 Apr 2013 11:51:11 +0200 | ||
7 | Message-ID: <4143483.eqrJjo7JEn@freedom> | ||
8 | User-Agent: KMail/4.11 pre (Linux/3.6.3-1-desktop; KDE/4.10.60; i686; | ||
9 | git-da50be0; 2013-03-12) | ||
10 | X-Mailman-Version: 2.1.14 | ||
11 | Precedence: list | ||
12 | Reply-To: plasma-devel@kde.org | ||
13 | List-Id: <plasma-devel.kde.org> | ||
14 | List-Unsubscribe: <https://mail.kde.org/mailman/options/plasma-devel>, | ||
15 | <mailto:plasma-devel-request@kde.org?subject=unsubscribe> | ||
16 | List-Archive: <http://mail.kde.org/pipermail/plasma-devel> | ||
17 | List-Post: <mailto:plasma-devel@kde.org> | ||
18 | List-Help: <mailto:plasma-devel-request@kde.org?subject=help> | ||
19 | List-Subscribe: <https://mail.kde.org/mailman/listinfo/plasma-devel>, | ||
20 | <mailto:plasma-devel-request@kde.org?subject=subscribe> | ||
21 | Errors-To: plasma-devel-bounces@kde.org | ||
22 | Sender: plasma-devel-bounces@kde.org | ||
23 | |||
24 | Oh man a header :) | ||
25 | |||
26 | --__--__-- | ||
27 | |||
28 | Message: | ||
29 | MIME-Version: 1.0 | ||
30 | Content-Type: multipart/signed; boundary="nextPart1996263.NlFDv9GTkA"; micalg="pgp-sha1"; protocol="application/pgp-signature" | ||
31 | |||
32 | |||
33 | --nextPart1996263.NlFDv9GTkA | ||
34 | Content-Transfer-Encoding: 7Bit | ||
35 | Content-Type: text/plain; charset="us-ascii" | ||
36 | |||
37 | hi.. | ||
38 | |||
39 | i noticed a new branch when i pulled kde-workspace today (finally!): | ||
40 | activities_optional | ||
41 | |||
42 | the lone commit in it was pushed on april 1, so maybe it's an april fools | ||
43 | joke, but if it isn't, it looks like someone is trying to do something that | ||
44 | makes no sense (and has no chance of being merged into master). so if this is | ||
45 | a "for reals" branch, perhaps the motivation behind it can be shared? | ||
46 | |||
47 | -- | ||
48 | Aaron J. Seigo | ||
49 | --nextPart1996263.NlFDv9GTkA | ||
50 | Content-Type: application/pgp-signature; name="signature.asc" | ||
51 | Content-Description: This is a digitally signed message part. | ||
52 | Content-Transfer-Encoding: 7Bit | ||
53 | |||
54 | -----BEGIN PGP SIGNATURE----- | ||
55 | Version: GnuPG v2.0.19 (GNU/Linux) | ||
56 | |||
57 | iEUEABECAAYFAlFikxAACgkQ1rcusafx20MHbwCfeXOgTDwtR81XJwAdcQB40Lt7 | ||
58 | t2IAmJpIZxdU+SSruySeEfbQs3VXq/8= | ||
59 | =BQPF | ||
60 | -----END PGP SIGNATURE----- | ||
61 | |||
62 | --__--__-- | ||
63 | |||
64 | _______________________________________________ | ||
65 | Plasma-devel mailing list | ||
66 | Plasma-devel@kde.org | ||
67 | https://mail.kde.org/mailman/listinfo/plasma-devel \ No newline at end of file | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+old.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+old.mbox.html new file mode 100644 index 00000000..59c6d690 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+old.mbox.html | |||
@@ -0,0 +1,94 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <div style="position: relative; word-wrap: break-word"> | ||
9 | <a name="att"/> | ||
10 | <div id="attachmentDiv"> | ||
11 | <div class="noquote"> | ||
12 | <div dir="ltr">Oh man a header :)</div> | ||
13 | <br/> | ||
14 | </div> | ||
15 | </div> | ||
16 | </div> | ||
17 | <div style="position: relative; word-wrap: break-word"> | ||
18 | <a name="att"/> | ||
19 | <div id="attachmentDiv"> | ||
20 | <table cellspacing="1" cellpadding="1" class="rfc822"> | ||
21 | <tr class="rfc822H"> | ||
22 | <td dir="ltr"> | ||
23 | <a href="attachment:e1:1?place=body">Encapsulated message</a> | ||
24 | </td> | ||
25 | </tr> | ||
26 | <tr class="rfc822B"> | ||
27 | <td> | ||
28 | <a name="att1"/> | ||
29 | <div id="attachmentDiv1"> | ||
30 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
31 | <tr class="signWarnH"> | ||
32 | <td dir="ltr"> | ||
33 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
34 | <tr> | ||
35 | <td>Not enough information to check signature validity.</td> | ||
36 | <td align="right"> | ||
37 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
38 | </td> | ||
39 | </tr> | ||
40 | </table> | ||
41 | </td> | ||
42 | </tr> | ||
43 | <tr class="signWarnB"> | ||
44 | <td> | ||
45 | <a name="att1.1"/> | ||
46 | <div id="attachmentDiv1.1"> | ||
47 | <div class="noquote"> | ||
48 | <div dir="ltr">hi..</div> | ||
49 | <br/> | ||
50 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
51 | <div dir="ltr">activities_optional</div> | ||
52 | <br/> | ||
53 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
54 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
55 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
56 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
57 | <br/> | ||
58 | <div dir="ltr">-- </div> | ||
59 | <div dir="ltr">Aaron J. Seigo</div> | ||
60 | </div> | ||
61 | </div> | ||
62 | </td> | ||
63 | </tr> | ||
64 | <tr class="signWarnH"> | ||
65 | <td dir="ltr">End of signed message</td> | ||
66 | </tr> | ||
67 | </table> | ||
68 | </div> | ||
69 | </td> | ||
70 | </tr> | ||
71 | <tr class="rfc822H"> | ||
72 | <td dir="ltr">End of encapsulated message</td> | ||
73 | </tr> | ||
74 | </table> | ||
75 | </div> | ||
76 | </div> | ||
77 | <div style="position: relative; word-wrap: break-word"> | ||
78 | <a name="att"/> | ||
79 | <div id="attachmentDiv"> | ||
80 | <div class="noquote"> | ||
81 | <div dir="ltr">Plasma-devel mailing list</div> | ||
82 | <div dir="ltr"> | ||
83 | <a href="mailto:Plasma-devel@kde.org">Plasma-devel@kde.org</a> | ||
84 | </div> | ||
85 | <div dir="ltr"> | ||
86 | <a href="https://mail.kde.org/mailman/listinfo/plasma-devel">https://mail.kde.org/mailman/listinfo/plasma-devel</a> | ||
87 | </div> | ||
88 | </div> | ||
89 | </div> | ||
90 | </div> | ||
91 | </div> | ||
92 | </div> | ||
93 | </body> | ||
94 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+old.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+old.mbox.tree new file mode 100644 index 00000000..c8310bc1 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist+old.mbox.tree | |||
@@ -0,0 +1,13 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MessagePartList | ||
3 | * MimeTreeParser::MimeMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
6 | * MimeTreeParser::MimeMessagePart | ||
7 | * MimeTreeParser::EncapsulatedRfc822MessagePart | ||
8 | * MimeTreeParser::SignedMessagePart | ||
9 | * MimeTreeParser::TextMessagePart | ||
10 | * MimeTreeParser::MessagePart | ||
11 | * MimeTreeParser::MimeMessagePart | ||
12 | * MimeTreeParser::TextMessagePart | ||
13 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox new file mode 100644 index 00000000..8adb9f4c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox | |||
@@ -0,0 +1,121 @@ | |||
1 | Return-Path: <plasma-devel-bounces@kde.org> | ||
2 | Delivered-To: einar@heavensinferno.net | ||
3 | Received: from localhost (localhost.localdomain [127.0.0.1]) | ||
4 | by akihabara.dennogumi.org (Postfix) with ESMTP id 15AB75CD846 | ||
5 | for <einar@heavensinferno.net>; Mon, 8 Apr 2013 12:15:03 +0200 (CEST) | ||
6 | Authentication-Results: akihabara.dennogumi.org; dkim=pass | ||
7 | (1024-bit key; insecure key) header.i=@kde.org header.b=vQ0NnJ9g; | ||
8 | dkim-adsp=pass | ||
9 | X-Virus-Scanned: Debian amavisd-new at akihabara.dennogumi.org | ||
10 | X-Spam-Flag: NO | ||
11 | X-Spam-Score: -3.818 | ||
12 | X-Spam-Level: | ||
13 | X-Spam-Status: No, score=-3.818 required=5 tests=[BAYES_50=0.8, | ||
14 | RCVD_IN_DNSWL_MED=-2.3, RP_MATCHES_RCVD=-2.328, T_DKIM_INVALID=0.01] | ||
15 | autolearn=unavailable | ||
16 | Received: from akihabara.dennogumi.org ([127.0.0.1]) | ||
17 | by localhost (akihabara.dennogumi.org [127.0.0.1]) (amavisd-new, port 10024) | ||
18 | with ESMTP id RMAq-XNJ040f for <einar@heavensinferno.net>; | ||
19 | Mon, 8 Apr 2013 12:14:44 +0200 (CEST) | ||
20 | Received: from postbox.kde.org (postbox.kde.org [46.4.96.248]) | ||
21 | by akihabara.dennogumi.org (Postfix) with ESMTP id 321675CD845 | ||
22 | for <einar@heavensinferno.net>; Mon, 8 Apr 2013 12:14:44 +0200 (CEST) | ||
23 | Authentication-Results: akihabara.dennogumi.org; dkim=pass | ||
24 | (1024-bit key; insecure key) header.i=@kde.org header.b=vQ0NnJ9g; | ||
25 | dkim-adsp=pass | ||
26 | Received: from postbox.kde.org (localhost [IPv6:::1]) | ||
27 | by postbox.kde.org (Postfix) with ESMTP id 9F5E1B37F95; | ||
28 | Mon, 8 Apr 2013 10:13:32 +0000 (UTC) | ||
29 | DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=kde.org; s=default; | ||
30 | t=1365416012; bh=ZJtmtbDLoGFwSyJUINdTk4UpuX+xzxcjGp7LSPrKNUs=; | ||
31 | h=From:To:Subject:Date:Message-ID:MIME-Version:Reply-To:List-Id: | ||
32 | List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: | ||
33 | Content-Type:Sender; b=vQ0NnJ9gjeyPLhPbQx6o9UxmILkS9KrhaKG6luAS/GR | ||
34 | 6iR3HKXR3HE0BCkTMD5xmKL5ztFMGcU5e79fz0ch0sd2pnZ0y1WVw7KjCxsv/YtO9HM | ||
35 | OplAHmhwRI5zH8KKQbyvdPULvssI/ISdViAXmHw04hNPsBjsIGkTPgvNbPFuk= | ||
36 | X-Original-To: plasma-devel@kde.org | ||
37 | Delivered-To: plasma-devel@localhost.kde.org | ||
38 | Received: from mail.bddf.ca (unknown [64.141.113.219]) | ||
39 | by postbox.kde.org (Postfix) with ESMTP id 782C6B37BE6 | ||
40 | for <plasma-devel@kde.org>; Mon, 8 Apr 2013 09:51:17 +0000 (UTC) | ||
41 | Received: from freedom.localnet (242.13.24.31.ftth.as8758.net [31.24.13.242]) | ||
42 | (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) | ||
43 | (No client certificate requested) | ||
44 | by mail.bddf.ca (Postfix) with ESMTPSA id 0CB712DC040 | ||
45 | for <plasma-devel@kde.org>; Mon, 8 Apr 2013 03:51:16 -0600 (MDT) | ||
46 | From: "Aaron J. Seigo" <aseigo@kde.org> | ||
47 | To: plasma-devel@kde.org | ||
48 | Subject: activities_optional branch in kde-workspace | ||
49 | Date: Mon, 08 Apr 2013 11:51:11 +0200 | ||
50 | Message-ID: <4143483.eqrJjo7JEn@freedom> | ||
51 | User-Agent: KMail/4.11 pre (Linux/3.6.3-1-desktop; KDE/4.10.60; i686; | ||
52 | git-da50be0; 2013-03-12) | ||
53 | MIME-Version: 1.0 | ||
54 | X-Scanned-By: MIMEDefang 2.71 on 46.4.96.248 | ||
55 | X-BeenThere: plasma-devel@kde.org | ||
56 | X-Mailman-Version: 2.1.14 | ||
57 | Precedence: list | ||
58 | Reply-To: plasma-devel@kde.org | ||
59 | List-Id: <plasma-devel.kde.org> | ||
60 | List-Unsubscribe: <https://mail.kde.org/mailman/options/plasma-devel>, | ||
61 | <mailto:plasma-devel-request@kde.org?subject=unsubscribe> | ||
62 | List-Archive: <http://mail.kde.org/pipermail/plasma-devel> | ||
63 | List-Post: <mailto:plasma-devel@kde.org> | ||
64 | List-Help: <mailto:plasma-devel-request@kde.org?subject=help> | ||
65 | List-Subscribe: <https://mail.kde.org/mailman/listinfo/plasma-devel>, | ||
66 | <mailto:plasma-devel-request@kde.org?subject=subscribe> | ||
67 | Content-Type: multipart/mixed; boundary="===============6664737512143839854==" | ||
68 | Errors-To: plasma-devel-bounces@kde.org | ||
69 | Sender: plasma-devel-bounces@kde.org | ||
70 | |||
71 | |||
72 | --===============6664737512143839854== | ||
73 | Content-Type: multipart/signed; boundary="nextPart1996263.NlFDv9GTkA"; micalg="pgp-sha1"; protocol="application/pgp-signature" | ||
74 | |||
75 | |||
76 | --nextPart1996263.NlFDv9GTkA | ||
77 | Content-Transfer-Encoding: 7Bit | ||
78 | Content-Type: text/plain; charset="us-ascii" | ||
79 | |||
80 | hi.. | ||
81 | |||
82 | i noticed a new branch when i pulled kde-workspace today (finally!): | ||
83 | activities_optional | ||
84 | |||
85 | the lone commit in it was pushed on april 1, so maybe it's an april fools | ||
86 | joke, but if it isn't, it looks like someone is trying to do something that | ||
87 | makes no sense (and has no chance of being merged into master). so if this is | ||
88 | a "for reals" branch, perhaps the motivation behind it can be shared? | ||
89 | |||
90 | -- | ||
91 | Aaron J. Seigo | ||
92 | --nextPart1996263.NlFDv9GTkA | ||
93 | Content-Type: application/pgp-signature; name="signature.asc" | ||
94 | Content-Description: This is a digitally signed message part. | ||
95 | Content-Transfer-Encoding: 7Bit | ||
96 | |||
97 | -----BEGIN PGP SIGNATURE----- | ||
98 | Version: GnuPG v2.0.19 (GNU/Linux) | ||
99 | |||
100 | iEUEABECAAYFAlFikxAACgkQ1rcusafx20MHbwCfeXOgTDwtR81XJwAdcQB40Lt7 | ||
101 | t2IAmJpIZxdU+SSruySeEfbQs3VXq/8= | ||
102 | =BQPF | ||
103 | -----END PGP SIGNATURE----- | ||
104 | |||
105 | --nextPart1996263.NlFDv9GTkA-- | ||
106 | |||
107 | |||
108 | --===============6664737512143839854== | ||
109 | Content-Type: text/plain; charset="us-ascii" | ||
110 | MIME-Version: 1.0 | ||
111 | Content-Transfer-Encoding: 7bit | ||
112 | Content-Disposition: inline | ||
113 | |||
114 | _______________________________________________ | ||
115 | Plasma-devel mailing list | ||
116 | Plasma-devel@kde.org | ||
117 | https://mail.kde.org/mailman/listinfo/plasma-devel | ||
118 | |||
119 | --===============6664737512143839854==-- | ||
120 | |||
121 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox.html new file mode 100644 index 00000000..7acb6fbf --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox.html | |||
@@ -0,0 +1,65 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="signWarn"> | ||
11 | <tr class="signWarnH"> | ||
12 | <td dir="ltr"> | ||
13 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
14 | <tr> | ||
15 | <td>Not enough information to check signature validity.</td> | ||
16 | <td align="right"> | ||
17 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
18 | </td> | ||
19 | </tr> | ||
20 | </table> | ||
21 | </td> | ||
22 | </tr> | ||
23 | <tr class="signWarnB"> | ||
24 | <td> | ||
25 | <a name="att1.1"/> | ||
26 | <div id="attachmentDiv1.1"> | ||
27 | <div class="noquote"> | ||
28 | <div dir="ltr">hi..</div> | ||
29 | <br/> | ||
30 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
31 | <div dir="ltr">activities_optional</div> | ||
32 | <br/> | ||
33 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
34 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
35 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
36 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
37 | <br/> | ||
38 | <div dir="ltr">-- </div> | ||
39 | <div dir="ltr">Aaron J. Seigo</div> | ||
40 | </div> | ||
41 | </div> | ||
42 | </td> | ||
43 | </tr> | ||
44 | <tr class="signWarnH"> | ||
45 | <td dir="ltr">End of signed message</td> | ||
46 | </tr> | ||
47 | </table> | ||
48 | </div> | ||
49 | <a name="att2"/> | ||
50 | <div id="attachmentDiv2"> | ||
51 | <div class="noquote"> | ||
52 | <div dir="ltr">_______________________________________________</div> | ||
53 | <div dir="ltr">Plasma-devel mailing list</div> | ||
54 | <div dir="ltr"> | ||
55 | <a href="mailto:Plasma-devel@kde.org">Plasma-devel@kde.org</a> | ||
56 | </div> | ||
57 | <div dir="ltr"> | ||
58 | <a href="https://mail.kde.org/mailman/listinfo/plasma-devel">https://mail.kde.org/mailman/listinfo/plasma-devel</a> | ||
59 | </div> | ||
60 | </div> | ||
61 | </div> | ||
62 | </div> | ||
63 | </div> | ||
64 | </body> | ||
65 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox.inProgress.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox.inProgress.html new file mode 100644 index 00000000..77c6b29b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox.inProgress.html | |||
@@ -0,0 +1,56 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <table cellspacing="1" cellpadding="1" class="signInProgress"> | ||
11 | <tr class="signInProgressH"> | ||
12 | <td dir="ltr">Please wait while the signature is being verified...</td> | ||
13 | </tr> | ||
14 | <tr class="signInProgressB"> | ||
15 | <td> | ||
16 | <a name="att1.1"/> | ||
17 | <div id="attachmentDiv1.1"> | ||
18 | <div class="noquote"> | ||
19 | <div dir="ltr">hi..</div> | ||
20 | <br/> | ||
21 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
22 | <div dir="ltr">activities_optional</div> | ||
23 | <br/> | ||
24 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
25 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
26 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
27 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
28 | <br/> | ||
29 | <div dir="ltr">-- </div> | ||
30 | <div dir="ltr">Aaron J. Seigo</div> | ||
31 | </div> | ||
32 | </div> | ||
33 | </td> | ||
34 | </tr> | ||
35 | <tr class="signInProgressH"> | ||
36 | <td dir="ltr">End of signed message</td> | ||
37 | </tr> | ||
38 | </table> | ||
39 | </div> | ||
40 | <a name="att2"/> | ||
41 | <div id="attachmentDiv2"> | ||
42 | <div class="noquote"> | ||
43 | <div dir="ltr">_______________________________________________</div> | ||
44 | <div dir="ltr">Plasma-devel mailing list</div> | ||
45 | <div dir="ltr"> | ||
46 | <a href="mailto:Plasma-devel@kde.org">Plasma-devel@kde.org</a> | ||
47 | </div> | ||
48 | <div dir="ltr"> | ||
49 | <a href="https://mail.kde.org/mailman/listinfo/plasma-devel">https://mail.kde.org/mailman/listinfo/plasma-devel</a> | ||
50 | </div> | ||
51 | </div> | ||
52 | </div> | ||
53 | </div> | ||
54 | </div> | ||
55 | </body> | ||
56 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox.tree new file mode 100644 index 00000000..2753978c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-mailinglist.mbox.tree | |||
@@ -0,0 +1,7 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::SignedMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
6 | * MimeTreeParser::AttachmentMessagePart | ||
7 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-no-protocol.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-no-protocol.mbox new file mode 100644 index 00000000..e50879b9 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-no-protocol.mbox | |||
@@ -0,0 +1,35 @@ | |||
1 | Return-Path: <plasma-devel-bounces@kde.org> | ||
2 | Delivered-To: einar@heavensinferno.net | ||
3 | Content-Type: multipart/signed; boundary="nextPart1996263.NlFDv9GTkA"; micalg="pgp-sha1"; protocol="application/broken-signature" | ||
4 | |||
5 | |||
6 | --nextPart1996263.NlFDv9GTkA | ||
7 | Content-Transfer-Encoding: 7Bit | ||
8 | Content-Type: text/plain; charset="us-ascii" | ||
9 | |||
10 | hi.. | ||
11 | |||
12 | i noticed a new branch when i pulled kde-workspace today (finally!): | ||
13 | activities_optional | ||
14 | |||
15 | the lone commit in it was pushed on april 1, so maybe it's an april fools | ||
16 | joke, but if it isn't, it looks like someone is trying to do something that | ||
17 | makes no sense (and has no chance of being merged into master). so if this is | ||
18 | a "for reals" branch, perhaps the motivation behind it can be shared? | ||
19 | |||
20 | -- | ||
21 | Aaron J. Seigo | ||
22 | --nextPart1996263.NlFDv9GTkA | ||
23 | Content-Type: application/broken-signature; name="signature.asc" | ||
24 | Content-Description: This is a digitally signed message part. | ||
25 | Content-Transfer-Encoding: 7Bit | ||
26 | |||
27 | -----BEGIN PGP SIGNATURE----- | ||
28 | Version: GnuPG v2.0.19 (GNU/Linux) | ||
29 | |||
30 | iEUEABECAAYFAlFikxAACgkQ1rcusafx20MHbwCfeXOgTDwtR81XJwAdcQB40Lt7 | ||
31 | t2IAmJpIZxdU+SSruySeEfbQs3VXq/8= | ||
32 | =BQPF | ||
33 | -----END PGP SIGNATURE----- | ||
34 | |||
35 | --nextPart1996263.NlFDv9GTkA-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-no-protocol.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-no-protocol.mbox.html new file mode 100644 index 00000000..4a5f337b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-no-protocol.mbox.html | |||
@@ -0,0 +1,36 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <div class="noquote"> | ||
11 | <div dir="ltr">hi..</div> | ||
12 | <br/> | ||
13 | <div dir="ltr">i noticed a new branch when i pulled kde-workspace today (finally!): </div> | ||
14 | <div dir="ltr">activities_optional</div> | ||
15 | <br/> | ||
16 | <div dir="ltr">the lone commit in it was pushed on april 1, so maybe it's an april fools </div> | ||
17 | <div dir="ltr">joke, but if it isn't, it looks like someone is trying to do something that </div> | ||
18 | <div dir="ltr">makes no sense (and has no chance of being merged into master). so if this is </div> | ||
19 | <div dir="ltr">a "for reals" branch, perhaps the motivation behind it can be shared?</div> | ||
20 | <br/> | ||
21 | <div dir="ltr">-- </div> | ||
22 | <div dir="ltr">Aaron J. Seigo</div> | ||
23 | </div> | ||
24 | </div> | ||
25 | <a name="att2"/> | ||
26 | <div id="attachmentDiv2"> | ||
27 | <hr/> | ||
28 | <div> | ||
29 | <a href="attachment:2?place=body"><img align="center" height="48" width="48" src="file:unknown.svg" border="0" style="max-width: 100%" alt=""/>signature.asc</a> | ||
30 | </div> | ||
31 | <div>This is a digitally signed message part.</div> | ||
32 | </div> | ||
33 | </div> | ||
34 | </div> | ||
35 | </body> | ||
36 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-no-protocol.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-no-protocol.mbox.tree new file mode 100644 index 00000000..d824a11b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-no-protocol.mbox.tree | |||
@@ -0,0 +1,5 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::TextMessagePart | ||
4 | * MimeTreeParser::MessagePart | ||
5 | * MimeTreeParser::AttachmentMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-two-attachments.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-two-attachments.mbox new file mode 100644 index 00000000..462f62a3 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-two-attachments.mbox | |||
@@ -0,0 +1,54 @@ | |||
1 | From: firstname.lastname@example.com | ||
2 | To: test@kolab.org | ||
3 | Subject: OpenPGP signed with 2 text attachments | ||
4 | Date: Sun, 30 Aug 2015 12:02:56 +0200 | ||
5 | Message-ID: <2033829.IGepAdxqt9@vkpc5> | ||
6 | X-KMail-Identity: 402312391 | ||
7 | X-KMail-Dictionary: en_US | ||
8 | User-Agent: KMail/5.0.42 pre (Linux/3.16.6-2-desktop; KDE/5.14.0; x86_64; ; ) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: multipart/signed; boundary="nextPart3682207.KLrp2sxpbf"; micalg="pgp-sha1"; protocol="application/pgp-signature" | ||
11 | |||
12 | --nextPart3682207.KLrp2sxpbf | ||
13 | Content-Type: multipart/mixed; boundary="nextPart2397422.QDHKUNdbyg" | ||
14 | Content-Transfer-Encoding: 7Bit | ||
15 | |||
16 | This is a multi-part message in MIME format. | ||
17 | |||
18 | --nextPart2397422.QDHKUNdbyg | ||
19 | Content-Transfer-Encoding: 7Bit | ||
20 | Content-Type: text/plain; charset="us-ascii" | ||
21 | |||
22 | this is the main body text | ||
23 | --nextPart2397422.QDHKUNdbyg | ||
24 | Content-Disposition: inline; filename="attachment1.txt" | ||
25 | Content-Transfer-Encoding: 7Bit | ||
26 | Content-Type: text/plain; charset="utf-8"; name="attachment1.txt" | ||
27 | |||
28 | this is attachment one | ||
29 | --nextPart2397422.QDHKUNdbyg | ||
30 | Content-Disposition: inline; filename="attachment2.txt" | ||
31 | Content-Transfer-Encoding: 7Bit | ||
32 | Content-Type: text/plain; charset="utf-8"; name="attachment2.txt" | ||
33 | |||
34 | this is attachment two | ||
35 | --nextPart2397422.QDHKUNdbyg-- | ||
36 | |||
37 | --nextPart3682207.KLrp2sxpbf | ||
38 | Content-Type: application/pgp-signature; name="signature.asc" | ||
39 | Content-Description: This is a digitally signed message part. | ||
40 | Content-Transfer-Encoding: 7Bit | ||
41 | |||
42 | -----BEGIN PGP SIGNATURE----- | ||
43 | Version: GnuPG v2 | ||
44 | |||
45 | iQEVAwUAVeLU0I2YYMWPJG3mAQL/fgf+LXmO7bKafdd4g5OOVHHyXRprVmX/6hBq | ||
46 | mZoor29KLIHkvAH9OJi4qBy/ZKwqqKLfttLzHb2UaAfl5kn4f0ckmnwUhU7u32Sm | ||
47 | JZ0Q50SxrRVFRyvTvPG22ho9IwQUO1YSZrL4wO9v8ZBQ3vkfpmAiUQVxPQMINc8L | ||
48 | i68xQEm4y1Dtoc+DTUkoIMeOOPnEl6PTMPrwn906K0r30hI4788fEGRn6uOXb+vD | ||
49 | G/ISlXu+JHIxxf/J5/jVjKNbra+trrfSPzB3piJIjBLEPO5FvLx8SgQFJcJHt/kw | ||
50 | ps8D5YULj/MVMLlsPtXDdZmbOi/G9pN0tr05MKcXsO5Ywe7n2BhASw== | ||
51 | =2Nzb | ||
52 | -----END PGP SIGNATURE----- | ||
53 | |||
54 | --nextPart3682207.KLrp2sxpbf-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-two-attachments.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-two-attachments.mbox.html new file mode 100644 index 00000000..06718641 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-two-attachments.mbox.html | |||
@@ -0,0 +1,71 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signOkKeyOkB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.1"/> | ||
26 | <div id="attachmentDiv1.1"> | ||
27 | <div class="noquote"> | ||
28 | <div dir="ltr">this is the main body text</div> | ||
29 | </div> | ||
30 | </div> | ||
31 | <a name="att1.2"/> | ||
32 | <div id="attachmentDiv1.2"> | ||
33 | <table cellspacing="1" class="textAtm"> | ||
34 | <tr class="textAtmH"> | ||
35 | <td dir="ltr">attachment1.txt</td> | ||
36 | </tr> | ||
37 | <tr class="textAtmB"> | ||
38 | <td> | ||
39 | <div class="noquote"> | ||
40 | <div dir="ltr">this is attachment one</div> | ||
41 | </div> | ||
42 | </td> | ||
43 | </tr> | ||
44 | </table> | ||
45 | </div> | ||
46 | <a name="att1.3"/> | ||
47 | <div id="attachmentDiv1.3"> | ||
48 | <table cellspacing="1" class="textAtm"> | ||
49 | <tr class="textAtmH"> | ||
50 | <td dir="ltr">attachment2.txt</td> | ||
51 | </tr> | ||
52 | <tr class="textAtmB"> | ||
53 | <td> | ||
54 | <div class="noquote"> | ||
55 | <div dir="ltr">this is attachment two</div> | ||
56 | </div> | ||
57 | </td> | ||
58 | </tr> | ||
59 | </table> | ||
60 | </div> | ||
61 | </div> | ||
62 | </td> | ||
63 | </tr> | ||
64 | <tr class="signOkKeyOkH"> | ||
65 | <td dir="ltr">End of signed message</td> | ||
66 | </tr> | ||
67 | </table> | ||
68 | </div> | ||
69 | </div> | ||
70 | </body> | ||
71 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-two-attachments.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-two-attachments.mbox.tree new file mode 100644 index 00000000..7133f4be --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/openpgp-signed-two-attachments.mbox.tree | |||
@@ -0,0 +1,9 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::SignedMessagePart | ||
3 | * MimeTreeParser::MimeMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
6 | * MimeTreeParser::AttachmentMessagePart | ||
7 | * MimeTreeParser::MessagePart | ||
8 | * MimeTreeParser::AttachmentMessagePart | ||
9 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/signed-forward-openpgp-signed-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/signed-forward-openpgp-signed-encrypted.mbox new file mode 100644 index 00000000..9b715161 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/signed-forward-openpgp-signed-encrypted.mbox | |||
@@ -0,0 +1,92 @@ | |||
1 | From test@kolab.org Wed, 08 Sep 2010 17:53:29 +0200 | ||
2 | From: OpenPGP Test <test@kolab.org> | ||
3 | Subject: Signed Fwd: OpenPGP signed and encrypted | ||
4 | Date: Wed, 08 Sep 2010 17:53:29 +0200 | ||
5 | User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: multipart/signed; boundary="nextPart4350242.cT7m6ulPOV"; micalg="pgp-sha1"; protocol="application/pgp-signature" | ||
8 | Content-Transfer-Encoding: 7Bit | ||
9 | |||
10 | |||
11 | --nextPart4350242.cT7m6ulPOV | ||
12 | Content-Type: multipart/mixed; boundary="nextPart1512490.WQBKYaOrt8" | ||
13 | Content-Transfer-Encoding: 7Bit | ||
14 | |||
15 | |||
16 | --nextPart1512490.WQBKYaOrt8 | ||
17 | Content-Transfer-Encoding: 7Bit | ||
18 | Content-Type: text/plain; charset="us-ascii" | ||
19 | |||
20 | bla bla bla | ||
21 | --nextPart1512490.WQBKYaOrt8 | ||
22 | Content-Type: message/rfc822 | ||
23 | Content-Disposition: inline; filename="forwarded message" | ||
24 | Content-Description: OpenPGP Test <test@kolab.org>: OpenPGP signed and encrypted | ||
25 | |||
26 | From: OpenPGP Test <test@kolab.org> | ||
27 | To: test@kolab.org | ||
28 | Subject: OpenPGP signed and encrypted | ||
29 | Date: Tue, 07 Sep 2010 18:08:44 +0200 | ||
30 | User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) | ||
31 | MIME-Version: 1.0 | ||
32 | Content-Type: multipart/encrypted; boundary="nextPart25203163.0xtB501Z4V"; protocol="application/pgp-encrypted" | ||
33 | Content-Transfer-Encoding: 7Bit | ||
34 | |||
35 | |||
36 | --nextPart25203163.0xtB501Z4V | ||
37 | Content-Type: application/pgp-encrypted | ||
38 | Content-Disposition: attachment | ||
39 | |||
40 | Version: 1 | ||
41 | --nextPart25203163.0xtB501Z4V | ||
42 | Content-Type: application/octet-stream | ||
43 | Content-Disposition: inline; filename="msg.asc" | ||
44 | |||
45 | -----BEGIN PGP MESSAGE----- | ||
46 | Version: GnuPG v2.0.15 (GNU/Linux) | ||
47 | |||
48 | hQEMAwzOQ1qnzNo7AQf7BFYWaGiCTGtXY59bSh3LCXNnWZejblYALxIUNXOFEXbm | ||
49 | y/YA95FmQsy3U5HRCAJV/DY1PEaJz1RTm9bcdIpDC3Ab2YzSwmOwV5fcoUOB2df4 | ||
50 | KjX19Q+2F3JxpPQ0N1gHf4dKfIu19LH+CKeFzUN13aJs5J4A5wlj+NjJikxzmxDS | ||
51 | kDtNYndynPmo9DJQcsUFw3gpvx5HaHvx1cT4mAB2M5cd2l+vN1jYbaWb0x5Zq41z | ||
52 | mRNI89aPieC3rcM2289m68fGloNbYvi8mZJu5RrI4Tbi/D7Rjm1y63lHgVV6AN88 | ||
53 | XAzRiedOeF99LoTBulrJdtT8AAgCs8nCetcWpIffdtLpAZiZkzHmYOU7nqGxqpRk | ||
54 | OVeUTrCn9DW2SMmHjaP4IiKnMvzEycu5F4a72+V1LeMIhMSjTRTq+ZE2PTaqH59z | ||
55 | QsMn7Nb6GlOICbTptRKNNtyJKO7xXlpT7YtvNKnCyEOkH2XrYH7GvpYCiuQ0/o+7 | ||
56 | SxV436ZejiYIg6DQDXJCoa2DXimGp0C10Jh0HwX0BixpoNtwEjkGRYcX6P/JzkH0 | ||
57 | oBood4Ly+Tiu6iVDisrK3AVGYpIzCrKkE9qULTw4R/jFKR2tcCqGb7Fxtk2LV7Md | ||
58 | 3S+DyOKrvKQ5GNwbp9OE97pwk+Lr1JS3UAvj5f6BR+1PVNcC0i0wWkgwDjPh1eGD | ||
59 | enMQmorE6+N0uHtH2F4fOxo/TbbA3+zhI25kVW3bO03xyUl/cmQZeb52nvfOvtOo | ||
60 | gSb2j6bPkzljDMPEzrtJjbFtGHJbPfUQYJgZv9OE2EQIqpg6goIw279alBq6GLIX | ||
61 | pkO+dRmztzjcDyhcLxMuQ4cTizel/0J/bU7U6lvwHSyZVbT4Ev+opG5K70Hbqbwr | ||
62 | NZcgdWXbSeesxGM/oQaMeSurOevxVl+/zrTVAek61aRRd1baAYqgi2pf2V7y4oK3 | ||
63 | qkdxzmoFpRdNlfrQW65NZWnHOi9rC9XxANIwnVn3kRcDf+t2K4PrFluI157lXM/o | ||
64 | wX91j88fazysbJlQ6TjsApO9ETiPOFEBqouxCTtCZzlUgyVG8jpIjdHWFnagHeXH | ||
65 | +lXNdYjxnTWTjTxMOZC9ySMpXkjWdFI1ecxVwu6Ik6RX51rvBJAAXWP75yUjPKJ4 | ||
66 | rRi5oQl/VLl0QznO7lvgMPtUwgDVNWO/r7Kn9B387h9fAJZ/kWFAEDW2yhAzABqO | ||
67 | rCNKDzBPgfAwCnikCpMoCbOL7SU8BdbzQHD8/Lkv4m0pzliHQ/KkGF710koBzTmF | ||
68 | N7+wk9pwIuvcrEBQj567 | ||
69 | =GV0c | ||
70 | -----END PGP MESSAGE----- | ||
71 | |||
72 | --nextPart25203163.0xtB501Z4V-- | ||
73 | |||
74 | --nextPart1512490.WQBKYaOrt8-- | ||
75 | |||
76 | --nextPart4350242.cT7m6ulPOV | ||
77 | Content-Type: application/pgp-signature; name="signature.asc" | ||
78 | Content-Description: This is a digitally signed message part. | ||
79 | |||
80 | -----BEGIN PGP SIGNATURE----- | ||
81 | Version: GnuPG v2.0.15 (GNU/Linux) | ||
82 | |||
83 | iQEcBAABAgAGBQJMh7F5AAoJEI2YYMWPJG3mOB0IALeHfwg8u7wK0tDKtKqxQSqC | ||
84 | 2Bbk4pTLuLw/VniQNauDG+kc1eUc5RJk/R31aB1ysiQCV5Q8ucI8c9vCDDMbd+s4 | ||
85 | t2bZUEzMpXrw/aFiHgYGXFAY+tpqZqDGNVRNHWsPYJKtx8cci9E5DLnBJcVXVqib | ||
86 | 3iiHlr9AQOok3PUmpPk1a61q2L0kk8wqRenC0yZXNw5qFn5WW/hFeCOfYB+t+s5N | ||
87 | IuE6ihFCJIlvGborrvl6VgPJTCyUQ3XgI90vS6ABN8TFlCNr3grXOWUePc2a20or | ||
88 | xFgh38cnSR64WJajU5K1nUL9/RgfIcs+PvyHuJaRf/iUFkj1jiMEuaSi9jVFco0= | ||
89 | =bArV | ||
90 | -----END PGP SIGNATURE----- | ||
91 | |||
92 | --nextPart4350242.cT7m6ulPOV-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/signed-forward-openpgp-signed-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/signed-forward-openpgp-signed-encrypted.mbox.html new file mode 100644 index 00000000..b91772b7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/signed-forward-openpgp-signed-encrypted.mbox.html | |||
@@ -0,0 +1,105 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signOkKeyOkB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.1"/> | ||
26 | <div id="attachmentDiv1.1"> | ||
27 | <div class="noquote"> | ||
28 | <div dir="ltr">bla bla bla</div> | ||
29 | </div> | ||
30 | </div> | ||
31 | <a name="att1.2"/> | ||
32 | <div id="attachmentDiv1.2"> | ||
33 | <table cellspacing="1" cellpadding="1" class="rfc822"> | ||
34 | <tr class="rfc822H"> | ||
35 | <td dir="ltr"> | ||
36 | <a href="attachment:1.2.1?place=body">Encapsulated message</a> | ||
37 | </td> | ||
38 | </tr> | ||
39 | <tr class="rfc822B"> | ||
40 | <td> | ||
41 | <a name="att1.2.1"/> | ||
42 | <div id="attachmentDiv1.2.1"> | ||
43 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
44 | <tr class="encrH"> | ||
45 | <td dir="ltr">Encrypted message</td> | ||
46 | </tr> | ||
47 | <tr class="encrB"> | ||
48 | <td> | ||
49 | <div style="position: relative; word-wrap: break-word"> | ||
50 | <a name="att"/> | ||
51 | <div id="attachmentDiv"> | ||
52 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
53 | <tr class="signOkKeyOkH"> | ||
54 | <td dir="ltr"> | ||
55 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
56 | <tr> | ||
57 | <td>Signed by <a href="mailto:test@kolab.org">test@kolab.org</a>.</td> | ||
58 | <td align="right"> | ||
59 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
60 | </td> | ||
61 | </tr> | ||
62 | </table> | ||
63 | </td> | ||
64 | </tr> | ||
65 | <tr class="signOkKeyOkB"> | ||
66 | <td> | ||
67 | <a name="att1"/> | ||
68 | <div id="attachmentDiv1"> | ||
69 | <div class="noquote"> | ||
70 | <div dir="ltr">encrypted message text</div> | ||
71 | </div> | ||
72 | </div> | ||
73 | </td> | ||
74 | </tr> | ||
75 | <tr class="signOkKeyOkH"> | ||
76 | <td dir="ltr">End of signed message</td> | ||
77 | </tr> | ||
78 | </table> | ||
79 | </div> | ||
80 | </div> | ||
81 | </td> | ||
82 | </tr> | ||
83 | <tr class="encrH"> | ||
84 | <td dir="ltr">End of encrypted message</td> | ||
85 | </tr> | ||
86 | </table> | ||
87 | </div> | ||
88 | </td> | ||
89 | </tr> | ||
90 | <tr class="rfc822H"> | ||
91 | <td dir="ltr">End of encapsulated message</td> | ||
92 | </tr> | ||
93 | </table> | ||
94 | </div> | ||
95 | </div> | ||
96 | </td> | ||
97 | </tr> | ||
98 | <tr class="signOkKeyOkH"> | ||
99 | <td dir="ltr">End of signed message</td> | ||
100 | </tr> | ||
101 | </table> | ||
102 | </div> | ||
103 | </div> | ||
104 | </body> | ||
105 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/signed-forward-openpgp-signed-encrypted.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/signed-forward-openpgp-signed-encrypted.mbox.tree new file mode 100644 index 00000000..818f894c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/signed-forward-openpgp-signed-encrypted.mbox.tree | |||
@@ -0,0 +1,10 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::SignedMessagePart | ||
3 | * MimeTreeParser::MimeMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
6 | * MimeTreeParser::EncapsulatedRfc822MessagePart | ||
7 | * MimeTreeParser::EncryptedMessagePart | ||
8 | * MimeTreeParser::SignedMessagePart | ||
9 | * MimeTreeParser::TextMessagePart | ||
10 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-cert.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-cert.mbox new file mode 100644 index 00000000..b3c8a19e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-cert.mbox | |||
@@ -0,0 +1,24 @@ | |||
1 | From test@example.com Sat, 13 Apr 2013 01:54:30 +0200 | ||
2 | From: test <test@example.com> | ||
3 | To: you@you.com | ||
4 | Subject: test | ||
5 | Date: Sat, 13 Apr 2013 01:54:30 +0200 | ||
6 | Message-ID: <1576646.QQxzHWx8dA@tabin> | ||
7 | X-KMail-Identity: 505942601 | ||
8 | User-Agent: KMail/4.10.2 (Linux/3.9.0-rc4-experimental-amd64; KDE/4.10.60; x86_64; git-fc9b82c; 2013-04-11) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: application/pkcs7-mime; name="smime.crt"; smime-type="certs-only" | ||
11 | Content-Transfer-Encoding: base64 | ||
12 | Content-Disposition: attachment; filename="smime.crt" | ||
13 | |||
14 | asdfasdfasdfasdfasdfasdfasdfasdf | ||
15 | asdfasdfadsfsadfasdf | ||
16 | asdfasdf | ||
17 | sadfas | ||
18 | dfasdf | ||
19 | sadf | ||
20 | sadf | ||
21 | adsf | ||
22 | adsf | ||
23 | asdf | ||
24 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-cert.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-cert.mbox.html new file mode 100644 index 00000000..1b86390f --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-cert.mbox.html | |||
@@ -0,0 +1,10 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv">Sorry, certificate could not be imported.<br/>Reason: BER error</div> | ||
8 | </div> | ||
9 | </body> | ||
10 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-cert.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-cert.mbox.tree new file mode 100644 index 00000000..c34c2eca --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-cert.mbox.tree | |||
@@ -0,0 +1,2 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::CertMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted-octet-stream.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted-octet-stream.mbox new file mode 100644 index 00000000..887fe358 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted-octet-stream.mbox | |||
@@ -0,0 +1,23 @@ | |||
1 | From test@example.com Sat, 13 Apr 2013 01:54:30 +0200 | ||
2 | From: test <test@example.com> | ||
3 | To: you@you.com | ||
4 | Subject: test | ||
5 | Date: Sat, 13 Apr 2013 01:54:30 +0200 | ||
6 | Message-ID: <1576646.QQxzHWx8dA@tabin> | ||
7 | X-KMail-Identity: 505942601 | ||
8 | User-Agent: KMail/4.10.2 (Linux/3.9.0-rc4-experimental-amd64; KDE/4.10.60; x86_64; git-fc9b82c; 2013-04-11) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: application/octet-stream; | ||
11 | name="smime.p7m" | ||
12 | Content-Transfer-Encoding: base64 | ||
13 | Content-Disposition: attachment; filename="smime.p7m" | ||
14 | |||
15 | MIAGCSqGSIb3DQEHA6CAMIACAQAxgfwwgfkCAQAwYjBVMQswCQYDVQQGEwJVUzENMAsGA1UECgwE | ||
16 | S0RBQjEWMBQGA1UEAwwNdW5pdHRlc3QgY2VydDEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxl | ||
17 | LmNvbQIJANNFIDoYY4XJMA0GCSqGSIb3DQEBAQUABIGAJwmmaOeidXUHSQGOf2OBIsPYafVqdORe | ||
18 | y54pEXbXiAfSVUWgI4a9CsiWwcDX8vlaX9ZLLr+L2VmOfr6Yc5214yxzausZVvnUFjy6LUXotuEX | ||
19 | tSar4EW7XI9DjaZc1l985naMsTx9JUa5GyQ9J6PGqhosAKpKMGgKkFAHaOwE1/IwgAYJKoZIhvcN | ||
20 | AQcBMBQGCCqGSIb3DQMHBAieDfmz3WGbN6CABHgEpsLrNn0PAZTDUfNomDypvSCl5bQH+9cKm80m | ||
21 | upMV2r8RBiXS7OaP4SpCxq18afDTTPatvboHIoEX92taTbq8soiAgEs6raSGtEYZNvFL0IYqm7MA | ||
22 | o5HCOmjiEcInyPf14lL3HnPk10FaP3hh58qTHUh4LPYtL7UECOZELYnUfUVhAAAAAAAAAAAAAA== | ||
23 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted-octet-stream.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted-octet-stream.mbox.html new file mode 100644 index 00000000..6b08c47e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted-octet-stream.mbox.html | |||
@@ -0,0 +1,31 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <div class="noquote"> | ||
18 | <div dir="ltr">The quick brown fox jumped over the lazy dog.</div> | ||
19 | </div> | ||
20 | </div> | ||
21 | </div> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr class="encrH"> | ||
25 | <td dir="ltr">End of encrypted message</td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </div> | ||
29 | </div> | ||
30 | </body> | ||
31 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted-octet-stream.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted-octet-stream.mbox.tree new file mode 100644 index 00000000..82f705c2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted-octet-stream.mbox.tree | |||
@@ -0,0 +1,4 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::TextMessagePart | ||
4 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox new file mode 100644 index 00000000..6b6d6a0d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox | |||
@@ -0,0 +1,22 @@ | |||
1 | From test@example.com Sat, 13 Apr 2013 01:54:30 +0200 | ||
2 | From: test <test@example.com> | ||
3 | To: you@you.com | ||
4 | Subject: test | ||
5 | Date: Sat, 13 Apr 2013 01:54:30 +0200 | ||
6 | Message-ID: <1576646.QQxzHWx8dA@tabin> | ||
7 | X-KMail-Identity: 505942601 | ||
8 | User-Agent: KMail/4.10.2 (Linux/3.9.0-rc4-experimental-amd64; KDE/4.10.60; x86_64; git-fc9b82c; 2013-04-11) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type="enveloped-data" | ||
11 | Content-Transfer-Encoding: base64 | ||
12 | Content-Disposition: attachment; filename="smime.p7m" | ||
13 | |||
14 | MIAGCSqGSIb3DQEHA6CAMIACAQAxgfwwgfkCAQAwYjBVMQswCQYDVQQGEwJVUzENMAsGA1UECgwE | ||
15 | S0RBQjEWMBQGA1UEAwwNdW5pdHRlc3QgY2VydDEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxl | ||
16 | LmNvbQIJANNFIDoYY4XJMA0GCSqGSIb3DQEBAQUABIGAJwmmaOeidXUHSQGOf2OBIsPYafVqdORe | ||
17 | y54pEXbXiAfSVUWgI4a9CsiWwcDX8vlaX9ZLLr+L2VmOfr6Yc5214yxzausZVvnUFjy6LUXotuEX | ||
18 | tSar4EW7XI9DjaZc1l985naMsTx9JUa5GyQ9J6PGqhosAKpKMGgKkFAHaOwE1/IwgAYJKoZIhvcN | ||
19 | AQcBMBQGCCqGSIb3DQMHBAieDfmz3WGbN6CABHgEpsLrNn0PAZTDUfNomDypvSCl5bQH+9cKm80m | ||
20 | upMV2r8RBiXS7OaP4SpCxq18afDTTPatvboHIoEX92taTbq8soiAgEs6raSGtEYZNvFL0IYqm7MA | ||
21 | o5HCOmjiEcInyPf14lL3HnPk10FaP3hh58qTHUh4LPYtL7UECOZELYnUfUVhAAAAAAAAAAAAAA== | ||
22 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox.html new file mode 100644 index 00000000..6b08c47e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox.html | |||
@@ -0,0 +1,31 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <div class="noquote"> | ||
18 | <div dir="ltr">The quick brown fox jumped over the lazy dog.</div> | ||
19 | </div> | ||
20 | </div> | ||
21 | </div> | ||
22 | </td> | ||
23 | </tr> | ||
24 | <tr class="encrH"> | ||
25 | <td dir="ltr">End of encrypted message</td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </div> | ||
29 | </div> | ||
30 | </body> | ||
31 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox.inProgress.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox.inProgress.html new file mode 100644 index 00000000..e5eb55d0 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox.inProgress.html | |||
@@ -0,0 +1,24 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Please wait while the message is being decrypted...</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="font-size:x-large; text-align:center; padding:20pt;"/> | ||
15 | </td> | ||
16 | </tr> | ||
17 | <tr class="encrH"> | ||
18 | <td dir="ltr">End of encrypted message</td> | ||
19 | </tr> | ||
20 | </table> | ||
21 | </div> | ||
22 | </div> | ||
23 | </body> | ||
24 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox.tree new file mode 100644 index 00000000..82f705c2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-encrypted.mbox.tree | |||
@@ -0,0 +1,4 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::TextMessagePart | ||
4 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-enc+sign.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-enc+sign.mbox new file mode 100644 index 00000000..be75c1e2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-enc+sign.mbox | |||
@@ -0,0 +1,37 @@ | |||
1 | From test@example.com Fri Sep 11 10:18:48 2015 | ||
2 | From: test <test@example.com> | ||
3 | To: you@you.com | ||
4 | Subject: enc+sign | ||
5 | Date: Fri, 11 Sep 2015 12:18:48 +0200 | ||
6 | Message-ID: <49743203.WFa6qKaG4S@tabin.local> | ||
7 | X-KMail-Identity: 792434561 | ||
8 | User-Agent: KMail/4.13.0.1 (Linux/4.1.5-towo.1-siduction-amd64; KDE/4.14.2; x86_64; ; ) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type="enveloped-data" | ||
11 | Content-Transfer-Encoding: base64 | ||
12 | Content-Disposition: attachment; filename="smime.p7m" | ||
13 | |||
14 | MIAGCSqGSIb3DQEHA6CAMIACAQAxgfwwgfkCAQAwYjBVMQswCQYDVQQGEwJVUzENMAsGA1UECgwE | ||
15 | S0RBQjEWMBQGA1UEAwwNdW5pdHRlc3QgY2VydDEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxl | ||
16 | LmNvbQIJANNFIDoYY4XJMA0GCSqGSIb3DQEBAQUABIGAkttyRl8OyZkRGfs3CMfzYchrG4rRMfbE | ||
17 | WIkAFIXf64yAzPZfo6cCn0Il/6q4793FeKUrsJUvzP21KBLp4u1t5qLL5iPAmAzBdLg0teoEzLZe | ||
18 | CEZHinM+WSMdz2wEV8lgAt8x/3yhXmDMB09FEapUaBCK5NhbLAFkpI2mFg66zxcwgAYJKoZIhvcN | ||
19 | AQcBMB0GCWCGSAFlAwQBAgQQ6DSjjkXJNm5cXQNek9eozqCABIIDsI7lufqw58g/uVM2gymkldmb | ||
20 | BOgdimxshJkYznbbG5sfQPNM9ROhXKRUOc8hfzgmZ9dOZvtAyzepROMHrcL1mFFx7c1vgyT85fai | ||
21 | PLEqRs8FRoztXJ0I3q57r+sPW4BtYJp9WCBSerdLSrBFK1zvKpVQtSCYbbDCc3462KnSsBrE4XTf | ||
22 | BiiLWkpok4fNIdqYG1aWPLgRbp7wwLiXcq5RxYCail1tlyAty6dWBrYE1+ABZoqnKUqNqbghxJUd | ||
23 | X9t3EziUnzw7c0Hq03sJEShzbXI9BxOTs8ZZ+1Ktx3rdh6RhZZ7XfJ7XIuN0yYhusBeOgC8AuILN | ||
24 | lYojgmXMin52VPFmz9siI8jnKaqsr1uUqVfMLNc+mLhZEjuOu99eAHwdJUS95BKWm9J8DBe/lpz3 | ||
25 | s09Oz2oOoiQx0WxKmQZ4GXW/UI9OwykfNLqWfmDrbMbGW4Mvq615ucHZixFdp2vf3kU72wfk8hFK | ||
26 | EIU/1Ov85glDj96ELdXErXn02BNvVBQIsRx3DbBGEgj9tz+WHbCR6RjEK4eV5lhInZplFGmYr4Uu | ||
27 | 9ALS+MRGTYZnALNPrWu6b1aWprnlJCyKZeeyqUzpQVPoWOh7CfdvBxvQoil4Z9Neb9O0AGCZ0axc | ||
28 | zZ4yYcS/LpHkLgYPC5BphNtpyciQh6ZFeexi8rsZuHRu+YUKnuM+DQyUxtUvDYhiX7CT49MMXIwt | ||
29 | bdyA0IAbIXXb/Us9GGX11gAfz2EFI3QBDHtsyciEgCIlA32OiiJF0T5CnQsku2yu6c3TWC4k+feL | ||
30 | jjTEhm/KPUL6SkksarFeEncJlVt7impW9FlHyBpISwlQF4RAxDYTRX475VTNu7wn3PQx376m8iBN | ||
31 | K20MjdfIM162jcQh9IWnqTZ0nH/gT2kQPYe7GqjFi6XmU3bwdzW9SXR0G9A8juIXaaNR7aXcsB53 | ||
32 | /W4WHPcdJBwRELa0dT1/bPg8z3EV2vM7Flc/Q5ugTWHxk8GHNEPpotArpLq1sEAZu78mSCqzzEDA | ||
33 | TwzEpj9LZYIv4rDYYLCAxUR9YGhiJ5Qm21YnklkE++4zfpsl/KJcwtNsp7SWdzeVuPoUYBNhsgp/ | ||
34 | PZgudzQoOhxcF4ChHMVSNk1f1tlvXZppeXwv9OwpSszz0zZUr46ievpkQwL0Sa1XAfKwAt7bFJwp | ||
35 | i95ae7p58ZdizJVsz0QUhFDxIDL76qiPEYXC7nIf4ZPQ36dzLAfZ6OwWGffluxHpE6oqUoM3l320 | ||
36 | 7yQT66xfRKLGl5Cr1Q8UBBABC6aR2dt6RVbsxbR3mB0PAAAAAAAAAAAAAA== | ||
37 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-enc+sign.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-enc+sign.mbox.html new file mode 100644 index 00000000..7f60c04f --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-enc+sign.mbox.html | |||
@@ -0,0 +1,57 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@example.com">test@example.com</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <div style="position: relative; word-wrap: break-word"> | ||
33 | <a name="att"/> | ||
34 | <div id="attachmentDiv"> | ||
35 | <div class="noquote"> | ||
36 | <div dir="ltr">Encrypted and signed mail.</div> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </td> | ||
41 | </tr> | ||
42 | <tr class="signOkKeyOkH"> | ||
43 | <td dir="ltr">End of signed message</td> | ||
44 | </tr> | ||
45 | </table> | ||
46 | </div> | ||
47 | </div> | ||
48 | </td> | ||
49 | </tr> | ||
50 | <tr class="encrH"> | ||
51 | <td dir="ltr">End of encrypted message</td> | ||
52 | </tr> | ||
53 | </table> | ||
54 | </div> | ||
55 | </div> | ||
56 | </body> | ||
57 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-enc+sign.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-enc+sign.mbox.tree new file mode 100644 index 00000000..7d5bbeb7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-enc+sign.mbox.tree | |||
@@ -0,0 +1,5 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::SignedMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox new file mode 100644 index 00000000..6e1739ac --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox | |||
@@ -0,0 +1,25 @@ | |||
1 | From test@example.com Fri Sep 11 10:16:06 2015 | ||
2 | From: test <test@example.com> | ||
3 | To: you@you.com | ||
4 | Subject: sign only | ||
5 | Date: Fri, 11 Sep 2015 12:16:06 +0200 | ||
6 | Message-ID: <3182420.pXWeMPZlAJ@tabin.local> | ||
7 | X-KMail-Identity: 792434561 | ||
8 | User-Agent: KMail/4.13.0.1 (Linux/4.1.5-towo.1-siduction-amd64; KDE/4.14.2; x86_64; ; ) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type="signed-data" | ||
11 | Content-Transfer-Encoding: base64 | ||
12 | Content-Disposition: attachment; filename="smime.p7m" | ||
13 | |||
14 | MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEZUNvbnRl | ||
15 | bnQtVHJhbnNmZXItRW5jb2Rpbmc6IDdCaXQKQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFy | ||
16 | c2V0PSJ1dGYtOCIKCkEgc2ltcGxlIHNpZ25lZCBvbmx5IHRlc3QuAAAAAAAAMYIBkjCCAY4CAQEw | ||
17 | YjBVMQswCQYDVQQGEwJVUzENMAsGA1UECgwES0RBQjEWMBQGA1UEAwwNdW5pdHRlc3QgY2VydDEf | ||
18 | MB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbQIJANNFIDoYY4XJMAkGBSsOAwIaBQCggYcw | ||
19 | GAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTMwMTEwMTU0ODEyWjAj | ||
20 | BgkqhkiG9w0BCQQxFgQUvJ5zI7oyv5fNx1H1wabIa6atsdcwKAYJKoZIhvcNAQkPMRswGTALBglg | ||
21 | hkgBZQMEAQIwCgYIKoZIhvcNAwcwDQYJKoZIhvcNAQEBBQAEgYAHFCw88FPy1n2lu5ql5sD2J4Yi | ||
22 | 2/N9gUQvNQF5F/kd48HncdihLPZRs7eEX7IzDZNeylTmyp2WIiGEwQrIHbxtqU32NRouc09Zv4bu | ||
23 | iUwUoz1SM2s7qipikwayQMD3d5zWNhszNLBsw8z48uXAzjZAejBCfPP0/w3z7DZDJC2R2QAAAAAA | ||
24 | AA== | ||
25 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox.html new file mode 100644 index 00000000..6088bc72 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox.html | |||
@@ -0,0 +1,40 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
9 | <tr class="signOkKeyOkH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Signed by <a href="mailto:test@example.com">test@example.com</a>.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signOkKeyOkB"> | ||
22 | <td> | ||
23 | <div style="position: relative; word-wrap: break-word"> | ||
24 | <a name="att"/> | ||
25 | <div id="attachmentDiv"> | ||
26 | <div class="noquote"> | ||
27 | <div dir="ltr">A simple signed only test.</div> | ||
28 | </div> | ||
29 | </div> | ||
30 | </div> | ||
31 | </td> | ||
32 | </tr> | ||
33 | <tr class="signOkKeyOkH"> | ||
34 | <td dir="ltr">End of signed message</td> | ||
35 | </tr> | ||
36 | </table> | ||
37 | </div> | ||
38 | </div> | ||
39 | </body> | ||
40 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox.inProgress.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox.inProgress.html new file mode 100644 index 00000000..45a999d3 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox.inProgress.html | |||
@@ -0,0 +1,22 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signInProgress"> | ||
9 | <tr class="signInProgressH"> | ||
10 | <td dir="ltr">Please wait while the signature is being verified...</td> | ||
11 | </tr> | ||
12 | <tr class="signInProgressB"> | ||
13 | <td/> | ||
14 | </tr> | ||
15 | <tr class="signInProgressH"> | ||
16 | <td dir="ltr">End of signed message</td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </div> | ||
20 | </div> | ||
21 | </body> | ||
22 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox.tree new file mode 100644 index 00000000..a469bb76 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-sign.mbox.tree | |||
@@ -0,0 +1,4 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::SignedMessagePart | ||
3 | * MimeTreeParser::TextMessagePart | ||
4 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-signed-encrypted-attachment.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-signed-encrypted-attachment.mbox new file mode 100644 index 00000000..2b1a0761 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-opaque-signed-encrypted-attachment.mbox | |||
@@ -0,0 +1,50 @@ | |||
1 | From test@example.com Thu Jun 09 12:52:44 2016 | ||
2 | From: test@example.com | ||
3 | To: test@example.com | ||
4 | Subject: Opaque S/MIME signed and encrypted message with attachment | ||
5 | Date: Thu, 09 Jun 2016 14:52:44 +0200 | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type="enveloped-data" | ||
8 | Content-Transfer-Encoding: base64 | ||
9 | Content-Disposition: attachment; filename="smime.p7m" | ||
10 | |||
11 | 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 | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox new file mode 100644 index 00000000..d5cd06f1 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox | |||
@@ -0,0 +1,197 @@ | |||
1 | From: Quack <quack@example.org> | ||
2 | Content-Type: multipart/signed; boundary="Apple-Mail=_607FF8D2-30E0-4FC3-86D9-1234567890AB"; protocol="application/pkcs7-signature"; micalg=sha1 | ||
3 | Message-Id: <468684BD-9CBD-48CF-B1BD-2824000F9541@example.org> | ||
4 | Mime-Version: 1.0 (Mac OS X Mail 9.3 \(3124\)) | ||
5 | Subject: Re: PDF bug - modified mail, signature is not valid! | ||
6 | Date: Fri, 20 Jan 2017 11:51:41 +0100 | ||
7 | To: Konqui <Konqui@kdab.com> | ||
8 | |||
9 | |||
10 | --Apple-Mail=_607FF8D2-30E0-4FC3-86D9-1234567890AB | ||
11 | Content-Type: multipart/alternative; | ||
12 | boundary="Apple-Mail=_C5F90221-8F52-4623-99DF-1234567890AB" | ||
13 | |||
14 | |||
15 | --Apple-Mail=_C5F90221-8F52-4623-99DF-1234567890AB | ||
16 | Content-Transfer-Encoding: quoted-printable | ||
17 | Content-Type: text/plain; | ||
18 | charset=utf-8 | ||
19 | |||
20 | Ol=C3=A1 Konqui, | ||
21 | |||
22 | Here is the pdf you asked for! | ||
23 | Cheers, | ||
24 | |||
25 | Quaak | ||
26 | |||
27 | =E2=80=A6 | ||
28 | Quack | UX/UI Designer | ||
29 | Klar=C3=A4lvdalens Datakonsult AB, a KDAB Group company | ||
30 | Sweden (HQ) +46-563-540090, Germany +49-30-521325470 | ||
31 | KDAB - The Qt, C++ and OpenGL Experts | www.kdab.com | ||
32 | |||
33 | |||
34 | --Apple-Mail=_C5F90221-8F52-4623-99DF-1234567890AB | ||
35 | Content-Type: multipart/mixed; | ||
36 | boundary="Apple-Mail=_1C4D1EDB-36C5-40D7-9AB6-1234567890AB" | ||
37 | |||
38 | |||
39 | --Apple-Mail=_1C4D1EDB-36C5-40D7-9AB6-1234567890AB | ||
40 | Content-Transfer-Encoding: quoted-printable | ||
41 | Content-Type: text/html; | ||
42 | charset=utf-8 | ||
43 | |||
44 | <html><head><meta http-equiv=3D"Content-Type" content=3D"text/html = | ||
45 | charset=3Dutf-8"></head><body style=3D"word-wrap: break-word; = | ||
46 | -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" = | ||
47 | class=3D"">Ol=C3=A1 Konqui,</div><div = | ||
48 | class=3D"">Here is the pdf you asked for!</div><div = | ||
49 | class=3D"">Cheers,</div><div = | ||
50 | class=3D"">Quaack</div></body></html>= | ||
51 | |||
52 | --Apple-Mail=_1C4D1EDB-36C5-40D7-9AB6-1234567890AB | ||
53 | Content-Disposition: attachment; filename="image.png" | ||
54 | Content-Transfer-Encoding: base64 | ||
55 | Content-Type: image/png; name="image.png" | ||
56 | |||
57 | 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 | ||
100 | o/0d59+Lh3Y1HHcAAAAASUVORK5CYII= | ||
101 | --Apple-Mail=_1C4D1EDB-36C5-40D7-9AB6-1234567890AB | ||
102 | Content-Transfer-Encoding: quoted-printable | ||
103 | Content-Type: text/html; | ||
104 | charset=utf-8 | ||
105 | |||
106 | <html><head><meta http-equiv=3D"Content-Type" content=3D"text/html = | ||
107 | charset=3Dutf-8"></head><body>= | ||
108 | <blockquote type=3D"cite" class=3D""><div = | ||
109 | class=3D"">On 20 Jan 2017, at 10:35, Konqui <<a = | ||
110 | href=3D"mailto:Konqui@kdab.com">Konqui</a>= | ||
111 | </div> | ||
112 | </blockquote>= | ||
113 | </body></html>= | ||
114 | |||
115 | --Apple-Mail=_1C4D1EDB-36C5-40D7-9AB6-1234567890AB-- | ||
116 | |||
117 | --Apple-Mail=_C5F90221-8F52-4623-99DF-1234567890AB-- | ||
118 | |||
119 | --Apple-Mail=_607FF8D2-30E0-4FC3-86D9-1234567890AB | ||
120 | Content-Disposition: attachment; | ||
121 | filename=smime.p7s | ||
122 | Content-Type: application/pkcs7-signature; | ||
123 | name=smime.p7s | ||
124 | Content-Transfer-Encoding: base64 | ||
125 | |||
126 | MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIILdTCCBRow | ||
127 | ggQCoAMCAQICEG0Z6qcZT2ozIuYiMnqqcd4wDQYJKoZIhvcNAQEFBQAwga4xCzAJBgNVBAYTAlVT | ||
128 | MQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAcBgNVBAoTFVRoZSBVU0VS | ||
129 | VFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3dy51c2VydHJ1c3QuY29tMTYwNAYDVQQD | ||
130 | Ey1VVE4tVVNFUkZpcnN0LUNsaWVudCBBdXRoZW50aWNhdGlvbiBhbmQgRW1haWwwHhcNMTEwNDI4 | ||
131 | MDAwMDAwWhcNMjAwNTMwMTA0ODM4WjCBkzELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIg | ||
132 | TWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQx | ||
133 | OTA3BgNVBAMTMENPTU9ETyBDbGllbnQgQXV0aGVudGljYXRpb24gYW5kIFNlY3VyZSBFbWFpbCBD | ||
134 | QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJKEhFtLV5jUXi+LpOFAyKNTWF9mZfEy | ||
135 | TvefMn1V0HhMVbdClOD5J3EHxcZppLkyxPFAGpDMJ1Zifxe1cWmu5SAb5MtjXmDKokH2auGj/7jf | ||
136 | H0htZUOMKi4rYzh337EXrMLaggLW1DJq1GdvIBOPXDX65VSAr9hxCh03CgJQU2yVHakQFLSZlVkS | ||
137 | Mf8JotJM3FLb3uJAAVtIaN3FSrTg7SQfOq9xXwfjrL8UO7AlcWg99A/WF1hGFYE8aIuLgw9teiFX | ||
138 | 5jSw2zJ+40rhpVJyZCaRTqWSD//gsWD9Gm9oUZljjRqLpcxCm5t9ImPTqaD8zp6Q30QZ9FxbNboW | ||
139 | 86eb/8ECAwEAAaOCAUswggFHMB8GA1UdIwQYMBaAFImCZ33EnSZwAEu0UEh83j2uBG59MB0GA1Ud | ||
140 | DgQWBBR6E04AdFvGeGNkJ8Ev4qBbvHnFezAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB | ||
141 | /wIBADARBgNVHSAECjAIMAYGBFUdIAAwWAYDVR0fBFEwTzBNoEugSYZHaHR0cDovL2NybC51c2Vy | ||
142 | dHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtQ2xpZW50QXV0aGVudGljYXRpb25hbmRFbWFpbC5jcmww | ||
143 | dAYIKwYBBQUHAQEEaDBmMD0GCCsGAQUFBzAChjFodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVRO | ||
144 | QWRkVHJ1c3RDbGllbnRfQ0EuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3Qu | ||
145 | Y29tMA0GCSqGSIb3DQEBBQUAA4IBAQCF1r54V1VtM39EUv5C1QaoAQOAivsNsv1Kv/avQUn1G1rF | ||
146 | 0q0bc24+6SZ85kyYwTAo38v7QjyhJT4KddbQPTmGZtGhm7VNm2+vKGwdr+XqdFqo2rHA8XV6L566 | ||
147 | k3nK/uKRHlZ0sviN0+BDchvtj/1gOSBH+4uvOmVIPJg9pSW/ve9g4EnlFsjrP0OD8ODuDcHTzTNf | ||
148 | m9C9YGqzO/761Mk6PB/tm/+bSTO+Qik5g+4zaS6CnUVNqGnagBsePdIaXXxHmaWbCG0SmYbWXVcH | ||
149 | G6cwvktJRLiQfsrReTjrtDP6oDpdJlieYVUYtCHVmdXgQ0BCML7qpeeU0rD+83X5f27nMIIGUzCC | ||
150 | BTugAwIBAgIQMFPel8s+Gckd6L+iGIwbpTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UEBhMCR0Ix | ||
151 | GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR | ||
152 | Q09NT0RPIENBIExpbWl0ZWQxOTA3BgNVBAMTMENPTU9ETyBDbGllbnQgQXV0aGVudGljYXRpb24g | ||
153 | YW5kIFNlY3VyZSBFbWFpbCBDQTAeFw0xNDA2MDIwMDAwMDBaFw0xNzA2MDEyMzU5NTlaMIIBXzEL | ||
154 | MAkGA1UEBhMCU0UxDzANBgNVBBETBjY4MyAzMTESMBAGA1UECBMJVmFlcm1sYW5kMRAwDgYDVQQH | ||
155 | EwdIYWdmb3JzMRgwFgYDVQQJEw9Ob3JyaW5ncyB2YWVnIDIxDzANBgNVBBITBkJveCAzMDEmMCQG | ||
156 | A1UECgwdS2xhcsOkbHZkYWxlbnMgRGF0YWtvbnN1bHQgQUIxHTAbBgNVBAsTFEEgS0RBQiBHcm91 | ||
157 | cCBDb21wYW55MUMwQQYDVQQLDDpJc3N1ZWQgdGhyb3VnaCBLbGFyw6RsdmRhbGVucyBEYXRha29u | ||
158 | c3VsdCBBQiBFLVBLSSBNYW5hZ2VyMR8wHQYDVQQLExZDb3Jwb3JhdGUgU2VjdXJlIEVtYWlsMRgw | ||
159 | FgYDVQQDEw9EaWFuYSBHb25jYWx2ZXMxJzAlBgkqhkiG9w0BCQEWGGRpYW5hLmdvbmNhbHZlc0Br | ||
160 | ZGFiLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALrHSvWD6MR2tvF9A+wayTDg | ||
161 | PvK3DahuvHWHzGQsd1p8bEh6qqupqgph2xO73P+ibM6EmNbCtZ+eQtW7l7iIyiC4IGsyEb5RSAtV | ||
162 | zGAyebsO7SPHokbGIV5SVobaRQiJ+1gOvWUbqHSQ0T9ZPvMX2nNGIKZpqAfocRreZr36AZWRo4AF | ||
163 | 0uf6wz5aLEtq912u2rTWVsM1F966lexaepo0cZB9fdnnD8/pQX3zroj+vBTFNAkZXxxVwGMO24Pz | ||
164 | 92d/B6K8o1SP1ArqV4sxVYIxyQTmfW4X3iV/6bcbLfEcpcUNt6MUsjFulqr6a+j51alpyT3vNuJ9 | ||
165 | V1UI9jz3t/daQr0CAwEAAaOCAdIwggHOMB8GA1UdIwQYMBaAFHoTTgB0W8Z4Y2QnwS/ioFu8ecV7 | ||
166 | MB0GA1UdDgQWBBRIYj+FxAEGllaHmLL+EMhopIEOQjAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/ | ||
167 | BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDBAYIKwYBBQUHAwIwRgYDVR0gBD8wPTA7BgwrBgEEAbIx | ||
168 | AQIBAwUwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLm5ldC9DUFMwVwYDVR0f | ||
169 | BFAwTjBMoEqgSIZGaHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPQ2xpZW50QXV0aGVudGlj | ||
170 | YXRpb25hbmRTZWN1cmVFbWFpbENBLmNybDCBiAYIKwYBBQUHAQEEfDB6MFIGCCsGAQUFBzAChkZo | ||
171 | dHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9DbGllbnRBdXRoZW50aWNhdGlvbmFuZFNlY3Vy | ||
172 | ZUVtYWlsQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wIwYDVR0R | ||
173 | BBwwGoEYZGlhbmEuZ29uY2FsdmVzQGtkYWIuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQACzCCZ4ppg | ||
174 | H7nXnCwisxjGLIgQMdwKPB6lnWk39YT0gEqvn85tDaXIZwGiRda7O1HWdWh7RoncolX3yHQ6p/BJ | ||
175 | 8RWkpxoc4es1wXSPmWMpspnglvtqYlfu7NZ/CqI6bvgqoy0w3KSv+GnVkiQ6SVKU4fV6itr5VG9q | ||
176 | X0JYXAbKO8hOIP3NO3MVacPgzSIv83B9eLpfi/BlG6q6XKxVf4581lYbLL0F7cKQt1UYPiDsmPJG | ||
177 | +5SEHT6ZOBiLgqQVhAw4Di+6wymUHONBRuH2bH3cjfFlkCCjiFF/cS7Oharro2RFnWQ6beZ3EzCG | ||
178 | FJILmq/dVMGsBFWme23hLYwtLJSXMYIDqzCCA6cCAQEwgagwgZMxCzAJBgNVBAYTAkdCMRswGQYD | ||
179 | VQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9E | ||
180 | TyBDQSBMaW1pdGVkMTkwNwYDVQQDEzBDT01PRE8gQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBT | ||
181 | ZWN1cmUgRW1haWwgQ0ECEDBT3pfLPhnJHei/ohiMG6UwCQYFKw4DAhoFAKCCAdcwGAYJKoZIhvcN | ||
182 | AQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTcwMTIwMTA1MTQxWjAjBgkqhkiG9w0B | ||
183 | CQQxFgQU/AV0Tj17RqaDDCeGXWhe4epgX6gwgbkGCSsGAQQBgjcQBDGBqzCBqDCBkzELMAkGA1UE | ||
184 | BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG | ||
185 | A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxOTA3BgNVBAMTMENPTU9ETyBDbGllbnQgQXV0aGVudGlj | ||
186 | YXRpb24gYW5kIFNlY3VyZSBFbWFpbCBDQQIQMFPel8s+Gckd6L+iGIwbpTCBuwYLKoZIhvcNAQkQ | ||
187 | AgsxgauggagwgZMxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO | ||
188 | BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTkwNwYDVQQDEzBDT01P | ||
189 | RE8gQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBTZWN1cmUgRW1haWwgQ0ECEDBT3pfLPhnJHei/ | ||
190 | ohiMG6UwDQYJKoZIhvcNAQEBBQAEggEAEIfTyPoqjyJwrpYmZWRF6OY5ZCFdpw1UUfSXYUU2IdbL | ||
191 | ph8QkMCc9uv5wk2IeE/9UxxvUR44J67Bu8hv/PCaeyMSh1j2peOlFG487SwyTjf5wIL+GEs8zvHo | ||
192 | 4+Dd2IPhAExt1Bjhmt6O7caF9LVrGQ/wlI6ZGN8MgjSgdrK4F3Ig4LbMuyTTcy3hDTvb+qzaQ4YI | ||
193 | E+F4tnwhXG8FGEBnlng6nB4iXhoWSvBsjc1qF6eHEHzsOIZeNL7K6Imn7oKHJg+THGwHxC1TZGFt | ||
194 | G92u6zV7Sc/i4ENH2MNzXT75mp8Gq/k6gpRz9nw8UVuLN/rDIb6esnEgVH9ad3awD154HAAAAAAA | ||
195 | AA== | ||
196 | --Apple-Mail=_607FF8D2-30E0-4FC3-86D9-1234567890AB-- | ||
197 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox.html new file mode 100644 index 00000000..11652a14 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox.html | |||
@@ -0,0 +1,58 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signErr"> | ||
9 | <tr class="signErrH"> | ||
10 | <td dir="ltr"> | ||
11 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
12 | <tr> | ||
13 | <td>Invalid signature.</td> | ||
14 | <td align="right"> | ||
15 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
16 | </td> | ||
17 | </tr> | ||
18 | </table> | ||
19 | </td> | ||
20 | </tr> | ||
21 | <tr class="signErrB"> | ||
22 | <td> | ||
23 | <a name="att1"/> | ||
24 | <div id="attachmentDiv1"> | ||
25 | <a name="att1.2"/> | ||
26 | <div id="attachmentDiv1.2"> | ||
27 | <a name="att1.2.1"/> | ||
28 | <div id="attachmentDiv1.2.1"> | ||
29 | <div style="position: relative">Olá Konqui,<div class="">Here is the pdf you asked for!</div><div class="">Cheers,</div><div class="">Quaack</div></div> | ||
30 | </div> | ||
31 | <a name="att1.2.2"/> | ||
32 | <div id="attachmentDiv1.2.2"> | ||
33 | <hr/> | ||
34 | <div> | ||
35 | <a href="attachment:1.2.2?place=body"><img align="center" height="48" width="48" src="file:image-png.svg" border="0" style="max-width: 100%" alt=""/>image.png</a> | ||
36 | </div> | ||
37 | <div/> | ||
38 | </div> | ||
39 | <a name="att1.2.3"/> | ||
40 | <div id="attachmentDiv1.2.3"> | ||
41 | <div style="position: relative"> | ||
42 | <blockquote type="cite" class=""> | ||
43 | <div class="">On 20 Jan 2017, at 10:35, Konqui <<a href="mailto:Konqui@kdab.com">Konqui</a></div> | ||
44 | </blockquote> | ||
45 | </div> | ||
46 | </div> | ||
47 | </div> | ||
48 | </div> | ||
49 | </td> | ||
50 | </tr> | ||
51 | <tr class="signErrH"> | ||
52 | <td dir="ltr">End of signed message</td> | ||
53 | </tr> | ||
54 | </table> | ||
55 | </div> | ||
56 | </div> | ||
57 | </body> | ||
58 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox.inProgress.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox.inProgress.html new file mode 100644 index 00000000..5b57b937 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox.inProgress.html | |||
@@ -0,0 +1,49 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="signInProgress"> | ||
9 | <tr class="signInProgressH"> | ||
10 | <td dir="ltr">Please wait while the signature is being verified...</td> | ||
11 | </tr> | ||
12 | <tr class="signInProgressB"> | ||
13 | <td> | ||
14 | <a name="att1"/> | ||
15 | <div id="attachmentDiv1"> | ||
16 | <a name="att1.2"/> | ||
17 | <div id="attachmentDiv1.2"> | ||
18 | <a name="att1.2.1"/> | ||
19 | <div id="attachmentDiv1.2.1"> | ||
20 | <div style="position: relative">Olá Konqui,<div class="">Here is the pdf you asked for!</div><div class="">Cheers,</div><div class="">Quaack</div></div> | ||
21 | </div> | ||
22 | <a name="att1.2.2"/> | ||
23 | <div id="attachmentDiv1.2.2"> | ||
24 | <hr/> | ||
25 | <div> | ||
26 | <a href="attachment:1.2.2?place=body"><img align="center" height="48" width="48" src="file:image-png.svg" border="0" style="max-width: 100%" alt=""/>image.png</a> | ||
27 | </div> | ||
28 | <div/> | ||
29 | </div> | ||
30 | <a name="att1.2.3"/> | ||
31 | <div id="attachmentDiv1.2.3"> | ||
32 | <div style="position: relative"> | ||
33 | <blockquote type="cite" class=""> | ||
34 | <div class="">On 20 Jan 2017, at 10:35, Konqui <<a href="mailto:Konqui@kdab.com">Konqui</a></div> | ||
35 | </blockquote> | ||
36 | </div> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </td> | ||
41 | </tr> | ||
42 | <tr class="signInProgressH"> | ||
43 | <td dir="ltr">End of signed message</td> | ||
44 | </tr> | ||
45 | </table> | ||
46 | </div> | ||
47 | </div> | ||
48 | </body> | ||
49 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox.tree new file mode 100644 index 00000000..3ade4efe --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-apple.mbox.tree | |||
@@ -0,0 +1,3 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::SignedMessagePart | ||
3 | * MimeTreeParser::AlternativeMessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-encrypted.mbox new file mode 100644 index 00000000..49857e15 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-encrypted.mbox | |||
@@ -0,0 +1,38 @@ | |||
1 | From test@example.com Wed, 08 Sep 2010 17:51:32 +0200 | ||
2 | From: S/MIME Test <test@example.com> | ||
3 | To: test@example.com | ||
4 | Subject: S/MIME signed and encrypted | ||
5 | Date: Wed, 08 Sep 2010 17:51:32 +0200 | ||
6 | User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) | ||
7 | MIME-Version: 1.0 | ||
8 | Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type="enveloped-data" | ||
9 | Content-Disposition: attachment; filename="smime.p7m" | ||
10 | Content-Transfer-Encoding: base64 | ||
11 | |||
12 | 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 | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-encrypted.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-encrypted.mbox.html new file mode 100644 index 00000000..e13d6841 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-encrypted.mbox.html | |||
@@ -0,0 +1,55 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <table cellspacing="1" cellpadding="1" class="encr"> | ||
9 | <tr class="encrH"> | ||
10 | <td dir="ltr">Encrypted message</td> | ||
11 | </tr> | ||
12 | <tr class="encrB"> | ||
13 | <td> | ||
14 | <div style="position: relative; word-wrap: break-word"> | ||
15 | <a name="att"/> | ||
16 | <div id="attachmentDiv"> | ||
17 | <table cellspacing="1" cellpadding="1" class="signOkKeyOk"> | ||
18 | <tr class="signOkKeyOkH"> | ||
19 | <td dir="ltr"> | ||
20 | <table cellspacing="0" cellpadding="0" width="100%"> | ||
21 | <tr> | ||
22 | <td>Signed by <a href="mailto:test@example.com">test@example.com</a>.</td> | ||
23 | <td align="right"> | ||
24 | <a href="kmail:showSignatureDetails">Show Details</a> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </td> | ||
29 | </tr> | ||
30 | <tr class="signOkKeyOkB"> | ||
31 | <td> | ||
32 | <a name="att1"/> | ||
33 | <div id="attachmentDiv1"> | ||
34 | <div class="noquote"> | ||
35 | <div dir="ltr">encrypted message text</div> | ||
36 | </div> | ||
37 | </div> | ||
38 | </td> | ||
39 | </tr> | ||
40 | <tr class="signOkKeyOkH"> | ||
41 | <td dir="ltr">End of signed message</td> | ||
42 | </tr> | ||
43 | </table> | ||
44 | </div> | ||
45 | </div> | ||
46 | </td> | ||
47 | </tr> | ||
48 | <tr class="encrH"> | ||
49 | <td dir="ltr">End of encrypted message</td> | ||
50 | </tr> | ||
51 | </table> | ||
52 | </div> | ||
53 | </div> | ||
54 | </body> | ||
55 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-encrypted.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-encrypted.mbox.tree new file mode 100644 index 00000000..7d5bbeb7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/smime-signed-encrypted.mbox.tree | |||
@@ -0,0 +1,5 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::EncryptedMessagePart | ||
3 | * MimeTreeParser::SignedMessagePart | ||
4 | * MimeTreeParser::TextMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/text+html-maillinglist.mbox b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/text+html-maillinglist.mbox new file mode 100644 index 00000000..f9c6387f --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/text+html-maillinglist.mbox | |||
@@ -0,0 +1,163 @@ | |||
1 | Return-Path: <bugzilla-bounces@lists.kolabsys.com> | ||
2 | Received: from kolab01.kolabsys.com ([unix socket]) | ||
3 | by kolab01.kolabsys.com (Cyrus v2.4.17-Kolab-2.4.17-1.el6.kolab_3.0) with LMTPA; | ||
4 | Thu, 11 Apr 2013 09:03:01 +0200 | ||
5 | X-Sieve: CMU Sieve 2.4 | ||
6 | Received: from ext-mx01.kolabsys.com (unknown [10.10.20.253]) | ||
7 | by kolab01.kolabsys.com (Postfix) with ESMTP id 3D8A9C0AE3 | ||
8 | for <shared+shared/lists/kolabsys.com/bugzilla@kolabsys.com>; Thu, 11 Apr 2013 09:03:01 +0200 (CEST) | ||
9 | Received: from localhost (localhost [127.0.0.1]) | ||
10 | by ext-mx01.kolabsys.com (Postfix) with ESMTP id 89D4E10057E | ||
11 | for <shared+shared/lists/kolabsys.com/bugzilla@kolabsys.com>; Thu, 11 Apr 2013 09:02:38 +0200 (CEST) | ||
12 | X-Virus-Scanned: amavisd-new at example.com | ||
13 | X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "MIME-Version" | ||
14 | Received: from ext-mx01.kolabsys.com ([127.0.0.1]) | ||
15 | by localhost (fw01.kolabsys.com [127.0.0.1]) (amavisd-new, port 10024) | ||
16 | with ESMTP id BJxrh9Yst1Ac | ||
17 | for <shared+shared/lists/kolabsys.com/bugzilla@kolabsys.com>; | ||
18 | Thu, 11 Apr 2013 09:02:38 +0200 (CEST) | ||
19 | Received: from lists.kolabsys.com (static.253.32.46.78.clients.your-server.de [78.46.32.253]) | ||
20 | by ext-mx01.kolabsys.com (Postfix) with ESMTP id 609821004A7 | ||
21 | for <shared+shared/lists/kolabsys.com/bugzilla@kolabsys.com>; Thu, 11 Apr 2013 09:02:38 +0200 (CEST) | ||
22 | Received: from localhost (localhost [127.0.0.1]) | ||
23 | by lists.kolabsys.com (Postfix) with ESMTP id BFA6941D4EAD; | ||
24 | Thu, 11 Apr 2013 09:03:00 +0200 (CEST) | ||
25 | X-Virus-Scanned: Debian amavisd-new at lists.kolabsys.com | ||
26 | X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "MIME-Version" | ||
27 | Received: from lists.kolabsys.com ([127.0.0.1]) | ||
28 | by localhost (lists.kolabsys.com [127.0.0.1]) (amavisd-new, port 10024) | ||
29 | with ESMTP id TYU5eAMK5J6T; Thu, 11 Apr 2013 09:02:58 +0200 (CEST) | ||
30 | Received: from lists.kolabsys.com (localhost [127.0.0.1]) | ||
31 | by lists.kolabsys.com (Postfix) with ESMTP id 182FC41D2A3B; | ||
32 | Thu, 11 Apr 2013 09:02:58 +0200 (CEST) | ||
33 | Received: from localhost (localhost [127.0.0.1]) | ||
34 | by lists.kolabsys.com (Postfix) with ESMTP id A2B3641D4EC2 | ||
35 | for <bugzilla@lists.kolabsys.com>; | ||
36 | Thu, 11 Apr 2013 09:02:56 +0200 (CEST) | ||
37 | X-Virus-Scanned: Debian amavisd-new at lists.kolabsys.com | ||
38 | Received: from lists.kolabsys.com ([127.0.0.1]) | ||
39 | by localhost (lists.kolabsys.com [127.0.0.1]) (amavisd-new, port 10024) | ||
40 | with ESMTP id cyO-CNB3vFwu for <bugzilla@lists.kolabsys.com>; | ||
41 | Thu, 11 Apr 2013 09:02:54 +0200 (CEST) | ||
42 | Received: from ext-mx02.kolabsys.com (ext-mx02.kolabsys.com [94.230.208.222]) | ||
43 | by lists.kolabsys.com (Postfix) with ESMTP id 1640E41D2A3B | ||
44 | for <bugzilla@lists.kolabsys.com>; | ||
45 | Thu, 11 Apr 2013 09:02:54 +0200 (CEST) | ||
46 | Received: from localhost (localhost [127.0.0.1]) | ||
47 | by ext-mx01.kolabsys.com (Postfix) with ESMTP id 58CBC160522 | ||
48 | for <bugzilla@lists.kolabsys.com>; | ||
49 | Thu, 11 Apr 2013 10:02:44 +0200 (CEST) | ||
50 | X-Virus-Scanned: amavisd-new at example.com | ||
51 | Received: from ext-mx02.kolabsys.com ([127.0.0.1]) | ||
52 | by localhost (fw02.kolabsys.com [127.0.0.1]) (amavisd-new, port 10024) | ||
53 | with ESMTP id 4VjnHg6Y6jo7 for <bugzilla@lists.kolabsys.com>; | ||
54 | Thu, 11 Apr 2013 10:02:42 +0200 (CEST) | ||
55 | Received: from app04.kolabsys.com (unknown [10.10.20.16]) | ||
56 | by ext-mx02.kolabsys.com (Postfix) with ESMTP id 062DF160521 | ||
57 | for <bugzilla@lists.kolabsys.com>; | ||
58 | Thu, 11 Apr 2013 10:02:42 +0200 (CEST) | ||
59 | Received: by app04.kolabsys.com (Postfix, from userid 48) | ||
60 | id 8E7524048C; Thu, 11 Apr 2013 09:02:51 +0200 (CEST) | ||
61 | From: Kolab Bugzilla <noreply@kolab.org> | ||
62 | To: bugzilla@lists.kolabsys.com | ||
63 | Subject: [Bug 1741] Standard folder name configuration ignored on creating | ||
64 | new users | ||
65 | Date: Thu, 11 Apr 2013 07:02:43 +0000 | ||
66 | X-Bugzilla-Reason: GlobalWatcher | ||
67 | X-Bugzilla-Type: changed | ||
68 | X-Bugzilla-Watch-Reason: None | ||
69 | X-Bugzilla-Product: UCS | ||
70 | X-Bugzilla-Component: roundcube | ||
71 | X-Bugzilla-Keywords: | ||
72 | X-Bugzilla-Severity: normal | ||
73 | X-Bugzilla-Who: wickert@kolabsys.com | ||
74 | X-Bugzilla-Status: NEW | ||
75 | X-Bugzilla-Priority: P3 | ||
76 | X-Bugzilla-Assigned-To: machniak@kolabsys.com | ||
77 | X-Bugzilla-Target-Milestone: 3.1-next | ||
78 | X-Bugzilla-Changed-Fields: | ||
79 | Message-ID: <bug-1741-12-HOSaBe3Z8l@http.issues.kolab.org/> | ||
80 | In-Reply-To: <bug-1741-12@http.issues.kolab.org/> | ||
81 | References: <bug-1741-12@http.issues.kolab.org/> | ||
82 | X-Bugzilla-URL: http://issues.kolab.org/ | ||
83 | Auto-Submitted: auto-generated | ||
84 | MIME-Version: 1.0 | ||
85 | X-BeenThere: bugzilla@lists.kolabsys.com | ||
86 | X-Mailman-Version: 2.1.11 | ||
87 | Precedence: list | ||
88 | Reply-To: server-team@lists.kolabsys.com | ||
89 | List-Id: All Bugzilla email notifications <bugzilla.lists.kolabsys.com> | ||
90 | List-Unsubscribe: <https://lists.kolabsys.com/mailman/options/bugzilla>, | ||
91 | <mailto:bugzilla-request@lists.kolabsys.com?subject=unsubscribe> | ||
92 | List-Archive: <http://lists.kolabsys.com/pipermail/bugzilla> | ||
93 | List-Post: <mailto:bugzilla@lists.kolabsys.com> | ||
94 | List-Help: <mailto:bugzilla-request@lists.kolabsys.com?subject=help> | ||
95 | List-Subscribe: <https://lists.kolabsys.com/mailman/listinfo/bugzilla>, | ||
96 | <mailto:bugzilla-request@lists.kolabsys.com?subject=subscribe> | ||
97 | Content-Type: multipart/mixed; boundary="===============1778809852==" | ||
98 | Mime-version: 1.0 | ||
99 | Sender: bugzilla-bounces@lists.kolabsys.com | ||
100 | Errors-To: bugzilla-bounces@lists.kolabsys.com | ||
101 | |||
102 | |||
103 | --===============1778809852== | ||
104 | Content-Type: multipart/alternative; boundary="1365663771.ec4d382.10226"; charset="us-ascii" | ||
105 | |||
106 | |||
107 | --1365663771.ec4d382.10226 | ||
108 | Date: Thu, 11 Apr 2013 09:02:51 +0200 | ||
109 | MIME-Version: 1.0 | ||
110 | Content-Type: text/plain; charset="UTF-8" | ||
111 | |||
112 | https://issues.kolab.org/show_bug.cgi?id=1741 | ||
113 | |||
114 | --- Comment #4 from Christoph Wickert <wickert@kolabsys.com> --- | ||
115 | You can get everything you need on test93-18. | ||
116 | |||
117 | -- | ||
118 | You are receiving this mail because: | ||
119 | You are watching all bug changes. | ||
120 | |||
121 | --1365663771.ec4d382.10226 | ||
122 | Date: Thu, 11 Apr 2013 09:02:51 +0200 | ||
123 | MIME-Version: 1.0 | ||
124 | Content-Type: text/html; charset="UTF-8" | ||
125 | |||
126 | <html> | ||
127 | <head> | ||
128 | <base href="https://issues.kolab.org/" /> | ||
129 | </head> | ||
130 | <body> | ||
131 | <b><a class="bz_bug_link | ||
132 | bz_status_NEW " | ||
133 | title="NEW --- - Standard folder name configuration ignored on creating new users" | ||
134 | href="https://issues.kolab.org/show_bug.cgi?id=1741#c4">Comment # 4</a> | ||
135 | on <a class="bz_bug_link | ||
136 | bz_status_NEW " | ||
137 | title="NEW --- - Standard folder name configuration ignored on creating new users" | ||
138 | href="https://issues.kolab.org/show_bug.cgi?id=1741">bug 1741</a> | ||
139 | from <span class="vcard"><a class="email" href="mailto:wickert@kolabsys.com" title="Christoph Wickert <wickert@kolabsys.com>"> <span class="fn">Christoph Wickert</span></a> | ||
140 | </span></b> | ||
141 | <pre>You can get everything you need on test93-18.</pre> | ||
142 | <span>You are receiving this mail because:</span> | ||
143 | <ul> | ||
144 | <li>You are watching all bug changes.</li> | ||
145 | </ul> | ||
146 | </body> | ||
147 | </html> | ||
148 | |||
149 | --1365663771.ec4d382.10226-- | ||
150 | |||
151 | --===============1778809852== | ||
152 | Content-Type: text/plain; charset="us-ascii" | ||
153 | MIME-Version: 1.0 | ||
154 | Content-Transfer-Encoding: 7bit | ||
155 | Content-Disposition: inline | ||
156 | |||
157 | _______________________________________________ | ||
158 | bugzilla mailing list | ||
159 | bugzilla@lists.kolabsys.com | ||
160 | https://lists.kolabsys.com/mailman/listinfo/bugzilla | ||
161 | |||
162 | --===============1778809852==-- | ||
163 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/text+html-maillinglist.mbox.html b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/text+html-maillinglist.mbox.html new file mode 100644 index 00000000..2b5af631 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/text+html-maillinglist.mbox.html | |||
@@ -0,0 +1,38 @@ | |||
1 | <?xml version="1.0" encoding="UTF8"?> | ||
2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
3 | <html> | ||
4 | <body> | ||
5 | <div style="position: relative; word-wrap: break-word"> | ||
6 | <a name="att"/> | ||
7 | <div id="attachmentDiv"> | ||
8 | <a name="att1"/> | ||
9 | <div id="attachmentDiv1"> | ||
10 | <a name="att1.2"/> | ||
11 | <div id="attachmentDiv1.2"> | ||
12 | <div style="position: relative"> | ||
13 | <b><a class="bz_bug_link bz_status_NEW " title="NEW --- - Standard folder name configuration ignored on creating new users" href="https://issues.kolab.org/show_bug.cgi?id=1741#c4">Comment # 4</a>on <a class="bz_bug_link bz_status_NEW " title="NEW --- - Standard folder name configuration ignored on creating new users" href="https://issues.kolab.org/show_bug.cgi?id=1741">bug 1741</a>from <span class="vcard"><a class="email" href="mailto:wickert@kolabsys.com" title="Christoph Wickert <wickert@kolabsys.com>"><span class="fn">Christoph Wickert</span></a></span></b> | ||
14 | <pre>You can get everything you need on test93-18.</pre> | ||
15 | <span>You are receiving this mail because:</span> | ||
16 | <ul> | ||
17 | <li>You are watching all bug changes.</li> | ||
18 | </ul> | ||
19 | </div> | ||
20 | </div> | ||
21 | </div> | ||
22 | <a name="att2"/> | ||
23 | <div id="attachmentDiv2"> | ||
24 | <div class="noquote"> | ||
25 | <div dir="ltr">_______________________________________________</div> | ||
26 | <div dir="ltr">bugzilla mailing list</div> | ||
27 | <div dir="ltr"> | ||
28 | <a href="mailto:bugzilla@lists.kolabsys.com">bugzilla@lists.kolabsys.com</a> | ||
29 | </div> | ||
30 | <div dir="ltr"> | ||
31 | <a href="https://lists.kolabsys.com/mailman/listinfo/bugzilla">https://lists.kolabsys.com/mailman/listinfo/bugzilla</a> | ||
32 | </div> | ||
33 | </div> | ||
34 | </div> | ||
35 | </div> | ||
36 | </div> | ||
37 | </body> | ||
38 | </html> | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/data/text+html-maillinglist.mbox.tree b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/text+html-maillinglist.mbox.tree new file mode 100644 index 00000000..3738cb37 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/data/text+html-maillinglist.mbox.tree | |||
@@ -0,0 +1,5 @@ | |||
1 | * MimeTreeParser::MessagePartList | ||
2 | * MimeTreeParser::MimeMessagePart | ||
3 | * MimeTreeParser::AlternativeMessagePart | ||
4 | * MimeTreeParser::AttachmentMessagePart | ||
5 | * MimeTreeParser::MessagePart | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/kdepim_add_gpg_crypto_test.cmake b/framework/src/domain/mime/mimetreeparser/otp/autotests/kdepim_add_gpg_crypto_test.cmake new file mode 100644 index 00000000..ea0ab8d2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/kdepim_add_gpg_crypto_test.cmake | |||
@@ -0,0 +1,61 @@ | |||
1 | # Copyright (c) 2013 Sandro Knauß <mail@sandroknauss.de> | ||
2 | # | ||
3 | # Redistribution and use is allowed according to the terms of the BSD license. | ||
4 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. | ||
5 | |||
6 | set( MIMETREEPARSERRELPATH framework/src/domain/mimetreeparser) | ||
7 | set( GNUPGHOME ${CMAKE_BINARY_DIR}/${MIMETREEPARSERRELPATH}/tests/gnupg_home ) | ||
8 | add_definitions( -DGNUPGHOME="${GNUPGHOME}" ) | ||
9 | |||
10 | macro (ADD_GPG_CRYPTO_TEST _target _testname) | ||
11 | if (UNIX) | ||
12 | if (APPLE) | ||
13 | set(_library_path_variable "DYLD_LIBRARY_PATH") | ||
14 | elseif (CYGWIN) | ||
15 | set(_library_path_variable "PATH") | ||
16 | else (APPLE) | ||
17 | set(_library_path_variable "LD_LIBRARY_PATH") | ||
18 | endif (APPLE) | ||
19 | |||
20 | if (APPLE) | ||
21 | # DYLD_LIBRARY_PATH does not work like LD_LIBRARY_PATH | ||
22 | # OSX already has the RPATH in libraries and executables, putting runtime directories in | ||
23 | # DYLD_LIBRARY_PATH actually breaks things | ||
24 | set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/") | ||
25 | else (APPLE) | ||
26 | set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/:${LIB_INSTALL_DIR}:${QT_LIBRARY_DIR}") | ||
27 | endif (APPLE) | ||
28 | set(_executable "$<TARGET_FILE:${_target}>") | ||
29 | |||
30 | # use add_custom_target() to have the sh-wrapper generated during build time instead of cmake time | ||
31 | add_custom_command(TARGET ${_target} POST_BUILD | ||
32 | COMMAND ${CMAKE_COMMAND} | ||
33 | -D_filename=${_executable}.shell -D_library_path_variable=${_library_path_variable} | ||
34 | -D_ld_library_path="${_ld_library_path}" -D_executable=$<TARGET_FILE:${_target}> | ||
35 | -D_gnupghome="${GNUPGHOME}" | ||
36 | -P ${CMAKE_SOURCE_DIR}/${MIMETREEPARSERRELPATH}/tests/kdepim_generate_crypto_test_wrapper.cmake | ||
37 | ) | ||
38 | |||
39 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${_executable}.shell" ) | ||
40 | add_test(NAME ${_testname} COMMAND ${_executable}.shell) | ||
41 | |||
42 | else (UNIX) | ||
43 | # under windows, set the property WRAPPER_SCRIPT just to the name of the executable | ||
44 | # maybe later this will change to a generated batch file (for setting the PATH so that the Qt libs are found) | ||
45 | set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}\;${LIB_INSTALL_DIR}\;${QT_LIBRARY_DIR}") | ||
46 | set(_executable "$<TARGET_FILE:${_target}>") | ||
47 | |||
48 | # use add_custom_target() to have the batch-file-wrapper generated during build time instead of cmake time | ||
49 | add_custom_command(TARGET ${_target} POST_BUILD | ||
50 | COMMAND ${CMAKE_COMMAND} | ||
51 | -D_filename="${_executable}.bat" | ||
52 | -D_ld_library_path="${_ld_library_path}" -D_executable="${_executable}" | ||
53 | -D_gnupghome="${GNUPGHOME}" | ||
54 | -P ${CMAKE_SOURCE_DIR}/${MIMETREEPARSERRELPATH}/tests/kdepim_generate_crypto_test_wrapper.cmake | ||
55 | ) | ||
56 | |||
57 | add_test(NAME ${_testname} COMMAND ${_executable}.bat) | ||
58 | |||
59 | endif (UNIX) | ||
60 | endmacro (ADD_GPG_CRYPTO_TEST) | ||
61 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/kdepim_generate_crypto_test_wrapper.cmake b/framework/src/domain/mime/mimetreeparser/otp/autotests/kdepim_generate_crypto_test_wrapper.cmake new file mode 100644 index 00000000..e1412f37 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/kdepim_generate_crypto_test_wrapper.cmake | |||
@@ -0,0 +1,45 @@ | |||
1 | # Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org> | ||
2 | # Copyright (c) 2013, Sandro Knauß <mail@sandroknauss.de> | ||
3 | # | ||
4 | # Redistribution and use is allowed according to the terms of the BSD license. | ||
5 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. | ||
6 | |||
7 | |||
8 | if (UNIX) | ||
9 | |||
10 | file(WRITE "${_filename}" | ||
11 | "#!/bin/sh | ||
12 | # created by cmake, don't edit, changes will be lost | ||
13 | |||
14 | # don't mess with a gpg-agent already running on the system | ||
15 | unset GPG_AGENT_INFO | ||
16 | |||
17 | ${_library_path_variable}=${_ld_library_path}\${${_library_path_variable}:+:\$${_library_path_variable}} GNUPGHOME=${_gnupghome} gpg-agent --daemon \"${_executable}\" \"$@\" | ||
18 | _result=$? | ||
19 | _pid=`echo GETINFO pid | GNUPGHOME=${_gnupghome} gpg-connect-agent | grep 'D' | cut -d' ' -f2` | ||
20 | if [ ! -z \"\$_pid\" ]; then | ||
21 | echo \"Waiting for gpg-agent to terminate (PID: $_pid)...\" | ||
22 | while kill -0 \"\$_pid\"; do | ||
23 | sleep 1 | ||
24 | done | ||
25 | fi | ||
26 | exit \$_result | ||
27 | ") | ||
28 | |||
29 | # make it executable | ||
30 | # since this is only executed on UNIX, it is safe to call chmod | ||
31 | exec_program(chmod ARGS ug+x \"${_filename}\" OUTPUT_VARIABLE _dummy ) | ||
32 | |||
33 | else (UNIX) | ||
34 | |||
35 | file(TO_NATIVE_PATH "${_ld_library_path}" win_path) | ||
36 | file(TO_NATIVE_PATH "${_gnupghome}" win_gnupghome) | ||
37 | |||
38 | file(WRITE "${_filename}" | ||
39 | " | ||
40 | set PATH=${win_path};$ENV{PATH} | ||
41 | set GNUPGHOME=${win_gnupghome};$ENV{GNUPGHOME} | ||
42 | gpg-agent --daemon \"${_executable}\" %* | ||
43 | ") | ||
44 | |||
45 | endif (UNIX) | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/nodehelpertest.cpp b/framework/src/domain/mime/mimetreeparser/otp/autotests/nodehelpertest.cpp new file mode 100644 index 00000000..d2a5d605 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/nodehelpertest.cpp | |||
@@ -0,0 +1,275 @@ | |||
1 | /* Copyright 2015 Sandro Knauß <bugs@sandroknauss.de> | ||
2 | |||
3 | This program is free software; you can redistribute it and/or | ||
4 | modify it under the terms of the GNU General Public License as | ||
5 | published by the Free Software Foundation; either version 2 of | ||
6 | the License or (at your option) version 3 or any later version | ||
7 | accepted by the membership of KDE e.V. (or its successor approved | ||
8 | by the membership of KDE e.V.), which shall act as a proxy | ||
9 | defined in Section 14 of version 3 of the license. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #include "nodehelpertest.h" | ||
20 | |||
21 | #include "nodehelper.h" | ||
22 | |||
23 | #include <qtest.h> | ||
24 | |||
25 | using namespace MimeTreeParser; | ||
26 | |||
27 | NodeHelperTest::NodeHelperTest() | ||
28 | : QObject() | ||
29 | { | ||
30 | |||
31 | } | ||
32 | |||
33 | void NodeHelperTest::testPersistentIndex() | ||
34 | { | ||
35 | NodeHelper helper; | ||
36 | |||
37 | KMime::Content *node = new KMime::Content(); | ||
38 | KMime::Content *node2 = new KMime::Content(); | ||
39 | KMime::Content *node2Extra = new KMime::Content(); | ||
40 | KMime::Content *subNode = new KMime::Content(); | ||
41 | KMime::Content *subsubNode = new KMime::Content(), *subsubNode2 = new KMime::Content(); | ||
42 | KMime::Content *node2ExtraSubNode = new KMime::Content(); | ||
43 | KMime::Content *node2ExtraSubsubNode = new KMime::Content(); | ||
44 | KMime::Content *node2ExtraSubsubNode2 = new KMime::Content(); | ||
45 | KMime::Content *extra = new KMime::Content(), *extra2 = new KMime::Content(); | ||
46 | KMime::Content *subExtra = new KMime::Content(); | ||
47 | KMime::Content *subsubExtra = new KMime::Content(); | ||
48 | KMime::Content *subsubExtraNode = new KMime::Content(); | ||
49 | |||
50 | subNode->addContent(subsubNode); | ||
51 | subNode->addContent(subsubNode2); | ||
52 | node->addContent(subNode); | ||
53 | subsubExtra->addContent(subsubExtraNode); | ||
54 | helper.attachExtraContent(node, extra); | ||
55 | helper.attachExtraContent(node, extra2); | ||
56 | helper.attachExtraContent(subNode, subExtra); | ||
57 | helper.attachExtraContent(subsubNode2, subsubExtra); | ||
58 | |||
59 | // This simulates Opaque S/MIME signed and encrypted message with attachment | ||
60 | // (attachment is node2SubsubNode2) | ||
61 | node2Extra->addContent(node2ExtraSubNode); | ||
62 | node2ExtraSubNode->addContent(node2ExtraSubsubNode); | ||
63 | node2ExtraSubNode->addContent(node2ExtraSubsubNode2); | ||
64 | helper.attachExtraContent(node2, node2Extra); | ||
65 | |||
66 | /* all content has a internal first child, so indexes starts at 2 | ||
67 | * node "" | ||
68 | * -> subNode "2" | ||
69 | * -> subsubNode "2.2" | ||
70 | * -> subsubNode2 "2.3" | ||
71 | * | ||
72 | * node "" | ||
73 | * -> extra "e0" | ||
74 | * -> extra2 "e1" | ||
75 | * | ||
76 | * subNode "2" | ||
77 | * -> subExtra "2:e0" | ||
78 | * | ||
79 | * subsubNode2 "2.3" | ||
80 | * -> subsubExtra "2.3:e0" | ||
81 | * -> subsubExtraNode "2.3:e0:2" | ||
82 | * | ||
83 | * node2 "" | ||
84 | * | ||
85 | * node2 "" | ||
86 | * -> node2Extra "e0" | ||
87 | * -> node2ExtraSubNode "e0:2" | ||
88 | * -> node2ExtraSubsubNode "e0:2.2" | ||
89 | * -> node2ExtraSubsubNode2 "e0:2.3" | ||
90 | */ | ||
91 | |||
92 | QCOMPARE(helper.persistentIndex(node), QStringLiteral("")); | ||
93 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("")), node); | ||
94 | |||
95 | QCOMPARE(helper.persistentIndex(node->contents()[0]), QStringLiteral("1")); | ||
96 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("1")), node->contents()[0]); | ||
97 | |||
98 | QCOMPARE(helper.persistentIndex(subNode), QStringLiteral("2")); | ||
99 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("2")), subNode); | ||
100 | |||
101 | QCOMPARE(helper.persistentIndex(subsubNode), QStringLiteral("2.2")); | ||
102 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("2.2")), subsubNode); | ||
103 | |||
104 | QCOMPARE(helper.persistentIndex(subsubNode2), QStringLiteral("2.3")); | ||
105 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("2.3")), subsubNode2); | ||
106 | |||
107 | QCOMPARE(helper.persistentIndex(extra), QStringLiteral("e0")); | ||
108 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("e0")), extra); | ||
109 | |||
110 | QCOMPARE(helper.persistentIndex(extra2), QStringLiteral("e1")); | ||
111 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("e1")), extra2); | ||
112 | |||
113 | QCOMPARE(helper.persistentIndex(subExtra), QStringLiteral("2:e0")); | ||
114 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("2:e0")), subExtra); | ||
115 | |||
116 | QCOMPARE(helper.persistentIndex(subsubExtra), QStringLiteral("2.3:e0")); | ||
117 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("2.3:e0")), subsubExtra); | ||
118 | |||
119 | QCOMPARE(helper.persistentIndex(subsubExtraNode), QStringLiteral("2.3:e0:2")); | ||
120 | QCOMPARE(helper.contentFromIndex(node, QStringLiteral("2.3:e0:2")), subsubExtraNode); | ||
121 | |||
122 | QCOMPARE(helper.persistentIndex(node2ExtraSubsubNode2), QStringLiteral("e0:2.3")); | ||
123 | QCOMPARE(helper.contentFromIndex(node2, QStringLiteral("e0:2.3")), node2ExtraSubsubNode2); | ||
124 | |||
125 | delete node; | ||
126 | } | ||
127 | |||
128 | void NodeHelperTest::testHREF() | ||
129 | { | ||
130 | NodeHelper helper; | ||
131 | KMime::Message::Ptr msg(new KMime::Message); | ||
132 | QUrl url; | ||
133 | |||
134 | KMime::Content *node = msg->topLevel(); | ||
135 | KMime::Content *subNode = new KMime::Content(); | ||
136 | KMime::Content *subsubNode = new KMime::Content(), *subsubNode2 = new KMime::Content(); | ||
137 | KMime::Content *extra = new KMime::Content(), *extra2 = new KMime::Content(); | ||
138 | KMime::Content *subExtra = new KMime::Content(); | ||
139 | KMime::Content *subsubExtra = new KMime::Content(); | ||
140 | KMime::Content *subsubExtraNode = new KMime::Content(); | ||
141 | |||
142 | subNode->addContent(subsubNode); | ||
143 | subNode->addContent(subsubNode2); | ||
144 | node->addContent(subNode); | ||
145 | subsubExtra->addContent(subsubExtraNode); | ||
146 | helper.attachExtraContent(node, extra); | ||
147 | helper.attachExtraContent(node, extra2); | ||
148 | helper.attachExtraContent(subNode, subExtra); | ||
149 | helper.attachExtraContent(subsubNode2, subsubExtra); | ||
150 | |||
151 | url = QUrl(QStringLiteral("")); | ||
152 | QCOMPARE(helper.fromHREF(msg, url), node); | ||
153 | |||
154 | url = QUrl(QStringLiteral("attachment:e0?place=body")); | ||
155 | QCOMPARE(helper.fromHREF(msg, url), extra); | ||
156 | |||
157 | url = QUrl(QStringLiteral("attachment:2.2?place=body")); | ||
158 | QCOMPARE(helper.fromHREF(msg, url), subsubNode); | ||
159 | |||
160 | url = QUrl(QStringLiteral("attachment:2.3:e0:2?place=body")); | ||
161 | QCOMPARE(helper.fromHREF(msg, url), subsubExtraNode); | ||
162 | |||
163 | QCOMPARE(helper.asHREF(node, QStringLiteral("body")), QStringLiteral("attachment:?place=body")); | ||
164 | QCOMPARE(helper.asHREF(extra, QStringLiteral("body")), QStringLiteral("attachment:e0?place=body")); | ||
165 | QCOMPARE(helper.asHREF(subsubNode, QStringLiteral("body")), QStringLiteral("attachment:2.2?place=body")); | ||
166 | QCOMPARE(helper.asHREF(subsubExtraNode, QStringLiteral("body")), QStringLiteral("attachment:2.3:e0:2?place=body")); | ||
167 | } | ||
168 | |||
169 | void NodeHelperTest::testLocalFiles() | ||
170 | { | ||
171 | NodeHelper helper; | ||
172 | KMime::Message::Ptr msg(new KMime::Message); | ||
173 | |||
174 | KMime::Content *node = msg->topLevel(); | ||
175 | KMime::Content *subNode = new KMime::Content(); | ||
176 | KMime::Content *subsubNode = new KMime::Content(), *subsubNode2 = new KMime::Content(); | ||
177 | KMime::Content *extra = new KMime::Content(), *extra2 = new KMime::Content(); | ||
178 | KMime::Content *subExtra = new KMime::Content(); | ||
179 | KMime::Content *subsubExtra = new KMime::Content(); | ||
180 | KMime::Content *subsubExtraNode = new KMime::Content(); | ||
181 | |||
182 | subNode->addContent(subsubNode); | ||
183 | subNode->addContent(subsubNode2); | ||
184 | node->addContent(subNode); | ||
185 | subsubExtra->addContent(subsubExtraNode); | ||
186 | helper.attachExtraContent(node, extra); | ||
187 | helper.attachExtraContent(node, extra2); | ||
188 | helper.attachExtraContent(subNode, subExtra); | ||
189 | helper.attachExtraContent(subsubNode2, subsubExtra); | ||
190 | |||
191 | helper.writeNodeToTempFile(node); | ||
192 | QCOMPARE(helper.fromHREF(msg, helper.tempFileUrlFromNode(node)), node); | ||
193 | helper.writeNodeToTempFile(subNode); | ||
194 | QCOMPARE(helper.fromHREF(msg, helper.tempFileUrlFromNode(subNode)), subNode); | ||
195 | helper.writeNodeToTempFile(subsubNode); | ||
196 | QCOMPARE(helper.fromHREF(msg, helper.tempFileUrlFromNode(subsubNode)), subsubNode); | ||
197 | helper.writeNodeToTempFile(subsubNode2); | ||
198 | QCOMPARE(helper.fromHREF(msg, helper.tempFileUrlFromNode(subsubNode2)), subsubNode2); | ||
199 | helper.writeNodeToTempFile(extra); | ||
200 | QCOMPARE(helper.fromHREF(msg, helper.tempFileUrlFromNode(extra)), extra); | ||
201 | helper.writeNodeToTempFile(subExtra); | ||
202 | QCOMPARE(helper.fromHREF(msg, helper.tempFileUrlFromNode(subExtra)), subExtra); | ||
203 | helper.writeNodeToTempFile(subsubExtra); | ||
204 | QCOMPARE(helper.fromHREF(msg, helper.tempFileUrlFromNode(subsubExtra)), subsubExtra); | ||
205 | helper.writeNodeToTempFile(subsubExtraNode); | ||
206 | QCOMPARE(helper.fromHREF(msg, helper.tempFileUrlFromNode(subsubExtraNode)), subsubExtraNode); | ||
207 | } | ||
208 | |||
209 | void NodeHelperTest::testCreateTempDir() | ||
210 | { | ||
211 | QString path; | ||
212 | { | ||
213 | NodeHelper helper; | ||
214 | path = helper.createTempDir(QStringLiteral("foo")); | ||
215 | |||
216 | QVERIFY(path.endsWith(QStringLiteral(".index.foo"))); | ||
217 | QVERIFY(QDir(path).exists()); | ||
218 | QVERIFY(QFile(path).permissions() & QFileDevice::WriteUser); | ||
219 | QVERIFY(QFile(path).permissions() & QFileDevice::ExeUser); | ||
220 | QVERIFY(QFile(path).permissions() & QFileDevice::ReadUser); | ||
221 | } | ||
222 | QVERIFY(!QDir(path).exists()); | ||
223 | } | ||
224 | |||
225 | void NodeHelperTest::testFromAsString() | ||
226 | { | ||
227 | const QString tlSender = QStringLiteral("Foo <foo@example.com>"); | ||
228 | const QString encSender = QStringLiteral("Bar <bar@example.com>"); | ||
229 | |||
230 | NodeHelper helper; | ||
231 | |||
232 | // msg (KMime::Message) | ||
233 | // |- subNode | ||
234 | // |- encNode (KMime::Message) | ||
235 | // |- encSubNode | ||
236 | // | ||
237 | // subNode | ||
238 | // |- subExtra | ||
239 | // | ||
240 | // encSubNode | ||
241 | // |- encSubExtra | ||
242 | |||
243 | KMime::Message msg; | ||
244 | msg.from(true)->fromUnicodeString(tlSender, "UTF-8"); | ||
245 | auto node = msg.topLevel(); | ||
246 | auto subNode = new KMime::Content(); | ||
247 | auto subExtra = new KMime::Content(); | ||
248 | |||
249 | // Encapsulated message | ||
250 | KMime::Message *encMsg = new KMime::Message; | ||
251 | encMsg->from(true)->fromUnicodeString(encSender, "UTF-8"); | ||
252 | auto encNode = encMsg->topLevel(); | ||
253 | auto encSubNode = new KMime::Content(); | ||
254 | auto encSubExtra = new KMime::Content(); | ||
255 | |||
256 | node->addContent(subNode); | ||
257 | node->addContent(encMsg); | ||
258 | encNode->addContent(encSubNode); | ||
259 | |||
260 | helper.attachExtraContent(subNode, subExtra); | ||
261 | helper.attachExtraContent(encSubNode, encSubExtra); | ||
262 | |||
263 | QCOMPARE(helper.fromAsString(node), tlSender); | ||
264 | QCOMPARE(helper.fromAsString(subNode), tlSender); | ||
265 | QCOMPARE(helper.fromAsString(subExtra), tlSender); | ||
266 | QEXPECT_FAIL("", "Returning sender of encapsulated message is not yet implemented", Continue); | ||
267 | QCOMPARE(helper.fromAsString(encNode), encSender); | ||
268 | QEXPECT_FAIL("", "Returning sender of encapsulated message is not yet implemented", Continue); | ||
269 | QCOMPARE(helper.fromAsString(encSubNode), encSender); | ||
270 | QEXPECT_FAIL("", "Returning sender of encapsulated message is not yet implemented", Continue); | ||
271 | QCOMPARE(helper.fromAsString(encSubExtra), encSender); | ||
272 | } | ||
273 | |||
274 | QTEST_GUILESS_MAIN(NodeHelperTest) | ||
275 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/nodehelpertest.h b/framework/src/domain/mime/mimetreeparser/otp/autotests/nodehelpertest.h new file mode 100644 index 00000000..d2ed772a --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/nodehelpertest.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* Copyright 2015 Sandro Knauß <bugs@sandroknauss.de> | ||
2 | |||
3 | This program is free software; you can redistribute it and/or | ||
4 | modify it under the terms of the GNU General Public License as | ||
5 | published by the Free Software Foundation; either version 2 of | ||
6 | the License or (at your option) version 3 or any later version | ||
7 | accepted by the membership of KDE e.V. (or its successor approved | ||
8 | by the membership of KDE e.V.), which shall act as a proxy | ||
9 | defined in Section 14 of version 3 of the license. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef NODEHELPERTEST_H | ||
20 | #define NODEHELPERTEST_H | ||
21 | |||
22 | #include <QObject> | ||
23 | |||
24 | #include <KMime/Message> | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class NodeHelperTest : public QObject | ||
30 | { | ||
31 | Q_OBJECT | ||
32 | |||
33 | public: | ||
34 | NodeHelperTest(); | ||
35 | |||
36 | private Q_SLOTS: | ||
37 | void testPersistentIndex(); | ||
38 | void testLocalFiles(); | ||
39 | void testHREF(); | ||
40 | void testCreateTempDir(); | ||
41 | void testFromAsString(); | ||
42 | }; | ||
43 | |||
44 | } | ||
45 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/setupenv.cpp b/framework/src/domain/mime/mimetreeparser/otp/autotests/setupenv.cpp new file mode 100644 index 00000000..be7a8685 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/setupenv.cpp | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com | ||
3 | Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> | ||
4 | |||
5 | This library is free software; you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Library General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, but WITHOUT | ||
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | ||
13 | License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public License | ||
16 | along with this library; see the file COPYING.LIB. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
18 | 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #include "setupenv.h" | ||
22 | |||
23 | #include <QStandardPaths> | ||
24 | |||
25 | #include <QFile> | ||
26 | #include <QDir> | ||
27 | |||
28 | void MimeTreeParser::Test::setupEnv() | ||
29 | { | ||
30 | setenv("LC_ALL", "C", 1); | ||
31 | setenv("KDEHOME", QFile::encodeName(QDir::homePath() + QString::fromLatin1("/.qttest")).constData(), 1); | ||
32 | QStandardPaths::setTestModeEnabled(true); | ||
33 | } | ||
34 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/setupenv.h b/framework/src/domain/mime/mimetreeparser/otp/autotests/setupenv.h new file mode 100644 index 00000000..3582853e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/setupenv.h | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com | ||
3 | Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> | ||
4 | |||
5 | This library is free software; you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Library General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, but WITHOUT | ||
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | ||
13 | License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public License | ||
16 | along with this library; see the file COPYING.LIB. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
18 | 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef MESSAGECORE_TESTS_UTIL_H | ||
22 | #define MESSAGECORE_TESTS_UTIL_H | ||
23 | |||
24 | #include <gpgme++/key.h> | ||
25 | #include <attachmentstrategy.h> | ||
26 | #include <bodypartformatter.h> | ||
27 | #include <bodypartformatterbasefactory.h> | ||
28 | #include <messagepartrenderer.h> | ||
29 | #include <objecttreesource.h> | ||
30 | |||
31 | namespace MimeTreeParser | ||
32 | { | ||
33 | |||
34 | namespace Test | ||
35 | { | ||
36 | |||
37 | /** | ||
38 | * setup a environment variables for tests: | ||
39 | * * set LC_ALL to C | ||
40 | * * set KDEHOME | ||
41 | */ | ||
42 | void setupEnv(); | ||
43 | |||
44 | // We can't use EmptySource, since we need to control some emelnets of the source for tests to also test | ||
45 | // loadExternal and htmlMail. | ||
46 | class TestObjectTreeSource : public MimeTreeParser::Interface::ObjectTreeSource | ||
47 | { | ||
48 | public: | ||
49 | TestObjectTreeSource(MimeTreeParser::HtmlWriter *writer) | ||
50 | : mWriter(writer) | ||
51 | , mAttachmentStrategy(QStringLiteral("smart")) | ||
52 | , mPreferredMode(Util::Html) | ||
53 | , mHtmlLoadExternal(false) | ||
54 | , mDecryptMessage(false) | ||
55 | { | ||
56 | } | ||
57 | |||
58 | MimeTreeParser::HtmlWriter *htmlWriter() Q_DECL_OVERRIDE { | ||
59 | return mWriter; | ||
60 | } | ||
61 | |||
62 | bool htmlLoadExternal() const Q_DECL_OVERRIDE | ||
63 | { | ||
64 | return mHtmlLoadExternal; | ||
65 | } | ||
66 | |||
67 | void setHtmlLoadExternal(bool loadExternal) | ||
68 | { | ||
69 | mHtmlLoadExternal = loadExternal; | ||
70 | } | ||
71 | |||
72 | void setAttachmentStrategy(QString strategy) | ||
73 | { | ||
74 | mAttachmentStrategy = strategy; | ||
75 | } | ||
76 | |||
77 | const AttachmentStrategy *attachmentStrategy() Q_DECL_OVERRIDE { | ||
78 | return AttachmentStrategy::create(mAttachmentStrategy); | ||
79 | } | ||
80 | |||
81 | bool autoImportKeys() const Q_DECL_OVERRIDE | ||
82 | { | ||
83 | return true; | ||
84 | } | ||
85 | |||
86 | bool showEmoticons() const Q_DECL_OVERRIDE | ||
87 | { | ||
88 | return false; | ||
89 | } | ||
90 | |||
91 | bool showExpandQuotesMark() const Q_DECL_OVERRIDE | ||
92 | { | ||
93 | return false; | ||
94 | } | ||
95 | |||
96 | const BodyPartFormatterBaseFactory *bodyPartFormatterFactory() Q_DECL_OVERRIDE { | ||
97 | return &mBodyPartFormatterBaseFactory; | ||
98 | } | ||
99 | |||
100 | bool decryptMessage() const Q_DECL_OVERRIDE | ||
101 | { | ||
102 | return mDecryptMessage; | ||
103 | } | ||
104 | |||
105 | void setAllowDecryption(bool allowDecryption) | ||
106 | { | ||
107 | mDecryptMessage = allowDecryption; | ||
108 | } | ||
109 | |||
110 | void setShowSignatureDetails(bool showSignatureDetails) | ||
111 | { | ||
112 | mShowSignatureDetails = showSignatureDetails; | ||
113 | } | ||
114 | |||
115 | bool showSignatureDetails() const Q_DECL_OVERRIDE | ||
116 | { | ||
117 | return mShowSignatureDetails; | ||
118 | } | ||
119 | |||
120 | void setHtmlMode(MimeTreeParser::Util::HtmlMode mode, const QList<MimeTreeParser::Util::HtmlMode> &availableModes) Q_DECL_OVERRIDE { | ||
121 | Q_UNUSED(mode); | ||
122 | Q_UNUSED(availableModes); | ||
123 | } | ||
124 | |||
125 | MimeTreeParser::Util::HtmlMode preferredMode() const Q_DECL_OVERRIDE | ||
126 | { | ||
127 | return mPreferredMode; | ||
128 | } | ||
129 | |||
130 | void setPreferredMode(MimeTreeParser::Util::HtmlMode mode) | ||
131 | { | ||
132 | mPreferredMode = mode; | ||
133 | } | ||
134 | |||
135 | int levelQuote() const Q_DECL_OVERRIDE | ||
136 | { | ||
137 | return 1; | ||
138 | } | ||
139 | |||
140 | const QTextCodec *overrideCodec() Q_DECL_OVERRIDE { | ||
141 | return nullptr; | ||
142 | } | ||
143 | |||
144 | QString createMessageHeader(KMime::Message *message) Q_DECL_OVERRIDE { | ||
145 | Q_UNUSED(message); | ||
146 | return QString(); //do nothing | ||
147 | } | ||
148 | |||
149 | QObject *sourceObject() Q_DECL_OVERRIDE { | ||
150 | return nullptr; | ||
151 | } | ||
152 | |||
153 | Interface::MessagePartRenderer::Ptr messagePartTheme(Interface::MessagePart::Ptr msgPart) Q_DECL_OVERRIDE { | ||
154 | Q_UNUSED(msgPart); | ||
155 | return Interface::MessagePartRenderer::Ptr(); | ||
156 | } | ||
157 | bool isPrinting() const Q_DECL_OVERRIDE | ||
158 | { | ||
159 | return false; | ||
160 | } | ||
161 | private: | ||
162 | MimeTreeParser::HtmlWriter *mWriter; | ||
163 | QString mAttachmentStrategy; | ||
164 | BodyPartFormatterBaseFactory mBodyPartFormatterBaseFactory; | ||
165 | MimeTreeParser::Util::HtmlMode mPreferredMode; | ||
166 | bool mHtmlLoadExternal; | ||
167 | bool mDecryptMessage; | ||
168 | bool mShowSignatureDetails; | ||
169 | }; | ||
170 | |||
171 | } | ||
172 | |||
173 | } | ||
174 | |||
175 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/testcsshelper.cpp b/framework/src/domain/mime/mimetreeparser/otp/autotests/testcsshelper.cpp new file mode 100644 index 00000000..0e411e8f --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/testcsshelper.cpp | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | testcsshelper.cpp | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2013 Sandro Knauß <bugs@sandroknauss.de> | ||
6 | |||
7 | KMail is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License, version 2, as | ||
9 | published by the Free Software Foundation. | ||
10 | |||
11 | KMail is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | |||
20 | In addition, as a special exception, the copyright holders give | ||
21 | permission to link the code of this program with any edition of | ||
22 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
23 | of Qt that use the same license as Qt), and distribute linked | ||
24 | combinations including the two. You must obey the GNU General | ||
25 | Public License in all respects for all of the code used other than | ||
26 | Qt. If you modify this file, you may extend this exception to | ||
27 | your version of the file, but you are not obligated to do so. If | ||
28 | you do not wish to do so, delete this exception statement from | ||
29 | your version. | ||
30 | */ | ||
31 | |||
32 | #include "testcsshelper.h" | ||
33 | |||
34 | #include <QColor> | ||
35 | #include <QFont> | ||
36 | #include <QPalette> | ||
37 | #include <QApplication> | ||
38 | |||
39 | namespace MimeTreeParser | ||
40 | { | ||
41 | |||
42 | TestCSSHelper::TestCSSHelper(const QPaintDevice *pd) : | ||
43 | CSSHelperBase(pd) | ||
44 | { | ||
45 | mRecycleQuoteColors = false; | ||
46 | mBackgroundColor = QColor(0xff, 0xff, 0xff); | ||
47 | mForegroundColor = QColor(0x1f, 0x1c, 0x1b); | ||
48 | mLinkColor = QColor(0x00, 0x57, 0xae); | ||
49 | cPgpEncrH = QColor(0x00, 0x80, 0xff); | ||
50 | cPgpOk1H = QColor(0x40, 0xff, 0x40); | ||
51 | cPgpOk0H = QColor(0xff, 0xff, 0x40); | ||
52 | cPgpWarnH = QColor(0xff, 0xff, 0x40); | ||
53 | cPgpErrH = QColor(0xff, 0x00, 0x00); | ||
54 | |||
55 | cPgpEncrHT = QColor(0xff, 0xff, 0xff); | ||
56 | cPgpOk1HT = QColor(0x27, 0xae, 0x60); | ||
57 | cPgpOk0HT = QColor(0xf6, 0x74, 0x00); | ||
58 | cPgpWarnHT = QColor(0xf6, 0x74, 0x00); | ||
59 | cPgpErrHT = QColor(0xda, 0x44, 0x53); | ||
60 | |||
61 | cHtmlWarning = QColor(0xff, 0x40, 0x40); | ||
62 | for (int i = 0; i < 3; ++i) { | ||
63 | mQuoteColor[i] = QColor(0x00, 0x80 - i * 0x10, 0x00); | ||
64 | } | ||
65 | |||
66 | QFont defaultFont = QFont(QStringLiteral("Sans Serif"), 9); | ||
67 | mBodyFont = defaultFont; | ||
68 | mPrintFont = defaultFont; | ||
69 | mFixedFont = defaultFont; | ||
70 | mFixedPrintFont = defaultFont; | ||
71 | defaultFont.setItalic(true); | ||
72 | for (int i = 0; i < 3; ++i) { | ||
73 | mQuoteFont[i] = defaultFont; | ||
74 | } | ||
75 | |||
76 | mShrinkQuotes = false; | ||
77 | |||
78 | QPalette pal; | ||
79 | |||
80 | pal.setColor(QPalette::Background, QColor(0xd6, 0xd2, 0xd0)); | ||
81 | pal.setColor(QPalette::Foreground, QColor(0x22, 0x1f, 0x1e)); | ||
82 | pal.setColor(QPalette::Highlight, QColor(0x43, 0xac, 0xe8)); | ||
83 | pal.setColor(QPalette::HighlightedText, QColor(0xff, 0xff, 0xff)); | ||
84 | pal.setColor(QPalette::Mid, QColor(0xb3, 0xab, 0xa7)); | ||
85 | |||
86 | QApplication::setPalette(pal); | ||
87 | |||
88 | recalculatePGPColors(); | ||
89 | } | ||
90 | |||
91 | TestCSSHelper::~TestCSSHelper() | ||
92 | { | ||
93 | |||
94 | } | ||
95 | |||
96 | QString TestCSSHelper::htmlHead(bool fixed) const | ||
97 | { | ||
98 | Q_UNUSED(fixed); | ||
99 | return | ||
100 | QStringLiteral("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n" | ||
101 | "<html>\n" | ||
102 | "<body>\n"); | ||
103 | } | ||
104 | |||
105 | } | ||
106 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/testcsshelper.h b/framework/src/domain/mime/mimetreeparser/otp/autotests/testcsshelper.h new file mode 100644 index 00000000..c21935cf --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/testcsshelper.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* -*- c++ -*- | ||
2 | testcsshelper.h | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2013 Sandro Knauß <bugs@sandroknauss.de> | ||
6 | |||
7 | KMail is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License, version 2, as | ||
9 | published by the Free Software Foundation. | ||
10 | |||
11 | KMail is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | |||
20 | In addition, as a special exception, the copyright holders give | ||
21 | permission to link the code of this program with any edition of | ||
22 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
23 | of Qt that use the same license as Qt), and distribute linked | ||
24 | combinations including the two. You must obey the GNU General | ||
25 | Public License in all respects for all of the code used other than | ||
26 | Qt. If you modify this file, you may extend this exception to | ||
27 | your version of the file, but you are not obligated to do so. If | ||
28 | you do not wish to do so, delete this exception statement from | ||
29 | your version. | ||
30 | */ | ||
31 | |||
32 | #ifndef __MIMETREEPARSER_TESTCSSHELPER_H__ | ||
33 | #define __MIMETREEPARSER_TESTCSSHELPER_H__ | ||
34 | |||
35 | #include "viewer/csshelperbase.h" | ||
36 | |||
37 | namespace MimeTreeParser | ||
38 | { | ||
39 | |||
40 | class TestCSSHelper : public CSSHelperBase | ||
41 | { | ||
42 | public: | ||
43 | explicit TestCSSHelper(const QPaintDevice *pd); | ||
44 | virtual ~TestCSSHelper(); | ||
45 | QString htmlHead(bool fixed) const Q_DECL_OVERRIDE; | ||
46 | }; | ||
47 | |||
48 | } | ||
49 | |||
50 | #endif // __MIMETREEPARSER_TESTCSSHELPER_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/util.cpp b/framework/src/domain/mime/mimetreeparser/otp/autotests/util.cpp new file mode 100644 index 00000000..5ea415b7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/util.cpp | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | Copyright (c) 2010 Thomas McGuire <thomas.mcguire@kdab.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 | #include "util.h" | ||
20 | |||
21 | #include <QFile> | ||
22 | |||
23 | KMime::Message::Ptr readAndParseMail(const QString &mailFile) | ||
24 | { | ||
25 | QFile file(QLatin1String(MAIL_DATA_DIR) + QLatin1Char('/') + mailFile); | ||
26 | file.open(QIODevice::ReadOnly); | ||
27 | Q_ASSERT(file.isOpen()); | ||
28 | const QByteArray data = KMime::CRLFtoLF(file.readAll()); | ||
29 | Q_ASSERT(!data.isEmpty()); | ||
30 | KMime::Message::Ptr msg(new KMime::Message); | ||
31 | msg->setContent(data); | ||
32 | msg->parse(); | ||
33 | return msg; | ||
34 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/autotests/util.h b/framework/src/domain/mime/mimetreeparser/otp/autotests/util.h new file mode 100644 index 00000000..ac4aa54f --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/autotests/util.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | Copyright (c) 2010 Thomas McGuire <thomas.mcguire@kdab.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 | #include "htmlwriter.h" | ||
20 | |||
21 | #include <KMime/Message> | ||
22 | |||
23 | class TestHtmlWriter : public MimeTreeParser::HtmlWriter | ||
24 | { | ||
25 | public: | ||
26 | explicit TestHtmlWriter() {} | ||
27 | virtual ~TestHtmlWriter() {} | ||
28 | |||
29 | void begin(const QString &) Q_DECL_OVERRIDE {} | ||
30 | void write(const QString &) Q_DECL_OVERRIDE {} | ||
31 | void end() Q_DECL_OVERRIDE {} | ||
32 | void reset() Q_DECL_OVERRIDE {} | ||
33 | void queue(const QString &str) Q_DECL_OVERRIDE { | ||
34 | html.append(str); | ||
35 | } | ||
36 | void flush() Q_DECL_OVERRIDE {} | ||
37 | void embedPart(const QByteArray &, const QString &) Q_DECL_OVERRIDE {} | ||
38 | void extraHead(const QString &) Q_DECL_OVERRIDE {} | ||
39 | |||
40 | QString html; | ||
41 | }; | ||
42 | |||
43 | KMime::Message::Ptr readAndParseMail(const QString &mailFile); | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/bodypart.cpp b/framework/src/domain/mime/mimetreeparser/otp/bodypart.cpp new file mode 100644 index 00000000..62e92d0c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/bodypart.cpp | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | This file is part of KMail's plugin interface. | ||
3 | Copyright (c) 2004 Marc Mutz <mutz@kde.org>, | ||
4 | Ingo Kloecker <kloecker@kde.org> | ||
5 | |||
6 | KMail is free software; you can redistribute it and/or modify it | ||
7 | under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | KMail is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | |||
20 | In addition, as a special exception, the copyright holders give | ||
21 | permission to link the code of this program with any edition of | ||
22 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
23 | of Qt that use the same license as Qt), and distribute linked | ||
24 | combinations including the two. You must obey the GNU General | ||
25 | Public License in all respects for all of the code used other than | ||
26 | Qt. If you modify this file, you may extend this exception to | ||
27 | your version of the file, but you are not obligated to do so. If | ||
28 | you do not wish to do so, delete this exception statement from | ||
29 | your version. | ||
30 | */ | ||
31 | |||
32 | #include "bodypart.h" | ||
33 | |||
34 | MimeTreeParser::Interface::BodyPartMemento::~BodyPartMemento() | ||
35 | { | ||
36 | } | ||
37 | |||
38 | MimeTreeParser::Interface::BodyPart::~BodyPart() | ||
39 | { | ||
40 | } | ||
41 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/bodypart.h b/framework/src/domain/mime/mimetreeparser/otp/bodypart.h new file mode 100644 index 00000000..f50c0360 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/bodypart.h | |||
@@ -0,0 +1,209 @@ | |||
1 | /* -*- mode: C++; c-file-style: "gnu" -*- | ||
2 | bodypart.h | ||
3 | |||
4 | This file is part of KMail's plugin interface. | ||
5 | Copyright (c) 2004 Marc Mutz <mutz@kde.org>, | ||
6 | Ingo Kloecker <kloecker@kde.org> | ||
7 | |||
8 | KMail is free software; you can redistribute it and/or modify it | ||
9 | under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #ifndef __MIMETREEPARSER_INTERFACES_BODYPART_H__ | ||
35 | #define __MIMETREEPARSER_INTERFACES_BODYPART_H__ | ||
36 | |||
37 | #include <QByteArray> | ||
38 | #include <QString> | ||
39 | |||
40 | namespace KMime | ||
41 | { | ||
42 | class Content; | ||
43 | } | ||
44 | |||
45 | namespace MimeTreeParser | ||
46 | { | ||
47 | class NodeHelper; | ||
48 | class ObjectTreeParser; | ||
49 | class ProcessResult; | ||
50 | |||
51 | namespace Interface | ||
52 | { | ||
53 | |||
54 | class ObjectTreeSource; | ||
55 | |||
56 | /*FIXME(Andras) review, port | ||
57 | class Observer; | ||
58 | class Observable; | ||
59 | */ | ||
60 | /** | ||
61 | @short interface of classes that implement status for BodyPartFormatters. | ||
62 | */ | ||
63 | class BodyPartMemento | ||
64 | { | ||
65 | public: | ||
66 | virtual ~BodyPartMemento(); | ||
67 | |||
68 | virtual void detach() = 0; | ||
69 | #if 0 | ||
70 | //FIXME(Andras) review, port | ||
71 | /** If your BodyPartMemento implementation also implements the | ||
72 | Observer interface, simply implement these as | ||
73 | <code>return this;</code>, else as <code>return | ||
74 | 0;</code>. This is needed to avoid forcing a dependency of | ||
75 | plugins on internal KMail classes. | ||
76 | */ | ||
77 | virtual Observer *asObserver() = 0; | ||
78 | |||
79 | /** If your BodyPartMemento implementation also implements the | ||
80 | Observable interface, simply implement these as | ||
81 | <code>return this;</code>, else as <code>return | ||
82 | 0;</code>. This is needed to avoid forcing a dependency of | ||
83 | plugins on internal KMail classes. | ||
84 | */ | ||
85 | virtual Observable *asObservable() = 0; | ||
86 | #endif | ||
87 | }; | ||
88 | |||
89 | /** | ||
90 | @short interface of message body parts. | ||
91 | */ | ||
92 | class BodyPart | ||
93 | { | ||
94 | public: | ||
95 | virtual ~BodyPart(); | ||
96 | |||
97 | /** | ||
98 | @return a string respresentation of an URL that can be used | ||
99 | to invoke a BodyPartURLHandler for this body part. | ||
100 | */ | ||
101 | virtual QString makeLink(const QString &path) const = 0; | ||
102 | |||
103 | /** | ||
104 | @return the decoded (CTE, canonicalisation, and charset | ||
105 | encoding undone) text contained in the body part, or | ||
106 | QString(), it the body part is not of type "text". | ||
107 | */ | ||
108 | virtual QString asText() const = 0; | ||
109 | |||
110 | /** | ||
111 | @return the decoded (CTE undone) content of the body part, or | ||
112 | a null array if this body part instance is of type text. | ||
113 | */ | ||
114 | virtual QByteArray asBinary() const = 0; | ||
115 | |||
116 | /** | ||
117 | @return the value of the content-type header field parameter | ||
118 | with name \a parameter, or QString(), if that that | ||
119 | parameter is not present in the body's content-type header | ||
120 | field. RFC 2231 encoding is removed first. | ||
121 | |||
122 | Note that this method will suppress queries to certain | ||
123 | standard parameters (most notably "charset") to keep plugins | ||
124 | decent. | ||
125 | |||
126 | Note2 that this method preserves the case of the parameter | ||
127 | value returned. So, if the parameter you want to use defines | ||
128 | the value to be case-insensitive (such as the smime-type | ||
129 | parameter), you need to make sure you do the casemap yourself | ||
130 | before comparing to a reference value. | ||
131 | */ | ||
132 | virtual QString contentTypeParameter(const char *parameter) const = 0; | ||
133 | |||
134 | /** | ||
135 | @return the content of the content-description header field, | ||
136 | or QString() if that header is not present in this body | ||
137 | part. RFC 2047 encoding is decoded first. | ||
138 | */ | ||
139 | virtual QString contentDescription() const = 0; | ||
140 | |||
141 | //virtual int contentDisposition() const = 0; | ||
142 | /** | ||
143 | @return the value of the content-disposition header field | ||
144 | parameter with name \a parameter, or QString() if that | ||
145 | parameter is not present in the body's content-disposition | ||
146 | header field. RFC 2231 encoding is removed first. | ||
147 | |||
148 | The notes made for contentTypeParameter() above apply here as | ||
149 | well. | ||
150 | */ | ||
151 | virtual QString contentDispositionParameter(const char *parameter) const = 0; | ||
152 | |||
153 | /** | ||
154 | @return whether this part already has it's complete body | ||
155 | fetched e.g. from an IMAP server. | ||
156 | */ | ||
157 | virtual bool hasCompleteBody() const = 0; | ||
158 | |||
159 | /** | ||
160 | @return the BodyPartMemento set for this part, or null, if | ||
161 | none is set. | ||
162 | */ | ||
163 | virtual BodyPartMemento *memento() const = 0; | ||
164 | |||
165 | /** | ||
166 | @return register an implementation of the BodyPartMemento | ||
167 | interface as a status object with this part. | ||
168 | */ | ||
169 | virtual void setBodyPartMemento(BodyPartMemento *) = 0; | ||
170 | |||
171 | enum Display { None, AsIcon, Inline }; | ||
172 | /** | ||
173 | @return whether this body part should be displayed iconic or inline | ||
174 | */ | ||
175 | virtual Display defaultDisplay() const = 0; | ||
176 | |||
177 | /** Returns the KMime::Content node represented here. Makes most of the above obsolete | ||
178 | and probably should be used in the interfaces in the first place. | ||
179 | */ | ||
180 | virtual KMime::Content *content() const = 0; | ||
181 | |||
182 | /** | ||
183 | * Returns the top-level content. | ||
184 | * Note that this is _not_ necessarily the same as content()->topLevel(), for example the later | ||
185 | * will not work for "extra nodes", i.e. nodes in encrypted parts of the mail. | ||
186 | * topLevelContent() will return the correct result in this case. Also note that | ||
187 | * topLevelContent() | ||
188 | */ | ||
189 | virtual KMime::Content *topLevelContent() const = 0; | ||
190 | |||
191 | /** | ||
192 | * Ok, this is ugly, exposing the node helper here, but there is too much useful stuff in there | ||
193 | * for real-world plugins. Still, there should be a nicer way for this. | ||
194 | */ | ||
195 | virtual MimeTreeParser::NodeHelper *nodeHelper() const = 0; | ||
196 | |||
197 | /** | ||
198 | * For making it easier to refactor, add objectTreeParser | ||
199 | */ | ||
200 | virtual MimeTreeParser::ObjectTreeParser *objectTreeParser() const = 0; | ||
201 | virtual MimeTreeParser::Interface::ObjectTreeSource *source() const = 0; | ||
202 | virtual MimeTreeParser::ProcessResult *processResult() const = 0; | ||
203 | }; | ||
204 | |||
205 | } // namespace Interface | ||
206 | |||
207 | } | ||
208 | |||
209 | #endif // __MIMETREEPARSER_INTERFACES_BODYPART_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/bodypartformatter.cpp b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatter.cpp new file mode 100644 index 00000000..63d7e92c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatter.cpp | |||
@@ -0,0 +1,147 @@ | |||
1 | /* -*- mode: C++; c-file-style: "gnu" -*- | ||
2 | bodypartformatter.cpp | ||
3 | |||
4 | This file is part of KMail's plugin interface. | ||
5 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
6 | |||
7 | KMail is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | KMail is distributed in the hope that it will be useful, but | ||
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | |||
21 | In addition, as a special exception, the copyright holders give | ||
22 | permission to link the code of this program with any edition of | ||
23 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
24 | of Qt that use the same license as Qt), and distribute linked | ||
25 | combinations including the two. You must obey the GNU General | ||
26 | Public License in all respects for all of the code used other than | ||
27 | Qt. If you modify this file, you may extend this exception to | ||
28 | your version of the file, but you are not obligated to do so. If | ||
29 | you do not wish to do so, delete this exception statement from | ||
30 | your version. | ||
31 | */ | ||
32 | |||
33 | #include "bodypartformatter.h" | ||
34 | |||
35 | #include "bodypart.h" | ||
36 | #include "queuehtmlwriter.h" | ||
37 | #include "objecttreeparser.h" | ||
38 | |||
39 | using namespace MimeTreeParser::Interface; | ||
40 | |||
41 | namespace MimeTreeParser | ||
42 | { | ||
43 | namespace Interface | ||
44 | { | ||
45 | |||
46 | class MessagePartPrivate | ||
47 | { | ||
48 | public: | ||
49 | MessagePartPrivate(const BodyPart *part) | ||
50 | : mHtmlWriter(nullptr) | ||
51 | , mPart(part) | ||
52 | , mParentPart(nullptr) | ||
53 | , mCreatedWriter(false) | ||
54 | { | ||
55 | } | ||
56 | |||
57 | ~MessagePartPrivate() | ||
58 | { | ||
59 | if (mCreatedWriter) { | ||
60 | delete mHtmlWriter; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | MimeTreeParser::HtmlWriter *htmlWriter() | ||
65 | { | ||
66 | if (!mHtmlWriter && mPart) { | ||
67 | mHtmlWriter = mPart->objectTreeParser()->htmlWriter(); | ||
68 | } | ||
69 | return mHtmlWriter; | ||
70 | } | ||
71 | |||
72 | MimeTreeParser::HtmlWriter *mHtmlWriter; | ||
73 | const BodyPart *mPart; | ||
74 | MessagePart *mParentPart; | ||
75 | bool mCreatedWriter; | ||
76 | |||
77 | }; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | MessagePart::MessagePart() | ||
82 | : QObject() | ||
83 | , d(new MessagePartPrivate(nullptr)) | ||
84 | { | ||
85 | } | ||
86 | |||
87 | MessagePart::MessagePart(const BodyPart &part) | ||
88 | : QObject() | ||
89 | , d(new MessagePartPrivate(&part)) | ||
90 | { | ||
91 | } | ||
92 | |||
93 | MessagePart::~MessagePart() | ||
94 | { | ||
95 | delete d; | ||
96 | } | ||
97 | |||
98 | void MessagePart::html(bool decorate) | ||
99 | { | ||
100 | Q_UNUSED(decorate); | ||
101 | static_cast<QueueHtmlWriter *>(d->mHtmlWriter)->replay(); | ||
102 | } | ||
103 | |||
104 | QString MessagePart::text() const | ||
105 | { | ||
106 | return QString(); | ||
107 | } | ||
108 | |||
109 | MessagePart *MessagePart::parentPart() const | ||
110 | { | ||
111 | return d->mParentPart; | ||
112 | } | ||
113 | |||
114 | void MessagePart::setParentPart(MessagePart *parentPart) | ||
115 | { | ||
116 | d->mParentPart = parentPart; | ||
117 | } | ||
118 | |||
119 | QString MessagePart::htmlContent() const | ||
120 | { | ||
121 | return text(); | ||
122 | } | ||
123 | |||
124 | QString MessagePart::plaintextContent() const | ||
125 | { | ||
126 | return text(); | ||
127 | } | ||
128 | |||
129 | MimeTreeParser::HtmlWriter *MessagePart::htmlWriter() const | ||
130 | { | ||
131 | return d->htmlWriter(); | ||
132 | } | ||
133 | |||
134 | void MessagePart::setHtmlWriter(MimeTreeParser::HtmlWriter *htmlWriter) const | ||
135 | { | ||
136 | if (d->mHtmlWriter) { | ||
137 | d->mHtmlWriter = htmlWriter; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | MessagePart::Ptr BodyPartFormatter::process(BodyPart &part) const | ||
142 | { | ||
143 | auto mp = MessagePart::Ptr(new MessagePart(part)); | ||
144 | mp->setHtmlWriter(new QueueHtmlWriter(mp->htmlWriter())); | ||
145 | mp->d->mCreatedWriter = true; | ||
146 | return mp; | ||
147 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/bodypartformatter.h b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatter.h new file mode 100644 index 00000000..0116c2e4 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatter.h | |||
@@ -0,0 +1,149 @@ | |||
1 | /* -*- mode: C++; c-file-style: "gnu" -*- | ||
2 | bodypartformatter.h | ||
3 | |||
4 | This file is part of KMail's plugin interface. | ||
5 | Copyright (c) 2004 Marc Mutz <mutz@kde.org>, | ||
6 | Ingo Kloecker <kloecker@kde.org> | ||
7 | |||
8 | KMail is free software; you can redistribute it and/or modify it | ||
9 | under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #ifndef __MIMETREEPARSER_INTERFACE_BODYPARTFORMATTER_H__ | ||
35 | #define __MIMETREEPARSER_INTERFACE_BODYPARTFORMATTER_H__ | ||
36 | |||
37 | #include <QObject> | ||
38 | #include <QSharedPointer> | ||
39 | |||
40 | #include "objecttreeparser.h" | ||
41 | |||
42 | namespace MimeTreeParser | ||
43 | { | ||
44 | class HtmlWriter; | ||
45 | |||
46 | namespace Interface | ||
47 | { | ||
48 | |||
49 | class BodyPartURLHandler; | ||
50 | class BodyPart; | ||
51 | class MessagePartPrivate; | ||
52 | |||
53 | class MessagePart : public QObject | ||
54 | { | ||
55 | Q_OBJECT | ||
56 | Q_PROPERTY(QString plaintextContent READ plaintextContent) | ||
57 | Q_PROPERTY(QString htmlContent READ htmlContent) | ||
58 | public: | ||
59 | typedef QSharedPointer<MessagePart> Ptr; | ||
60 | explicit MessagePart(); | ||
61 | explicit MessagePart(const BodyPart &part); | ||
62 | virtual ~MessagePart(); | ||
63 | |||
64 | virtual void html(bool decorate); | ||
65 | virtual QString text() const; | ||
66 | |||
67 | void setParentPart(MessagePart *parentPart); | ||
68 | MessagePart *parentPart() const; | ||
69 | |||
70 | virtual QString plaintextContent() const; | ||
71 | virtual QString htmlContent() const; | ||
72 | |||
73 | virtual MimeTreeParser::HtmlWriter *htmlWriter() const; | ||
74 | virtual void setHtmlWriter(MimeTreeParser::HtmlWriter *htmlWriter) const; | ||
75 | private: | ||
76 | MessagePartPrivate *d; | ||
77 | |||
78 | friend class BodyPartFormatter; | ||
79 | }; | ||
80 | |||
81 | class BodyPartFormatter | ||
82 | { | ||
83 | public: | ||
84 | virtual ~BodyPartFormatter() {} | ||
85 | |||
86 | /** | ||
87 | @li Ok returned when format() generated some HTML | ||
88 | @li NeedContent returned when format() needs the body of the part | ||
89 | @li AsIcon returned when the part should be shown iconified | ||
90 | @li Failed returned when formatting failed. Currently equivalent to Ok | ||
91 | */ | ||
92 | enum Result { Ok, NeedContent, AsIcon, Failed }; | ||
93 | |||
94 | /** | ||
95 | Format body part \a part by generating some HTML and writing | ||
96 | that to \a writer. | ||
97 | |||
98 | @return the result code (see above) | ||
99 | */ | ||
100 | virtual Result format(BodyPart *part, MimeTreeParser::HtmlWriter *writer) const = 0; | ||
101 | |||
102 | /** | ||
103 | Variant of format that allows implementors to hook notifications up to | ||
104 | a listener interested in the result, for async operations. | ||
105 | |||
106 | @return the result code (see above) | ||
107 | */ | ||
108 | virtual Result format(BodyPart *part, MimeTreeParser::HtmlWriter *writer, QObject *asyncResultObserver) const | ||
109 | { | ||
110 | Q_UNUSED(asyncResultObserver); | ||
111 | return format(part, writer); | ||
112 | } | ||
113 | |||
114 | virtual void adaptProcessResult(ProcessResult &result) const | ||
115 | { | ||
116 | Q_UNUSED(result); | ||
117 | } | ||
118 | virtual MessagePart::Ptr process(BodyPart &part) const; | ||
119 | }; | ||
120 | |||
121 | /** | ||
122 | @short interface for BodyPartFormatter plugins | ||
123 | |||
124 | The interface is queried by for types, subtypes, and the | ||
125 | corresponding bodypart formatter, and the result inserted into | ||
126 | the bodypart formatter factory. | ||
127 | |||
128 | Subtype alone or both type and subtype may be "*", which is | ||
129 | taken as a wildcard, so that e.g. type=text subtype=* matches | ||
130 | any text subtype, but with lesser specificity than a concrete | ||
131 | mimetype such as text/plain. type=* is only allowed when | ||
132 | subtype=*, too. | ||
133 | */ | ||
134 | class BodyPartFormatterPlugin | ||
135 | { | ||
136 | public: | ||
137 | virtual ~BodyPartFormatterPlugin() {} | ||
138 | |||
139 | virtual const BodyPartFormatter *bodyPartFormatter(int idx) const = 0; | ||
140 | virtual const char *type(int idx) const = 0; | ||
141 | virtual const char *subtype(int idx) const = 0; | ||
142 | |||
143 | virtual const BodyPartURLHandler *urlHandler(int idx) const = 0; | ||
144 | }; | ||
145 | |||
146 | } // namespace Interface | ||
147 | |||
148 | } | ||
149 | #endif // __MIMETREEPARSER_INTERFACE_BODYPARTFORMATTER_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/bodypartformatter_impl.cpp b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatter_impl.cpp new file mode 100644 index 00000000..c8622ba3 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatter_impl.cpp | |||
@@ -0,0 +1,193 @@ | |||
1 | /* -*- c++ -*- | ||
2 | bodypartformatter.cpp | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | |||
7 | KMail is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License, version 2, as | ||
9 | published by the Free Software Foundation. | ||
10 | |||
11 | KMail is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | |||
20 | In addition, as a special exception, the copyright holders give | ||
21 | permission to link the code of this program with any edition of | ||
22 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
23 | of Qt that use the same license as Qt), and distribute linked | ||
24 | combinations including the two. You must obey the GNU General | ||
25 | Public License in all respects for all of the code used other than | ||
26 | Qt. If you modify this file, you may extend this exception to | ||
27 | your version of the file, but you are not obligated to do so. If | ||
28 | you do not wish to do so, delete this exception statement from | ||
29 | your version. | ||
30 | */ | ||
31 | |||
32 | #include "mimetreeparser_debug.h" | ||
33 | |||
34 | #include "applicationpgpencrypted.h" | ||
35 | #include "applicationpkcs7mime.h" | ||
36 | #include "mailman.h" | ||
37 | #include "multipartalternative.h" | ||
38 | #include "multipartmixed.h" | ||
39 | #include "multipartencrypted.h" | ||
40 | #include "multipartsigned.h" | ||
41 | #include "texthtml.h" | ||
42 | #include "textplain.h" | ||
43 | |||
44 | #include "bodypartformatter.h" | ||
45 | #include "bodypart.h" | ||
46 | |||
47 | #include "bodypartformatterbasefactory.h" | ||
48 | #include "bodypartformatterbasefactory_p.h" | ||
49 | |||
50 | #include "attachmentstrategy.h" | ||
51 | #include "objecttreeparser.h" | ||
52 | #include "messagepart.h" | ||
53 | |||
54 | #include <KMime/Content> | ||
55 | |||
56 | using namespace MimeTreeParser; | ||
57 | |||
58 | namespace | ||
59 | { | ||
60 | class AnyTypeBodyPartFormatter | ||
61 | : public MimeTreeParser::Interface::BodyPartFormatter | ||
62 | { | ||
63 | static const AnyTypeBodyPartFormatter *self; | ||
64 | public: | ||
65 | Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE | ||
66 | { | ||
67 | qCDebug(MIMETREEPARSER_LOG) << "Acting as a Interface::BodyPartFormatter!"; | ||
68 | return AsIcon; | ||
69 | } | ||
70 | |||
71 | // unhide the overload with three arguments | ||
72 | using MimeTreeParser::Interface::BodyPartFormatter::format; | ||
73 | |||
74 | void adaptProcessResult(ProcessResult &result) const Q_DECL_OVERRIDE | ||
75 | { | ||
76 | result.setNeverDisplayInline(true); | ||
77 | } | ||
78 | static const MimeTreeParser::Interface::BodyPartFormatter *create() | ||
79 | { | ||
80 | if (!self) { | ||
81 | self = new AnyTypeBodyPartFormatter(); | ||
82 | } | ||
83 | return self; | ||
84 | } | ||
85 | }; | ||
86 | |||
87 | const AnyTypeBodyPartFormatter *AnyTypeBodyPartFormatter::self = nullptr; | ||
88 | |||
89 | class ImageTypeBodyPartFormatter | ||
90 | : public MimeTreeParser::Interface::BodyPartFormatter | ||
91 | { | ||
92 | static const ImageTypeBodyPartFormatter *self; | ||
93 | public: | ||
94 | Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE | ||
95 | { | ||
96 | return AsIcon; | ||
97 | } | ||
98 | |||
99 | // unhide the overload with three arguments | ||
100 | using MimeTreeParser::Interface::BodyPartFormatter::format; | ||
101 | |||
102 | void adaptProcessResult(ProcessResult &result) const Q_DECL_OVERRIDE | ||
103 | { | ||
104 | result.setNeverDisplayInline(false); | ||
105 | result.setIsImage(true); | ||
106 | } | ||
107 | static const MimeTreeParser::Interface::BodyPartFormatter *create() | ||
108 | { | ||
109 | if (!self) { | ||
110 | self = new ImageTypeBodyPartFormatter(); | ||
111 | } | ||
112 | return self; | ||
113 | } | ||
114 | }; | ||
115 | |||
116 | const ImageTypeBodyPartFormatter *ImageTypeBodyPartFormatter::self = nullptr; | ||
117 | |||
118 | class MessageRfc822BodyPartFormatter | ||
119 | : public MimeTreeParser::Interface::BodyPartFormatter | ||
120 | { | ||
121 | static const MessageRfc822BodyPartFormatter *self; | ||
122 | public: | ||
123 | Interface::MessagePart::Ptr process(Interface::BodyPart &) const Q_DECL_OVERRIDE; | ||
124 | MimeTreeParser::Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
125 | using MimeTreeParser::Interface::BodyPartFormatter::format; | ||
126 | static const MimeTreeParser::Interface::BodyPartFormatter *create(); | ||
127 | }; | ||
128 | |||
129 | const MessageRfc822BodyPartFormatter *MessageRfc822BodyPartFormatter::self; | ||
130 | |||
131 | const MimeTreeParser::Interface::BodyPartFormatter *MessageRfc822BodyPartFormatter::create() | ||
132 | { | ||
133 | if (!self) { | ||
134 | self = new MessageRfc822BodyPartFormatter(); | ||
135 | } | ||
136 | return self; | ||
137 | } | ||
138 | |||
139 | Interface::MessagePart::Ptr MessageRfc822BodyPartFormatter::process(Interface::BodyPart &part) const | ||
140 | { | ||
141 | const KMime::Message::Ptr message = part.content()->bodyAsMessage(); | ||
142 | return MessagePart::Ptr(new EncapsulatedRfc822MessagePart(part.objectTreeParser(), part.content(), message)); | ||
143 | } | ||
144 | |||
145 | Interface::BodyPartFormatter::Result MessageRfc822BodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
146 | { | ||
147 | Q_UNUSED(writer) | ||
148 | const ObjectTreeParser *otp = part->objectTreeParser(); | ||
149 | const auto p = process(*part); | ||
150 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
151 | if (mp) { | ||
152 | if (!otp->attachmentStrategy()->inlineNestedMessages() && !otp->showOnlyOneMimePart()) { | ||
153 | return Failed; | ||
154 | } else { | ||
155 | mp->html(true); | ||
156 | return Ok; | ||
157 | } | ||
158 | } else { | ||
159 | return Failed; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | typedef TextPlainBodyPartFormatter ApplicationPgpBodyPartFormatter; | ||
164 | |||
165 | } // anon namespace | ||
166 | |||
167 | void BodyPartFormatterBaseFactoryPrivate::messageviewer_create_builtin_bodypart_formatters() | ||
168 | { | ||
169 | insert("application", "octet-stream", AnyTypeBodyPartFormatter::create()); | ||
170 | insert("application", "pgp", ApplicationPgpBodyPartFormatter::create()); | ||
171 | insert("application", "pkcs7-mime", ApplicationPkcs7MimeBodyPartFormatter::create()); | ||
172 | insert("application", "x-pkcs7-mime", ApplicationPkcs7MimeBodyPartFormatter::create()); | ||
173 | insert("application", "pgp-encrypted", ApplicationPGPEncryptedBodyPartFormatter::create()); | ||
174 | insert("application", "*", AnyTypeBodyPartFormatter::create()); | ||
175 | |||
176 | insert("text", "html", TextHtmlBodyPartFormatter::create()); | ||
177 | insert("text", "rtf", AnyTypeBodyPartFormatter::create()); | ||
178 | insert("text", "plain", MailmanBodyPartFormatter::create()); | ||
179 | insert("text", "plain", TextPlainBodyPartFormatter::create()); | ||
180 | insert("text", "*", MailmanBodyPartFormatter::create()); | ||
181 | insert("text", "*", TextPlainBodyPartFormatter::create()); | ||
182 | |||
183 | insert("image", "*", ImageTypeBodyPartFormatter::create()); | ||
184 | |||
185 | insert("message", "rfc822", MessageRfc822BodyPartFormatter::create()); | ||
186 | insert("message", "*", AnyTypeBodyPartFormatter::create()); | ||
187 | |||
188 | insert("multipart", "alternative", MultiPartAlternativeBodyPartFormatter::create()); | ||
189 | insert("multipart", "encrypted", MultiPartEncryptedBodyPartFormatter::create()); | ||
190 | insert("multipart", "signed", MultiPartSignedBodyPartFormatter::create()); | ||
191 | insert("multipart", "*", MultiPartMixedBodyPartFormatter::create()); | ||
192 | insert("*", "*", AnyTypeBodyPartFormatter::create()); | ||
193 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/bodypartformatterbasefactory.cpp b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatterbasefactory.cpp new file mode 100644 index 00000000..fb02945b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatterbasefactory.cpp | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | bodypartformatterfactory.cpp | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2004 Marc Mutz <mutz@kde.org>, | ||
6 | Ingo Kloecker <kloecker@kde.org> | ||
7 | |||
8 | KMail is free software; you can redistribute it and/or modify it | ||
9 | under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #include "bodypartformatterbasefactory.h" | ||
35 | #include "bodypartformatterbasefactory_p.h" | ||
36 | #include "mimetreeparser_debug.h" | ||
37 | |||
38 | // Qt | ||
39 | |||
40 | #include <assert.h> | ||
41 | |||
42 | using namespace MimeTreeParser; | ||
43 | |||
44 | BodyPartFormatterBaseFactoryPrivate::BodyPartFormatterBaseFactoryPrivate(BodyPartFormatterBaseFactory *factory) | ||
45 | : q(factory) | ||
46 | , all(nullptr) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | BodyPartFormatterBaseFactoryPrivate::~BodyPartFormatterBaseFactoryPrivate() | ||
51 | { | ||
52 | if (all) { | ||
53 | delete all; | ||
54 | all = nullptr; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | void BodyPartFormatterBaseFactoryPrivate::setup() | ||
59 | { | ||
60 | if (!all) { | ||
61 | all = new TypeRegistry(); | ||
62 | messageviewer_create_builtin_bodypart_formatters(); | ||
63 | q->loadPlugins(); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | void BodyPartFormatterBaseFactoryPrivate::insert(const char *type, const char *subtype, const Interface::BodyPartFormatter *formatter) | ||
68 | { | ||
69 | if (!type || !*type || !subtype || !*subtype || !formatter || !all) { | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | TypeRegistry::iterator type_it = all->find(type); | ||
74 | if (type_it == all->end()) { | ||
75 | qCDebug(MIMETREEPARSER_LOG) << "BodyPartFormatterBaseFactory: instantiating new Subtype Registry for \"" | ||
76 | << type << "\""; | ||
77 | type_it = all->insert(std::make_pair(type, SubtypeRegistry())).first; | ||
78 | assert(type_it != all->end()); | ||
79 | } | ||
80 | |||
81 | SubtypeRegistry &subtype_reg = type_it->second; | ||
82 | |||
83 | subtype_reg.insert(std::make_pair(subtype, formatter)); | ||
84 | } | ||
85 | |||
86 | BodyPartFormatterBaseFactory::BodyPartFormatterBaseFactory() | ||
87 | : d(new BodyPartFormatterBaseFactoryPrivate(this)) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | BodyPartFormatterBaseFactory::~BodyPartFormatterBaseFactory() | ||
92 | { | ||
93 | delete d; | ||
94 | } | ||
95 | |||
96 | void BodyPartFormatterBaseFactory::insert(const char *type, const char *subtype, const Interface::BodyPartFormatter *formatter) | ||
97 | { | ||
98 | d->insert(type, subtype, formatter); | ||
99 | } | ||
100 | |||
101 | const SubtypeRegistry &BodyPartFormatterBaseFactory::subtypeRegistry(const char *type) const | ||
102 | { | ||
103 | if (!type || !*type) { | ||
104 | type = "*"; //krazy:exclude=doublequote_chars | ||
105 | } | ||
106 | |||
107 | d->setup(); | ||
108 | assert(d->all); | ||
109 | |||
110 | static SubtypeRegistry emptyRegistry; | ||
111 | if (d->all->empty()) { | ||
112 | return emptyRegistry; | ||
113 | } | ||
114 | |||
115 | TypeRegistry::const_iterator type_it = d->all->find(type); | ||
116 | if (type_it == d->all->end()) { | ||
117 | type_it = d->all->find("*"); | ||
118 | } | ||
119 | if (type_it == d->all->end()) { | ||
120 | return emptyRegistry; | ||
121 | } | ||
122 | |||
123 | const SubtypeRegistry &subtype_reg = type_it->second; | ||
124 | if (subtype_reg.empty()) { | ||
125 | return emptyRegistry; | ||
126 | } | ||
127 | return subtype_reg; | ||
128 | } | ||
129 | |||
130 | SubtypeRegistry::const_iterator BodyPartFormatterBaseFactory::createForIterator(const char *type, const char *subtype) const | ||
131 | { | ||
132 | if (!type || !*type) { | ||
133 | type = "*"; //krazy:exclude=doublequote_chars | ||
134 | } | ||
135 | if (!subtype || !*subtype) { | ||
136 | subtype = "*"; //krazy:exclude=doublequote_chars | ||
137 | } | ||
138 | |||
139 | d->setup(); | ||
140 | assert(d->all); | ||
141 | |||
142 | if (d->all->empty()) { | ||
143 | return SubtypeRegistry::const_iterator(); | ||
144 | } | ||
145 | |||
146 | TypeRegistry::const_iterator type_it = d->all->find(type); | ||
147 | if (type_it == d->all->end()) { | ||
148 | type_it = d->all->find("*"); | ||
149 | } | ||
150 | if (type_it == d->all->end()) { | ||
151 | return SubtypeRegistry::const_iterator(); | ||
152 | } | ||
153 | |||
154 | const SubtypeRegistry &subtype_reg = type_it->second; | ||
155 | if (subtype_reg.empty()) { | ||
156 | return SubtypeRegistry::const_iterator(); | ||
157 | } | ||
158 | |||
159 | SubtypeRegistry::const_iterator subtype_it = subtype_reg.find(subtype); | ||
160 | qCWarning(MIMETREEPARSER_LOG) << type << subtype << subtype_reg.size(); | ||
161 | if (subtype_it == subtype_reg.end()) { | ||
162 | subtype_it = subtype_reg.find("*"); | ||
163 | } | ||
164 | if (subtype_it == subtype_reg.end()) { | ||
165 | return SubtypeRegistry::const_iterator(); | ||
166 | } | ||
167 | |||
168 | if (!(*subtype_it).second) { | ||
169 | qCWarning(MIMETREEPARSER_LOG) << "BodyPartFormatterBaseFactory: a null bodypart formatter sneaked in for \"" | ||
170 | << type << "/" << subtype << "\"!"; | ||
171 | } | ||
172 | |||
173 | return subtype_it; | ||
174 | } | ||
175 | |||
176 | void BodyPartFormatterBaseFactory::loadPlugins() | ||
177 | { | ||
178 | qCDebug(MIMETREEPARSER_LOG) << "plugin loading is not enabled in libmimetreeparser"; | ||
179 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/bodypartformatterbasefactory.h b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatterbasefactory.h new file mode 100644 index 00000000..2bba551d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatterbasefactory.h | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | bodypartformatterfactory.h | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2004 Marc Mutz <mutz@kde.org>, | ||
6 | Ingo Kloecker <kloecker@kde.org> | ||
7 | |||
8 | KMail is free software; you can redistribute it and/or modify it | ||
9 | under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #ifndef __MIMETREEPARSER_BODYPARTFORMATTERBASEFACTORY_H__ | ||
35 | #define __MIMETREEPARSER_BODYPARTFORMATTERBASEFACTORY_H__ | ||
36 | |||
37 | #include <map> | ||
38 | #include <QByteArray> | ||
39 | |||
40 | namespace MimeTreeParser | ||
41 | { | ||
42 | |||
43 | namespace Interface | ||
44 | { | ||
45 | class BodyPartFormatter; | ||
46 | } | ||
47 | |||
48 | struct ltstr { | ||
49 | bool operator()(const char *s1, const char *s2) const | ||
50 | { | ||
51 | return qstricmp(s1, s2) < 0; | ||
52 | } | ||
53 | }; | ||
54 | |||
55 | typedef std::multimap<const char *, const Interface::BodyPartFormatter *, ltstr> SubtypeRegistry; | ||
56 | typedef std::map<const char *, MimeTreeParser::SubtypeRegistry, MimeTreeParser::ltstr> TypeRegistry; | ||
57 | |||
58 | class BodyPartFormatterBaseFactoryPrivate; | ||
59 | |||
60 | class BodyPartFormatterBaseFactory | ||
61 | { | ||
62 | public: | ||
63 | BodyPartFormatterBaseFactory(); | ||
64 | virtual ~BodyPartFormatterBaseFactory(); | ||
65 | |||
66 | SubtypeRegistry::const_iterator createForIterator(const char *type, const char *subtype) const; | ||
67 | const SubtypeRegistry &subtypeRegistry(const char *type) const; | ||
68 | |||
69 | protected: | ||
70 | void insert(const char *type, const char *subtype, const Interface::BodyPartFormatter *formatter); | ||
71 | virtual void loadPlugins(); | ||
72 | private: | ||
73 | static BodyPartFormatterBaseFactory *mSelf; | ||
74 | |||
75 | BodyPartFormatterBaseFactoryPrivate *d; | ||
76 | friend class BodyPartFormatterBaseFactoryPrivate; | ||
77 | private: | ||
78 | // disabled | ||
79 | const BodyPartFormatterBaseFactory &operator=(const BodyPartFormatterBaseFactory &); | ||
80 | BodyPartFormatterBaseFactory(const BodyPartFormatterBaseFactory &); | ||
81 | }; | ||
82 | |||
83 | } | ||
84 | |||
85 | #endif // __MIMETREEPARSER_BODYPARTFORMATTERFACTORY_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/bodypartformatterbasefactory_p.h b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatterbasefactory_p.h new file mode 100644 index 00000000..1f71f183 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/bodypartformatterbasefactory_p.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* -*- mode: C++; c-file-style: "gnu" -*- | ||
2 | bodypartformatterfactory.h | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2004 Marc Mutz <mutz@kde.org>, | ||
6 | Ingo Kloecker <kloecker@kde.org> | ||
7 | |||
8 | KMail is free software; you can redistribute it and/or modify it | ||
9 | under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #ifndef __MIMETREEPARSER_BODYPARTFORMATTERBASEFACTORY_P_H__ | ||
35 | #define __MIMETREEPARSER_BODYPARTFORMATTERBASEFACTORY_P_H__ | ||
36 | |||
37 | namespace MimeTreeParser | ||
38 | { | ||
39 | class BodyPartFormatterBaseFactory; | ||
40 | |||
41 | class BodyPartFormatterBaseFactoryPrivate | ||
42 | { | ||
43 | public: | ||
44 | BodyPartFormatterBaseFactoryPrivate(BodyPartFormatterBaseFactory *factory); | ||
45 | ~BodyPartFormatterBaseFactoryPrivate(); | ||
46 | |||
47 | void setup(); | ||
48 | void messageviewer_create_builtin_bodypart_formatters(); //defined in bodypartformatter.cpp | ||
49 | void insert(const char *type, const char *subtype, const Interface::BodyPartFormatter *formatter); | ||
50 | |||
51 | BodyPartFormatterBaseFactory *q; | ||
52 | TypeRegistry *all; | ||
53 | }; | ||
54 | |||
55 | } | ||
56 | |||
57 | #endif // __MIMETREEPARSER_BODYPARTFORMATTERFACTORY_P_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/cryptobodypartmemento.cpp b/framework/src/domain/mime/mimetreeparser/otp/cryptobodypartmemento.cpp new file mode 100644 index 00000000..a884ec36 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/cryptobodypartmemento.cpp | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | Copyright (c) 2014-2017 Montel Laurent <montel@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License, version 2, as | ||
6 | published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, but | ||
9 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along | ||
14 | with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
16 | */ | ||
17 | |||
18 | #include "cryptobodypartmemento.h" | ||
19 | |||
20 | using namespace GpgME; | ||
21 | using namespace MimeTreeParser; | ||
22 | |||
23 | CryptoBodyPartMemento::CryptoBodyPartMemento() | ||
24 | : QObject(nullptr), | ||
25 | Interface::BodyPartMemento(), | ||
26 | m_running(false) | ||
27 | { | ||
28 | |||
29 | } | ||
30 | |||
31 | CryptoBodyPartMemento::~CryptoBodyPartMemento() | ||
32 | { | ||
33 | |||
34 | } | ||
35 | |||
36 | bool CryptoBodyPartMemento::isRunning() const | ||
37 | { | ||
38 | return m_running; | ||
39 | } | ||
40 | |||
41 | void CryptoBodyPartMemento::setAuditLog(const Error &err, const QString &log) | ||
42 | { | ||
43 | m_auditLogError = err; | ||
44 | m_auditLog = log; | ||
45 | } | ||
46 | |||
47 | void CryptoBodyPartMemento::setRunning(bool running) | ||
48 | { | ||
49 | m_running = running; | ||
50 | } | ||
51 | |||
52 | void CryptoBodyPartMemento::detach() | ||
53 | { | ||
54 | disconnect(this, SIGNAL(update(MimeTreeParser::UpdateMode)), nullptr, nullptr); | ||
55 | } | ||
56 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/cryptobodypartmemento.h b/framework/src/domain/mime/mimetreeparser/otp/cryptobodypartmemento.h new file mode 100644 index 00000000..076ed890 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/cryptobodypartmemento.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | Copyright (c) 2014-2016 Montel Laurent <montel@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License, version 2, as | ||
6 | published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, but | ||
9 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along | ||
14 | with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef __MIMETREEPARSER_CRYPTOBODYPARTMEMENTO_H__ | ||
19 | #define __MIMETREEPARSER_CRYPTOBODYPARTMEMENTO_H__ | ||
20 | |||
21 | #include <gpgme++/error.h> | ||
22 | |||
23 | #include <QObject> | ||
24 | #include <QString> | ||
25 | |||
26 | #include "bodypart.h" | ||
27 | #include "enums.h" | ||
28 | |||
29 | namespace MimeTreeParser | ||
30 | { | ||
31 | |||
32 | class CryptoBodyPartMemento | ||
33 | : public QObject, | ||
34 | public Interface::BodyPartMemento | ||
35 | { | ||
36 | Q_OBJECT | ||
37 | public: | ||
38 | CryptoBodyPartMemento(); | ||
39 | ~CryptoBodyPartMemento(); | ||
40 | |||
41 | virtual bool start() = 0; | ||
42 | virtual void exec() = 0; | ||
43 | bool isRunning() const; | ||
44 | |||
45 | const QString &auditLogAsHtml() const | ||
46 | { | ||
47 | return m_auditLog; | ||
48 | } | ||
49 | GpgME::Error auditLogError() const | ||
50 | { | ||
51 | return m_auditLogError; | ||
52 | } | ||
53 | |||
54 | void detach() Q_DECL_OVERRIDE; | ||
55 | |||
56 | Q_SIGNALS: | ||
57 | void update(MimeTreeParser::UpdateMode); | ||
58 | |||
59 | protected Q_SLOTS: | ||
60 | void notify() | ||
61 | { | ||
62 | Q_EMIT update(MimeTreeParser::Force); | ||
63 | } | ||
64 | |||
65 | protected: | ||
66 | void setAuditLog(const GpgME::Error &err, const QString &log); | ||
67 | void setRunning(bool running); | ||
68 | |||
69 | private: | ||
70 | bool m_running; | ||
71 | QString m_auditLog; | ||
72 | GpgME::Error m_auditLogError; | ||
73 | }; | ||
74 | } | ||
75 | #endif // __MIMETREEPARSER_CRYPTOBODYPARTMEMENTO_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/cryptohelper.cpp b/framework/src/domain/mime/mimetreeparser/otp/cryptohelper.cpp new file mode 100644 index 00000000..8e5df576 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/cryptohelper.cpp | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | Copyright (C) 2015 Sandro Knauß <knauss@kolabsys.com> | ||
3 | Copyright (C) 2001,2002 the KPGP authors | ||
4 | See file AUTHORS.kpgp for details | ||
5 | |||
6 | Kmail is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | You should have received a copy of the GNU General Public License | ||
12 | along with this program; if not, write to the Free Software Foundation, | ||
13 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA | ||
14 | */ | ||
15 | |||
16 | #include "cryptohelper.h" | ||
17 | |||
18 | using namespace MimeTreeParser; | ||
19 | |||
20 | PGPBlockType Block::determineType() const | ||
21 | { | ||
22 | const QByteArray data = text(); | ||
23 | if (data.startsWith("-----BEGIN PGP SIGNED")) { | ||
24 | return ClearsignedBlock; | ||
25 | } else if (data.startsWith("-----BEGIN PGP SIGNATURE")) { | ||
26 | return SignatureBlock; | ||
27 | } else if (data.startsWith("-----BEGIN PGP PUBLIC")) { | ||
28 | return PublicKeyBlock; | ||
29 | } else if (data.startsWith("-----BEGIN PGP PRIVATE") | ||
30 | || data.startsWith("-----BEGIN PGP SECRET")) { | ||
31 | return PrivateKeyBlock; | ||
32 | } else if (data.startsWith("-----BEGIN PGP MESSAGE")) { | ||
33 | if (data.startsWith("-----BEGIN PGP MESSAGE PART")) { | ||
34 | return MultiPgpMessageBlock; | ||
35 | } else { | ||
36 | return PgpMessageBlock; | ||
37 | } | ||
38 | } else if (data.startsWith("-----BEGIN PGP ARMORED FILE")) { | ||
39 | return PgpMessageBlock; | ||
40 | } else if (data.startsWith("-----BEGIN PGP ")) { | ||
41 | return UnknownBlock; | ||
42 | } else { | ||
43 | return NoPgpBlock; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | QList<Block> MimeTreeParser::prepareMessageForDecryption(const QByteArray &msg) | ||
48 | { | ||
49 | PGPBlockType pgpBlock = NoPgpBlock; | ||
50 | QList<Block> blocks; | ||
51 | int start = -1; // start of the current PGP block | ||
52 | int lastEnd = -1; // end of the last PGP block | ||
53 | const int length = msg.length(); | ||
54 | |||
55 | if (msg.isEmpty()) { | ||
56 | return blocks; | ||
57 | } | ||
58 | |||
59 | if (msg.startsWith("-----BEGIN PGP ")) { | ||
60 | start = 0; | ||
61 | } else { | ||
62 | start = msg.indexOf("\n-----BEGIN PGP ") + 1; | ||
63 | if (start == 0) { | ||
64 | blocks.append(Block(msg, NoPgpBlock)); | ||
65 | return blocks; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | while (start != -1) { | ||
70 | int nextEnd, nextStart; | ||
71 | |||
72 | // is the PGP block a clearsigned block? | ||
73 | if (!strncmp(msg.constData() + start + 15, "SIGNED", 6)) { | ||
74 | pgpBlock = ClearsignedBlock; | ||
75 | } else { | ||
76 | pgpBlock = UnknownBlock; | ||
77 | } | ||
78 | |||
79 | nextEnd = msg.indexOf("\n-----END PGP ", start + 15); | ||
80 | nextStart = msg.indexOf("\n-----BEGIN PGP ", start + 15); | ||
81 | |||
82 | if (nextEnd == -1) { // Missing END PGP line | ||
83 | if (lastEnd != -1) { | ||
84 | blocks.append(Block(msg.mid(lastEnd + 1), UnknownBlock)); | ||
85 | } else { | ||
86 | blocks.append(Block(msg.mid(start), UnknownBlock)); | ||
87 | } | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | if ((nextStart == -1) || (nextEnd < nextStart) || (pgpBlock == ClearsignedBlock)) { | ||
92 | // most likely we found a PGP block (but we don't check if it's valid) | ||
93 | |||
94 | // store the preceding non-PGP block | ||
95 | if (start - lastEnd - 1 > 0) { | ||
96 | blocks.append(Block(msg.mid(lastEnd + 1, start - lastEnd - 1), NoPgpBlock)); | ||
97 | } | ||
98 | |||
99 | lastEnd = msg.indexOf("\n", nextEnd + 14); | ||
100 | if (lastEnd == -1) { | ||
101 | if (start < length) { | ||
102 | blocks.append(Block(msg.mid(start))); | ||
103 | } | ||
104 | break; | ||
105 | } else { | ||
106 | blocks.append(Block(msg.mid(start, lastEnd + 1 - start))); | ||
107 | if ((nextStart != -1) && (nextEnd > nextStart)) { | ||
108 | nextStart = msg.indexOf("\n-----BEGIN PGP ", lastEnd + 1); | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | start = nextStart; | ||
114 | |||
115 | if (start == -1) { | ||
116 | if (lastEnd + 1 < length) { | ||
117 | //rest of mail is no PGP Block | ||
118 | blocks.append(Block(msg.mid(lastEnd + 1), NoPgpBlock)); | ||
119 | } | ||
120 | break; | ||
121 | } else { | ||
122 | start++; // move start behind the '\n' | ||
123 | } | ||
124 | } | ||
125 | |||
126 | return blocks; | ||
127 | } | ||
128 | |||
129 | Block::Block(const QByteArray &m) | ||
130 | : msg(m) | ||
131 | { | ||
132 | mType = determineType(); | ||
133 | } | ||
134 | |||
135 | Block::Block(const QByteArray &m, PGPBlockType t) | ||
136 | : msg(m) | ||
137 | , mType(t) | ||
138 | { | ||
139 | |||
140 | } | ||
141 | |||
142 | QByteArray MimeTreeParser::Block::text() const | ||
143 | { | ||
144 | return msg; | ||
145 | } | ||
146 | |||
147 | PGPBlockType Block::type() const | ||
148 | { | ||
149 | return mType; | ||
150 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/cryptohelper.h b/framework/src/domain/mime/mimetreeparser/otp/cryptohelper.h new file mode 100644 index 00000000..f09771c3 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/cryptohelper.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | cryptohelper.h | ||
3 | |||
4 | Copyright (C) 2015 Sandro Knauß <knauss@kolabsys.com> | ||
5 | Copyright (C) 2001,2002 the KPGP authors | ||
6 | See file AUTHORS.kpgp for details | ||
7 | |||
8 | KMail is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License | ||
14 | along with this program; if not, write to the Free Software Foundation, | ||
15 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA | ||
16 | */ | ||
17 | |||
18 | #ifndef __MIMETREEPARSER_CRYPTOHELPER_H__ | ||
19 | #define __MIMETREEPARSER_CRYPTOHELPER_H__ | ||
20 | |||
21 | #include <QByteArray> | ||
22 | #include <QList> | ||
23 | |||
24 | namespace MimeTreeParser | ||
25 | { | ||
26 | |||
27 | enum PGPBlockType { | ||
28 | UnknownBlock = -1, // BEGIN PGP ??? | ||
29 | NoPgpBlock = 0, | ||
30 | PgpMessageBlock = 1, // BEGIN PGP MESSAGE | ||
31 | MultiPgpMessageBlock = 2, // BEGIN PGP MESSAGE, PART X[/Y] | ||
32 | SignatureBlock = 3, // BEGIN PGP SIGNATURE | ||
33 | ClearsignedBlock = 4, // BEGIN PGP SIGNED MESSAGE | ||
34 | PublicKeyBlock = 5, // BEGIN PGP PUBLIC KEY BLOCK | ||
35 | PrivateKeyBlock = 6 // BEGIN PGP PRIVATE KEY BLOCK (PGP 2.x: ...SECRET...) | ||
36 | }; | ||
37 | |||
38 | class Block | ||
39 | { | ||
40 | public: | ||
41 | Block(const QByteArray &m); | ||
42 | |||
43 | Block(const QByteArray &m, PGPBlockType t); | ||
44 | |||
45 | QByteArray text() const; | ||
46 | PGPBlockType type() const; | ||
47 | PGPBlockType determineType() const; | ||
48 | |||
49 | QByteArray msg; | ||
50 | PGPBlockType mType; | ||
51 | }; | ||
52 | |||
53 | /** Parses the given message and splits it into OpenPGP blocks and | ||
54 | Non-OpenPGP blocks. | ||
55 | */ | ||
56 | QList<Block> prepareMessageForDecryption(const QByteArray &msg); | ||
57 | |||
58 | } // namespace MimeTreeParser | ||
59 | |||
60 | Q_DECLARE_TYPEINFO(MimeTreeParser::Block, Q_MOVABLE_TYPE); | ||
61 | |||
62 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/decryptverifybodypartmemento.cpp b/framework/src/domain/mime/mimetreeparser/otp/decryptverifybodypartmemento.cpp new file mode 100644 index 00000000..9810797a --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/decryptverifybodypartmemento.cpp | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | Copyright (c) 2014-2017 Montel Laurent <montel@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License, version 2, as | ||
6 | published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, but | ||
9 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along | ||
14 | with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
16 | */ | ||
17 | |||
18 | #include "decryptverifybodypartmemento.h" | ||
19 | |||
20 | #include <QGpgME/DecryptVerifyJob> | ||
21 | |||
22 | #include <qstringlist.h> | ||
23 | |||
24 | using namespace QGpgME; | ||
25 | using namespace GpgME; | ||
26 | using namespace MimeTreeParser; | ||
27 | |||
28 | DecryptVerifyBodyPartMemento::DecryptVerifyBodyPartMemento(DecryptVerifyJob *job, const QByteArray &cipherText) | ||
29 | : CryptoBodyPartMemento(), | ||
30 | m_cipherText(cipherText), | ||
31 | m_job(job) | ||
32 | { | ||
33 | Q_ASSERT(m_job); | ||
34 | } | ||
35 | |||
36 | DecryptVerifyBodyPartMemento::~DecryptVerifyBodyPartMemento() | ||
37 | { | ||
38 | if (m_job) { | ||
39 | m_job->slotCancel(); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | bool DecryptVerifyBodyPartMemento::start() | ||
44 | { | ||
45 | Q_ASSERT(m_job); | ||
46 | if (const Error err = m_job->start(m_cipherText)) { | ||
47 | m_dr = DecryptionResult(err); | ||
48 | return false; | ||
49 | } | ||
50 | connect(m_job.data(), &DecryptVerifyJob::result, | ||
51 | this, &DecryptVerifyBodyPartMemento::slotResult); | ||
52 | setRunning(true); | ||
53 | return true; | ||
54 | } | ||
55 | |||
56 | void DecryptVerifyBodyPartMemento::exec() | ||
57 | { | ||
58 | Q_ASSERT(m_job); | ||
59 | QByteArray plainText; | ||
60 | setRunning(true); | ||
61 | const std::pair<DecryptionResult, VerificationResult> p = m_job->exec(m_cipherText, plainText); | ||
62 | saveResult(p.first, p.second, plainText); | ||
63 | m_job->deleteLater(); // exec'ed jobs don't delete themselves | ||
64 | m_job = nullptr; | ||
65 | } | ||
66 | |||
67 | void DecryptVerifyBodyPartMemento::saveResult(const DecryptionResult &dr, | ||
68 | const VerificationResult &vr, | ||
69 | const QByteArray &plainText) | ||
70 | { | ||
71 | Q_ASSERT(m_job); | ||
72 | setRunning(false); | ||
73 | m_dr = dr; | ||
74 | m_vr = vr; | ||
75 | m_plainText = plainText; | ||
76 | setAuditLog(m_job->auditLogError(), m_job->auditLogAsHtml()); | ||
77 | } | ||
78 | |||
79 | void DecryptVerifyBodyPartMemento::slotResult(const DecryptionResult &dr, | ||
80 | const VerificationResult &vr, | ||
81 | const QByteArray &plainText) | ||
82 | { | ||
83 | saveResult(dr, vr, plainText); | ||
84 | m_job = nullptr; | ||
85 | notify(); | ||
86 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/decryptverifybodypartmemento.h b/framework/src/domain/mime/mimetreeparser/otp/decryptverifybodypartmemento.h new file mode 100644 index 00000000..4781abe2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/decryptverifybodypartmemento.h | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | Copyright (c) 2014-2016 Montel Laurent <montel@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License, version 2, as | ||
6 | published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, but | ||
9 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along | ||
14 | with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef __MIMETREEPARSER_DECRYPTVERIFYBODYPARTMEMENTO_H__ | ||
19 | #define __MIMETREEPARSER_DECRYPTVERIFYBODYPARTMEMENTO_H__ | ||
20 | |||
21 | #include "cryptobodypartmemento.h" | ||
22 | |||
23 | #include <gpgme++/verificationresult.h> | ||
24 | #include <gpgme++/decryptionresult.h> | ||
25 | |||
26 | #include <QPointer> | ||
27 | |||
28 | #include "bodypart.h" | ||
29 | |||
30 | namespace QGpgME | ||
31 | { | ||
32 | class DecryptVerifyJob; | ||
33 | } | ||
34 | |||
35 | namespace MimeTreeParser | ||
36 | { | ||
37 | |||
38 | class DecryptVerifyBodyPartMemento | ||
39 | : public CryptoBodyPartMemento | ||
40 | { | ||
41 | Q_OBJECT | ||
42 | public: | ||
43 | DecryptVerifyBodyPartMemento(QGpgME::DecryptVerifyJob *job, const QByteArray &cipherText); | ||
44 | ~DecryptVerifyBodyPartMemento(); | ||
45 | |||
46 | bool start() Q_DECL_OVERRIDE; | ||
47 | void exec() Q_DECL_OVERRIDE; | ||
48 | |||
49 | const QByteArray &plainText() const | ||
50 | { | ||
51 | return m_plainText; | ||
52 | } | ||
53 | const GpgME::DecryptionResult &decryptResult() const | ||
54 | { | ||
55 | return m_dr; | ||
56 | } | ||
57 | const GpgME::VerificationResult &verifyResult() const | ||
58 | { | ||
59 | return m_vr; | ||
60 | } | ||
61 | |||
62 | private Q_SLOTS: | ||
63 | void slotResult(const GpgME::DecryptionResult &dr, | ||
64 | const GpgME::VerificationResult &vr, | ||
65 | const QByteArray &plainText); | ||
66 | |||
67 | private: | ||
68 | void saveResult(const GpgME::DecryptionResult &, | ||
69 | const GpgME::VerificationResult &, | ||
70 | const QByteArray &); | ||
71 | private: | ||
72 | // input: | ||
73 | const QByteArray m_cipherText; | ||
74 | QPointer<QGpgME::DecryptVerifyJob> m_job; | ||
75 | // output: | ||
76 | GpgME::DecryptionResult m_dr; | ||
77 | GpgME::VerificationResult m_vr; | ||
78 | QByteArray m_plainText; | ||
79 | }; | ||
80 | } | ||
81 | #endif // __MIMETREEPARSER_DECRYPTVERIFYBODYPARTMEMENTO_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/enums.h b/framework/src/domain/mime/mimetreeparser/otp/enums.h new file mode 100644 index 00000000..bec5a028 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/enums.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along | ||
15 | with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef __MIMETREEPARSER_ENUMS_H__ | ||
20 | #define __MIMETREEPARSER_ENUMS_H__ | ||
21 | |||
22 | namespace MimeTreeParser | ||
23 | { | ||
24 | |||
25 | /** | ||
26 | * The display update mode: Force updates the display immediately, Delayed updates | ||
27 | * after some time (150ms by default) | ||
28 | */ | ||
29 | enum UpdateMode { | ||
30 | Force = 0, | ||
31 | Delayed | ||
32 | }; | ||
33 | |||
34 | /** Flags for the encryption state. */ | ||
35 | typedef enum { | ||
36 | KMMsgEncryptionStateUnknown = ' ', | ||
37 | KMMsgNotEncrypted = 'N', | ||
38 | KMMsgPartiallyEncrypted = 'P', | ||
39 | KMMsgFullyEncrypted = 'F', | ||
40 | KMMsgEncryptionProblematic = 'X' | ||
41 | } KMMsgEncryptionState; | ||
42 | |||
43 | /** Flags for the signature state. */ | ||
44 | typedef enum { | ||
45 | KMMsgSignatureStateUnknown = ' ', | ||
46 | KMMsgNotSigned = 'N', | ||
47 | KMMsgPartiallySigned = 'P', | ||
48 | KMMsgFullySigned = 'F', | ||
49 | KMMsgSignatureProblematic = 'X' | ||
50 | } KMMsgSignatureState; | ||
51 | |||
52 | } | ||
53 | |||
54 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/filehtmlwriter.cpp b/framework/src/domain/mime/mimetreeparser/otp/filehtmlwriter.cpp new file mode 100644 index 00000000..a143f944 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/filehtmlwriter.cpp | |||
@@ -0,0 +1,119 @@ | |||
1 | /* -*- c++ -*- | ||
2 | filehtmlwriter.cpp | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | |||
7 | KMail is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License, version 2, as | ||
9 | published by the Free Software Foundation. | ||
10 | |||
11 | KMail is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | |||
20 | In addition, as a special exception, the copyright holders give | ||
21 | permission to link the code of this program with any edition of | ||
22 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
23 | of Qt that use the same license as Qt), and distribute linked | ||
24 | combinations including the two. You must obey the GNU General | ||
25 | Public License in all respects for all of the code used other than | ||
26 | Qt. If you modify this file, you may extend this exception to | ||
27 | your version of the file, but you are not obligated to do so. If | ||
28 | you do not wish to do so, delete this exception statement from | ||
29 | your version. | ||
30 | */ | ||
31 | |||
32 | #include "filehtmlwriter.h" | ||
33 | |||
34 | #include "mimetreeparser_debug.h" | ||
35 | |||
36 | namespace MimeTreeParser | ||
37 | { | ||
38 | |||
39 | FileHtmlWriter::FileHtmlWriter(const QString &filename) | ||
40 | : HtmlWriter(), | ||
41 | mFile(filename.isEmpty() ? QStringLiteral("filehtmlwriter.out") : filename) | ||
42 | { | ||
43 | } | ||
44 | |||
45 | FileHtmlWriter::~FileHtmlWriter() | ||
46 | { | ||
47 | if (mFile.isOpen()) { | ||
48 | qCWarning(MIMETREEPARSER_LOG) << "FileHtmlWriter: file still open!"; | ||
49 | mStream.setDevice(nullptr); | ||
50 | mFile.close(); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | void FileHtmlWriter::begin(const QString &css) | ||
55 | { | ||
56 | openOrWarn(); | ||
57 | if (!css.isEmpty()) { | ||
58 | write(QLatin1String("<!-- CSS Definitions \n") + css + QLatin1String("-->\n")); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | void FileHtmlWriter::end() | ||
63 | { | ||
64 | flush(); | ||
65 | mStream.setDevice(nullptr); | ||
66 | mFile.close(); | ||
67 | } | ||
68 | |||
69 | void FileHtmlWriter::reset() | ||
70 | { | ||
71 | if (mFile.isOpen()) { | ||
72 | mStream.setDevice(nullptr); | ||
73 | mFile.close(); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | void FileHtmlWriter::write(const QString &str) | ||
78 | { | ||
79 | mStream << str; | ||
80 | flush(); | ||
81 | } | ||
82 | |||
83 | void FileHtmlWriter::queue(const QString &str) | ||
84 | { | ||
85 | write(str); | ||
86 | } | ||
87 | |||
88 | void FileHtmlWriter::flush() | ||
89 | { | ||
90 | mStream.flush(); | ||
91 | mFile.flush(); | ||
92 | } | ||
93 | |||
94 | void FileHtmlWriter::openOrWarn() | ||
95 | { | ||
96 | if (mFile.isOpen()) { | ||
97 | qCWarning(MIMETREEPARSER_LOG) << "FileHtmlWriter: file still open!"; | ||
98 | mStream.setDevice(nullptr); | ||
99 | mFile.close(); | ||
100 | } | ||
101 | if (!mFile.open(QIODevice::WriteOnly)) { | ||
102 | qCWarning(MIMETREEPARSER_LOG) << "FileHtmlWriter: Cannot open file" << mFile.fileName(); | ||
103 | } else { | ||
104 | mStream.setDevice(&mFile); | ||
105 | mStream.setCodec("UTF-8"); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | void FileHtmlWriter::embedPart(const QByteArray &contentId, const QString &url) | ||
110 | { | ||
111 | mStream << "<!-- embedPart(contentID=" << contentId << ", url=" << url << ") -->" << endl; | ||
112 | flush(); | ||
113 | } | ||
114 | void FileHtmlWriter::extraHead(const QString &) | ||
115 | { | ||
116 | |||
117 | } | ||
118 | |||
119 | } // | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/filehtmlwriter.h b/framework/src/domain/mime/mimetreeparser/otp/filehtmlwriter.h new file mode 100644 index 00000000..5dafb593 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/filehtmlwriter.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* -*- c++ -*- | ||
2 | filehtmlwriter.h | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | |||
7 | KMail is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License, version 2, as | ||
9 | published by the Free Software Foundation. | ||
10 | |||
11 | KMail is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | |||
20 | In addition, as a special exception, the copyright holders give | ||
21 | permission to link the code of this program with any edition of | ||
22 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
23 | of Qt that use the same license as Qt), and distribute linked | ||
24 | combinations including the two. You must obey the GNU General | ||
25 | Public License in all respects for all of the code used other than | ||
26 | Qt. If you modify this file, you may extend this exception to | ||
27 | your version of the file, but you are not obligated to do so. If | ||
28 | you do not wish to do so, delete this exception statement from | ||
29 | your version. | ||
30 | */ | ||
31 | |||
32 | #ifndef __MIMETREEPARSER_FILEHTMLWRITER_H__ | ||
33 | #define __MIMETREEPARSER_FILEHTMLWRITER_H__ | ||
34 | |||
35 | #include "mimetreeparser_export.h" | ||
36 | #include "mimetreeparser/htmlwriter.h" | ||
37 | |||
38 | #include <QFile> | ||
39 | #include <QTextStream> | ||
40 | |||
41 | class QString; | ||
42 | |||
43 | namespace MimeTreeParser | ||
44 | { | ||
45 | |||
46 | class MIMETREEPARSER_EXPORT FileHtmlWriter : public HtmlWriter | ||
47 | { | ||
48 | public: | ||
49 | explicit FileHtmlWriter(const QString &filename); | ||
50 | virtual ~FileHtmlWriter(); | ||
51 | |||
52 | void begin(const QString &cssDefs) Q_DECL_OVERRIDE; | ||
53 | void end() Q_DECL_OVERRIDE; | ||
54 | void reset() Q_DECL_OVERRIDE; | ||
55 | void write(const QString &str) Q_DECL_OVERRIDE; | ||
56 | void queue(const QString &str) Q_DECL_OVERRIDE; | ||
57 | void flush() Q_DECL_OVERRIDE; | ||
58 | void embedPart(const QByteArray &contentId, const QString &url) Q_DECL_OVERRIDE; | ||
59 | void extraHead(const QString &str) Q_DECL_OVERRIDE; | ||
60 | private: | ||
61 | void openOrWarn(); | ||
62 | |||
63 | private: | ||
64 | QFile mFile; | ||
65 | QTextStream mStream; | ||
66 | }; | ||
67 | |||
68 | } // namespace MimeTreeParser | ||
69 | |||
70 | #endif // __MIMETREEPARSER_FILEHTMLWRITER_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/htmlwriter.cpp b/framework/src/domain/mime/mimetreeparser/otp/htmlwriter.cpp new file mode 100644 index 00000000..3c98d997 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/htmlwriter.cpp | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | This file is part of KMail's plugin interface. | ||
3 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
4 | |||
5 | KMail is free software; you can redistribute it and/or modify it | ||
6 | under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | KMail is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | |||
19 | In addition, as a special exception, the copyright holders give | ||
20 | permission to link the code of this program with any edition of | ||
21 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
22 | of Qt that use the same license as Qt), and distribute linked | ||
23 | combinations including the two. You must obey the GNU General | ||
24 | Public License in all respects for all of the code used other than | ||
25 | Qt. If you modify this file, you may extend this exception to | ||
26 | your version of the file, but you are not obligated to do so. If | ||
27 | you do not wish to do so, delete this exception statement from | ||
28 | your version. | ||
29 | */ | ||
30 | |||
31 | #include "htmlwriter.h" | ||
32 | |||
33 | MimeTreeParser::Interface::HtmlWriter::~HtmlWriter() | ||
34 | { | ||
35 | } | ||
36 | |||
37 | MimeTreeParser::HtmlWriter::~HtmlWriter() | ||
38 | { | ||
39 | } | ||
40 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/htmlwriter.h b/framework/src/domain/mime/mimetreeparser/otp/htmlwriter.h new file mode 100644 index 00000000..382c80fb --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/htmlwriter.h | |||
@@ -0,0 +1,125 @@ | |||
1 | /* -*- c++ -*- | ||
2 | interfaces/htmlwriter.h | ||
3 | |||
4 | This file is part of KMail's plugin interface. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | |||
7 | KMail is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | KMail is distributed in the hope that it will be useful, but | ||
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | |||
21 | In addition, as a special exception, the copyright holders give | ||
22 | permission to link the code of this program with any edition of | ||
23 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
24 | of Qt that use the same license as Qt), and distribute linked | ||
25 | combinations including the two. You must obey the GNU General | ||
26 | Public License in all respects for all of the code used other than | ||
27 | Qt. If you modify this file, you may extend this exception to | ||
28 | your version of the file, but you are not obligated to do so. If | ||
29 | you do not wish to do so, delete this exception statement from | ||
30 | your version. | ||
31 | */ | ||
32 | |||
33 | #ifndef __MIMETREEPARSER_INTERFACES_HTMLWRITER_H__ | ||
34 | #define __MIMETREEPARSER_INTERFACES_HTMLWRITER_H__ | ||
35 | |||
36 | class QByteArray; | ||
37 | class QString; | ||
38 | |||
39 | namespace MimeTreeParser | ||
40 | { | ||
41 | /** | ||
42 | * @short An interface for HTML sinks. | ||
43 | * @author Marc Mutz <mutz@kde.org> | ||
44 | * | ||
45 | */ | ||
46 | namespace Interface | ||
47 | { | ||
48 | class HtmlWriter | ||
49 | { | ||
50 | public: | ||
51 | virtual ~HtmlWriter(); | ||
52 | |||
53 | /** Signal the begin of stuff to write, and give the CSS definitions */ | ||
54 | virtual void begin(const QString &cssDefinitions) = 0; | ||
55 | /** Write out a chunk of text. No HTML escaping is performed. */ | ||
56 | virtual void write(const QString &html) = 0; | ||
57 | /** Signal the end of stuff to write. */ | ||
58 | virtual void end() = 0; | ||
59 | }; | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * @short An interface to HTML sinks | ||
64 | * @author Marc Mutz <mutz@kde.org> | ||
65 | * | ||
66 | * @deprecated KMail should be ported to Interface::HtmlWriter. This | ||
67 | * interface exposes internal working models. The queuing | ||
68 | * vs. writing() issues exposed here should be hidden by using two | ||
69 | * different implementations of KHTMLPartHtmlWriter: one for | ||
70 | * queuing, and one for writing. This should be fixed before the | ||
71 | * release, so we an keep the plugin interface stable. | ||
72 | * | ||
73 | * Operate this interface in one and only one of the following two | ||
74 | * modes: | ||
75 | * | ||
76 | * @section Sync Mode | ||
77 | * | ||
78 | * In sync mode, use #begin() to initiate a session, then | ||
79 | * #write() some chunks of HTML code and finally #end() the session. | ||
80 | * | ||
81 | * @section Async Mode | ||
82 | * | ||
83 | * In async mode, use #begin() to initialize a session, then | ||
84 | * #queue() some chunks of HTML code and finally end the | ||
85 | * session by calling #flush(). | ||
86 | * | ||
87 | * Queued HTML code is fed to the html sink using a timer. For this | ||
88 | * to work, control must return to the event loop so timer events | ||
89 | * are delivered. | ||
90 | * | ||
91 | * @section Combined mode | ||
92 | * | ||
93 | * You may combine the two modes in the following way only. Any | ||
94 | * number of #write() calls can precede #queue() calls, | ||
95 | * but once a chunk has been queued, you @em must @em not | ||
96 | * #write() more data, only #queue() it. | ||
97 | * | ||
98 | * Naturally, whenever you queued data in a given session, that | ||
99 | * session must be ended by calling #flush(), not #end(). | ||
100 | */ | ||
101 | class HtmlWriter : public Interface::HtmlWriter | ||
102 | { | ||
103 | public: | ||
104 | virtual ~HtmlWriter(); | ||
105 | |||
106 | /** Stop all possibly pending processing in order to be able to | ||
107 | * call #begin() again. */ | ||
108 | virtual void reset() = 0; | ||
109 | |||
110 | virtual void queue(const QString &str) = 0; | ||
111 | /** (Start) flushing internal buffers, if any. */ | ||
112 | virtual void flush() = 0; | ||
113 | |||
114 | /** | ||
115 | * Embed a part with Content-ID @p contentId, using url @p url. | ||
116 | */ | ||
117 | virtual void embedPart(const QByteArray &contentId, const QString &url) = 0; | ||
118 | |||
119 | virtual void extraHead(const QString &str) = 0; | ||
120 | }; | ||
121 | |||
122 | } | ||
123 | |||
124 | #endif // __MIMETREEPARSER_INTERFACES_HTMLWRITER_H__ | ||
125 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/mailman.cpp b/framework/src/domain/mime/mimetreeparser/otp/mailman.cpp new file mode 100644 index 00000000..e79ef0fa --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/mailman.cpp | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "mailman.h" | ||
21 | |||
22 | #include "utils.h" | ||
23 | |||
24 | #include "objecttreeparser.h" | ||
25 | #include "messagepart.h" | ||
26 | |||
27 | #include <KMime/Content> | ||
28 | |||
29 | #include "mimetreeparser_debug.h" | ||
30 | |||
31 | using namespace MimeTreeParser; | ||
32 | |||
33 | const MailmanBodyPartFormatter *MailmanBodyPartFormatter::self; | ||
34 | |||
35 | const Interface::BodyPartFormatter *MailmanBodyPartFormatter::create() | ||
36 | { | ||
37 | if (!self) { | ||
38 | self = new MailmanBodyPartFormatter(); | ||
39 | } | ||
40 | return self; | ||
41 | } | ||
42 | Interface::BodyPartFormatter::Result MailmanBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
43 | { | ||
44 | Q_UNUSED(writer) | ||
45 | const auto p = process(*part); | ||
46 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
47 | if (mp) { | ||
48 | mp->html(false); | ||
49 | return Ok; | ||
50 | } | ||
51 | return Failed; | ||
52 | } | ||
53 | |||
54 | bool MailmanBodyPartFormatter::isMailmanMessage(KMime::Content *curNode) const | ||
55 | { | ||
56 | if (!curNode || curNode->head().isEmpty()) { | ||
57 | return false; | ||
58 | } | ||
59 | if (curNode->hasHeader("X-Mailman-Version")) { | ||
60 | return true; | ||
61 | } | ||
62 | if (KMime::Headers::Base *header = curNode->headerByType("X-Mailer")) { | ||
63 | if (header->asUnicodeString().contains(QStringLiteral("MAILMAN"), Qt::CaseInsensitive)) { | ||
64 | return true; | ||
65 | } | ||
66 | } | ||
67 | return false; | ||
68 | } | ||
69 | |||
70 | Interface::MessagePart::Ptr MailmanBodyPartFormatter::process(Interface::BodyPart &part) const | ||
71 | { | ||
72 | KMime::Content *curNode = part.content(); | ||
73 | |||
74 | if (!isMailmanMessage(curNode)) { | ||
75 | return MessagePart::Ptr(); | ||
76 | } | ||
77 | |||
78 | const QString str = QString::fromLatin1(curNode->decodedContent()); | ||
79 | |||
80 | //### | ||
81 | const QLatin1String delim1("--__--__--\n\nMessage:"); | ||
82 | const QLatin1String delim2("--__--__--\r\n\r\nMessage:"); | ||
83 | const QLatin1String delimZ2("--__--__--\n\n_____________"); | ||
84 | const QLatin1String delimZ1("--__--__--\r\n\r\n_____________"); | ||
85 | QString partStr, digestHeaderStr; | ||
86 | int thisDelim = str.indexOf(delim1, Qt::CaseInsensitive); | ||
87 | if (thisDelim == -1) { | ||
88 | thisDelim = str.indexOf(delim2, Qt::CaseInsensitive); | ||
89 | } | ||
90 | if (thisDelim == -1) { | ||
91 | return MessagePart::Ptr(); | ||
92 | } | ||
93 | |||
94 | int nextDelim = str.indexOf(delim1, thisDelim + 1, Qt::CaseInsensitive); | ||
95 | if (-1 == nextDelim) { | ||
96 | nextDelim = str.indexOf(delim2, thisDelim + 1, Qt::CaseInsensitive); | ||
97 | } | ||
98 | if (-1 == nextDelim) { | ||
99 | nextDelim = str.indexOf(delimZ1, thisDelim + 1, Qt::CaseInsensitive); | ||
100 | } | ||
101 | if (-1 == nextDelim) { | ||
102 | nextDelim = str.indexOf(delimZ2, thisDelim + 1, Qt::CaseInsensitive); | ||
103 | } | ||
104 | if (nextDelim < 0) { | ||
105 | return MessagePart::Ptr(); | ||
106 | } | ||
107 | |||
108 | //if ( curNode->mRoot ) | ||
109 | // curNode = curNode->mRoot; | ||
110 | |||
111 | // at least one message found: build a mime tree | ||
112 | digestHeaderStr = QStringLiteral("Content-Type: text/plain\nContent-Description: digest header\n\n"); | ||
113 | digestHeaderStr += str.midRef(0, thisDelim); | ||
114 | |||
115 | MessagePartList::Ptr mpl(new MessagePartList(part.objectTreeParser())); | ||
116 | mpl->appendSubPart(createAndParseTempNode(part, part.topLevelContent(), digestHeaderStr.toLatin1().constData(), "Digest Header")); | ||
117 | //mReader->queueHtml("<br><hr><br>"); | ||
118 | // temporarily change curent node's Content-Type | ||
119 | // to get our embedded RfC822 messages properly inserted | ||
120 | curNode->contentType()->setMimeType("multipart/digest"); | ||
121 | while (-1 < nextDelim) { | ||
122 | int thisEoL = str.indexOf(QLatin1String("\nMessage:"), thisDelim, Qt::CaseInsensitive); | ||
123 | if (-1 < thisEoL) { | ||
124 | thisDelim = thisEoL + 1; | ||
125 | } else { | ||
126 | thisEoL = str.indexOf(QLatin1String("\n_____________"), thisDelim, Qt::CaseInsensitive); | ||
127 | if (-1 < thisEoL) { | ||
128 | thisDelim = thisEoL + 1; | ||
129 | } | ||
130 | } | ||
131 | thisEoL = str.indexOf(QLatin1Char('\n'), thisDelim); | ||
132 | if (-1 < thisEoL) { | ||
133 | thisDelim = thisEoL + 1; | ||
134 | } else { | ||
135 | thisDelim = thisDelim + 1; | ||
136 | } | ||
137 | //while( thisDelim < cstr.size() && '\n' == cstr[thisDelim] ) | ||
138 | // ++thisDelim; | ||
139 | |||
140 | partStr = QStringLiteral("Content-Type: message/rfc822\nContent-Description: embedded message\n\n"); | ||
141 | partStr += str.midRef(thisDelim, nextDelim - thisDelim); | ||
142 | QString subject = QStringLiteral("embedded message"); | ||
143 | QString subSearch = QStringLiteral("\nSubject:"); | ||
144 | int subPos = partStr.indexOf(subSearch, 0, Qt::CaseInsensitive); | ||
145 | if (-1 < subPos) { | ||
146 | subject = partStr.mid(subPos + subSearch.length()); | ||
147 | thisEoL = subject.indexOf(QLatin1Char('\n')); | ||
148 | if (-1 < thisEoL) { | ||
149 | subject.truncate(thisEoL); | ||
150 | } | ||
151 | } | ||
152 | qCDebug(MIMETREEPARSER_LOG) << " embedded message found: \"" << subject; | ||
153 | mpl->appendSubPart(createAndParseTempNode(part, part.topLevelContent(), partStr.toLatin1().constData(), subject.toLatin1().constData())); | ||
154 | //mReader->queueHtml("<br><hr><br>"); | ||
155 | thisDelim = nextDelim + 1; | ||
156 | nextDelim = str.indexOf(delim1, thisDelim, Qt::CaseInsensitive); | ||
157 | if (-1 == nextDelim) { | ||
158 | nextDelim = str.indexOf(delim2, thisDelim, Qt::CaseInsensitive); | ||
159 | } | ||
160 | if (-1 == nextDelim) { | ||
161 | nextDelim = str.indexOf(delimZ1, thisDelim, Qt::CaseInsensitive); | ||
162 | } | ||
163 | if (-1 == nextDelim) { | ||
164 | nextDelim = str.indexOf(delimZ2, thisDelim, Qt::CaseInsensitive); | ||
165 | } | ||
166 | } | ||
167 | // reset curent node's Content-Type | ||
168 | curNode->contentType()->setMimeType("text/plain"); | ||
169 | int thisEoL = str.indexOf(QLatin1String("_____________"), thisDelim); | ||
170 | if (-1 < thisEoL) { | ||
171 | thisDelim = thisEoL; | ||
172 | thisEoL = str.indexOf(QLatin1Char('\n'), thisDelim); | ||
173 | if (-1 < thisEoL) { | ||
174 | thisDelim = thisEoL + 1; | ||
175 | } | ||
176 | } else { | ||
177 | thisDelim = thisDelim + 1; | ||
178 | } | ||
179 | partStr = QStringLiteral("Content-Type: text/plain\nContent-Description: digest footer\n\n"); | ||
180 | partStr += str.midRef(thisDelim); | ||
181 | mpl->appendSubPart(createAndParseTempNode(part, part.topLevelContent(), partStr.toLatin1().constData(), "Digest Footer")); | ||
182 | return mpl; | ||
183 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/mailman.h b/framework/src/domain/mime/mimetreeparser/otp/mailman.h new file mode 100644 index 00000000..742830b2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/mailman.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_MAILMAN_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_MAILMAN_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "bodypart.h" | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class MailmanBodyPartFormatter : public Interface::BodyPartFormatter | ||
30 | { | ||
31 | static const MailmanBodyPartFormatter *self; | ||
32 | public: | ||
33 | Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; | ||
34 | Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
35 | using Interface::BodyPartFormatter::format; | ||
36 | static const Interface::BodyPartFormatter *create(); | ||
37 | |||
38 | private: | ||
39 | bool isMailmanMessage(KMime::Content *curNode) const; | ||
40 | }; | ||
41 | |||
42 | } | ||
43 | |||
44 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/messagepart.cpp b/framework/src/domain/mime/mimetreeparser/otp/messagepart.cpp new file mode 100644 index 00000000..3228a387 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/messagepart.cpp | |||
@@ -0,0 +1,1352 @@ | |||
1 | /* | ||
2 | Copyright (c) 2015 Sandro Knauß <sknauss@kde.org> | ||
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 "messagepart.h" | ||
21 | #include "mimetreeparser_debug.h" | ||
22 | #include "attachmentstrategy.h" | ||
23 | #include "cryptohelper.h" | ||
24 | #include "objecttreeparser.h" | ||
25 | #include "htmlwriter.h" | ||
26 | #include "qgpgmejobexecutor.h" | ||
27 | |||
28 | #include "cryptobodypartmemento.h" | ||
29 | #include "decryptverifybodypartmemento.h" | ||
30 | #include "verifydetachedbodypartmemento.h" | ||
31 | #include "verifyopaquebodypartmemento.h" | ||
32 | |||
33 | #include "utils.h" | ||
34 | |||
35 | #include <KMime/Content> | ||
36 | |||
37 | #include <QGpgME/DN> | ||
38 | #include <QGpgME/Protocol> | ||
39 | #include <QGpgME/ImportJob> | ||
40 | #include <QGpgME/KeyListJob> | ||
41 | #include <QGpgME/VerifyDetachedJob> | ||
42 | #include <QGpgME/VerifyOpaqueJob> | ||
43 | |||
44 | #include <gpgme++/key.h> | ||
45 | #include <gpgme++/keylistresult.h> | ||
46 | #include <gpgme.h> | ||
47 | |||
48 | #include <KLocalizedString> | ||
49 | |||
50 | #include <QTextCodec> | ||
51 | |||
52 | using namespace MimeTreeParser; | ||
53 | |||
54 | //------MessagePart----------------------- | ||
55 | MessagePart::MessagePart(ObjectTreeParser *otp, | ||
56 | const QString &text) | ||
57 | : mText(text) | ||
58 | , mOtp(otp) | ||
59 | , mAttachmentNode(nullptr) | ||
60 | , mRoot(false) | ||
61 | { | ||
62 | } | ||
63 | |||
64 | MessagePart::~MessagePart() | ||
65 | { | ||
66 | } | ||
67 | |||
68 | PartMetaData *MessagePart::partMetaData() | ||
69 | { | ||
70 | return &mMetaData; | ||
71 | } | ||
72 | |||
73 | void MessagePart::setAttachmentFlag(KMime::Content *node) | ||
74 | { | ||
75 | mAttachmentNode = node; | ||
76 | } | ||
77 | |||
78 | bool MessagePart::isAttachment() const | ||
79 | { | ||
80 | return mAttachmentNode; | ||
81 | } | ||
82 | |||
83 | KMime::Content *MessagePart::attachmentNode() const | ||
84 | { | ||
85 | return mAttachmentNode; | ||
86 | } | ||
87 | |||
88 | void MessagePart::setIsRoot(bool root) | ||
89 | { | ||
90 | mRoot = root; | ||
91 | } | ||
92 | |||
93 | bool MessagePart::isRoot() const | ||
94 | { | ||
95 | return mRoot; | ||
96 | } | ||
97 | |||
98 | QString MessagePart::text() const | ||
99 | { | ||
100 | return mText; | ||
101 | } | ||
102 | |||
103 | void MessagePart::setText(const QString &text) | ||
104 | { | ||
105 | mText = text; | ||
106 | } | ||
107 | |||
108 | bool MessagePart::isHtml() const | ||
109 | { | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | bool MessagePart::isHidden() const | ||
114 | { | ||
115 | return false; | ||
116 | } | ||
117 | |||
118 | Interface::ObjectTreeSource *MessagePart::source() const | ||
119 | { | ||
120 | Q_ASSERT(mOtp); | ||
121 | return mOtp->mSource; | ||
122 | } | ||
123 | |||
124 | HtmlWriter *MessagePart::htmlWriter() const | ||
125 | { | ||
126 | Q_ASSERT(mOtp); | ||
127 | return mOtp->htmlWriter(); | ||
128 | } | ||
129 | |||
130 | void MessagePart::setHtmlWriter(HtmlWriter *htmlWriter) const | ||
131 | { | ||
132 | mOtp->mHtmlWriter = htmlWriter; | ||
133 | } | ||
134 | |||
135 | void MessagePart::parseInternal(KMime::Content *node, bool onlyOneMimePart) | ||
136 | { | ||
137 | auto subMessagePart = mOtp->parseObjectTreeInternal(node, onlyOneMimePart); | ||
138 | mRoot = subMessagePart->isRoot(); | ||
139 | foreach (const auto &part, subMessagePart->subParts()) { | ||
140 | appendSubPart(part); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | QString MessagePart::renderInternalText() const | ||
145 | { | ||
146 | QString text; | ||
147 | foreach (const auto &mp, subParts()) { | ||
148 | text += mp->text(); | ||
149 | } | ||
150 | return text; | ||
151 | } | ||
152 | |||
153 | void MessagePart::copyContentFrom() const | ||
154 | { | ||
155 | foreach (const auto &mp, subParts()) { | ||
156 | const auto m = mp.dynamicCast<MessagePart>(); | ||
157 | if (m) { | ||
158 | m->copyContentFrom(); | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | void MessagePart::fix() const | ||
164 | { | ||
165 | foreach (const auto &mp, subParts()) { | ||
166 | const auto m = mp.dynamicCast<MessagePart>(); | ||
167 | if (m) { | ||
168 | m->fix(); | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | |||
173 | void MessagePart::appendSubPart(const Interface::MessagePart::Ptr &messagePart) | ||
174 | { | ||
175 | messagePart->setParentPart(this); | ||
176 | mBlocks.append(messagePart); | ||
177 | } | ||
178 | |||
179 | const QVector<Interface::MessagePart::Ptr> &MessagePart::subParts() const | ||
180 | { | ||
181 | return mBlocks; | ||
182 | } | ||
183 | |||
184 | bool MessagePart::hasSubParts() const | ||
185 | { | ||
186 | return !mBlocks.isEmpty(); | ||
187 | } | ||
188 | |||
189 | //-----MessagePartList---------------------- | ||
190 | MessagePartList::MessagePartList(ObjectTreeParser *otp) | ||
191 | : MessagePart(otp, QString()) | ||
192 | { | ||
193 | } | ||
194 | |||
195 | MessagePartList::~MessagePartList() | ||
196 | { | ||
197 | |||
198 | } | ||
199 | |||
200 | QString MessagePartList::text() const | ||
201 | { | ||
202 | return renderInternalText(); | ||
203 | } | ||
204 | |||
205 | QString MessagePartList::plaintextContent() const | ||
206 | { | ||
207 | return QString(); | ||
208 | } | ||
209 | |||
210 | QString MessagePartList::htmlContent() const | ||
211 | { | ||
212 | return QString(); | ||
213 | } | ||
214 | |||
215 | //-----TextMessageBlock---------------------- | ||
216 | |||
217 | TextMessagePart::TextMessagePart(ObjectTreeParser *otp, KMime::Content *node, bool drawFrame, bool showLink, bool decryptMessage) | ||
218 | : MessagePartList(otp) | ||
219 | , mNode(node) | ||
220 | , mDrawFrame(drawFrame) | ||
221 | , mShowLink(showLink) | ||
222 | , mDecryptMessage(decryptMessage) | ||
223 | , mIsHidden(false) | ||
224 | { | ||
225 | if (!mNode) { | ||
226 | qCWarning(MIMETREEPARSER_LOG) << "not a valid node"; | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | mIsHidden = mOtp->nodeHelper()->isNodeDisplayedHidden(mNode); | ||
231 | |||
232 | parseContent(); | ||
233 | } | ||
234 | |||
235 | TextMessagePart::~TextMessagePart() | ||
236 | { | ||
237 | |||
238 | } | ||
239 | |||
240 | bool TextMessagePart::decryptMessage() const | ||
241 | { | ||
242 | return mDecryptMessage; | ||
243 | } | ||
244 | |||
245 | void TextMessagePart::parseContent() | ||
246 | { | ||
247 | const auto aCodec = mOtp->codecFor(mNode); | ||
248 | const QString &fromAddress = mOtp->nodeHelper()->fromAsString(mNode); | ||
249 | mSignatureState = KMMsgNotSigned; | ||
250 | mEncryptionState = KMMsgNotEncrypted; | ||
251 | const auto blocks = prepareMessageForDecryption(mNode->decodedContent()); | ||
252 | |||
253 | const auto cryptProto = QGpgME::openpgp(); | ||
254 | |||
255 | if (!blocks.isEmpty()) { | ||
256 | |||
257 | /* The (overall) signature/encrypted status is broken | ||
258 | * if one unencrypted part is at the beginning or in the middle | ||
259 | * because mailmain adds an unencrypted part at the end this should not break the overall status | ||
260 | * | ||
261 | * That's why we first set the tmp status and if one crypted/signed block comes afterwards, than | ||
262 | * the status is set to unencryped | ||
263 | */ | ||
264 | bool fullySignedOrEncrypted = true; | ||
265 | bool fullySignedOrEncryptedTmp = true; | ||
266 | |||
267 | for (const auto &block : blocks) { | ||
268 | |||
269 | if (!fullySignedOrEncryptedTmp) { | ||
270 | fullySignedOrEncrypted = false; | ||
271 | } | ||
272 | |||
273 | if (block.type() == NoPgpBlock && !block.text().trimmed().isEmpty()) { | ||
274 | fullySignedOrEncryptedTmp = false; | ||
275 | appendSubPart(MessagePart::Ptr(new MessagePart(mOtp, aCodec->toUnicode(block.text())))); | ||
276 | } else if (block.type() == PgpMessageBlock) { | ||
277 | EncryptedMessagePart::Ptr mp(new EncryptedMessagePart(mOtp, QString(), cryptProto, fromAddress, nullptr)); | ||
278 | mp->setDecryptMessage(decryptMessage()); | ||
279 | mp->setIsEncrypted(true); | ||
280 | appendSubPart(mp); | ||
281 | if (!decryptMessage()) { | ||
282 | continue; | ||
283 | } | ||
284 | mp->startDecryption(block.text(), aCodec); | ||
285 | if (mp->partMetaData()->inProgress) { | ||
286 | continue; | ||
287 | } | ||
288 | } else if (block.type() == ClearsignedBlock) { | ||
289 | SignedMessagePart::Ptr mp(new SignedMessagePart(mOtp, QString(), cryptProto, fromAddress, nullptr)); | ||
290 | appendSubPart(mp); | ||
291 | mp->startVerification(block.text(), aCodec); | ||
292 | } else { | ||
293 | continue; | ||
294 | } | ||
295 | |||
296 | const auto mp = subParts().last().staticCast<MessagePart>(); | ||
297 | const PartMetaData *messagePart(mp->partMetaData()); | ||
298 | |||
299 | if (!messagePart->isEncrypted && !messagePart->isSigned && !block.text().trimmed().isEmpty()) { | ||
300 | mp->setText(aCodec->toUnicode(block.text())); | ||
301 | } | ||
302 | |||
303 | if (messagePart->isEncrypted) { | ||
304 | mEncryptionState = KMMsgPartiallyEncrypted; | ||
305 | } | ||
306 | |||
307 | if (messagePart->isSigned) { | ||
308 | mSignatureState = KMMsgPartiallySigned; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | //Do we have an fully Signed/Encrypted Message? | ||
313 | if (fullySignedOrEncrypted) { | ||
314 | if (mSignatureState == KMMsgPartiallySigned) { | ||
315 | mSignatureState = KMMsgFullySigned; | ||
316 | } | ||
317 | if (mEncryptionState == KMMsgPartiallyEncrypted) { | ||
318 | mEncryptionState = KMMsgFullyEncrypted; | ||
319 | } | ||
320 | } | ||
321 | } | ||
322 | } | ||
323 | |||
324 | KMMsgEncryptionState TextMessagePart::encryptionState() const | ||
325 | { | ||
326 | return mEncryptionState; | ||
327 | } | ||
328 | |||
329 | KMMsgSignatureState TextMessagePart::signatureState() const | ||
330 | { | ||
331 | return mSignatureState; | ||
332 | } | ||
333 | |||
334 | bool TextMessagePart::isHidden() const | ||
335 | { | ||
336 | return mIsHidden; | ||
337 | } | ||
338 | |||
339 | bool TextMessagePart::showLink() const | ||
340 | { | ||
341 | return mShowLink; | ||
342 | } | ||
343 | |||
344 | bool TextMessagePart::showTextFrame() const | ||
345 | { | ||
346 | return mDrawFrame; | ||
347 | } | ||
348 | |||
349 | //-----AttachmentMessageBlock---------------------- | ||
350 | |||
351 | AttachmentMessagePart::AttachmentMessagePart(ObjectTreeParser *otp, KMime::Content *node, bool drawFrame, bool showLink, bool decryptMessage) | ||
352 | : TextMessagePart(otp, node, drawFrame, showLink, decryptMessage) | ||
353 | , mIsImage(false) | ||
354 | , mNeverDisplayInline(false) | ||
355 | { | ||
356 | |||
357 | } | ||
358 | |||
359 | AttachmentMessagePart::~AttachmentMessagePart() | ||
360 | { | ||
361 | |||
362 | } | ||
363 | |||
364 | bool AttachmentMessagePart::neverDisplayInline() const | ||
365 | { | ||
366 | return mNeverDisplayInline; | ||
367 | } | ||
368 | |||
369 | void AttachmentMessagePart::setNeverDisplayInline(bool displayInline) | ||
370 | { | ||
371 | mNeverDisplayInline = displayInline; | ||
372 | } | ||
373 | |||
374 | bool AttachmentMessagePart::isImage() const | ||
375 | { | ||
376 | return mIsImage; | ||
377 | } | ||
378 | |||
379 | void AttachmentMessagePart::setIsImage(bool image) | ||
380 | { | ||
381 | mIsImage = image; | ||
382 | } | ||
383 | |||
384 | IconType AttachmentMessagePart::asIcon() const | ||
385 | { | ||
386 | const AttachmentStrategy *const as = mOtp->attachmentStrategy(); | ||
387 | const bool defaultHidden(as && as->defaultDisplay(mNode) == AttachmentStrategy::None); | ||
388 | const bool showOnlyOneMimePart(mOtp->showOnlyOneMimePart()); | ||
389 | auto preferredMode = source()->preferredMode(); | ||
390 | bool isHtmlPreferred = (preferredMode == Util::Html) || (preferredMode == Util::MultipartHtml); | ||
391 | |||
392 | QByteArray mediaType("text"); | ||
393 | QByteArray subType("plain"); | ||
394 | if (mNode->contentType(false) && !mNode->contentType()->mediaType().isEmpty() && | ||
395 | !mNode->contentType()->subType().isEmpty()) { | ||
396 | mediaType = mNode->contentType()->mediaType(); | ||
397 | subType = mNode->contentType()->subType(); | ||
398 | } | ||
399 | const bool isTextPart = (mediaType == QByteArrayLiteral("text")); | ||
400 | |||
401 | bool defaultAsIcon = true; | ||
402 | if (!neverDisplayInline()) { | ||
403 | if (as) { | ||
404 | defaultAsIcon = as->defaultDisplay(mNode) == AttachmentStrategy::AsIcon; | ||
405 | } | ||
406 | } | ||
407 | if (isImage() && showOnlyOneMimePart && !neverDisplayInline()) { | ||
408 | defaultAsIcon = false; | ||
409 | } | ||
410 | |||
411 | // neither image nor text -> show as icon | ||
412 | if (!isImage() && !isTextPart) { | ||
413 | defaultAsIcon = true; | ||
414 | } | ||
415 | |||
416 | if (isTextPart) { | ||
417 | if (as && as->defaultDisplay(mNode) != AttachmentStrategy::Inline) { | ||
418 | return MimeTreeParser::IconExternal; | ||
419 | } | ||
420 | return MimeTreeParser::NoIcon; | ||
421 | } else { | ||
422 | if (isImage() && isHtmlPreferred && | ||
423 | mNode->parent() && mNode->parent()->contentType()->subType() == "related") { | ||
424 | return MimeTreeParser::IconInline; | ||
425 | } | ||
426 | |||
427 | if (defaultHidden && !showOnlyOneMimePart && mNode->parent()) { | ||
428 | return MimeTreeParser::IconInline; | ||
429 | } | ||
430 | |||
431 | if (defaultAsIcon) { | ||
432 | return MimeTreeParser::IconExternal; | ||
433 | } else if (isImage()) { | ||
434 | return MimeTreeParser::IconInline; | ||
435 | } else { | ||
436 | return MimeTreeParser::NoIcon; | ||
437 | } | ||
438 | } | ||
439 | } | ||
440 | |||
441 | bool AttachmentMessagePart::isHidden() const | ||
442 | { | ||
443 | const AttachmentStrategy *const as = mOtp->attachmentStrategy(); | ||
444 | const bool defaultHidden(as && as->defaultDisplay(mNode) == AttachmentStrategy::None); | ||
445 | const bool showOnlyOneMimePart(mOtp->showOnlyOneMimePart()); | ||
446 | auto preferredMode = source()->preferredMode(); | ||
447 | bool isHtmlPreferred = (preferredMode == Util::Html) || (preferredMode == Util::MultipartHtml); | ||
448 | |||
449 | QByteArray mediaType("text"); | ||
450 | QByteArray subType("plain"); | ||
451 | if (mNode->contentType(false) && !mNode->contentType()->mediaType().isEmpty() && | ||
452 | !mNode->contentType()->subType().isEmpty()) { | ||
453 | mediaType = mNode->contentType()->mediaType(); | ||
454 | subType = mNode->contentType()->subType(); | ||
455 | } | ||
456 | const bool isTextPart = (mediaType == QByteArrayLiteral("text")); | ||
457 | |||
458 | bool defaultAsIcon = true; | ||
459 | if (!neverDisplayInline()) { | ||
460 | if (as) { | ||
461 | defaultAsIcon = as->defaultDisplay(mNode) == AttachmentStrategy::AsIcon; | ||
462 | } | ||
463 | } | ||
464 | if (isImage() && showOnlyOneMimePart && !neverDisplayInline()) { | ||
465 | defaultAsIcon = false; | ||
466 | } | ||
467 | |||
468 | // neither image nor text -> show as icon | ||
469 | if (!isImage() && !isTextPart) { | ||
470 | defaultAsIcon = true; | ||
471 | } | ||
472 | |||
473 | bool hidden(false); | ||
474 | if (isTextPart) { | ||
475 | hidden = defaultHidden && !showOnlyOneMimePart; | ||
476 | } else { | ||
477 | if (isImage() && isHtmlPreferred && | ||
478 | mNode->parent() && mNode->parent()->contentType()->subType() == "related") { | ||
479 | hidden = true; | ||
480 | } else { | ||
481 | hidden = defaultHidden && !showOnlyOneMimePart && mNode->parent(); | ||
482 | hidden |= defaultAsIcon && (defaultHidden || showOnlyOneMimePart); | ||
483 | } | ||
484 | } | ||
485 | mOtp->nodeHelper()->setNodeDisplayedHidden(mNode, hidden); | ||
486 | return hidden; | ||
487 | } | ||
488 | |||
489 | //-----HtmlMessageBlock---------------------- | ||
490 | |||
491 | HtmlMessagePart::HtmlMessagePart(ObjectTreeParser *otp, KMime::Content *node, Interface::ObjectTreeSource *source) | ||
492 | : MessagePart(otp, QString()) | ||
493 | , mNode(node) | ||
494 | , mSource(source) | ||
495 | { | ||
496 | if (!mNode) { | ||
497 | qCWarning(MIMETREEPARSER_LOG) << "not a valid node"; | ||
498 | return; | ||
499 | } | ||
500 | |||
501 | const QByteArray partBody(mNode->decodedContent()); | ||
502 | mBodyHTML = mOtp->codecFor(mNode)->toUnicode(partBody); | ||
503 | mCharset = NodeHelper::charset(mNode); | ||
504 | } | ||
505 | |||
506 | HtmlMessagePart::~HtmlMessagePart() | ||
507 | { | ||
508 | } | ||
509 | |||
510 | void HtmlMessagePart::fix() const | ||
511 | { | ||
512 | mOtp->mHtmlContent += mBodyHTML; | ||
513 | mOtp->mHtmlContentCharset = mCharset; | ||
514 | } | ||
515 | |||
516 | QString HtmlMessagePart::text() const | ||
517 | { | ||
518 | return mBodyHTML; | ||
519 | } | ||
520 | |||
521 | bool HtmlMessagePart::isHtml() const | ||
522 | { | ||
523 | return true; | ||
524 | } | ||
525 | |||
526 | //-----MimeMessageBlock---------------------- | ||
527 | |||
528 | MimeMessagePart::MimeMessagePart(ObjectTreeParser *otp, KMime::Content *node, bool onlyOneMimePart) | ||
529 | : MessagePart(otp, QString()) | ||
530 | , mNode(node) | ||
531 | , mOnlyOneMimePart(onlyOneMimePart) | ||
532 | { | ||
533 | if (!mNode) { | ||
534 | qCWarning(MIMETREEPARSER_LOG) << "not a valid node"; | ||
535 | return; | ||
536 | } | ||
537 | |||
538 | parseInternal(mNode, mOnlyOneMimePart); | ||
539 | } | ||
540 | |||
541 | MimeMessagePart::~MimeMessagePart() | ||
542 | { | ||
543 | |||
544 | } | ||
545 | |||
546 | QString MimeMessagePart::text() const | ||
547 | { | ||
548 | return renderInternalText(); | ||
549 | } | ||
550 | |||
551 | QString MimeMessagePart::plaintextContent() const | ||
552 | { | ||
553 | return QString(); | ||
554 | } | ||
555 | |||
556 | QString MimeMessagePart::htmlContent() const | ||
557 | { | ||
558 | return QString(); | ||
559 | } | ||
560 | |||
561 | //-----AlternativeMessagePart---------------------- | ||
562 | |||
563 | AlternativeMessagePart::AlternativeMessagePart(ObjectTreeParser *otp, KMime::Content *node, Util::HtmlMode preferredMode) | ||
564 | : MessagePart(otp, QString()) | ||
565 | , mNode(node) | ||
566 | , mPreferredMode(preferredMode) | ||
567 | { | ||
568 | KMime::Content *dataIcal = findTypeInDirectChilds(mNode, "text/calendar"); | ||
569 | KMime::Content *dataHtml = findTypeInDirectChilds(mNode, "text/html"); | ||
570 | KMime::Content *dataText = findTypeInDirectChilds(mNode, "text/plain"); | ||
571 | |||
572 | if (!dataHtml) { | ||
573 | // If we didn't find the HTML part as the first child of the multipart/alternative, it might | ||
574 | // be that this is a HTML message with images, and text/plain and multipart/related are the | ||
575 | // immediate children of this multipart/alternative node. | ||
576 | // In this case, the HTML node is a child of multipart/related. | ||
577 | dataHtml = findTypeInDirectChilds(mNode, "multipart/related"); | ||
578 | |||
579 | // Still not found? Stupid apple mail actually puts the attachments inside of the | ||
580 | // multipart/alternative, which is wrong. Therefore we also have to look for multipart/mixed | ||
581 | // here. | ||
582 | // Do this only when prefering HTML mail, though, since otherwise the attachments are hidden | ||
583 | // when displaying plain text. | ||
584 | if (!dataHtml) { | ||
585 | dataHtml = findTypeInDirectChilds(mNode, "multipart/mixed"); | ||
586 | } | ||
587 | } | ||
588 | |||
589 | if (dataIcal) { | ||
590 | mChildNodes[Util::MultipartIcal] = dataIcal; | ||
591 | } | ||
592 | |||
593 | if (dataText) { | ||
594 | mChildNodes[Util::MultipartPlain] = dataText; | ||
595 | } | ||
596 | |||
597 | if (dataHtml) { | ||
598 | mChildNodes[Util::MultipartHtml] = dataHtml; | ||
599 | } | ||
600 | |||
601 | if (mChildNodes.isEmpty()) { | ||
602 | qCWarning(MIMETREEPARSER_LOG) << "no valid nodes"; | ||
603 | return; | ||
604 | } | ||
605 | |||
606 | QMapIterator<Util::HtmlMode, KMime::Content *> i(mChildNodes); | ||
607 | while (i.hasNext()) { | ||
608 | i.next(); | ||
609 | mChildParts[i.key()] = MimeMessagePart::Ptr(new MimeMessagePart(mOtp, i.value(), true)); | ||
610 | } | ||
611 | } | ||
612 | |||
613 | AlternativeMessagePart::~AlternativeMessagePart() | ||
614 | { | ||
615 | |||
616 | } | ||
617 | |||
618 | Util::HtmlMode AlternativeMessagePart::preferredMode() const | ||
619 | { | ||
620 | return mPreferredMode; | ||
621 | } | ||
622 | |||
623 | QList<Util::HtmlMode> AlternativeMessagePart::availableModes() | ||
624 | { | ||
625 | return mChildParts.keys(); | ||
626 | } | ||
627 | |||
628 | QString AlternativeMessagePart::text() const | ||
629 | { | ||
630 | if (mChildParts.contains(Util::MultipartPlain)) { | ||
631 | return mChildParts[Util::MultipartPlain]->text(); | ||
632 | } | ||
633 | return QString(); | ||
634 | } | ||
635 | |||
636 | void AlternativeMessagePart::fix() const | ||
637 | { | ||
638 | if (mChildParts.contains(Util::MultipartPlain)) { | ||
639 | mChildParts[Util::MultipartPlain]->fix(); | ||
640 | } | ||
641 | |||
642 | const auto mode = preferredMode(); | ||
643 | if (mode != Util::MultipartPlain && mChildParts.contains(mode)) { | ||
644 | mChildParts[mode]->fix(); | ||
645 | } | ||
646 | } | ||
647 | |||
648 | void AlternativeMessagePart::copyContentFrom() const | ||
649 | { | ||
650 | if (mChildParts.contains(Util::MultipartPlain)) { | ||
651 | mChildParts[Util::MultipartPlain]->copyContentFrom(); | ||
652 | } | ||
653 | |||
654 | const auto mode = preferredMode(); | ||
655 | if (mode != Util::MultipartPlain && mChildParts.contains(mode)) { | ||
656 | mChildParts[mode]->copyContentFrom(); | ||
657 | } | ||
658 | } | ||
659 | |||
660 | bool AlternativeMessagePart::isHtml() const | ||
661 | { | ||
662 | return mChildParts.contains(Util::MultipartHtml); | ||
663 | } | ||
664 | |||
665 | QString AlternativeMessagePart::plaintextContent() const | ||
666 | { | ||
667 | return text(); | ||
668 | } | ||
669 | |||
670 | QString AlternativeMessagePart::htmlContent() const | ||
671 | { | ||
672 | if (mChildParts.contains(Util::MultipartHtml)) { | ||
673 | return mChildParts[Util::MultipartHtml]->text(); | ||
674 | } else { | ||
675 | return plaintextContent(); | ||
676 | } | ||
677 | } | ||
678 | |||
679 | //-----CertMessageBlock---------------------- | ||
680 | |||
681 | CertMessagePart::CertMessagePart(ObjectTreeParser *otp, KMime::Content *node, const QGpgME::Protocol *cryptoProto, bool autoImport) | ||
682 | : MessagePart(otp, QString()) | ||
683 | , mNode(node) | ||
684 | , mAutoImport(autoImport) | ||
685 | , mCryptoProto(cryptoProto) | ||
686 | { | ||
687 | if (!mNode) { | ||
688 | qCWarning(MIMETREEPARSER_LOG) << "not a valid node"; | ||
689 | return; | ||
690 | } | ||
691 | |||
692 | if (!mAutoImport) { | ||
693 | return; | ||
694 | } | ||
695 | |||
696 | const QByteArray certData = node->decodedContent(); | ||
697 | |||
698 | QGpgME::ImportJob *import = mCryptoProto->importJob(); | ||
699 | QGpgMEJobExecutor executor; | ||
700 | mImportResult = executor.exec(import, certData); | ||
701 | } | ||
702 | |||
703 | CertMessagePart::~CertMessagePart() | ||
704 | { | ||
705 | |||
706 | } | ||
707 | |||
708 | QString CertMessagePart::text() const | ||
709 | { | ||
710 | return QString(); | ||
711 | } | ||
712 | |||
713 | //-----SignedMessageBlock--------------------- | ||
714 | SignedMessagePart::SignedMessagePart(ObjectTreeParser *otp, | ||
715 | const QString &text, | ||
716 | const QGpgME::Protocol *cryptoProto, | ||
717 | const QString &fromAddress, | ||
718 | KMime::Content *node) | ||
719 | : MessagePart(otp, text) | ||
720 | , mCryptoProto(cryptoProto) | ||
721 | , mFromAddress(fromAddress) | ||
722 | , mNode(node) | ||
723 | { | ||
724 | mMetaData.technicalProblem = (mCryptoProto == nullptr); | ||
725 | mMetaData.isSigned = true; | ||
726 | mMetaData.isGoodSignature = false; | ||
727 | mMetaData.keyTrust = GpgME::Signature::Unknown; | ||
728 | mMetaData.status = i18n("Wrong Crypto Plug-In."); | ||
729 | mMetaData.status_code = GPGME_SIG_STAT_NONE; | ||
730 | } | ||
731 | |||
732 | SignedMessagePart::~SignedMessagePart() | ||
733 | { | ||
734 | |||
735 | } | ||
736 | |||
737 | void SignedMessagePart::setIsSigned(bool isSigned) | ||
738 | { | ||
739 | mMetaData.isSigned = isSigned; | ||
740 | } | ||
741 | |||
742 | bool SignedMessagePart::isSigned() const | ||
743 | { | ||
744 | return mMetaData.isSigned; | ||
745 | } | ||
746 | |||
747 | bool SignedMessagePart::okVerify(const QByteArray &data, const QByteArray &signature, KMime::Content *textNode) | ||
748 | { | ||
749 | NodeHelper *nodeHelper = mOtp->nodeHelper(); | ||
750 | Interface::ObjectTreeSource *_source = source(); | ||
751 | |||
752 | mMetaData.isSigned = false; | ||
753 | mMetaData.technicalProblem = (mCryptoProto == nullptr); | ||
754 | mMetaData.keyTrust = GpgME::Signature::Unknown; | ||
755 | mMetaData.status = i18n("Wrong Crypto Plug-In."); | ||
756 | mMetaData.status_code = GPGME_SIG_STAT_NONE; | ||
757 | |||
758 | const QByteArray mementoName = "verification"; | ||
759 | |||
760 | CryptoBodyPartMemento *m = dynamic_cast<CryptoBodyPartMemento *>(nodeHelper->bodyPartMemento(mNode, mementoName)); | ||
761 | Q_ASSERT(!m || mCryptoProto); //No CryptoPlugin and having a bodyPartMemento -> there is something completely wrong | ||
762 | |||
763 | if (!m && mCryptoProto) { | ||
764 | if (!signature.isEmpty()) { | ||
765 | QGpgME::VerifyDetachedJob *job = mCryptoProto->verifyDetachedJob(); | ||
766 | if (job) { | ||
767 | m = new VerifyDetachedBodyPartMemento(job, mCryptoProto->keyListJob(), signature, data); | ||
768 | } | ||
769 | } else { | ||
770 | QGpgME::VerifyOpaqueJob *job = mCryptoProto->verifyOpaqueJob(); | ||
771 | if (job) { | ||
772 | m = new VerifyOpaqueBodyPartMemento(job, mCryptoProto->keyListJob(), data); | ||
773 | } | ||
774 | } | ||
775 | if (m) { | ||
776 | if (mOtp->allowAsync()) { | ||
777 | QObject::connect(m, &CryptoBodyPartMemento::update, | ||
778 | nodeHelper, &NodeHelper::update); | ||
779 | QObject::connect(m, SIGNAL(update(MimeTreeParser::UpdateMode)), | ||
780 | _source->sourceObject(), SLOT(update(MimeTreeParser::UpdateMode))); | ||
781 | |||
782 | if (m->start()) { | ||
783 | mMetaData.inProgress = true; | ||
784 | mOtp->mHasPendingAsyncJobs = true; | ||
785 | } | ||
786 | } else { | ||
787 | m->exec(); | ||
788 | } | ||
789 | nodeHelper->setBodyPartMemento(mNode, mementoName, m); | ||
790 | } | ||
791 | } else if (m->isRunning()) { | ||
792 | mMetaData.inProgress = true; | ||
793 | mOtp->mHasPendingAsyncJobs = true; | ||
794 | } else { | ||
795 | mMetaData.inProgress = false; | ||
796 | mOtp->mHasPendingAsyncJobs = false; | ||
797 | } | ||
798 | |||
799 | if (m && !mMetaData.inProgress) { | ||
800 | if (!signature.isEmpty()) { | ||
801 | mVerifiedText = data; | ||
802 | } | ||
803 | setVerificationResult(m, textNode); | ||
804 | } | ||
805 | |||
806 | if (!m && !mMetaData.inProgress) { | ||
807 | QString errorMsg; | ||
808 | QString cryptPlugLibName; | ||
809 | QString cryptPlugDisplayName; | ||
810 | if (mCryptoProto) { | ||
811 | cryptPlugLibName = mCryptoProto->name(); | ||
812 | cryptPlugDisplayName = mCryptoProto->displayName(); | ||
813 | } | ||
814 | |||
815 | if (!mCryptoProto) { | ||
816 | if (cryptPlugDisplayName.isEmpty()) { | ||
817 | errorMsg = i18n("No appropriate crypto plug-in was found."); | ||
818 | } else { | ||
819 | errorMsg = i18nc("%1 is either 'OpenPGP' or 'S/MIME'", | ||
820 | "No %1 plug-in was found.", | ||
821 | cryptPlugDisplayName); | ||
822 | } | ||
823 | } else { | ||
824 | errorMsg = i18n("Crypto plug-in \"%1\" cannot verify signatures.", | ||
825 | cryptPlugLibName); | ||
826 | } | ||
827 | mMetaData.errorText = i18n("The message is signed, but the " | ||
828 | "validity of the signature cannot be " | ||
829 | "verified.<br />" | ||
830 | "Reason: %1", | ||
831 | errorMsg); | ||
832 | } | ||
833 | |||
834 | return mMetaData.isSigned; | ||
835 | } | ||
836 | |||
837 | static int signatureToStatus(const GpgME::Signature &sig) | ||
838 | { | ||
839 | switch (sig.status().code()) { | ||
840 | case GPG_ERR_NO_ERROR: | ||
841 | return GPGME_SIG_STAT_GOOD; | ||
842 | case GPG_ERR_BAD_SIGNATURE: | ||
843 | return GPGME_SIG_STAT_BAD; | ||
844 | case GPG_ERR_NO_PUBKEY: | ||
845 | return GPGME_SIG_STAT_NOKEY; | ||
846 | case GPG_ERR_NO_DATA: | ||
847 | return GPGME_SIG_STAT_NOSIG; | ||
848 | case GPG_ERR_SIG_EXPIRED: | ||
849 | return GPGME_SIG_STAT_GOOD_EXP; | ||
850 | case GPG_ERR_KEY_EXPIRED: | ||
851 | return GPGME_SIG_STAT_GOOD_EXPKEY; | ||
852 | default: | ||
853 | return GPGME_SIG_STAT_ERROR; | ||
854 | } | ||
855 | } | ||
856 | |||
857 | QString prettifyDN(const char *uid) | ||
858 | { | ||
859 | return QGpgME::DN(uid).prettyDN(); | ||
860 | } | ||
861 | |||
862 | void SignedMessagePart::sigStatusToMetaData() | ||
863 | { | ||
864 | GpgME::Key key; | ||
865 | if (mMetaData.isSigned) { | ||
866 | GpgME::Signature signature = mSignatures.front(); | ||
867 | mMetaData.status_code = signatureToStatus(signature); | ||
868 | mMetaData.isGoodSignature = mMetaData.status_code & GPGME_SIG_STAT_GOOD; | ||
869 | // save extended signature status flags | ||
870 | mMetaData.sigSummary = signature.summary(); | ||
871 | |||
872 | if (mMetaData.isGoodSignature && !key.keyID()) { | ||
873 | // Search for the key by its fingerprint so that we can check for | ||
874 | // trust etc. | ||
875 | QGpgME::KeyListJob *job = mCryptoProto->keyListJob(false); // local, no sigs | ||
876 | if (!job) { | ||
877 | qCDebug(MIMETREEPARSER_LOG) << "The Crypto backend does not support listing keys. "; | ||
878 | } else { | ||
879 | std::vector<GpgME::Key> found_keys; | ||
880 | // As we are local it is ok to make this synchronous | ||
881 | GpgME::KeyListResult res = job->exec(QStringList(QLatin1String(signature.fingerprint())), false, found_keys); | ||
882 | if (res.error()) { | ||
883 | qCDebug(MIMETREEPARSER_LOG) << "Error while searching key for Fingerprint: " << signature.fingerprint(); | ||
884 | } | ||
885 | if (found_keys.size() > 1) { | ||
886 | // Should not Happen | ||
887 | qCDebug(MIMETREEPARSER_LOG) << "Oops: Found more then one Key for Fingerprint: " << signature.fingerprint(); | ||
888 | } | ||
889 | if (found_keys.size() != 1) { | ||
890 | // Should not Happen at this point | ||
891 | qCDebug(MIMETREEPARSER_LOG) << "Oops: Found no Key for Fingerprint: " << signature.fingerprint(); | ||
892 | } else { | ||
893 | key = found_keys[0]; | ||
894 | } | ||
895 | delete job; | ||
896 | } | ||
897 | } | ||
898 | |||
899 | if (key.keyID()) { | ||
900 | mMetaData.keyId = key.keyID(); | ||
901 | } | ||
902 | if (mMetaData.keyId.isEmpty()) { | ||
903 | mMetaData.keyId = signature.fingerprint(); | ||
904 | } | ||
905 | mMetaData.keyTrust = signature.validity(); | ||
906 | if (key.numUserIDs() > 0 && key.userID(0).id()) { | ||
907 | mMetaData.signer = prettifyDN(key.userID(0).id()); | ||
908 | } | ||
909 | for (uint iMail = 0; iMail < key.numUserIDs(); ++iMail) { | ||
910 | // The following if /should/ always result in TRUE but we | ||
911 | // won't trust implicitely the plugin that gave us these data. | ||
912 | if (key.userID(iMail).email()) { | ||
913 | QString email = QString::fromUtf8(key.userID(iMail).email()); | ||
914 | // ### work around gpgme 0.3.QString text() const Q_DECL_OVERRIDE;x / cryptplug bug where the | ||
915 | // ### email addresses are specified as angle-addr, not addr-spec: | ||
916 | if (email.startsWith(QLatin1Char('<')) && email.endsWith(QLatin1Char('>'))) { | ||
917 | email = email.mid(1, email.length() - 2); | ||
918 | } | ||
919 | if (!email.isEmpty()) { | ||
920 | mMetaData.signerMailAddresses.append(email); | ||
921 | } | ||
922 | } | ||
923 | } | ||
924 | |||
925 | if (signature.creationTime()) { | ||
926 | mMetaData.creationTime.setTime_t(signature.creationTime()); | ||
927 | } else { | ||
928 | mMetaData.creationTime = QDateTime(); | ||
929 | } | ||
930 | if (mMetaData.signer.isEmpty()) { | ||
931 | if (key.numUserIDs() > 0 && key.userID(0).name()) { | ||
932 | mMetaData.signer = prettifyDN(key.userID(0).name()); | ||
933 | } | ||
934 | if (!mMetaData.signerMailAddresses.empty()) { | ||
935 | if (mMetaData.signer.isEmpty()) { | ||
936 | mMetaData.signer = mMetaData.signerMailAddresses.front(); | ||
937 | } else { | ||
938 | mMetaData.signer += QLatin1String(" <") + mMetaData.signerMailAddresses.front() + QLatin1Char('>'); | ||
939 | } | ||
940 | } | ||
941 | } | ||
942 | } | ||
943 | } | ||
944 | |||
945 | void SignedMessagePart::startVerification(const QByteArray &text, const QTextCodec *aCodec) | ||
946 | { | ||
947 | startVerificationDetached(text, nullptr, QByteArray()); | ||
948 | |||
949 | if (!mNode && mMetaData.isSigned) { | ||
950 | setText(aCodec->toUnicode(mVerifiedText)); | ||
951 | } | ||
952 | } | ||
953 | |||
954 | void SignedMessagePart::startVerificationDetached(const QByteArray &text, KMime::Content *textNode, const QByteArray &signature) | ||
955 | { | ||
956 | mMetaData.isEncrypted = false; | ||
957 | mMetaData.isDecryptable = false; | ||
958 | |||
959 | if (textNode) { | ||
960 | parseInternal(textNode, false); | ||
961 | } | ||
962 | |||
963 | okVerify(text, signature, textNode); | ||
964 | |||
965 | if (!mMetaData.isSigned) { | ||
966 | mMetaData.creationTime = QDateTime(); | ||
967 | } | ||
968 | } | ||
969 | |||
970 | void SignedMessagePart::setVerificationResult(const CryptoBodyPartMemento *m, KMime::Content *textNode) | ||
971 | { | ||
972 | { | ||
973 | const auto vm = dynamic_cast<const VerifyDetachedBodyPartMemento *>(m); | ||
974 | if (vm) { | ||
975 | mSignatures = vm->verifyResult().signatures(); | ||
976 | } | ||
977 | } | ||
978 | { | ||
979 | const auto vm = dynamic_cast<const VerifyOpaqueBodyPartMemento *>(m); | ||
980 | if (vm) { | ||
981 | mVerifiedText = vm->plainText(); | ||
982 | mSignatures = vm->verifyResult().signatures(); | ||
983 | } | ||
984 | } | ||
985 | { | ||
986 | const auto vm = dynamic_cast<const DecryptVerifyBodyPartMemento *>(m); | ||
987 | if (vm) { | ||
988 | mVerifiedText = vm->plainText(); | ||
989 | mSignatures = vm->verifyResult().signatures(); | ||
990 | } | ||
991 | } | ||
992 | mMetaData.auditLogError = m->auditLogError(); | ||
993 | mMetaData.auditLog = m->auditLogAsHtml(); | ||
994 | mMetaData.isSigned = !mSignatures.empty(); | ||
995 | |||
996 | if (mMetaData.isSigned) { | ||
997 | sigStatusToMetaData(); | ||
998 | if (mNode) { | ||
999 | mOtp->nodeHelper()->setSignatureState(mNode, KMMsgFullySigned); | ||
1000 | if (!textNode) { | ||
1001 | mOtp->mNodeHelper->setPartMetaData(mNode, mMetaData); | ||
1002 | |||
1003 | if (!mVerifiedText.isEmpty()) { | ||
1004 | auto tempNode = new KMime::Content(); | ||
1005 | tempNode->setContent(KMime::CRLFtoLF(mVerifiedText.constData())); | ||
1006 | tempNode->parse(); | ||
1007 | |||
1008 | if (!tempNode->head().isEmpty()) { | ||
1009 | tempNode->contentDescription()->from7BitString("signed data"); | ||
1010 | } | ||
1011 | mOtp->mNodeHelper->attachExtraContent(mNode, tempNode); | ||
1012 | |||
1013 | parseInternal(tempNode, false); | ||
1014 | } | ||
1015 | } | ||
1016 | } | ||
1017 | } | ||
1018 | } | ||
1019 | |||
1020 | QString SignedMessagePart::plaintextContent() const | ||
1021 | { | ||
1022 | if (!mNode) { | ||
1023 | return MessagePart::text(); | ||
1024 | } else { | ||
1025 | return QString(); | ||
1026 | } | ||
1027 | } | ||
1028 | |||
1029 | QString SignedMessagePart::htmlContent() const | ||
1030 | { | ||
1031 | if (!mNode) { | ||
1032 | return MessagePart::text(); | ||
1033 | } else { | ||
1034 | return QString(); | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | //-----CryptMessageBlock--------------------- | ||
1039 | EncryptedMessagePart::EncryptedMessagePart(ObjectTreeParser *otp, | ||
1040 | const QString &text, | ||
1041 | const QGpgME::Protocol *cryptoProto, | ||
1042 | const QString &fromAddress, | ||
1043 | KMime::Content *node) | ||
1044 | : MessagePart(otp, text) | ||
1045 | , mPassphraseError(false) | ||
1046 | , mNoSecKey(false) | ||
1047 | , mCryptoProto(cryptoProto) | ||
1048 | , mFromAddress(fromAddress) | ||
1049 | , mNode(node) | ||
1050 | , mDecryptMessage(false) | ||
1051 | { | ||
1052 | mMetaData.technicalProblem = (mCryptoProto == nullptr); | ||
1053 | mMetaData.isSigned = false; | ||
1054 | mMetaData.isGoodSignature = false; | ||
1055 | mMetaData.isEncrypted = false; | ||
1056 | mMetaData.isDecryptable = false; | ||
1057 | mMetaData.keyTrust = GpgME::Signature::Unknown; | ||
1058 | mMetaData.status = i18n("Wrong Crypto Plug-In."); | ||
1059 | mMetaData.status_code = GPGME_SIG_STAT_NONE; | ||
1060 | } | ||
1061 | |||
1062 | EncryptedMessagePart::~EncryptedMessagePart() | ||
1063 | { | ||
1064 | |||
1065 | } | ||
1066 | |||
1067 | void EncryptedMessagePart::setDecryptMessage(bool decrypt) | ||
1068 | { | ||
1069 | mDecryptMessage = decrypt; | ||
1070 | } | ||
1071 | |||
1072 | bool EncryptedMessagePart::decryptMessage() const | ||
1073 | { | ||
1074 | return mDecryptMessage; | ||
1075 | } | ||
1076 | |||
1077 | void EncryptedMessagePart::setIsEncrypted(bool encrypted) | ||
1078 | { | ||
1079 | mMetaData.isEncrypted = encrypted; | ||
1080 | } | ||
1081 | |||
1082 | bool EncryptedMessagePart::isEncrypted() const | ||
1083 | { | ||
1084 | return mMetaData.isEncrypted; | ||
1085 | } | ||
1086 | |||
1087 | bool EncryptedMessagePart::isDecryptable() const | ||
1088 | { | ||
1089 | return mMetaData.isDecryptable; | ||
1090 | } | ||
1091 | |||
1092 | bool EncryptedMessagePart::passphraseError() const | ||
1093 | { | ||
1094 | return mPassphraseError; | ||
1095 | } | ||
1096 | |||
1097 | void EncryptedMessagePart::startDecryption(const QByteArray &text, const QTextCodec *aCodec) | ||
1098 | { | ||
1099 | KMime::Content *content = new KMime::Content; | ||
1100 | content->setBody(text); | ||
1101 | content->parse(); | ||
1102 | |||
1103 | startDecryption(content); | ||
1104 | |||
1105 | if (!mMetaData.inProgress && mMetaData.isDecryptable) { | ||
1106 | if (hasSubParts()) { | ||
1107 | auto _mp = (subParts()[0]).dynamicCast<SignedMessagePart>(); | ||
1108 | if (_mp) { | ||
1109 | _mp->setText(aCodec->toUnicode(mDecryptedData)); | ||
1110 | } else { | ||
1111 | setText(aCodec->toUnicode(mDecryptedData)); | ||
1112 | } | ||
1113 | } else { | ||
1114 | setText(aCodec->toUnicode(mDecryptedData)); | ||
1115 | } | ||
1116 | } | ||
1117 | } | ||
1118 | |||
1119 | bool EncryptedMessagePart::okDecryptMIME(KMime::Content &data) | ||
1120 | { | ||
1121 | mPassphraseError = false; | ||
1122 | mMetaData.inProgress = false; | ||
1123 | mMetaData.errorText.clear(); | ||
1124 | mMetaData.auditLogError = GpgME::Error(); | ||
1125 | mMetaData.auditLog.clear(); | ||
1126 | bool bDecryptionOk = false; | ||
1127 | bool cannotDecrypt = false; | ||
1128 | Interface::ObjectTreeSource *_source = source(); | ||
1129 | NodeHelper *nodeHelper = mOtp->nodeHelper(); | ||
1130 | |||
1131 | Q_ASSERT(decryptMessage()); | ||
1132 | |||
1133 | // Check whether the memento contains a result from last time: | ||
1134 | const DecryptVerifyBodyPartMemento *m | ||
1135 | = dynamic_cast<DecryptVerifyBodyPartMemento *>(nodeHelper->bodyPartMemento(&data, "decryptverify")); | ||
1136 | |||
1137 | Q_ASSERT(!m || mCryptoProto); //No CryptoPlugin and having a bodyPartMemento -> there is something completely wrong | ||
1138 | |||
1139 | if (!m && mCryptoProto) { | ||
1140 | QGpgME::DecryptVerifyJob *job = mCryptoProto->decryptVerifyJob(); | ||
1141 | if (!job) { | ||
1142 | cannotDecrypt = true; | ||
1143 | } else { | ||
1144 | const QByteArray ciphertext = data.decodedContent(); | ||
1145 | DecryptVerifyBodyPartMemento *newM | ||
1146 | = new DecryptVerifyBodyPartMemento(job, ciphertext); | ||
1147 | if (mOtp->allowAsync()) { | ||
1148 | QObject::connect(newM, &CryptoBodyPartMemento::update, | ||
1149 | nodeHelper, &NodeHelper::update); | ||
1150 | QObject::connect(newM, SIGNAL(update(MimeTreeParser::UpdateMode)), _source->sourceObject(), | ||
1151 | SLOT(update(MimeTreeParser::UpdateMode))); | ||
1152 | if (newM->start()) { | ||
1153 | mMetaData.inProgress = true; | ||
1154 | mOtp->mHasPendingAsyncJobs = true; | ||
1155 | } else { | ||
1156 | m = newM; | ||
1157 | } | ||
1158 | } else { | ||
1159 | newM->exec(); | ||
1160 | m = newM; | ||
1161 | } | ||
1162 | nodeHelper->setBodyPartMemento(&data, "decryptverify", newM); | ||
1163 | } | ||
1164 | } else if (m->isRunning()) { | ||
1165 | mMetaData.inProgress = true; | ||
1166 | mOtp->mHasPendingAsyncJobs = true; | ||
1167 | m = nullptr; | ||
1168 | } | ||
1169 | |||
1170 | if (m) { | ||
1171 | const QByteArray &plainText = m->plainText(); | ||
1172 | const GpgME::DecryptionResult &decryptResult = m->decryptResult(); | ||
1173 | const GpgME::VerificationResult &verifyResult = m->verifyResult(); | ||
1174 | mMetaData.isSigned = verifyResult.signatures().size() > 0; | ||
1175 | |||
1176 | if (verifyResult.signatures().size() > 0) { | ||
1177 | auto subPart = SignedMessagePart::Ptr(new SignedMessagePart(mOtp, MessagePart::text(), mCryptoProto, mFromAddress, mNode)); | ||
1178 | subPart->setVerificationResult(m, nullptr); | ||
1179 | appendSubPart(subPart); | ||
1180 | } | ||
1181 | |||
1182 | mDecryptRecipients = decryptResult.recipients(); | ||
1183 | bDecryptionOk = !decryptResult.error(); | ||
1184 | // std::stringstream ss; | ||
1185 | // ss << decryptResult << '\n' << verifyResult; | ||
1186 | // qCDebug(MIMETREEPARSER_LOG) << ss.str().c_str(); | ||
1187 | |||
1188 | if (!bDecryptionOk && mMetaData.isSigned) { | ||
1189 | //Only a signed part | ||
1190 | mMetaData.isEncrypted = false; | ||
1191 | bDecryptionOk = true; | ||
1192 | mDecryptedData = plainText; | ||
1193 | } else { | ||
1194 | mPassphraseError = decryptResult.error().isCanceled() || decryptResult.error().code() == GPG_ERR_NO_SECKEY; | ||
1195 | mMetaData.isEncrypted = decryptResult.error().code() != GPG_ERR_NO_DATA; | ||
1196 | mMetaData.errorText = QString::fromLocal8Bit(decryptResult.error().asString()); | ||
1197 | if (mMetaData.isEncrypted && decryptResult.numRecipients() > 0) { | ||
1198 | mMetaData.keyId = decryptResult.recipient(0).keyID(); | ||
1199 | } | ||
1200 | |||
1201 | if (bDecryptionOk) { | ||
1202 | mDecryptedData = plainText; | ||
1203 | } else { | ||
1204 | mNoSecKey = true; | ||
1205 | foreach (const GpgME::DecryptionResult::Recipient &recipient, decryptResult.recipients()) { | ||
1206 | mNoSecKey &= (recipient.status().code() == GPG_ERR_NO_SECKEY); | ||
1207 | } | ||
1208 | if (!mPassphraseError && !mNoSecKey) { // GpgME do not detect passphrase error correctly | ||
1209 | mPassphraseError = true; | ||
1210 | } | ||
1211 | } | ||
1212 | } | ||
1213 | } | ||
1214 | |||
1215 | if (!bDecryptionOk) { | ||
1216 | QString cryptPlugLibName; | ||
1217 | if (mCryptoProto) { | ||
1218 | cryptPlugLibName = mCryptoProto->name(); | ||
1219 | } | ||
1220 | |||
1221 | if (!mCryptoProto) { | ||
1222 | mMetaData.errorText = i18n("No appropriate crypto plug-in was found."); | ||
1223 | } else if (cannotDecrypt) { | ||
1224 | mMetaData.errorText = i18n("Crypto plug-in \"%1\" cannot decrypt messages.", | ||
1225 | cryptPlugLibName); | ||
1226 | } else if (!passphraseError()) { | ||
1227 | mMetaData.errorText = i18n("Crypto plug-in \"%1\" could not decrypt the data.", cryptPlugLibName) | ||
1228 | + QLatin1String("<br />") | ||
1229 | + i18n("Error: %1", mMetaData.errorText); | ||
1230 | } | ||
1231 | } | ||
1232 | return bDecryptionOk; | ||
1233 | } | ||
1234 | |||
1235 | void EncryptedMessagePart::startDecryption(KMime::Content *data) | ||
1236 | { | ||
1237 | if (!mNode && !data) { | ||
1238 | return; | ||
1239 | } | ||
1240 | |||
1241 | if (!data) { | ||
1242 | data = mNode; | ||
1243 | } | ||
1244 | |||
1245 | mMetaData.isEncrypted = true; | ||
1246 | |||
1247 | bool bOkDecrypt = okDecryptMIME(*data); | ||
1248 | |||
1249 | if (mMetaData.inProgress) { | ||
1250 | return; | ||
1251 | } | ||
1252 | mMetaData.isDecryptable = bOkDecrypt; | ||
1253 | |||
1254 | if (!mMetaData.isDecryptable) { | ||
1255 | setText(QString::fromUtf8(mDecryptedData.constData())); | ||
1256 | } | ||
1257 | |||
1258 | if (mMetaData.isEncrypted && !decryptMessage()) { | ||
1259 | mMetaData.isDecryptable = true; | ||
1260 | } | ||
1261 | |||
1262 | if (mNode && !mMetaData.isSigned) { | ||
1263 | mOtp->mNodeHelper->setPartMetaData(mNode, mMetaData); | ||
1264 | |||
1265 | if (decryptMessage()) { | ||
1266 | auto tempNode = new KMime::Content(); | ||
1267 | tempNode->setContent(KMime::CRLFtoLF(mDecryptedData.constData())); | ||
1268 | tempNode->parse(); | ||
1269 | |||
1270 | if (!tempNode->head().isEmpty()) { | ||
1271 | tempNode->contentDescription()->from7BitString("encrypted data"); | ||
1272 | } | ||
1273 | mOtp->mNodeHelper->attachExtraContent(mNode, tempNode); | ||
1274 | |||
1275 | parseInternal(tempNode, false); | ||
1276 | } | ||
1277 | } | ||
1278 | } | ||
1279 | |||
1280 | QString EncryptedMessagePart::plaintextContent() const | ||
1281 | { | ||
1282 | if (!mNode) { | ||
1283 | return MessagePart::text(); | ||
1284 | } else { | ||
1285 | return QString(); | ||
1286 | } | ||
1287 | } | ||
1288 | |||
1289 | QString EncryptedMessagePart::htmlContent() const | ||
1290 | { | ||
1291 | if (!mNode) { | ||
1292 | return MessagePart::text(); | ||
1293 | } else { | ||
1294 | return QString(); | ||
1295 | } | ||
1296 | } | ||
1297 | |||
1298 | QString EncryptedMessagePart::text() const | ||
1299 | { | ||
1300 | if (hasSubParts()) { | ||
1301 | auto _mp = (subParts()[0]).dynamicCast<SignedMessagePart>(); | ||
1302 | if (_mp) { | ||
1303 | return _mp->text(); | ||
1304 | } else { | ||
1305 | return MessagePart::text(); | ||
1306 | } | ||
1307 | } else { | ||
1308 | return MessagePart::text(); | ||
1309 | } | ||
1310 | } | ||
1311 | |||
1312 | EncapsulatedRfc822MessagePart::EncapsulatedRfc822MessagePart(ObjectTreeParser *otp, KMime::Content *node, const KMime::Message::Ptr &message) | ||
1313 | : MessagePart(otp, QString()) | ||
1314 | , mMessage(message) | ||
1315 | , mNode(node) | ||
1316 | { | ||
1317 | mMetaData.isEncrypted = false; | ||
1318 | mMetaData.isSigned = false; | ||
1319 | mMetaData.isEncapsulatedRfc822Message = true; | ||
1320 | |||
1321 | mOtp->nodeHelper()->setNodeDisplayedEmbedded(mNode, true); | ||
1322 | mOtp->nodeHelper()->setPartMetaData(mNode, mMetaData); | ||
1323 | |||
1324 | if (!mMessage) { | ||
1325 | qCWarning(MIMETREEPARSER_LOG) << "Node is of type message/rfc822 but doesn't have a message!"; | ||
1326 | return; | ||
1327 | } | ||
1328 | |||
1329 | // The link to "Encapsulated message" is clickable, therefore the temp file needs to exists, | ||
1330 | // since the user can click the link and expect to have normal attachment operations there. | ||
1331 | mOtp->nodeHelper()->writeNodeToTempFile(message.data()); | ||
1332 | |||
1333 | parseInternal(message.data(), false); | ||
1334 | } | ||
1335 | |||
1336 | EncapsulatedRfc822MessagePart::~EncapsulatedRfc822MessagePart() | ||
1337 | { | ||
1338 | |||
1339 | } | ||
1340 | |||
1341 | QString EncapsulatedRfc822MessagePart::text() const | ||
1342 | { | ||
1343 | return renderInternalText(); | ||
1344 | } | ||
1345 | |||
1346 | void EncapsulatedRfc822MessagePart::copyContentFrom() const | ||
1347 | { | ||
1348 | } | ||
1349 | |||
1350 | void EncapsulatedRfc822MessagePart::fix() const | ||
1351 | { | ||
1352 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/messagepart.h b/framework/src/domain/mime/mimetreeparser/otp/messagepart.h new file mode 100644 index 00000000..433f3f6b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/messagepart.h | |||
@@ -0,0 +1,422 @@ | |||
1 | /* | ||
2 | Copyright (c) 2015 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_MESSAGEPART_H__ | ||
21 | #define __MIMETREEPARSER_MESSAGEPART_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "util.h" | ||
25 | |||
26 | #include <KMime/Message> | ||
27 | |||
28 | #include <gpgme++/verificationresult.h> | ||
29 | #include <gpgme++/decryptionresult.h> | ||
30 | #include <gpgme++/importresult.h> | ||
31 | |||
32 | #include <QString> | ||
33 | #include <QSharedPointer> | ||
34 | |||
35 | class QTextCodec; | ||
36 | class PartPrivate; | ||
37 | |||
38 | namespace GpgME | ||
39 | { | ||
40 | class ImportResult; | ||
41 | } | ||
42 | |||
43 | namespace QGpgME | ||
44 | { | ||
45 | class Protocol; | ||
46 | } | ||
47 | |||
48 | namespace KMime | ||
49 | { | ||
50 | class Content; | ||
51 | } | ||
52 | |||
53 | namespace MimeTreeParser | ||
54 | { | ||
55 | class ObjectTreeParser; | ||
56 | class HtmlWriter; | ||
57 | class HTMLBlock; | ||
58 | typedef QSharedPointer<HTMLBlock> HTMLBlockPtr; | ||
59 | class CryptoBodyPartMemento; | ||
60 | class MultiPartAlternativeBodyPartFormatter; | ||
61 | namespace Interface | ||
62 | { | ||
63 | class ObjectTreeSource; | ||
64 | } | ||
65 | |||
66 | class MessagePart : public Interface::MessagePart | ||
67 | { | ||
68 | Q_OBJECT | ||
69 | Q_PROPERTY(bool attachment READ isAttachment) | ||
70 | Q_PROPERTY(bool root READ isRoot) | ||
71 | Q_PROPERTY(bool isHtml READ isHtml) | ||
72 | Q_PROPERTY(bool isHidden READ isHidden) | ||
73 | public: | ||
74 | typedef QSharedPointer<MessagePart> Ptr; | ||
75 | MessagePart(ObjectTreeParser *otp, | ||
76 | const QString &text); | ||
77 | |||
78 | virtual ~MessagePart(); | ||
79 | |||
80 | virtual QString text() const Q_DECL_OVERRIDE; | ||
81 | void setText(const QString &text); | ||
82 | void setAttachmentFlag(KMime::Content *node); | ||
83 | bool isAttachment() const; | ||
84 | |||
85 | void setIsRoot(bool root); | ||
86 | bool isRoot() const; | ||
87 | |||
88 | virtual bool isHtml() const; | ||
89 | virtual bool isHidden() const; | ||
90 | |||
91 | PartMetaData *partMetaData(); | ||
92 | |||
93 | /* only a function that should be removed if the refactoring is over */ | ||
94 | virtual void fix() const; | ||
95 | virtual void copyContentFrom() const; | ||
96 | |||
97 | void appendSubPart(const Interface::MessagePart::Ptr &messagePart); | ||
98 | const QVector<Interface::MessagePart::Ptr> &subParts() const; | ||
99 | bool hasSubParts() const; | ||
100 | |||
101 | HtmlWriter *htmlWriter() const Q_DECL_OVERRIDE; | ||
102 | void setHtmlWriter(HtmlWriter *htmlWriter) const Q_DECL_OVERRIDE; | ||
103 | |||
104 | Interface::ObjectTreeSource *source() const; | ||
105 | KMime::Content *attachmentNode() const; | ||
106 | |||
107 | protected: | ||
108 | void parseInternal(KMime::Content *node, bool onlyOneMimePart); | ||
109 | QString renderInternalText() const; | ||
110 | |||
111 | QString mText; | ||
112 | ObjectTreeParser *mOtp; | ||
113 | PartMetaData mMetaData; | ||
114 | |||
115 | private: | ||
116 | QVector<Interface::MessagePart::Ptr> mBlocks; | ||
117 | |||
118 | KMime::Content *mAttachmentNode; | ||
119 | bool mRoot; | ||
120 | }; | ||
121 | |||
122 | class MimeMessagePart : public MessagePart | ||
123 | { | ||
124 | Q_OBJECT | ||
125 | public: | ||
126 | typedef QSharedPointer<MimeMessagePart> Ptr; | ||
127 | MimeMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, bool onlyOneMimePart); | ||
128 | virtual ~MimeMessagePart(); | ||
129 | |||
130 | QString text() const Q_DECL_OVERRIDE; | ||
131 | |||
132 | QString plaintextContent() const Q_DECL_OVERRIDE; | ||
133 | QString htmlContent() const Q_DECL_OVERRIDE; | ||
134 | private: | ||
135 | KMime::Content *mNode; | ||
136 | bool mOnlyOneMimePart; | ||
137 | |||
138 | friend class AlternativeMessagePart; | ||
139 | friend class ::PartPrivate; | ||
140 | }; | ||
141 | |||
142 | class MessagePartList : public MessagePart | ||
143 | { | ||
144 | Q_OBJECT | ||
145 | public: | ||
146 | typedef QSharedPointer<MessagePartList> Ptr; | ||
147 | MessagePartList(MimeTreeParser::ObjectTreeParser *otp); | ||
148 | virtual ~MessagePartList(); | ||
149 | |||
150 | QString text() const Q_DECL_OVERRIDE; | ||
151 | |||
152 | QString plaintextContent() const Q_DECL_OVERRIDE; | ||
153 | QString htmlContent() const Q_DECL_OVERRIDE; | ||
154 | private: | ||
155 | }; | ||
156 | |||
157 | enum IconType { | ||
158 | NoIcon = 0, | ||
159 | IconExternal, | ||
160 | IconInline | ||
161 | }; | ||
162 | |||
163 | class TextMessagePart : public MessagePartList | ||
164 | { | ||
165 | Q_OBJECT | ||
166 | public: | ||
167 | typedef QSharedPointer<TextMessagePart> Ptr; | ||
168 | TextMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, bool drawFrame, bool showLink, bool decryptMessage); | ||
169 | virtual ~TextMessagePart(); | ||
170 | |||
171 | KMMsgSignatureState signatureState() const; | ||
172 | KMMsgEncryptionState encryptionState() const; | ||
173 | |||
174 | bool decryptMessage() const; | ||
175 | |||
176 | bool isHidden() const Q_DECL_OVERRIDE; | ||
177 | |||
178 | bool showLink() const; | ||
179 | bool showTextFrame() const; | ||
180 | |||
181 | protected: | ||
182 | KMime::Content *mNode; | ||
183 | |||
184 | private: | ||
185 | void parseContent(); | ||
186 | |||
187 | KMMsgSignatureState mSignatureState; | ||
188 | KMMsgEncryptionState mEncryptionState; | ||
189 | bool mDrawFrame; | ||
190 | bool mShowLink; | ||
191 | bool mDecryptMessage; | ||
192 | bool mIsHidden; | ||
193 | |||
194 | friend class DefaultRendererPrivate; | ||
195 | friend class ObjectTreeParser; | ||
196 | friend class ::PartPrivate; | ||
197 | }; | ||
198 | |||
199 | class AttachmentMessagePart : public TextMessagePart | ||
200 | { | ||
201 | Q_OBJECT | ||
202 | public: | ||
203 | typedef QSharedPointer<AttachmentMessagePart> Ptr; | ||
204 | AttachmentMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, bool drawFrame, bool showLink, bool decryptMessage); | ||
205 | virtual ~AttachmentMessagePart(); | ||
206 | |||
207 | IconType asIcon() const; | ||
208 | bool neverDisplayInline() const; | ||
209 | void setNeverDisplayInline(bool displayInline); | ||
210 | bool isImage() const; | ||
211 | void setIsImage(bool image); | ||
212 | |||
213 | bool isHidden() const Q_DECL_OVERRIDE; | ||
214 | |||
215 | private: | ||
216 | bool mIsImage; | ||
217 | bool mNeverDisplayInline; | ||
218 | }; | ||
219 | |||
220 | class HtmlMessagePart : public MessagePart | ||
221 | { | ||
222 | Q_OBJECT | ||
223 | public: | ||
224 | typedef QSharedPointer<HtmlMessagePart> Ptr; | ||
225 | HtmlMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, MimeTreeParser::Interface::ObjectTreeSource *source); | ||
226 | virtual ~HtmlMessagePart(); | ||
227 | |||
228 | QString text() const Q_DECL_OVERRIDE; | ||
229 | |||
230 | void fix() const Q_DECL_OVERRIDE; | ||
231 | bool isHtml() const Q_DECL_OVERRIDE; | ||
232 | |||
233 | private: | ||
234 | KMime::Content *mNode; | ||
235 | Interface::ObjectTreeSource *mSource; | ||
236 | QString mBodyHTML; | ||
237 | QByteArray mCharset; | ||
238 | |||
239 | friend class DefaultRendererPrivate; | ||
240 | friend class ::PartPrivate; | ||
241 | }; | ||
242 | |||
243 | class AlternativeMessagePart : public MessagePart | ||
244 | { | ||
245 | Q_OBJECT | ||
246 | public: | ||
247 | typedef QSharedPointer<AlternativeMessagePart> Ptr; | ||
248 | AlternativeMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, Util::HtmlMode preferredMode); | ||
249 | virtual ~AlternativeMessagePart(); | ||
250 | |||
251 | QString text() const Q_DECL_OVERRIDE; | ||
252 | |||
253 | Util::HtmlMode preferredMode() const; | ||
254 | |||
255 | bool isHtml() const Q_DECL_OVERRIDE; | ||
256 | |||
257 | QString plaintextContent() const Q_DECL_OVERRIDE; | ||
258 | QString htmlContent() const Q_DECL_OVERRIDE; | ||
259 | |||
260 | QList<Util::HtmlMode> availableModes(); | ||
261 | |||
262 | void fix() const Q_DECL_OVERRIDE; | ||
263 | void copyContentFrom() const Q_DECL_OVERRIDE; | ||
264 | private: | ||
265 | KMime::Content *mNode; | ||
266 | |||
267 | Util::HtmlMode mPreferredMode; | ||
268 | |||
269 | QMap<Util::HtmlMode, KMime::Content *> mChildNodes; | ||
270 | QMap<Util::HtmlMode, MimeMessagePart::Ptr> mChildParts; | ||
271 | |||
272 | friend class DefaultRendererPrivate; | ||
273 | friend class ObjectTreeParser; | ||
274 | friend class MultiPartAlternativeBodyPartFormatter; | ||
275 | friend class ::PartPrivate; | ||
276 | }; | ||
277 | |||
278 | class CertMessagePart : public MessagePart | ||
279 | { | ||
280 | Q_OBJECT | ||
281 | public: | ||
282 | typedef QSharedPointer<CertMessagePart> Ptr; | ||
283 | CertMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, const QGpgME::Protocol *cryptoProto, bool autoImport); | ||
284 | virtual ~CertMessagePart(); | ||
285 | |||
286 | QString text() const Q_DECL_OVERRIDE; | ||
287 | |||
288 | private: | ||
289 | KMime::Content *mNode; | ||
290 | bool mAutoImport; | ||
291 | GpgME::ImportResult mImportResult; | ||
292 | const QGpgME::Protocol *mCryptoProto; | ||
293 | friend class DefaultRendererPrivate; | ||
294 | }; | ||
295 | |||
296 | class EncapsulatedRfc822MessagePart : public MessagePart | ||
297 | { | ||
298 | Q_OBJECT | ||
299 | public: | ||
300 | typedef QSharedPointer<EncapsulatedRfc822MessagePart> Ptr; | ||
301 | EncapsulatedRfc822MessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, const KMime::Message::Ptr &message); | ||
302 | virtual ~EncapsulatedRfc822MessagePart(); | ||
303 | |||
304 | QString text() const Q_DECL_OVERRIDE; | ||
305 | |||
306 | void copyContentFrom() const Q_DECL_OVERRIDE; | ||
307 | void fix() const Q_DECL_OVERRIDE; | ||
308 | private: | ||
309 | const KMime::Message::Ptr mMessage; | ||
310 | KMime::Content *mNode; | ||
311 | |||
312 | friend class DefaultRendererPrivate; | ||
313 | }; | ||
314 | |||
315 | class EncryptedMessagePart : public MessagePart | ||
316 | { | ||
317 | Q_OBJECT | ||
318 | Q_PROPERTY(bool decryptMessage READ decryptMessage WRITE setDecryptMessage) | ||
319 | Q_PROPERTY(bool isEncrypted READ isEncrypted) | ||
320 | Q_PROPERTY(bool passphraseError READ passphraseError) | ||
321 | public: | ||
322 | typedef QSharedPointer<EncryptedMessagePart> Ptr; | ||
323 | EncryptedMessagePart(ObjectTreeParser *otp, | ||
324 | const QString &text, | ||
325 | const QGpgME::Protocol *cryptoProto, | ||
326 | const QString &fromAddress, | ||
327 | KMime::Content *node); | ||
328 | |||
329 | virtual ~EncryptedMessagePart(); | ||
330 | |||
331 | QString text() const Q_DECL_OVERRIDE; | ||
332 | |||
333 | void setDecryptMessage(bool decrypt); | ||
334 | bool decryptMessage() const; | ||
335 | |||
336 | void setIsEncrypted(bool encrypted); | ||
337 | bool isEncrypted() const; | ||
338 | |||
339 | bool isDecryptable() const; | ||
340 | |||
341 | bool passphraseError() const; | ||
342 | |||
343 | void startDecryption(const QByteArray &text, const QTextCodec *aCodec); | ||
344 | void startDecryption(KMime::Content *data = nullptr); | ||
345 | |||
346 | QByteArray mDecryptedData; | ||
347 | |||
348 | QString plaintextContent() const Q_DECL_OVERRIDE; | ||
349 | QString htmlContent() const Q_DECL_OVERRIDE; | ||
350 | |||
351 | private: | ||
352 | /** Handles the dectyptioon of a given content | ||
353 | * returns true if the decryption was successfull | ||
354 | * if used in async mode, check if mMetaData.inProgress is true, it inicates a running decryption process. | ||
355 | */ | ||
356 | bool okDecryptMIME(KMime::Content &data); | ||
357 | |||
358 | protected: | ||
359 | bool mPassphraseError; | ||
360 | bool mNoSecKey; | ||
361 | const QGpgME::Protocol *mCryptoProto; | ||
362 | QString mFromAddress; | ||
363 | KMime::Content *mNode; | ||
364 | bool mDecryptMessage; | ||
365 | QByteArray mVerifiedText; | ||
366 | std::vector<GpgME::DecryptionResult::Recipient> mDecryptRecipients; | ||
367 | |||
368 | friend class DefaultRendererPrivate; | ||
369 | friend class ::PartPrivate; | ||
370 | }; | ||
371 | |||
372 | class SignedMessagePart : public MessagePart | ||
373 | { | ||
374 | Q_OBJECT | ||
375 | Q_PROPERTY(bool isSigned READ isSigned) | ||
376 | public: | ||
377 | typedef QSharedPointer<SignedMessagePart> Ptr; | ||
378 | SignedMessagePart(ObjectTreeParser *otp, | ||
379 | const QString &text, | ||
380 | const QGpgME::Protocol *cryptoProto, | ||
381 | const QString &fromAddress, | ||
382 | KMime::Content *node); | ||
383 | |||
384 | virtual ~SignedMessagePart(); | ||
385 | |||
386 | void setIsSigned(bool isSigned); | ||
387 | bool isSigned() const; | ||
388 | |||
389 | void startVerification(const QByteArray &text, const QTextCodec *aCodec); | ||
390 | void startVerificationDetached(const QByteArray &text, KMime::Content *textNode, const QByteArray &signature); | ||
391 | |||
392 | QByteArray mDecryptedData; | ||
393 | std::vector<GpgME::Signature> mSignatures; | ||
394 | |||
395 | QString plaintextContent() const Q_DECL_OVERRIDE; | ||
396 | QString htmlContent() const Q_DECL_OVERRIDE; | ||
397 | |||
398 | private: | ||
399 | /** Handles the verification of data | ||
400 | * If signature is empty it is handled as inline signature otherwise as detached signature mode. | ||
401 | * Returns true if the verfication was successfull and the block is signed. | ||
402 | * If used in async mode, check if mMetaData.inProgress is true, it inicates a running verification process. | ||
403 | */ | ||
404 | bool okVerify(const QByteArray &data, const QByteArray &signature, KMime::Content *textNode); | ||
405 | |||
406 | void sigStatusToMetaData(); | ||
407 | |||
408 | void setVerificationResult(const CryptoBodyPartMemento *m, KMime::Content *textNode); | ||
409 | protected: | ||
410 | const QGpgME::Protocol *mCryptoProto; | ||
411 | QString mFromAddress; | ||
412 | KMime::Content *mNode; | ||
413 | QByteArray mVerifiedText; | ||
414 | |||
415 | friend EncryptedMessagePart; | ||
416 | friend class DefaultRendererPrivate; | ||
417 | friend class ::PartPrivate; | ||
418 | }; | ||
419 | |||
420 | } | ||
421 | |||
422 | #endif //__MIMETREEPARSER_MESSAGEPART_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/messagepartrenderer.cpp b/framework/src/domain/mime/mimetreeparser/otp/messagepartrenderer.cpp new file mode 100644 index 00000000..7f622268 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/messagepartrenderer.cpp | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | Copyright (C) 2016 Sandro Knauß <sknauss@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along | ||
15 | with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
17 | */ | ||
18 | |||
19 | #include "messagepartrenderer.h" | ||
20 | |||
21 | MimeTreeParser::Interface::MessagePartRenderer::~MessagePartRenderer() | ||
22 | { | ||
23 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/messagepartrenderer.h b/framework/src/domain/mime/mimetreeparser/otp/messagepartrenderer.h new file mode 100644 index 00000000..a90c17e6 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/messagepartrenderer.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | Copyright (C) 2016 Sandro Knauß <sknauss@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along | ||
15 | with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef __MIMETREEPARSER_MESSAGEPARTRENDERER_IF_H__ | ||
20 | #define __MIMETREEPARSER_MESSAGEPARTRENDERER_IF_H__ | ||
21 | |||
22 | #include <QSharedPointer> | ||
23 | |||
24 | namespace MimeTreeParser | ||
25 | { | ||
26 | namespace Interface | ||
27 | { | ||
28 | /** | ||
29 | * Interface for rendering messageparts to html. | ||
30 | * @author Andras Mantia <sknauss@kde.org> | ||
31 | */ | ||
32 | class MessagePartRenderer | ||
33 | { | ||
34 | public: | ||
35 | typedef QSharedPointer<MessagePartRenderer> Ptr; | ||
36 | |||
37 | virtual ~MessagePartRenderer(); | ||
38 | |||
39 | virtual QString html() const = 0; | ||
40 | }; | ||
41 | } | ||
42 | } | ||
43 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/mimetreeparser_debug.cpp b/framework/src/domain/mime/mimetreeparser/otp/mimetreeparser_debug.cpp new file mode 100644 index 00000000..f8ac36cd --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/mimetreeparser_debug.cpp | |||
@@ -0,0 +1,3 @@ | |||
1 | #include "mimetreeparser_debug.h" | ||
2 | |||
3 | Q_LOGGING_CATEGORY(MIMETREEPARSER_LOG, "mimetreeparser") | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/mimetreeparser_debug.h b/framework/src/domain/mime/mimetreeparser/otp/mimetreeparser_debug.h new file mode 100644 index 00000000..ddfa6315 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/mimetreeparser_debug.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <QLoggingCategory> | ||
4 | Q_DECLARE_LOGGING_CATEGORY(MIMETREEPARSER_LOG) | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/multipartalternative.cpp b/framework/src/domain/mime/mimetreeparser/otp/multipartalternative.cpp new file mode 100644 index 00000000..42c70e28 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/multipartalternative.cpp | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "multipartalternative.h" | ||
21 | |||
22 | #include "utils.h" | ||
23 | |||
24 | #include "objecttreeparser.h" | ||
25 | #include "messagepart.h" | ||
26 | |||
27 | #include <KMime/Content> | ||
28 | |||
29 | #include "mimetreeparser_debug.h" | ||
30 | |||
31 | using namespace MimeTreeParser; | ||
32 | |||
33 | const MultiPartAlternativeBodyPartFormatter *MultiPartAlternativeBodyPartFormatter::self; | ||
34 | |||
35 | const Interface::BodyPartFormatter *MultiPartAlternativeBodyPartFormatter::create() | ||
36 | { | ||
37 | if (!self) { | ||
38 | self = new MultiPartAlternativeBodyPartFormatter(); | ||
39 | } | ||
40 | return self; | ||
41 | } | ||
42 | Interface::BodyPartFormatter::Result MultiPartAlternativeBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
43 | { | ||
44 | Q_UNUSED(writer) | ||
45 | const auto p = process(*part); | ||
46 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
47 | if (mp) { | ||
48 | mp->html(false); | ||
49 | return Ok; | ||
50 | } | ||
51 | return Failed; | ||
52 | } | ||
53 | |||
54 | Interface::MessagePart::Ptr MultiPartAlternativeBodyPartFormatter::process(Interface::BodyPart &part) const | ||
55 | { | ||
56 | KMime::Content *node = part.content(); | ||
57 | if (node->contents().isEmpty()) { | ||
58 | return MessagePart::Ptr(); | ||
59 | } | ||
60 | |||
61 | auto preferredMode = part.source()->preferredMode(); | ||
62 | AlternativeMessagePart::Ptr mp(new AlternativeMessagePart(part.objectTreeParser(), node, preferredMode)); | ||
63 | if (mp->mChildNodes.isEmpty()) { | ||
64 | MimeMessagePart::Ptr _mp(new MimeMessagePart(part.objectTreeParser(), node->contents().at(0), false)); | ||
65 | return _mp; | ||
66 | } | ||
67 | |||
68 | KMime::Content *dataIcal = mp->mChildNodes.contains(Util::MultipartIcal) ? mp->mChildNodes[Util::MultipartIcal] : nullptr; | ||
69 | KMime::Content *dataHtml = mp->mChildNodes.contains(Util::MultipartHtml) ? mp->mChildNodes[Util::MultipartHtml] : nullptr; | ||
70 | KMime::Content *dataPlain = mp->mChildNodes.contains(Util::MultipartPlain) ? mp->mChildNodes[Util::MultipartPlain] : nullptr; | ||
71 | |||
72 | // Make sure that in default ical is prefered over html and plain text | ||
73 | if (dataIcal && ((preferredMode != Util::MultipartHtml && preferredMode != Util::MultipartPlain))) { | ||
74 | if (dataHtml) { | ||
75 | part.nodeHelper()->setNodeProcessed(dataHtml, false); | ||
76 | } | ||
77 | if (dataPlain) { | ||
78 | part.nodeHelper()->setNodeProcessed(dataPlain, false); | ||
79 | } | ||
80 | preferredMode = Util::MultipartIcal; | ||
81 | } else if ((dataHtml && (preferredMode == Util::MultipartHtml || preferredMode == Util::Html)) || | ||
82 | (dataHtml && dataPlain && dataPlain->body().isEmpty())) { | ||
83 | if (dataPlain) { | ||
84 | part.nodeHelper()->setNodeProcessed(dataPlain, false); | ||
85 | } | ||
86 | preferredMode = Util::MultipartHtml; | ||
87 | } else if (!(preferredMode == Util::MultipartHtml) && dataPlain) { | ||
88 | part.nodeHelper()->setNodeProcessed(dataHtml, false); | ||
89 | preferredMode = Util::MultipartPlain; | ||
90 | } | ||
91 | part.source()->setHtmlMode(preferredMode, mp->availableModes()); | ||
92 | mp->mPreferredMode = preferredMode; | ||
93 | return mp; | ||
94 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/multipartalternative.h b/framework/src/domain/mime/mimetreeparser/otp/multipartalternative.h new file mode 100644 index 00000000..78e5ef38 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/multipartalternative.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTALTERNATIVE_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTALTERNATIVE_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "bodypart.h" | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class MultiPartAlternativeBodyPartFormatter : public Interface::BodyPartFormatter | ||
30 | { | ||
31 | static const MultiPartAlternativeBodyPartFormatter *self; | ||
32 | public: | ||
33 | Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; | ||
34 | Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
35 | using Interface::BodyPartFormatter::format; | ||
36 | static const Interface::BodyPartFormatter *create(); | ||
37 | }; | ||
38 | |||
39 | } | ||
40 | |||
41 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/multipartencrypted.cpp b/framework/src/domain/mime/mimetreeparser/otp/multipartencrypted.cpp new file mode 100644 index 00000000..7a049318 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/multipartencrypted.cpp | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "multipartencrypted.h" | ||
21 | |||
22 | #include "utils.h" | ||
23 | |||
24 | #include "objecttreeparser.h" | ||
25 | #include "messagepart.h" | ||
26 | |||
27 | #include <KMime/Content> | ||
28 | |||
29 | #include <QGpgME/Protocol> | ||
30 | |||
31 | #include "mimetreeparser_debug.h" | ||
32 | |||
33 | using namespace MimeTreeParser; | ||
34 | |||
35 | const MultiPartEncryptedBodyPartFormatter *MultiPartEncryptedBodyPartFormatter::self; | ||
36 | |||
37 | const Interface::BodyPartFormatter *MultiPartEncryptedBodyPartFormatter::create() | ||
38 | { | ||
39 | if (!self) { | ||
40 | self = new MultiPartEncryptedBodyPartFormatter(); | ||
41 | } | ||
42 | return self; | ||
43 | } | ||
44 | Interface::BodyPartFormatter::Result MultiPartEncryptedBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
45 | { | ||
46 | Q_UNUSED(writer) | ||
47 | const auto p = process(*part); | ||
48 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
49 | if (mp) { | ||
50 | mp->html(false); | ||
51 | return Ok; | ||
52 | } | ||
53 | return Failed; | ||
54 | } | ||
55 | |||
56 | Interface::MessagePart::Ptr MultiPartEncryptedBodyPartFormatter::process(Interface::BodyPart &part) const | ||
57 | { | ||
58 | KMime::Content *node = part.content(); | ||
59 | |||
60 | if (node->contents().isEmpty()) { | ||
61 | Q_ASSERT(false); | ||
62 | return MessagePart::Ptr(); | ||
63 | } | ||
64 | |||
65 | const QGpgME::Protocol *useThisCryptProto = nullptr; | ||
66 | |||
67 | /* | ||
68 | ATTENTION: This code is to be replaced by the new 'auto-detect' feature. -------------------------------------- | ||
69 | */ | ||
70 | KMime::Content *data = findTypeInDirectChilds(node, "application/octet-stream"); | ||
71 | if (data) { | ||
72 | useThisCryptProto = QGpgME::openpgp(); | ||
73 | } | ||
74 | if (!data) { | ||
75 | data = findTypeInDirectChilds(node, "application/pkcs7-mime"); | ||
76 | if (data) { | ||
77 | useThisCryptProto = QGpgME::smime(); | ||
78 | } | ||
79 | } | ||
80 | /* | ||
81 | --------------------------------------------------------------------------------------------------------------- | ||
82 | */ | ||
83 | |||
84 | if (!data) { | ||
85 | return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), node->contents().at(0), false)); | ||
86 | } | ||
87 | |||
88 | part.nodeHelper()->setEncryptionState(node, KMMsgFullyEncrypted); | ||
89 | |||
90 | EncryptedMessagePart::Ptr mp(new EncryptedMessagePart(part.objectTreeParser(), | ||
91 | data->decodedText(), useThisCryptProto, | ||
92 | part.nodeHelper()->fromAsString(data), node)); | ||
93 | mp->setIsEncrypted(true); | ||
94 | mp->setDecryptMessage(part.source()->decryptMessage()); | ||
95 | PartMetaData *messagePart(mp->partMetaData()); | ||
96 | if (!part.source()->decryptMessage()) { | ||
97 | part.nodeHelper()->setNodeProcessed(data, false); // Set the data node to done to prevent it from being processed | ||
98 | } else if (KMime::Content *newNode = part.nodeHelper()->decryptedNodeForContent(data)) { | ||
99 | // if we already have a decrypted node for part.objectTreeParser() encrypted node, don't do the decryption again | ||
100 | return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), newNode, true)); | ||
101 | } else { | ||
102 | mp->startDecryption(data); | ||
103 | |||
104 | qCDebug(MIMETREEPARSER_LOG) << "decrypted, signed?:" << messagePart->isSigned; | ||
105 | |||
106 | if (!messagePart->inProgress) { | ||
107 | part.nodeHelper()->setNodeProcessed(data, false); // Set the data node to done to prevent it from being processed | ||
108 | } | ||
109 | } | ||
110 | return mp; | ||
111 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/multipartencrypted.h b/framework/src/domain/mime/mimetreeparser/otp/multipartencrypted.h new file mode 100644 index 00000000..0d2e01a8 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/multipartencrypted.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTENCRYPTED_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTENCRYPTED_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "bodypart.h" | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class MultiPartEncryptedBodyPartFormatter : public Interface::BodyPartFormatter | ||
30 | { | ||
31 | static const MultiPartEncryptedBodyPartFormatter *self; | ||
32 | public: | ||
33 | Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; | ||
34 | Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
35 | using Interface::BodyPartFormatter::format; | ||
36 | static const Interface::BodyPartFormatter *create(); | ||
37 | }; | ||
38 | |||
39 | } | ||
40 | |||
41 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/multipartmixed.cpp b/framework/src/domain/mime/mimetreeparser/otp/multipartmixed.cpp new file mode 100644 index 00000000..43056e51 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/multipartmixed.cpp | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "multipartmixed.h" | ||
21 | |||
22 | #include "objecttreeparser.h" | ||
23 | #include "messagepart.h" | ||
24 | |||
25 | #include <KMime/Content> | ||
26 | |||
27 | #include "mimetreeparser_debug.h" | ||
28 | |||
29 | using namespace MimeTreeParser; | ||
30 | |||
31 | const MultiPartMixedBodyPartFormatter *MultiPartMixedBodyPartFormatter::self; | ||
32 | |||
33 | const Interface::BodyPartFormatter *MultiPartMixedBodyPartFormatter::create() | ||
34 | { | ||
35 | if (!self) { | ||
36 | self = new MultiPartMixedBodyPartFormatter(); | ||
37 | } | ||
38 | return self; | ||
39 | } | ||
40 | Interface::BodyPartFormatter::Result MultiPartMixedBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
41 | { | ||
42 | Q_UNUSED(writer) | ||
43 | const auto p = process(*part); | ||
44 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
45 | if (mp) { | ||
46 | mp->html(false); | ||
47 | return Ok; | ||
48 | } | ||
49 | return Failed; | ||
50 | } | ||
51 | |||
52 | Interface::MessagePart::Ptr MultiPartMixedBodyPartFormatter::process(Interface::BodyPart &part) const | ||
53 | { | ||
54 | if (part.content()->contents().isEmpty()) { | ||
55 | return MessagePart::Ptr(); | ||
56 | } | ||
57 | |||
58 | // normal treatment of the parts in the mp/mixed container | ||
59 | MimeMessagePart::Ptr mp(new MimeMessagePart(part.objectTreeParser(), part.content()->contents().at(0), false)); | ||
60 | return mp; | ||
61 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/multipartmixed.h b/framework/src/domain/mime/mimetreeparser/otp/multipartmixed.h new file mode 100644 index 00000000..0029501b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/multipartmixed.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTMIXED_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTMIXED_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "bodypart.h" | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class MultiPartMixedBodyPartFormatter : public Interface::BodyPartFormatter | ||
30 | { | ||
31 | static const MultiPartMixedBodyPartFormatter *self; | ||
32 | public: | ||
33 | Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; | ||
34 | Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
35 | using Interface::BodyPartFormatter::format; | ||
36 | static const Interface::BodyPartFormatter *create(); | ||
37 | }; | ||
38 | |||
39 | } | ||
40 | |||
41 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/multipartsigned.cpp b/framework/src/domain/mime/mimetreeparser/otp/multipartsigned.cpp new file mode 100644 index 00000000..cb0def6c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/multipartsigned.cpp | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "multipartsigned.h" | ||
21 | |||
22 | #include "objecttreeparser.h" | ||
23 | #include "messagepart.h" | ||
24 | |||
25 | #include <KMime/Content> | ||
26 | |||
27 | #include <QGpgME/Protocol> | ||
28 | |||
29 | #include "mimetreeparser_debug.h" | ||
30 | |||
31 | #include <QTextCodec> | ||
32 | |||
33 | using namespace MimeTreeParser; | ||
34 | |||
35 | const MultiPartSignedBodyPartFormatter *MultiPartSignedBodyPartFormatter::self; | ||
36 | |||
37 | const Interface::BodyPartFormatter *MultiPartSignedBodyPartFormatter::create() | ||
38 | { | ||
39 | if (!self) { | ||
40 | self = new MultiPartSignedBodyPartFormatter(); | ||
41 | } | ||
42 | return self; | ||
43 | } | ||
44 | Interface::BodyPartFormatter::Result MultiPartSignedBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
45 | { | ||
46 | Q_UNUSED(writer) | ||
47 | const auto p = process(*part); | ||
48 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
49 | if (mp) { | ||
50 | mp->html(false); | ||
51 | return Ok; | ||
52 | } | ||
53 | return Failed; | ||
54 | } | ||
55 | |||
56 | Interface::MessagePart::Ptr MultiPartSignedBodyPartFormatter::process(Interface::BodyPart &part) const | ||
57 | { | ||
58 | KMime::Content *node = part.content(); | ||
59 | if (node->contents().size() != 2) { | ||
60 | qCDebug(MIMETREEPARSER_LOG) << "mulitpart/signed must have exactly two child parts!" << endl | ||
61 | << "processing as multipart/mixed"; | ||
62 | if (!node->contents().isEmpty()) { | ||
63 | return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), node->contents().at(0), false)); | ||
64 | } else { | ||
65 | return MessagePart::Ptr(); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | KMime::Content *signedData = node->contents().at(0); | ||
70 | KMime::Content *signature = node->contents().at(1); | ||
71 | Q_ASSERT(signedData); | ||
72 | Q_ASSERT(signature); | ||
73 | |||
74 | QString protocolContentType = node->contentType()->parameter(QStringLiteral("protocol")).toLower(); | ||
75 | const QString signatureContentType = QLatin1String(signature->contentType()->mimeType().toLower()); | ||
76 | if (protocolContentType.isEmpty()) { | ||
77 | qCWarning(MIMETREEPARSER_LOG) << "Message doesn't set the protocol for the multipart/signed content-type, " | ||
78 | "using content-type of the signature:" << signatureContentType; | ||
79 | protocolContentType = signatureContentType; | ||
80 | } | ||
81 | |||
82 | const QGpgME::Protocol *protocol = nullptr; | ||
83 | if (protocolContentType == QLatin1String("application/pkcs7-signature") || | ||
84 | protocolContentType == QLatin1String("application/x-pkcs7-signature")) { | ||
85 | protocol = QGpgME::smime(); | ||
86 | } else if (protocolContentType == QLatin1String("application/pgp-signature") || | ||
87 | protocolContentType == QLatin1String("application/x-pgp-signature")) { | ||
88 | protocol = QGpgME::openpgp(); | ||
89 | } | ||
90 | |||
91 | if (!protocol) { | ||
92 | return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), signedData, false)); | ||
93 | } | ||
94 | |||
95 | part.nodeHelper()->setNodeProcessed(signature, true); | ||
96 | |||
97 | part.nodeHelper()->setSignatureState(node, KMMsgFullySigned); | ||
98 | |||
99 | const QByteArray cleartext = KMime::LFtoCRLF(signedData->encodedContent()); | ||
100 | const QTextCodec *aCodec(part.objectTreeParser()->codecFor(signedData)); | ||
101 | |||
102 | SignedMessagePart::Ptr mp(new SignedMessagePart(part.objectTreeParser(), | ||
103 | aCodec->toUnicode(cleartext), protocol, | ||
104 | part.nodeHelper()->fromAsString(node), signature)); | ||
105 | PartMetaData *messagePart(mp->partMetaData()); | ||
106 | |||
107 | if (protocol) { | ||
108 | mp->startVerificationDetached(cleartext, signedData, signature->decodedContent()); | ||
109 | } else { | ||
110 | messagePart->auditLogError = GpgME::Error(GPG_ERR_NOT_IMPLEMENTED); | ||
111 | } | ||
112 | |||
113 | return mp; | ||
114 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/multipartsigned.h b/framework/src/domain/mime/mimetreeparser/otp/multipartsigned.h new file mode 100644 index 00000000..4b8921ad --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/multipartsigned.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTSIGNED_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_MULTIPARTSIGNED_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "bodypart.h" | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class MultiPartSignedBodyPartFormatter : public Interface::BodyPartFormatter | ||
30 | { | ||
31 | static const MultiPartSignedBodyPartFormatter *self; | ||
32 | public: | ||
33 | Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; | ||
34 | Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
35 | using Interface::BodyPartFormatter::format; | ||
36 | static const Interface::BodyPartFormatter *create(); | ||
37 | }; | ||
38 | |||
39 | } | ||
40 | |||
41 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/nodehelper.cpp b/framework/src/domain/mime/mimetreeparser/otp/nodehelper.cpp new file mode 100644 index 00000000..8e224f1b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/nodehelper.cpp | |||
@@ -0,0 +1,1069 @@ | |||
1 | /* | ||
2 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
3 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along | ||
16 | with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #include "nodehelper.h" | ||
21 | #include "mimetreeparser_debug.h" | ||
22 | #include "partmetadata.h" | ||
23 | #include "bodypart.h" | ||
24 | #include "attachmenttemporaryfilesdirs.h" | ||
25 | |||
26 | #include <KMime/Content> | ||
27 | #include <KMime/Message> | ||
28 | #include <KMime/Headers> | ||
29 | |||
30 | #include <QTemporaryFile> | ||
31 | #include <KLocalizedString> | ||
32 | #include <kcharsets.h> | ||
33 | |||
34 | #include <QUrl> | ||
35 | #include <QDir> | ||
36 | #include <QTextCodec> | ||
37 | |||
38 | #include <string> | ||
39 | #include <sstream> | ||
40 | #include <algorithm> | ||
41 | #include <KCharsets> | ||
42 | #include <QMimeDatabase> | ||
43 | #include <QMimeType> | ||
44 | #include <QFileDevice> | ||
45 | |||
46 | namespace MimeTreeParser | ||
47 | { | ||
48 | |||
49 | QStringList replySubjPrefixes(QStringList() << QStringLiteral("Re\\s*:") << QStringLiteral("Re\\[\\d+\\]:") << QStringLiteral("Re\\d+:")); | ||
50 | QStringList forwardSubjPrefixes(QStringList() << QStringLiteral("Fwd:") << QStringLiteral("FW:")); | ||
51 | |||
52 | NodeHelper::NodeHelper() : | ||
53 | mAttachmentFilesDir(new AttachmentTemporaryFilesDirs()) | ||
54 | { | ||
55 | //TODO(Andras) add methods to modify these prefixes | ||
56 | |||
57 | mLocalCodec = QTextCodec::codecForLocale(); | ||
58 | |||
59 | // In the case of Japan. Japanese locale name is "eucjp" but | ||
60 | // The Japanese mail systems normally used "iso-2022-jp" of locale name. | ||
61 | // We want to change locale name from eucjp to iso-2022-jp at KMail only. | ||
62 | |||
63 | // (Introduction to i18n, 6.6 Limit of Locale technology): | ||
64 | // EUC-JP is the de-facto standard for UNIX systems, ISO 2022-JP | ||
65 | // is the standard for Internet, and Shift-JIS is the encoding | ||
66 | // for Windows and Macintosh. | ||
67 | if (mLocalCodec) { | ||
68 | const QByteArray codecNameLower = mLocalCodec->name().toLower(); | ||
69 | if (codecNameLower == "eucjp" | ||
70 | #if defined Q_OS_WIN || defined Q_OS_MACX | ||
71 | || codecNameLower == "shift-jis" // OK? | ||
72 | #endif | ||
73 | ) { | ||
74 | mLocalCodec = QTextCodec::codecForName("jis7"); | ||
75 | // QTextCodec *cdc = QTextCodec::codecForName("jis7"); | ||
76 | // QTextCodec::setCodecForLocale(cdc); | ||
77 | // KLocale::global()->setEncoding(cdc->mibEnum()); | ||
78 | } | ||
79 | } | ||
80 | } | ||
81 | |||
82 | NodeHelper::~NodeHelper() | ||
83 | { | ||
84 | if (mAttachmentFilesDir) { | ||
85 | mAttachmentFilesDir->forceCleanTempFiles(); | ||
86 | delete mAttachmentFilesDir; | ||
87 | mAttachmentFilesDir = nullptr; | ||
88 | } | ||
89 | clear(); | ||
90 | } | ||
91 | |||
92 | void NodeHelper::setNodeProcessed(KMime::Content *node, bool recurse) | ||
93 | { | ||
94 | if (!node) { | ||
95 | return; | ||
96 | } | ||
97 | mProcessedNodes.append(node); | ||
98 | qCDebug(MIMETREEPARSER_LOG) << "Node processed: " << node->index().toString() << node->contentType()->as7BitString(); | ||
99 | //<< " decodedContent" << node->decodedContent(); | ||
100 | if (recurse) { | ||
101 | const auto contents = node->contents(); | ||
102 | for (KMime::Content *c : contents) { | ||
103 | setNodeProcessed(c, true); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | |||
108 | void NodeHelper::setNodeUnprocessed(KMime::Content *node, bool recurse) | ||
109 | { | ||
110 | if (!node) { | ||
111 | return; | ||
112 | } | ||
113 | mProcessedNodes.removeAll(node); | ||
114 | |||
115 | //avoid double addition of extra nodes, eg. encrypted attachments | ||
116 | const QMap<KMime::Content *, QList<KMime::Content *> >::iterator it = mExtraContents.find(node); | ||
117 | if (it != mExtraContents.end()) { | ||
118 | Q_FOREACH (KMime::Content *c, it.value()) { | ||
119 | KMime::Content *p = c->parent(); | ||
120 | if (p) { | ||
121 | p->removeContent(c); | ||
122 | } | ||
123 | } | ||
124 | qDeleteAll(it.value()); | ||
125 | qCDebug(MIMETREEPARSER_LOG) << "mExtraContents deleted for" << it.key(); | ||
126 | mExtraContents.erase(it); | ||
127 | } | ||
128 | |||
129 | qCDebug(MIMETREEPARSER_LOG) << "Node UNprocessed: " << node; | ||
130 | if (recurse) { | ||
131 | const auto contents = node->contents(); | ||
132 | for (KMime::Content *c : contents) { | ||
133 | setNodeUnprocessed(c, true); | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | bool NodeHelper::nodeProcessed(KMime::Content *node) const | ||
139 | { | ||
140 | if (!node) { | ||
141 | return true; | ||
142 | } | ||
143 | return mProcessedNodes.contains(node); | ||
144 | } | ||
145 | |||
146 | static void clearBodyPartMemento(QMap<QByteArray, Interface::BodyPartMemento *> &bodyPartMementoMap) | ||
147 | { | ||
148 | for (QMap<QByteArray, Interface::BodyPartMemento *>::iterator | ||
149 | it = bodyPartMementoMap.begin(), end = bodyPartMementoMap.end(); | ||
150 | it != end; ++it) { | ||
151 | Interface::BodyPartMemento *memento = it.value(); | ||
152 | memento->detach(); | ||
153 | delete memento; | ||
154 | } | ||
155 | bodyPartMementoMap.clear(); | ||
156 | } | ||
157 | |||
158 | void NodeHelper::clear() | ||
159 | { | ||
160 | mProcessedNodes.clear(); | ||
161 | mEncryptionState.clear(); | ||
162 | mSignatureState.clear(); | ||
163 | mOverrideCodecs.clear(); | ||
164 | std::for_each(mBodyPartMementoMap.begin(), mBodyPartMementoMap.end(), | ||
165 | &clearBodyPartMemento); | ||
166 | mBodyPartMementoMap.clear(); | ||
167 | QMap<KMime::Content *, QList<KMime::Content *> >::ConstIterator end(mExtraContents.constEnd()); | ||
168 | |||
169 | for (QMap<KMime::Content *, QList<KMime::Content *> >::ConstIterator it = mExtraContents.constBegin(); it != end; ++it) { | ||
170 | Q_FOREACH (KMime::Content *c, it.value()) { | ||
171 | KMime::Content *p = c->parent(); | ||
172 | if (p) { | ||
173 | p->removeContent(c); | ||
174 | } | ||
175 | } | ||
176 | qDeleteAll(it.value()); | ||
177 | qCDebug(MIMETREEPARSER_LOG) << "mExtraContents deleted for" << it.key(); | ||
178 | } | ||
179 | mExtraContents.clear(); | ||
180 | mDisplayEmbeddedNodes.clear(); | ||
181 | mDisplayHiddenNodes.clear(); | ||
182 | } | ||
183 | |||
184 | void NodeHelper::setEncryptionState(const KMime::Content *node, const KMMsgEncryptionState state) | ||
185 | { | ||
186 | mEncryptionState[node] = state; | ||
187 | } | ||
188 | |||
189 | KMMsgEncryptionState NodeHelper::encryptionState(const KMime::Content *node) const | ||
190 | { | ||
191 | return mEncryptionState.value(node, KMMsgNotEncrypted); | ||
192 | } | ||
193 | |||
194 | void NodeHelper::setSignatureState(const KMime::Content *node, const KMMsgSignatureState state) | ||
195 | { | ||
196 | mSignatureState[node] = state; | ||
197 | } | ||
198 | |||
199 | KMMsgSignatureState NodeHelper::signatureState(const KMime::Content *node) const | ||
200 | { | ||
201 | return mSignatureState.value(node, KMMsgNotSigned); | ||
202 | } | ||
203 | |||
204 | PartMetaData NodeHelper::partMetaData(KMime::Content *node) | ||
205 | { | ||
206 | return mPartMetaDatas.value(node, PartMetaData()); | ||
207 | } | ||
208 | |||
209 | void NodeHelper::setPartMetaData(KMime::Content *node, const PartMetaData &metaData) | ||
210 | { | ||
211 | mPartMetaDatas.insert(node, metaData); | ||
212 | } | ||
213 | |||
214 | QString NodeHelper::writeNodeToTempFile(KMime::Content *node) | ||
215 | { | ||
216 | // If the message part is already written to a file, no point in doing it again. | ||
217 | // This function is called twice actually, once from the rendering of the attachment | ||
218 | // in the body and once for the header. | ||
219 | QUrl existingFileName = tempFileUrlFromNode(node); | ||
220 | if (!existingFileName.isEmpty()) { | ||
221 | return existingFileName.toLocalFile(); | ||
222 | } | ||
223 | |||
224 | QString fname = createTempDir(persistentIndex(node)); | ||
225 | if (fname.isEmpty()) { | ||
226 | return QString(); | ||
227 | } | ||
228 | |||
229 | QString fileName = NodeHelper::fileName(node); | ||
230 | // strip off a leading path | ||
231 | int slashPos = fileName.lastIndexOf(QLatin1Char('/')); | ||
232 | if (-1 != slashPos) { | ||
233 | fileName = fileName.mid(slashPos + 1); | ||
234 | } | ||
235 | if (fileName.isEmpty()) { | ||
236 | fileName = QStringLiteral("unnamed"); | ||
237 | } | ||
238 | fname += QLatin1Char('/') + fileName; | ||
239 | |||
240 | qCDebug(MIMETREEPARSER_LOG) << "Create temp file: " << fname; | ||
241 | QByteArray data = node->decodedContent(); | ||
242 | if (node->contentType()->isText() && !data.isEmpty()) { | ||
243 | // convert CRLF to LF before writing text attachments to disk | ||
244 | data = KMime::CRLFtoLF(data); | ||
245 | } | ||
246 | QFile f(fname); | ||
247 | if (!f.open(QIODevice::ReadWrite)) { | ||
248 | qCWarning(MIMETREEPARSER_LOG) << "Failed to write note to file:" << f.errorString(); | ||
249 | return QString(); | ||
250 | } | ||
251 | f.write(data); | ||
252 | mAttachmentFilesDir->addTempFile(fname); | ||
253 | // make file read-only so that nobody gets the impression that he might | ||
254 | // edit attached files (cf. bug #52813) | ||
255 | f.setPermissions(QFileDevice::ReadUser); | ||
256 | f.close(); | ||
257 | |||
258 | return fname; | ||
259 | } | ||
260 | |||
261 | QUrl NodeHelper::tempFileUrlFromNode(const KMime::Content *node) | ||
262 | { | ||
263 | if (!node) { | ||
264 | return QUrl(); | ||
265 | } | ||
266 | |||
267 | const QString index = persistentIndex(node); | ||
268 | |||
269 | foreach (const QString &path, mAttachmentFilesDir->temporaryFiles()) { | ||
270 | const int right = path.lastIndexOf(QLatin1Char('/')); | ||
271 | int left = path.lastIndexOf(QLatin1String(".index."), right); | ||
272 | if (left != -1) { | ||
273 | left += 7; | ||
274 | } | ||
275 | |||
276 | QStringRef storedIndex(&path, left, right - left); | ||
277 | if (left != -1 && storedIndex == index) { | ||
278 | return QUrl::fromLocalFile(path); | ||
279 | } | ||
280 | } | ||
281 | return QUrl(); | ||
282 | } | ||
283 | |||
284 | QString NodeHelper::createTempDir(const QString ¶m) | ||
285 | { | ||
286 | QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/messageviewer_XXXXXX") + QLatin1String(".index.") + param); | ||
287 | tempFile->open(); | ||
288 | const QString fname = tempFile->fileName(); | ||
289 | delete tempFile; | ||
290 | |||
291 | QFile fFile(fname); | ||
292 | if (!(fFile.permissions() & QFileDevice::WriteUser)) { | ||
293 | // Not there or not writable | ||
294 | if (!QDir().mkpath(fname) || | ||
295 | !fFile.setPermissions(QFileDevice::WriteUser | QFileDevice::ReadUser | QFileDevice::ExeUser)) { | ||
296 | return QString(); //failed create | ||
297 | } | ||
298 | } | ||
299 | |||
300 | Q_ASSERT(!fname.isNull()); | ||
301 | |||
302 | mAttachmentFilesDir->addTempDir(fname); | ||
303 | return fname; | ||
304 | } | ||
305 | |||
306 | void NodeHelper::forceCleanTempFiles() | ||
307 | { | ||
308 | mAttachmentFilesDir->forceCleanTempFiles(); | ||
309 | delete mAttachmentFilesDir; | ||
310 | mAttachmentFilesDir = nullptr; | ||
311 | } | ||
312 | |||
313 | void NodeHelper::removeTempFiles() | ||
314 | { | ||
315 | //Don't delete it it will delete in class | ||
316 | mAttachmentFilesDir->removeTempFiles(); | ||
317 | mAttachmentFilesDir = new AttachmentTemporaryFilesDirs(); | ||
318 | } | ||
319 | |||
320 | void NodeHelper::addTempFile(const QString &file) | ||
321 | { | ||
322 | mAttachmentFilesDir->addTempFile(file); | ||
323 | } | ||
324 | |||
325 | bool NodeHelper::isInEncapsulatedMessage(KMime::Content *node) | ||
326 | { | ||
327 | const KMime::Content *const topLevel = node->topLevel(); | ||
328 | const KMime::Content *cur = node; | ||
329 | while (cur && cur != topLevel) { | ||
330 | const bool parentIsMessage = cur->parent() && cur->parent()->contentType(false) && | ||
331 | cur->parent()->contentType()->mimeType().toLower() == "message/rfc822"; | ||
332 | if (parentIsMessage && cur->parent() != topLevel) { | ||
333 | return true; | ||
334 | } | ||
335 | cur = cur->parent(); | ||
336 | } | ||
337 | return false; | ||
338 | } | ||
339 | |||
340 | QByteArray NodeHelper::charset(KMime::Content *node) | ||
341 | { | ||
342 | if (node->contentType(false)) { | ||
343 | return node->contentType(false)->charset(); | ||
344 | } else { | ||
345 | return node->defaultCharset(); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | KMMsgEncryptionState NodeHelper::overallEncryptionState(KMime::Content *node) const | ||
350 | { | ||
351 | KMMsgEncryptionState myState = KMMsgEncryptionStateUnknown; | ||
352 | if (!node) { | ||
353 | return myState; | ||
354 | } | ||
355 | |||
356 | KMime::Content *parent = node->parent(); | ||
357 | auto contents = parent ? parent->contents() : KMime::Content::List(); | ||
358 | if (contents.isEmpty()) { | ||
359 | contents.append(node); | ||
360 | } | ||
361 | int i = contents.indexOf(const_cast<KMime::Content *>(node)); | ||
362 | for (; i < contents.size(); ++i) { | ||
363 | auto next = contents.at(i); | ||
364 | KMMsgEncryptionState otherState = encryptionState(next); | ||
365 | |||
366 | // NOTE: children are tested ONLY when parent is not encrypted | ||
367 | if (otherState == KMMsgNotEncrypted && !next->contents().isEmpty()) { | ||
368 | otherState = overallEncryptionState(next->contents().at(0)); | ||
369 | } | ||
370 | |||
371 | if (otherState == KMMsgNotEncrypted && !extraContents(next).isEmpty()) { | ||
372 | otherState = overallEncryptionState(extraContents(next).at(0)); | ||
373 | } | ||
374 | |||
375 | if (next == node) { | ||
376 | myState = otherState; | ||
377 | } | ||
378 | |||
379 | switch (otherState) { | ||
380 | case KMMsgEncryptionStateUnknown: | ||
381 | break; | ||
382 | case KMMsgNotEncrypted: | ||
383 | if (myState == KMMsgFullyEncrypted) { | ||
384 | myState = KMMsgPartiallyEncrypted; | ||
385 | } else if (myState != KMMsgPartiallyEncrypted) { | ||
386 | myState = KMMsgNotEncrypted; | ||
387 | } | ||
388 | break; | ||
389 | case KMMsgPartiallyEncrypted: | ||
390 | myState = KMMsgPartiallyEncrypted; | ||
391 | break; | ||
392 | case KMMsgFullyEncrypted: | ||
393 | if (myState != KMMsgFullyEncrypted) { | ||
394 | myState = KMMsgPartiallyEncrypted; | ||
395 | } | ||
396 | break; | ||
397 | case KMMsgEncryptionProblematic: | ||
398 | break; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | qCDebug(MIMETREEPARSER_LOG) << "\n\n KMMsgEncryptionState:" << myState; | ||
403 | |||
404 | return myState; | ||
405 | } | ||
406 | |||
407 | KMMsgSignatureState NodeHelper::overallSignatureState(KMime::Content *node) const | ||
408 | { | ||
409 | KMMsgSignatureState myState = KMMsgSignatureStateUnknown; | ||
410 | if (!node) { | ||
411 | return myState; | ||
412 | } | ||
413 | |||
414 | KMime::Content *parent = node->parent(); | ||
415 | auto contents = parent ? parent->contents() : KMime::Content::List(); | ||
416 | if (contents.isEmpty()) { | ||
417 | contents.append(node); | ||
418 | } | ||
419 | int i = contents.indexOf(const_cast<KMime::Content *>(node)); | ||
420 | for (; i < contents.size(); ++i) { | ||
421 | auto next = contents.at(i); | ||
422 | KMMsgSignatureState otherState = signatureState(next); | ||
423 | |||
424 | // NOTE: children are tested ONLY when parent is not encrypted | ||
425 | if (otherState == KMMsgNotSigned && !next->contents().isEmpty()) { | ||
426 | otherState = overallSignatureState(next->contents().at(0)); | ||
427 | } | ||
428 | |||
429 | if (otherState == KMMsgNotSigned && !extraContents(next).isEmpty()) { | ||
430 | otherState = overallSignatureState(extraContents(next).at(0)); | ||
431 | } | ||
432 | |||
433 | if (next == node) { | ||
434 | myState = otherState; | ||
435 | } | ||
436 | |||
437 | switch (otherState) { | ||
438 | case KMMsgSignatureStateUnknown: | ||
439 | break; | ||
440 | case KMMsgNotSigned: | ||
441 | if (myState == KMMsgFullySigned) { | ||
442 | myState = KMMsgPartiallySigned; | ||
443 | } else if (myState != KMMsgPartiallySigned) { | ||
444 | myState = KMMsgNotSigned; | ||
445 | } | ||
446 | break; | ||
447 | case KMMsgPartiallySigned: | ||
448 | myState = KMMsgPartiallySigned; | ||
449 | break; | ||
450 | case KMMsgFullySigned: | ||
451 | if (myState != KMMsgFullySigned) { | ||
452 | myState = KMMsgPartiallySigned; | ||
453 | } | ||
454 | break; | ||
455 | case KMMsgSignatureProblematic: | ||
456 | break; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | qCDebug(MIMETREEPARSER_LOG) << "\n\n KMMsgSignatureState:" << myState; | ||
461 | |||
462 | return myState; | ||
463 | } | ||
464 | |||
465 | void NodeHelper::magicSetType(KMime::Content *node, bool aAutoDecode) | ||
466 | { | ||
467 | const QByteArray body = (aAutoDecode) ? node->decodedContent() : node->body(); | ||
468 | QMimeDatabase db; | ||
469 | QMimeType mime = db.mimeTypeForData(body); | ||
470 | |||
471 | QString mimetype = mime.name(); | ||
472 | node->contentType()->setMimeType(mimetype.toLatin1()); | ||
473 | } | ||
474 | |||
475 | // static | ||
476 | QString NodeHelper::replacePrefixes(const QString &str, | ||
477 | const QStringList &prefixRegExps, | ||
478 | bool replace, | ||
479 | const QString &newPrefix) | ||
480 | { | ||
481 | bool recognized = false; | ||
482 | // construct a big regexp that | ||
483 | // 1. is anchored to the beginning of str (sans whitespace) | ||
484 | // 2. matches at least one of the part regexps in prefixRegExps | ||
485 | QString bigRegExp = QStringLiteral("^(?:\\s+|(?:%1))+\\s*") | ||
486 | .arg(prefixRegExps.join(QStringLiteral(")|(?:"))); | ||
487 | QRegExp rx(bigRegExp, Qt::CaseInsensitive); | ||
488 | if (!rx.isValid()) { | ||
489 | qCWarning(MIMETREEPARSER_LOG) << "bigRegExp = \"" | ||
490 | << bigRegExp << "\"\n" | ||
491 | << "prefix regexp is invalid!"; | ||
492 | // try good ole Re/Fwd: | ||
493 | recognized = str.startsWith(newPrefix); | ||
494 | } else { // valid rx | ||
495 | QString tmp = str; | ||
496 | if (rx.indexIn(tmp) == 0) { | ||
497 | recognized = true; | ||
498 | if (replace) { | ||
499 | return tmp.replace(0, rx.matchedLength(), newPrefix + QLatin1Char(' ')); | ||
500 | } | ||
501 | } | ||
502 | } | ||
503 | if (!recognized) { | ||
504 | return newPrefix + QLatin1Char(' ') + str; | ||
505 | } else { | ||
506 | return str; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | QString NodeHelper::cleanSubject(KMime::Message *message) | ||
511 | { | ||
512 | return cleanSubject(message, replySubjPrefixes + forwardSubjPrefixes, | ||
513 | true, QString()).trimmed(); | ||
514 | } | ||
515 | |||
516 | QString NodeHelper::cleanSubject(KMime::Message *message, | ||
517 | const QStringList &prefixRegExps, | ||
518 | bool replace, | ||
519 | const QString &newPrefix) | ||
520 | { | ||
521 | QString cleanStr; | ||
522 | if (message) { | ||
523 | cleanStr = | ||
524 | NodeHelper::replacePrefixes( | ||
525 | message->subject()->asUnicodeString(), prefixRegExps, replace, newPrefix); | ||
526 | } | ||
527 | return cleanStr; | ||
528 | } | ||
529 | |||
530 | void NodeHelper::setOverrideCodec(KMime::Content *node, const QTextCodec *codec) | ||
531 | { | ||
532 | if (!node) { | ||
533 | return; | ||
534 | } | ||
535 | |||
536 | mOverrideCodecs[node] = codec; | ||
537 | } | ||
538 | |||
539 | const QTextCodec *NodeHelper::codec(KMime::Content *node) | ||
540 | { | ||
541 | if (! node) { | ||
542 | return mLocalCodec; | ||
543 | } | ||
544 | |||
545 | const QTextCodec *c = mOverrideCodecs.value(node, nullptr); | ||
546 | if (!c) { | ||
547 | // no override-codec set for this message, try the CT charset parameter: | ||
548 | QByteArray charset = node->contentType()->charset(); | ||
549 | |||
550 | // utf-8 is a superset of us-ascii, so we don't loose anything, if we it insead | ||
551 | // utf-8 is nowadays that widely, that it is a good guess to use it to fix issus with broken clients. | ||
552 | if (charset.toLower() == "us-ascii") { | ||
553 | charset = "utf-8"; | ||
554 | } | ||
555 | c = codecForName(charset); | ||
556 | } | ||
557 | if (!c) { | ||
558 | // no charset means us-ascii (RFC 2045), so using local encoding should | ||
559 | // be okay | ||
560 | c = mLocalCodec; | ||
561 | } | ||
562 | return c; | ||
563 | } | ||
564 | |||
565 | const QTextCodec *NodeHelper::codecForName(const QByteArray &_str) | ||
566 | { | ||
567 | if (_str.isEmpty()) { | ||
568 | return nullptr; | ||
569 | } | ||
570 | QByteArray codec = _str.toLower(); | ||
571 | return KCharsets::charsets()->codecForName(QLatin1String(codec)); | ||
572 | } | ||
573 | |||
574 | QString NodeHelper::fileName(const KMime::Content *node) | ||
575 | { | ||
576 | QString name = const_cast<KMime::Content *>(node)->contentDisposition()->filename(); | ||
577 | if (name.isEmpty()) { | ||
578 | name = const_cast<KMime::Content *>(node)->contentType()->name(); | ||
579 | } | ||
580 | |||
581 | name = name.trimmed(); | ||
582 | return name; | ||
583 | } | ||
584 | |||
585 | //FIXME(Andras) review it (by Marc?) to see if I got it right. This is supposed to be the partNode::internalBodyPartMemento replacement | ||
586 | Interface::BodyPartMemento *NodeHelper::bodyPartMemento(KMime::Content *node, | ||
587 | const QByteArray &which) const | ||
588 | { | ||
589 | const QMap< QString, QMap<QByteArray, Interface::BodyPartMemento *> >::const_iterator nit | ||
590 | = mBodyPartMementoMap.find(persistentIndex(node)); | ||
591 | if (nit == mBodyPartMementoMap.end()) { | ||
592 | return nullptr; | ||
593 | } | ||
594 | const QMap<QByteArray, Interface::BodyPartMemento *>::const_iterator it = | ||
595 | nit->find(which.toLower()); | ||
596 | return it != nit->end() ? it.value() : nullptr; | ||
597 | } | ||
598 | |||
599 | //FIXME(Andras) review it (by Marc?) to see if I got it right. This is supposed to be the partNode::internalSetBodyPartMemento replacement | ||
600 | void NodeHelper::setBodyPartMemento(KMime::Content *node, const QByteArray &which, | ||
601 | Interface::BodyPartMemento *memento) | ||
602 | { | ||
603 | QMap<QByteArray, Interface::BodyPartMemento *> &mementos | ||
604 | = mBodyPartMementoMap[persistentIndex(node)]; | ||
605 | |||
606 | const QByteArray whichLower = which.toLower(); | ||
607 | const QMap<QByteArray, Interface::BodyPartMemento *>::iterator it = | ||
608 | mementos.lowerBound(whichLower); | ||
609 | |||
610 | if (it != mementos.end() && it.key() == whichLower) { | ||
611 | delete it.value(); | ||
612 | if (memento) { | ||
613 | it.value() = memento; | ||
614 | } else { | ||
615 | mementos.erase(it); | ||
616 | } | ||
617 | } else { | ||
618 | mementos.insert(whichLower, memento); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | bool NodeHelper::isNodeDisplayedEmbedded(KMime::Content *node) const | ||
623 | { | ||
624 | qCDebug(MIMETREEPARSER_LOG) << "IS NODE: " << mDisplayEmbeddedNodes.contains(node); | ||
625 | return mDisplayEmbeddedNodes.contains(node); | ||
626 | } | ||
627 | |||
628 | void NodeHelper::setNodeDisplayedEmbedded(KMime::Content *node, bool displayedEmbedded) | ||
629 | { | ||
630 | qCDebug(MIMETREEPARSER_LOG) << "SET NODE: " << node << displayedEmbedded; | ||
631 | if (displayedEmbedded) { | ||
632 | mDisplayEmbeddedNodes.insert(node); | ||
633 | } else { | ||
634 | mDisplayEmbeddedNodes.remove(node); | ||
635 | } | ||
636 | } | ||
637 | |||
638 | bool NodeHelper::isNodeDisplayedHidden(KMime::Content *node) const | ||
639 | { | ||
640 | return mDisplayHiddenNodes.contains(node); | ||
641 | } | ||
642 | |||
643 | void NodeHelper::setNodeDisplayedHidden(KMime::Content *node, bool displayedHidden) | ||
644 | { | ||
645 | if (displayedHidden) { | ||
646 | mDisplayHiddenNodes.insert(node); | ||
647 | } else { | ||
648 | mDisplayEmbeddedNodes.remove(node); | ||
649 | } | ||
650 | } | ||
651 | |||
652 | /*! | ||
653 | Creates a persistent index string that bridges the gap between the | ||
654 | permanent nodes and the temporary ones. | ||
655 | |||
656 | Used internally for robust indexing. | ||
657 | */ | ||
658 | QString NodeHelper::persistentIndex(const KMime::Content *node) const | ||
659 | { | ||
660 | if (!node) { | ||
661 | return QString(); | ||
662 | } | ||
663 | |||
664 | QString indexStr = node->index().toString(); | ||
665 | if (indexStr.isEmpty()) { | ||
666 | QMapIterator<KMime::Message::Content *, QList<KMime::Content *> > it(mExtraContents); | ||
667 | while (it.hasNext()) { | ||
668 | it.next(); | ||
669 | const auto &extraNodes = it.value(); | ||
670 | for (int i = 0; i < extraNodes.size(); i++) { | ||
671 | if (extraNodes[i] == node) { | ||
672 | indexStr = QString::fromLatin1("e%1").arg(i); | ||
673 | const QString parentIndex = persistentIndex(it.key()); | ||
674 | if (!parentIndex.isEmpty()) { | ||
675 | indexStr = QString::fromLatin1("%1:%2").arg(parentIndex, indexStr); | ||
676 | } | ||
677 | return indexStr; | ||
678 | } | ||
679 | } | ||
680 | } | ||
681 | } else { | ||
682 | const KMime::Content *const topLevel = node->topLevel(); | ||
683 | //if the node is an extra node, prepend the index of the extra node to the url | ||
684 | QMapIterator<KMime::Message::Content *, QList<KMime::Content *> > it(mExtraContents); | ||
685 | while (it.hasNext()) { | ||
686 | it.next(); | ||
687 | const QList<KMime::Content *> &extraNodes = extraContents(it.key()); | ||
688 | for (int i = 0; i < extraNodes.size(); ++i) { | ||
689 | KMime::Content *const extraNode = extraNodes[i]; | ||
690 | if (topLevel == extraNode) { | ||
691 | indexStr.prepend(QStringLiteral("e%1:").arg(i)); | ||
692 | const QString parentIndex = persistentIndex(it.key()); | ||
693 | if (!parentIndex.isEmpty()) { | ||
694 | indexStr = QStringLiteral("%1:%2").arg(parentIndex, indexStr); | ||
695 | } | ||
696 | return indexStr; | ||
697 | } | ||
698 | } | ||
699 | } | ||
700 | } | ||
701 | |||
702 | return indexStr; | ||
703 | } | ||
704 | |||
705 | KMime::Content *NodeHelper::contentFromIndex(KMime::Content *node, const QString &persistentIndex) const | ||
706 | { | ||
707 | KMime::Content *c = node->topLevel(); | ||
708 | if (c) { | ||
709 | const QStringList pathParts = persistentIndex.split(QLatin1Char(':'), QString::SkipEmptyParts); | ||
710 | const int pathPartsSize(pathParts.size()); | ||
711 | for (int i = 0; i < pathPartsSize; ++i) { | ||
712 | const QString &path = pathParts[i]; | ||
713 | if (path.startsWith(QLatin1Char('e'))) { | ||
714 | const QList<KMime::Content *> &extraParts = mExtraContents.value(c); | ||
715 | const int idx = path.midRef(1, -1).toInt(); | ||
716 | c = (idx < extraParts.size()) ? extraParts[idx] : nullptr; | ||
717 | } else { | ||
718 | c = c->content(KMime::ContentIndex(path)); | ||
719 | } | ||
720 | if (!c) { | ||
721 | break; | ||
722 | } | ||
723 | } | ||
724 | } | ||
725 | return c; | ||
726 | } | ||
727 | |||
728 | QString NodeHelper::asHREF(const KMime::Content *node, const QString &place) const | ||
729 | { | ||
730 | return QStringLiteral("attachment:%1?place=%2").arg(persistentIndex(node), place); | ||
731 | } | ||
732 | |||
733 | KMime::Content *NodeHelper::fromHREF(const KMime::Message::Ptr &mMessage, const QUrl &url) const | ||
734 | { | ||
735 | if (url.isEmpty()) { | ||
736 | return mMessage.data(); | ||
737 | } | ||
738 | |||
739 | if (!url.isLocalFile()) { | ||
740 | return contentFromIndex(mMessage.data(), url.adjusted(QUrl::StripTrailingSlash).path()); | ||
741 | } else { | ||
742 | const QString path = url.toLocalFile(); | ||
743 | // extract from /<path>/qttestn28554.index.2.3:0:2/unnamed -> "2.3:0:2" | ||
744 | // start of the index is something that is not a number followed by a dot: \D. | ||
745 | // index is only made of numbers,"." and ":": ([0-9.:]+) | ||
746 | // index is the last part of the folder name: / | ||
747 | const QRegExp rIndex(QStringLiteral("\\D\\.([e0-9.:]+)/")); | ||
748 | |||
749 | //search the occurence at most at the end | ||
750 | if (rIndex.lastIndexIn(path) != -1) { | ||
751 | return contentFromIndex(mMessage.data(), rIndex.cap(1)); | ||
752 | } | ||
753 | return mMessage.data(); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | QString NodeHelper::fixEncoding(const QString &encoding) | ||
758 | { | ||
759 | QString returnEncoding = encoding; | ||
760 | // According to http://www.iana.org/assignments/character-sets, uppercase is | ||
761 | // preferred in MIME headers | ||
762 | const QString returnEncodingToUpper = returnEncoding.toUpper(); | ||
763 | if (returnEncodingToUpper.contains(QStringLiteral("ISO "))) { | ||
764 | returnEncoding = returnEncodingToUpper; | ||
765 | returnEncoding.replace(QLatin1String("ISO "), QStringLiteral("ISO-")); | ||
766 | } | ||
767 | return returnEncoding; | ||
768 | } | ||
769 | |||
770 | //----------------------------------------------------------------------------- | ||
771 | QString NodeHelper::encodingForName(const QString &descriptiveName) | ||
772 | { | ||
773 | QString encoding = KCharsets::charsets()->encodingForName(descriptiveName); | ||
774 | return NodeHelper::fixEncoding(encoding); | ||
775 | } | ||
776 | |||
777 | QStringList NodeHelper::supportedEncodings(bool usAscii) | ||
778 | { | ||
779 | QStringList encodingNames = KCharsets::charsets()->availableEncodingNames(); | ||
780 | QStringList encodings; | ||
781 | QMap<QString, bool> mimeNames; | ||
782 | QStringList::ConstIterator constEnd(encodingNames.constEnd()); | ||
783 | for (QStringList::ConstIterator it = encodingNames.constBegin(); | ||
784 | it != constEnd; ++it) { | ||
785 | QTextCodec *codec = KCharsets::charsets()->codecForName(*it); | ||
786 | QString mimeName = (codec) ? QString::fromLatin1(codec->name()).toLower() : (*it); | ||
787 | if (!mimeNames.contains(mimeName)) { | ||
788 | encodings.append(KCharsets::charsets()->descriptionForEncoding(*it)); | ||
789 | mimeNames.insert(mimeName, true); | ||
790 | } | ||
791 | } | ||
792 | encodings.sort(); | ||
793 | if (usAscii) { | ||
794 | encodings.prepend(KCharsets::charsets()->descriptionForEncoding(QStringLiteral("us-ascii"))); | ||
795 | } | ||
796 | return encodings; | ||
797 | } | ||
798 | |||
799 | QString NodeHelper::fromAsString(KMime::Content *node) const | ||
800 | { | ||
801 | if (auto topLevel = dynamic_cast<KMime::Message *>(node->topLevel())) { | ||
802 | return topLevel->from()->asUnicodeString(); | ||
803 | } else { | ||
804 | auto realNode = std::find_if(mExtraContents.cbegin(), mExtraContents.cend(), | ||
805 | [node](const QList<KMime::Content *> &nodes) { | ||
806 | return nodes.contains(node); | ||
807 | }); | ||
808 | if (realNode != mExtraContents.cend()) { | ||
809 | return fromAsString(realNode.key()); | ||
810 | } | ||
811 | } | ||
812 | |||
813 | return QString(); | ||
814 | } | ||
815 | |||
816 | void NodeHelper::attachExtraContent(KMime::Content *topLevelNode, KMime::Content *content) | ||
817 | { | ||
818 | qCDebug(MIMETREEPARSER_LOG) << "mExtraContents added for" << topLevelNode << " extra content: " << content; | ||
819 | mExtraContents[topLevelNode].append(content); | ||
820 | } | ||
821 | |||
822 | QList< KMime::Content * > NodeHelper::extraContents(KMime::Content *topLevelnode) const | ||
823 | { | ||
824 | return mExtraContents.value(topLevelnode); | ||
825 | } | ||
826 | |||
827 | void NodeHelper::mergeExtraNodes(KMime::Content *node) | ||
828 | { | ||
829 | if (!node) { | ||
830 | return; | ||
831 | } | ||
832 | |||
833 | const QList<KMime::Content * > extraNodes = extraContents(node); | ||
834 | for (KMime::Content *extra : extraNodes) { | ||
835 | if (node->bodyIsMessage()) { | ||
836 | qCWarning(MIMETREEPARSER_LOG) << "Asked to attach extra content to a kmime::message, this does not make sense. Attaching to:" << node << | ||
837 | node->encodedContent() << "\n====== with =======\n" << extra << extra->encodedContent(); | ||
838 | continue; | ||
839 | } | ||
840 | KMime::Content *c = new KMime::Content(node); | ||
841 | c->setContent(extra->encodedContent()); | ||
842 | c->parse(); | ||
843 | node->addContent(c); | ||
844 | } | ||
845 | |||
846 | Q_FOREACH (KMime::Content *child, node->contents()) { | ||
847 | mergeExtraNodes(child); | ||
848 | } | ||
849 | } | ||
850 | |||
851 | void NodeHelper::cleanFromExtraNodes(KMime::Content *node) | ||
852 | { | ||
853 | if (!node) { | ||
854 | return; | ||
855 | } | ||
856 | const QList<KMime::Content * > extraNodes = extraContents(node); | ||
857 | for (KMime::Content *extra : extraNodes) { | ||
858 | QByteArray s = extra->encodedContent(); | ||
859 | const auto children = node->contents(); | ||
860 | for (KMime::Content *c : children) { | ||
861 | if (c->encodedContent() == s) { | ||
862 | node->removeContent(c); | ||
863 | } | ||
864 | } | ||
865 | } | ||
866 | Q_FOREACH (KMime::Content *child, node->contents()) { | ||
867 | cleanFromExtraNodes(child); | ||
868 | } | ||
869 | } | ||
870 | |||
871 | KMime::Message *NodeHelper::messageWithExtraContent(KMime::Content *topLevelNode) | ||
872 | { | ||
873 | /*The merge is done in several steps: | ||
874 | 1) merge the extra nodes into topLevelNode | ||
875 | 2) copy the modified (merged) node tree into a new node tree | ||
876 | 3) restore the original node tree in topLevelNode by removing the extra nodes from it | ||
877 | |||
878 | The reason is that extra nodes are assigned by pointer value to the nodes in the original tree. | ||
879 | */ | ||
880 | if (!topLevelNode) { | ||
881 | return nullptr; | ||
882 | } | ||
883 | |||
884 | mergeExtraNodes(topLevelNode); | ||
885 | |||
886 | KMime::Message *m = new KMime::Message; | ||
887 | m->setContent(topLevelNode->encodedContent()); | ||
888 | m->parse(); | ||
889 | |||
890 | cleanFromExtraNodes(topLevelNode); | ||
891 | // qCDebug(MIMETREEPARSER_LOG) << "MESSAGE WITH EXTRA: " << m->encodedContent(); | ||
892 | // qCDebug(MIMETREEPARSER_LOG) << "MESSAGE WITHOUT EXTRA: " << topLevelNode->encodedContent(); | ||
893 | |||
894 | return m; | ||
895 | } | ||
896 | |||
897 | KMime::Content *NodeHelper::decryptedNodeForContent(KMime::Content *content) const | ||
898 | { | ||
899 | const QList<KMime::Content *> xc = extraContents(content); | ||
900 | if (!xc.empty()) { | ||
901 | if (xc.size() == 1) { | ||
902 | return xc.front(); | ||
903 | } else { | ||
904 | qCWarning(MIMETREEPARSER_LOG) << "WTF, encrypted node has multiple extra contents?"; | ||
905 | } | ||
906 | } | ||
907 | return nullptr; | ||
908 | } | ||
909 | |||
910 | bool NodeHelper::unencryptedMessage_helper(KMime::Content *node, QByteArray &resultingData, bool addHeaders, | ||
911 | int recursionLevel) | ||
912 | { | ||
913 | bool returnValue = false; | ||
914 | if (node) { | ||
915 | KMime::Content *curNode = node; | ||
916 | KMime::Content *decryptedNode = nullptr; | ||
917 | const QByteArray type = node->contentType(false) ? QByteArray(node->contentType()->mediaType()).toLower() : "text"; | ||
918 | const QByteArray subType = node->contentType(false) ? node->contentType()->subType().toLower() : "plain"; | ||
919 | const bool isMultipart = node->contentType(false) && node->contentType()->isMultipart(); | ||
920 | bool isSignature = false; | ||
921 | |||
922 | qCDebug(MIMETREEPARSER_LOG) << "(" << recursionLevel << ") Looking at" << type << "/" << subType; | ||
923 | |||
924 | if (isMultipart) { | ||
925 | if (subType == "signed") { | ||
926 | isSignature = true; | ||
927 | } else if (subType == "encrypted") { | ||
928 | decryptedNode = decryptedNodeForContent(curNode); | ||
929 | } | ||
930 | } else if (type == "application") { | ||
931 | if (subType == "octet-stream") { | ||
932 | decryptedNode = decryptedNodeForContent(curNode); | ||
933 | } else if (subType == "pkcs7-signature") { | ||
934 | isSignature = true; | ||
935 | } else if (subType == "pkcs7-mime") { | ||
936 | // note: subtype pkcs7-mime can also be signed | ||
937 | // and we do NOT want to remove the signature! | ||
938 | if (encryptionState(curNode) != KMMsgNotEncrypted) { | ||
939 | decryptedNode = decryptedNodeForContent(curNode); | ||
940 | } | ||
941 | } | ||
942 | } | ||
943 | |||
944 | if (decryptedNode) { | ||
945 | qCDebug(MIMETREEPARSER_LOG) << "Current node has an associated decrypted node, adding a modified header " | ||
946 | "and then processing the children."; | ||
947 | |||
948 | Q_ASSERT(addHeaders); | ||
949 | KMime::Content headers; | ||
950 | headers.setHead(curNode->head()); | ||
951 | headers.parse(); | ||
952 | if (decryptedNode->contentType(false)) { | ||
953 | headers.contentType()->from7BitString(decryptedNode->contentType()->as7BitString(false)); | ||
954 | } else { | ||
955 | headers.removeHeader<KMime::Headers::ContentType>(); | ||
956 | } | ||
957 | if (decryptedNode->contentTransferEncoding(false)) { | ||
958 | headers.contentTransferEncoding()->from7BitString(decryptedNode->contentTransferEncoding()->as7BitString(false)); | ||
959 | } else { | ||
960 | headers.removeHeader<KMime::Headers::ContentTransferEncoding>(); | ||
961 | } | ||
962 | if (decryptedNode->contentDisposition(false)) { | ||
963 | headers.contentDisposition()->from7BitString(decryptedNode->contentDisposition()->as7BitString(false)); | ||
964 | } else { | ||
965 | headers.removeHeader<KMime::Headers::ContentDisposition>(); | ||
966 | } | ||
967 | if (decryptedNode->contentDescription(false)) { | ||
968 | headers.contentDescription()->from7BitString(decryptedNode->contentDescription()->as7BitString(false)); | ||
969 | } else { | ||
970 | headers.removeHeader<KMime::Headers::ContentDescription>(); | ||
971 | } | ||
972 | headers.assemble(); | ||
973 | |||
974 | resultingData += headers.head() + '\n'; | ||
975 | unencryptedMessage_helper(decryptedNode, resultingData, false, recursionLevel + 1); | ||
976 | |||
977 | returnValue = true; | ||
978 | } | ||
979 | |||
980 | else if (isSignature) { | ||
981 | qCDebug(MIMETREEPARSER_LOG) << "Current node is a signature, adding it as-is."; | ||
982 | // We can't change the nodes under the signature, as that would invalidate it. Add the signature | ||
983 | // and its child as-is | ||
984 | if (addHeaders) { | ||
985 | resultingData += curNode->head() + '\n'; | ||
986 | } | ||
987 | resultingData += curNode->encodedBody(); | ||
988 | returnValue = false; | ||
989 | } | ||
990 | |||
991 | else if (isMultipart) { | ||
992 | qCDebug(MIMETREEPARSER_LOG) << "Current node is a multipart node, adding its header and then processing all children."; | ||
993 | // Normal multipart node, add the header and all of its children | ||
994 | bool somethingChanged = false; | ||
995 | if (addHeaders) { | ||
996 | resultingData += curNode->head() + '\n'; | ||
997 | } | ||
998 | const QByteArray boundary = curNode->contentType()->boundary(); | ||
999 | foreach (KMime::Content *child, curNode->contents()) { | ||
1000 | resultingData += "\n--" + boundary + '\n'; | ||
1001 | const bool changed = unencryptedMessage_helper(child, resultingData, true, recursionLevel + 1); | ||
1002 | if (changed) { | ||
1003 | somethingChanged = true; | ||
1004 | } | ||
1005 | } | ||
1006 | resultingData += "\n--" + boundary + "--\n\n"; | ||
1007 | returnValue = somethingChanged; | ||
1008 | } | ||
1009 | |||
1010 | else if (curNode->bodyIsMessage()) { | ||
1011 | qCDebug(MIMETREEPARSER_LOG) << "Current node is a message, adding the header and then processing the child."; | ||
1012 | if (addHeaders) { | ||
1013 | resultingData += curNode->head() + '\n'; | ||
1014 | } | ||
1015 | |||
1016 | returnValue = unencryptedMessage_helper(curNode->bodyAsMessage().data(), resultingData, true, recursionLevel + 1); | ||
1017 | } | ||
1018 | |||
1019 | else { | ||
1020 | qCDebug(MIMETREEPARSER_LOG) << "Current node is an ordinary leaf node, adding it as-is."; | ||
1021 | if (addHeaders) { | ||
1022 | resultingData += curNode->head() + '\n'; | ||
1023 | } | ||
1024 | resultingData += curNode->body(); | ||
1025 | returnValue = false; | ||
1026 | } | ||
1027 | } | ||
1028 | |||
1029 | qCDebug(MIMETREEPARSER_LOG) << "(" << recursionLevel << ") done."; | ||
1030 | return returnValue; | ||
1031 | } | ||
1032 | |||
1033 | KMime::Message::Ptr NodeHelper::unencryptedMessage(const KMime::Message::Ptr &originalMessage) | ||
1034 | { | ||
1035 | QByteArray resultingData; | ||
1036 | const bool messageChanged = unencryptedMessage_helper(originalMessage.data(), resultingData, true); | ||
1037 | if (messageChanged) { | ||
1038 | #if 0 | ||
1039 | qCDebug(MIMETREEPARSER_LOG) << "Resulting data is:" << resultingData; | ||
1040 | QFile bla("stripped.mbox"); | ||
1041 | bla.open(QIODevice::WriteOnly); | ||
1042 | bla.write(resultingData); | ||
1043 | bla.close(); | ||
1044 | #endif | ||
1045 | KMime::Message::Ptr newMessage(new KMime::Message); | ||
1046 | newMessage->setContent(resultingData); | ||
1047 | newMessage->parse(); | ||
1048 | return newMessage; | ||
1049 | } else { | ||
1050 | return KMime::Message::Ptr(); | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | QVector<KMime::Content *> NodeHelper::attachmentsOfExtraContents() const | ||
1055 | { | ||
1056 | QVector<KMime::Content *> result; | ||
1057 | for (auto it = mExtraContents.begin(); it != mExtraContents.end(); ++it) { | ||
1058 | foreach (auto content, it.value()) { | ||
1059 | if (KMime::isAttachment(content)) { | ||
1060 | result.push_back(content); | ||
1061 | } else { | ||
1062 | result += content->attachments(); | ||
1063 | } | ||
1064 | } | ||
1065 | } | ||
1066 | return result; | ||
1067 | } | ||
1068 | |||
1069 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/nodehelper.h b/framework/src/domain/mime/mimetreeparser/otp/nodehelper.h new file mode 100644 index 00000000..70253f21 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/nodehelper.h | |||
@@ -0,0 +1,290 @@ | |||
1 | /* | ||
2 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
3 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along | ||
16 | with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef __MIMETREEPARSER_NODEHELPER_H__ | ||
21 | #define __MIMETREEPARSER_NODEHELPER_H__ | ||
22 | |||
23 | #include "partmetadata.h" | ||
24 | #include "enums.h" | ||
25 | |||
26 | #include <KMime/Message> | ||
27 | |||
28 | #include <QList> | ||
29 | #include <QMap> | ||
30 | #include <QSet> | ||
31 | |||
32 | class QUrl; | ||
33 | class QTextCodec; | ||
34 | |||
35 | namespace MimeTreeParser | ||
36 | { | ||
37 | class AttachmentTemporaryFilesDirs; | ||
38 | namespace Interface | ||
39 | { | ||
40 | class BodyPartMemento; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | namespace MimeTreeParser | ||
45 | { | ||
46 | |||
47 | /** | ||
48 | * @author Andras Mantia <andras@kdab.net> | ||
49 | */ | ||
50 | class NodeHelper: public QObject | ||
51 | { | ||
52 | Q_OBJECT | ||
53 | public: | ||
54 | NodeHelper(); | ||
55 | |||
56 | ~NodeHelper(); | ||
57 | |||
58 | void setNodeProcessed(KMime::Content *node, bool recurse); | ||
59 | void setNodeUnprocessed(KMime::Content *node, bool recurse); | ||
60 | bool nodeProcessed(KMime::Content *node) const; | ||
61 | void clear(); | ||
62 | void forceCleanTempFiles(); | ||
63 | |||
64 | void setEncryptionState(const KMime::Content *node, const KMMsgEncryptionState state); | ||
65 | KMMsgEncryptionState encryptionState(const KMime::Content *node) const; | ||
66 | |||
67 | void setSignatureState(const KMime::Content *node, const KMMsgSignatureState state); | ||
68 | KMMsgSignatureState signatureState(const KMime::Content *node) const; | ||
69 | |||
70 | KMMsgSignatureState overallSignatureState(KMime::Content *node) const; | ||
71 | KMMsgEncryptionState overallEncryptionState(KMime::Content *node) const; | ||
72 | |||
73 | void setPartMetaData(KMime::Content *node, const PartMetaData &metaData); | ||
74 | PartMetaData partMetaData(KMime::Content *node); | ||
75 | |||
76 | /** | ||
77 | * Set the 'Content-Type' by mime-magic from the contents of the body. | ||
78 | * If autoDecode is true the decoded body will be used for mime type | ||
79 | * determination (this does not change the body itself). | ||
80 | */ | ||
81 | void magicSetType(KMime::Content *node, bool autoDecode = true); | ||
82 | |||
83 | /** | ||
84 | * Return this mails subject, with all "forward" and "reply" | ||
85 | * prefixes removed | ||
86 | */ | ||
87 | static QString cleanSubject(KMime::Message *message); | ||
88 | |||
89 | /** Attach an extra node to an existing node */ | ||
90 | void attachExtraContent(KMime::Content *topLevelNode, KMime::Content *content); | ||
91 | |||
92 | /** Get the extra nodes attached to the @param topLevelNode and all sub-nodes of @param topLevelNode */ | ||
93 | QList<KMime::Content *> extraContents(KMime::Content *topLevelNode) const; | ||
94 | |||
95 | /** Return a modified message (node tree) starting from @param topLevelNode that has the original nodes and the extra nodes. | ||
96 | The caller has the responsibility to delete the new message. | ||
97 | */ | ||
98 | KMime::Message *messageWithExtraContent(KMime::Content *topLevelNode); | ||
99 | |||
100 | /** Get a QTextCodec suitable for this message part */ | ||
101 | const QTextCodec *codec(KMime::Content *node); | ||
102 | |||
103 | /** Set the charset the user selected for the message to display */ | ||
104 | void setOverrideCodec(KMime::Content *node, const QTextCodec *codec); | ||
105 | |||
106 | Interface::BodyPartMemento *bodyPartMemento(KMime::Content *node, const QByteArray &which) const; | ||
107 | |||
108 | void setBodyPartMemento(KMime::Content *node, const QByteArray &which, | ||
109 | Interface::BodyPartMemento *memento); | ||
110 | |||
111 | // A flag to remember if the node was embedded. This is useful for attachment nodes, the reader | ||
112 | // needs to know if they were displayed inline or not. | ||
113 | bool isNodeDisplayedEmbedded(KMime::Content *node) const; | ||
114 | void setNodeDisplayedEmbedded(KMime::Content *node, bool displayedEmbedded); | ||
115 | |||
116 | // Same as above, but this time determines if the node was hidden or not | ||
117 | bool isNodeDisplayedHidden(KMime::Content *node) const; | ||
118 | void setNodeDisplayedHidden(KMime::Content *node, bool displayedHidden); | ||
119 | |||
120 | /** | ||
121 | * Writes the given message part to a temporary file and returns the | ||
122 | * name of this file or QString() if writing failed. | ||
123 | */ | ||
124 | QString writeNodeToTempFile(KMime::Content *node); | ||
125 | |||
126 | /** | ||
127 | * Returns the temporary file path and name where this node was saved, or an empty url | ||
128 | * if it wasn't saved yet with writeNodeToTempFile() | ||
129 | */ | ||
130 | QUrl tempFileUrlFromNode(const KMime::Content *node); | ||
131 | |||
132 | /** | ||
133 | * Creates a temporary dir for saving attachments, etc. | ||
134 | * Will be automatically deleted when another message is viewed. | ||
135 | * @param param Optional part of the directory name. | ||
136 | */ | ||
137 | QString createTempDir(const QString ¶m = QString()); | ||
138 | |||
139 | /** | ||
140 | * Cleanup the attachment temp files | ||
141 | */ | ||
142 | void removeTempFiles(); | ||
143 | |||
144 | /** | ||
145 | * Add a file to the list of managed temporary files | ||
146 | */ | ||
147 | void addTempFile(const QString &file); | ||
148 | |||
149 | // Get a href in the form attachment:<nodeId>?place=<place>, used by ObjectTreeParser and | ||
150 | // UrlHandlerManager. | ||
151 | QString asHREF(const KMime::Content *node, const QString &place) const; | ||
152 | KMime::Content *fromHREF(const KMime::Message::Ptr &mMessage, const QUrl &href) const; | ||
153 | |||
154 | /** | ||
155 | * @return true if this node is a child or an encapsulated message | ||
156 | */ | ||
157 | static bool isInEncapsulatedMessage(KMime::Content *node); | ||
158 | |||
159 | /** | ||
160 | * Returns the charset for the given node. If no charset is specified | ||
161 | * for the node, the defaultCharset() is returned. | ||
162 | */ | ||
163 | static QByteArray charset(KMime::Content *node); | ||
164 | |||
165 | /** | ||
166 | * Check for prefixes @p prefixRegExps in @p str. If none | ||
167 | * is found, @p newPrefix + ' ' is prepended to @p str and the | ||
168 | * resulting string is returned. If @p replace is true, any | ||
169 | * sequence of whitespace-delimited prefixes at the beginning of | ||
170 | * @p str is replaced by @p newPrefix. | ||
171 | */ | ||
172 | static QString replacePrefixes(const QString &str, | ||
173 | const QStringList &prefixRegExps, | ||
174 | bool replace, | ||
175 | const QString &newPrefix); | ||
176 | |||
177 | /** | ||
178 | * Return a QTextCodec for the specified charset. | ||
179 | * This function is a bit more tolerant, than QTextCodec::codecForName | ||
180 | */ | ||
181 | static const QTextCodec *codecForName(const QByteArray &_str); | ||
182 | |||
183 | /** | ||
184 | * Returns a usable filename for a node, that can be the filename from the | ||
185 | * content disposition header, or if that one is empty, the name from the | ||
186 | * content type header. | ||
187 | */ | ||
188 | static QString fileName(const KMime::Content *node); | ||
189 | |||
190 | /** | ||
191 | * Fixes an encoding received by a KDE function and returns the proper, | ||
192 | * MIME-compilant encoding name instead. | ||
193 | * @see encodingForName | ||
194 | */ | ||
195 | static QString fixEncoding(const QString &encoding); //TODO(Andras) move to a utility class? | ||
196 | |||
197 | /** | ||
198 | * Drop-in replacement for KCharsets::encodingForName(). The problem with | ||
199 | * the KCharsets function is that it returns "human-readable" encoding names | ||
200 | * like "ISO 8859-15" instead of valid encoding names like "ISO-8859-15". | ||
201 | * This function fixes this by replacing whitespace with a hyphen. | ||
202 | */ | ||
203 | static QString encodingForName(const QString &descriptiveName); //TODO(Andras) move to a utility class? | ||
204 | |||
205 | /** | ||
206 | * Return a list of the supported encodings | ||
207 | * @param usAscii if true, US-Ascii encoding will be prepended to the list. | ||
208 | */ | ||
209 | static QStringList supportedEncodings(bool usAscii); //TODO(Andras) move to a utility class? | ||
210 | |||
211 | QString fromAsString(KMime::Content *node) const; | ||
212 | |||
213 | KMime::Content *decryptedNodeForContent(KMime::Content *content) const; | ||
214 | |||
215 | /** | ||
216 | * This function returns the unencrypted message that is based on @p originalMessage. | ||
217 | * All encrypted MIME parts are removed and replaced by their decrypted plain-text versions. | ||
218 | * Encrypted parts that are within signed parts are not replaced, since that would invalidate | ||
219 | * the signature. | ||
220 | * | ||
221 | * This only works if the message was run through ObjectTreeParser::parseObjectTree() with the | ||
222 | * currrent NodeHelper before, because parseObjectTree() actually decrypts the message and stores | ||
223 | * the decrypted nodes by calling attachExtraContent(). | ||
224 | * | ||
225 | * @return the unencrypted message or an invalid pointer if the original message didn't contain | ||
226 | * a part that needed to be modified. | ||
227 | */ | ||
228 | KMime::Message::Ptr unencryptedMessage(const KMime::Message::Ptr &originalMessage); | ||
229 | |||
230 | /** | ||
231 | * Returns a list of attachments of attached extra content nodes. | ||
232 | * This is mainly useful is order to get attachments of encrypted messages. | ||
233 | * Note that this does not include attachments from the primary node tree. | ||
234 | * @see KMime::Content::attachments(). | ||
235 | */ | ||
236 | QVector<KMime::Content *> attachmentsOfExtraContents() const; | ||
237 | |||
238 | Q_SIGNALS: | ||
239 | void update(MimeTreeParser::UpdateMode); | ||
240 | |||
241 | private: | ||
242 | Q_DISABLE_COPY(NodeHelper) | ||
243 | bool unencryptedMessage_helper(KMime::Content *node, QByteArray &resultingData, bool addHeaders, | ||
244 | int recursionLevel = 1); | ||
245 | |||
246 | /** Check for prefixes @p prefixRegExps in #subject(). If none | ||
247 | is found, @p newPrefix + ' ' is prepended to the subject and the | ||
248 | resulting string is returned. If @p replace is true, any | ||
249 | sequence of whitespace-delimited prefixes at the beginning of | ||
250 | #subject() is replaced by @p newPrefix | ||
251 | **/ | ||
252 | static QString cleanSubject(KMime::Message *message, const QStringList &prefixRegExps, | ||
253 | bool replace, const QString &newPrefix); | ||
254 | |||
255 | void mergeExtraNodes(KMime::Content *node); | ||
256 | void cleanFromExtraNodes(KMime::Content *node); | ||
257 | |||
258 | /** Creates a persistent index string that bridges the gap between the | ||
259 | permanent nodes and the temporary ones. | ||
260 | |||
261 | Used internally for robust indexing. | ||
262 | **/ | ||
263 | QString persistentIndex(const KMime::Content *node) const; | ||
264 | |||
265 | /** Translates the persistentIndex into a node back | ||
266 | |||
267 | node: any node of the actually message to what the persistentIndex is interpreded | ||
268 | **/ | ||
269 | KMime::Content *contentFromIndex(KMime::Content *node, const QString &persistentIndex) const; | ||
270 | |||
271 | private: | ||
272 | QList<KMime::Content *> mProcessedNodes; | ||
273 | QList<KMime::Content *> mNodesUnderProcess; | ||
274 | QMap<const KMime::Content *, KMMsgEncryptionState> mEncryptionState; | ||
275 | QMap<const KMime::Content *, KMMsgSignatureState> mSignatureState; | ||
276 | QSet<KMime::Content *> mDisplayEmbeddedNodes; | ||
277 | QSet<KMime::Content *> mDisplayHiddenNodes; | ||
278 | QTextCodec *mLocalCodec; | ||
279 | QMap<KMime::Content *, const QTextCodec *> mOverrideCodecs; | ||
280 | QMap<QString, QMap<QByteArray, Interface::BodyPartMemento *> > mBodyPartMementoMap; | ||
281 | QMap<KMime::Content *, PartMetaData> mPartMetaDatas; | ||
282 | QMap<KMime::Message::Content *, QList<KMime::Content *> > mExtraContents; | ||
283 | AttachmentTemporaryFilesDirs *mAttachmentFilesDir; | ||
284 | |||
285 | friend class NodeHelperTest; | ||
286 | }; | ||
287 | |||
288 | } | ||
289 | |||
290 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/objecttreeparser.cpp b/framework/src/domain/mime/mimetreeparser/otp/objecttreeparser.cpp new file mode 100644 index 00000000..b0d514b6 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/objecttreeparser.cpp | |||
@@ -0,0 +1,495 @@ | |||
1 | /* | ||
2 | objecttreeparser.cpp | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | Copyright (C) 2002-2004 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
7 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
8 | Copyright (c) 2015 Sandro Knauß <sknauss@kde.org> | ||
9 | |||
10 | KMail is free software; you can redistribute it and/or modify it | ||
11 | under the terms of the GNU General Public License, version 2, as | ||
12 | published by the Free Software Foundation. | ||
13 | |||
14 | KMail is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
22 | |||
23 | In addition, as a special exception, the copyright holders give | ||
24 | permission to link the code of this program with any edition of | ||
25 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
26 | of Qt that use the same license as Qt), and distribute linked | ||
27 | combinations including the two. You must obey the GNU General | ||
28 | Public License in all respects for all of the code used other than | ||
29 | Qt. If you modify this file, you may extend this exception to | ||
30 | your version of the file, but you are not obligated to do so. If | ||
31 | you do not wish to do so, delete this exception statement from | ||
32 | your version. | ||
33 | */ | ||
34 | |||
35 | // MessageViewer includes | ||
36 | |||
37 | #include "objecttreeparser.h" | ||
38 | |||
39 | #include "attachmentstrategy.h" | ||
40 | #include "bodypartformatterbasefactory.h" | ||
41 | #include "nodehelper.h" | ||
42 | #include "messagepart.h" | ||
43 | #include "partnodebodypart.h" | ||
44 | |||
45 | #include "mimetreeparser_debug.h" | ||
46 | |||
47 | #include "utils.h" | ||
48 | #include "bodypartformatter.h" | ||
49 | #include "htmlwriter.h" | ||
50 | #include "messagepartrenderer.h" | ||
51 | #include "util.h" | ||
52 | |||
53 | #include <KMime/Headers> | ||
54 | #include <KMime/Message> | ||
55 | |||
56 | // KDE includes | ||
57 | |||
58 | // Qt includes | ||
59 | #include <QByteArray> | ||
60 | #include <QTextCodec> | ||
61 | #include <QUrl> | ||
62 | |||
63 | using namespace MimeTreeParser; | ||
64 | |||
65 | ObjectTreeParser::ObjectTreeParser(const ObjectTreeParser *topLevelParser, | ||
66 | bool showOnlyOneMimePart, | ||
67 | const AttachmentStrategy *strategy) | ||
68 | : mSource(topLevelParser->mSource), | ||
69 | mNodeHelper(topLevelParser->mNodeHelper), | ||
70 | mHtmlWriter(topLevelParser->mHtmlWriter), | ||
71 | mTopLevelContent(topLevelParser->mTopLevelContent), | ||
72 | mShowOnlyOneMimePart(showOnlyOneMimePart), | ||
73 | mHasPendingAsyncJobs(false), | ||
74 | mAllowAsync(topLevelParser->mAllowAsync), | ||
75 | mAttachmentStrategy(strategy) | ||
76 | { | ||
77 | init(); | ||
78 | } | ||
79 | |||
80 | ObjectTreeParser::ObjectTreeParser(Interface::ObjectTreeSource *source, | ||
81 | MimeTreeParser::NodeHelper *nodeHelper, | ||
82 | bool showOnlyOneMimePart, | ||
83 | const AttachmentStrategy *strategy) | ||
84 | : mSource(source), | ||
85 | mNodeHelper(nodeHelper), | ||
86 | mHtmlWriter(nullptr), | ||
87 | mTopLevelContent(nullptr), | ||
88 | mShowOnlyOneMimePart(showOnlyOneMimePart), | ||
89 | mHasPendingAsyncJobs(false), | ||
90 | mAllowAsync(false), | ||
91 | mAttachmentStrategy(strategy) | ||
92 | { | ||
93 | init(); | ||
94 | } | ||
95 | |||
96 | void ObjectTreeParser::init() | ||
97 | { | ||
98 | Q_ASSERT(mSource); | ||
99 | if (!attachmentStrategy()) { | ||
100 | mAttachmentStrategy = mSource->attachmentStrategy(); | ||
101 | } | ||
102 | |||
103 | if (!mNodeHelper) { | ||
104 | mNodeHelper = new NodeHelper(); | ||
105 | mDeleteNodeHelper = true; | ||
106 | } else { | ||
107 | mDeleteNodeHelper = false; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | ObjectTreeParser::ObjectTreeParser(const ObjectTreeParser &other) | ||
112 | : mSource(other.mSource), | ||
113 | mNodeHelper(other.nodeHelper()), //TODO(Andras) hm, review what happens if mDeleteNodeHelper was true in the source | ||
114 | mHtmlWriter(other.mHtmlWriter), | ||
115 | mTopLevelContent(other.mTopLevelContent), | ||
116 | mShowOnlyOneMimePart(other.showOnlyOneMimePart()), | ||
117 | mHasPendingAsyncJobs(other.hasPendingAsyncJobs()), | ||
118 | mAllowAsync(other.allowAsync()), | ||
119 | mAttachmentStrategy(other.attachmentStrategy()), | ||
120 | mDeleteNodeHelper(false) | ||
121 | { | ||
122 | |||
123 | } | ||
124 | |||
125 | ObjectTreeParser::~ObjectTreeParser() | ||
126 | { | ||
127 | if (mDeleteNodeHelper) { | ||
128 | delete mNodeHelper; | ||
129 | mNodeHelper = nullptr; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | void ObjectTreeParser::setAllowAsync(bool allow) | ||
134 | { | ||
135 | Q_ASSERT(!mHasPendingAsyncJobs); | ||
136 | mAllowAsync = allow; | ||
137 | } | ||
138 | |||
139 | bool ObjectTreeParser::allowAsync() const | ||
140 | { | ||
141 | return mAllowAsync; | ||
142 | } | ||
143 | |||
144 | bool ObjectTreeParser::hasPendingAsyncJobs() const | ||
145 | { | ||
146 | return mHasPendingAsyncJobs; | ||
147 | } | ||
148 | |||
149 | QString ObjectTreeParser::plainTextContent() const | ||
150 | { | ||
151 | return mPlainTextContent; | ||
152 | } | ||
153 | |||
154 | QString ObjectTreeParser::htmlContent() const | ||
155 | { | ||
156 | return mHtmlContent; | ||
157 | } | ||
158 | |||
159 | void ObjectTreeParser::copyContentFrom(const ObjectTreeParser *other) | ||
160 | { | ||
161 | mPlainTextContent += other->plainTextContent(); | ||
162 | mHtmlContent += other->htmlContent(); | ||
163 | if (!other->plainTextContentCharset().isEmpty()) { | ||
164 | mPlainTextContentCharset = other->plainTextContentCharset(); | ||
165 | } | ||
166 | if (!other->htmlContentCharset().isEmpty()) { | ||
167 | mHtmlContentCharset = other->htmlContentCharset(); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | //----------------------------------------------------------------------------- | ||
172 | |||
173 | void ObjectTreeParser::parseObjectTree(KMime::Content *node) | ||
174 | { | ||
175 | mTopLevelContent = node; | ||
176 | mParsedPart = parseObjectTreeInternal(node, showOnlyOneMimePart()); | ||
177 | |||
178 | if (mParsedPart) { | ||
179 | mParsedPart->fix(); | ||
180 | mParsedPart->copyContentFrom(); | ||
181 | if (auto mp = toplevelTextNode(mParsedPart)) { | ||
182 | if (auto _mp = mp.dynamicCast<TextMessagePart>()) { | ||
183 | extractNodeInfos(_mp->mNode, true); | ||
184 | } else if (auto _mp = mp.dynamicCast<AlternativeMessagePart>()) { | ||
185 | if (_mp->mChildNodes.contains(Util::MultipartPlain)) { | ||
186 | extractNodeInfos(_mp->mChildNodes[Util::MultipartPlain], true); | ||
187 | } | ||
188 | } | ||
189 | setPlainTextContent(mp->text()); | ||
190 | } | ||
191 | |||
192 | if (htmlWriter()) { | ||
193 | const auto renderer = mSource->messagePartTheme(mParsedPart); | ||
194 | if (renderer) { | ||
195 | mHtmlWriter->queue(renderer->html()); | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | |||
201 | MessagePartPtr ObjectTreeParser::parsedPart() const | ||
202 | { | ||
203 | return mParsedPart; | ||
204 | } | ||
205 | |||
206 | bool ObjectTreeParser::processType(KMime::Content *node, ProcessResult &processResult, const QByteArray &mediaType, const QByteArray &subType, Interface::MessagePartPtr &mpRet, bool onlyOneMimePart) | ||
207 | { | ||
208 | bool bRendered = false; | ||
209 | const auto sub = mSource->bodyPartFormatterFactory()->subtypeRegistry(mediaType.constData()); | ||
210 | auto range = sub.equal_range(subType.constData()); | ||
211 | for (auto it = range.first; it != range.second; ++it) { | ||
212 | const auto formatter = (*it).second; | ||
213 | if (!formatter) { | ||
214 | continue; | ||
215 | } | ||
216 | PartNodeBodyPart part(this, &processResult, mTopLevelContent, node, mNodeHelper); | ||
217 | // Set the default display strategy for this body part relying on the | ||
218 | // identity of Interface::BodyPart::Display and AttachmentStrategy::Display | ||
219 | part.setDefaultDisplay((Interface::BodyPart::Display) attachmentStrategy()->defaultDisplay(node)); | ||
220 | |||
221 | mNodeHelper->setNodeDisplayedEmbedded(node, true); | ||
222 | |||
223 | const Interface::MessagePart::Ptr result = formatter->process(part); | ||
224 | if (!result) { | ||
225 | continue; | ||
226 | } | ||
227 | |||
228 | if (const auto mp = result.dynamicCast<MessagePart>()) { | ||
229 | mp->setAttachmentFlag(node); | ||
230 | mpRet = result; | ||
231 | bRendered = true; | ||
232 | break; | ||
233 | } else if (dynamic_cast<MimeTreeParser::Interface::MessagePart *>(result.data())) { | ||
234 | QObject *asyncResultObserver = allowAsync() ? mSource->sourceObject() : nullptr; | ||
235 | const auto r = formatter->format(&part, result->htmlWriter(), asyncResultObserver); | ||
236 | if (r == Interface::BodyPartFormatter::AsIcon) { | ||
237 | processResult.setNeverDisplayInline(true); | ||
238 | formatter->adaptProcessResult(processResult); | ||
239 | mNodeHelper->setNodeDisplayedEmbedded(node, false); | ||
240 | const Interface::MessagePart::Ptr mp = defaultHandling(node, processResult, onlyOneMimePart); | ||
241 | if (mp) { | ||
242 | if (auto _mp = mp.dynamicCast<MessagePart>()) { | ||
243 | _mp->setAttachmentFlag(node); | ||
244 | } | ||
245 | mpRet = mp; | ||
246 | } | ||
247 | bRendered = true; | ||
248 | break; | ||
249 | } else if (r == Interface::BodyPartFormatter::Ok) { | ||
250 | processResult.setNeverDisplayInline(true); | ||
251 | formatter->adaptProcessResult(processResult); | ||
252 | mpRet = result; | ||
253 | bRendered = true; | ||
254 | break; | ||
255 | } | ||
256 | continue; | ||
257 | } else { | ||
258 | continue; | ||
259 | } | ||
260 | } | ||
261 | return bRendered; | ||
262 | } | ||
263 | |||
264 | MessagePart::Ptr ObjectTreeParser::parseObjectTreeInternal(KMime::Content *node, bool onlyOneMimePart) | ||
265 | { | ||
266 | if (!node) { | ||
267 | return MessagePart::Ptr(); | ||
268 | } | ||
269 | |||
270 | // reset pending async jobs state (we'll rediscover pending jobs as we go) | ||
271 | mHasPendingAsyncJobs = false; | ||
272 | |||
273 | // reset "processed" flags for... | ||
274 | if (onlyOneMimePart) { | ||
275 | // ... this node and all descendants | ||
276 | mNodeHelper->setNodeUnprocessed(node, false); | ||
277 | if (!node->contents().isEmpty()) { | ||
278 | mNodeHelper->setNodeUnprocessed(node, true); | ||
279 | } | ||
280 | } else if (!node->parent()) { | ||
281 | // ...this node and all it's siblings and descendants | ||
282 | mNodeHelper->setNodeUnprocessed(node, true); | ||
283 | } | ||
284 | |||
285 | const bool isRoot = node->isTopLevel(); | ||
286 | auto parsedPart = MessagePart::Ptr(new MessagePartList(this)); | ||
287 | parsedPart->setIsRoot(isRoot); | ||
288 | KMime::Content *parent = node->parent(); | ||
289 | auto contents = parent ? parent->contents() : KMime::Content::List(); | ||
290 | if (contents.isEmpty()) { | ||
291 | contents.append(node); | ||
292 | } | ||
293 | int i = contents.indexOf(const_cast<KMime::Content *>(node)); | ||
294 | for (; i < contents.size(); ++i) { | ||
295 | node = contents.at(i); | ||
296 | if (mNodeHelper->nodeProcessed(node)) { | ||
297 | continue; | ||
298 | } | ||
299 | |||
300 | ProcessResult processResult(mNodeHelper); | ||
301 | |||
302 | QByteArray mediaType("text"); | ||
303 | QByteArray subType("plain"); | ||
304 | if (node->contentType(false) && !node->contentType()->mediaType().isEmpty() && | ||
305 | !node->contentType()->subType().isEmpty()) { | ||
306 | mediaType = node->contentType()->mediaType(); | ||
307 | subType = node->contentType()->subType(); | ||
308 | } | ||
309 | |||
310 | Interface::MessagePartPtr mp; | ||
311 | if (processType(node, processResult, mediaType, subType, mp, onlyOneMimePart)) { | ||
312 | if (mp) { | ||
313 | parsedPart->appendSubPart(mp); | ||
314 | } | ||
315 | } else if (processType(node, processResult, mediaType, "*", mp, onlyOneMimePart)) { | ||
316 | if (mp) { | ||
317 | parsedPart->appendSubPart(mp); | ||
318 | } | ||
319 | } else { | ||
320 | qCWarning(MIMETREEPARSER_LOG) << "THIS SHOULD NO LONGER HAPPEN:" << mediaType << '/' << subType; | ||
321 | const auto mp = defaultHandling(node, processResult, onlyOneMimePart); | ||
322 | if (mp) { | ||
323 | if (auto _mp = mp.dynamicCast<MessagePart>()) { | ||
324 | _mp->setAttachmentFlag(node); | ||
325 | } | ||
326 | parsedPart->appendSubPart(mp); | ||
327 | } | ||
328 | } | ||
329 | mNodeHelper->setNodeProcessed(node, false); | ||
330 | |||
331 | // adjust signed/encrypted flags if inline PGP was found | ||
332 | processResult.adjustCryptoStatesOfNode(node); | ||
333 | |||
334 | if (onlyOneMimePart) { | ||
335 | break; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | return parsedPart; | ||
340 | } | ||
341 | |||
342 | Interface::MessagePart::Ptr ObjectTreeParser::defaultHandling(KMime::Content *node, ProcessResult &result, bool onlyOneMimePart) | ||
343 | { | ||
344 | Interface::MessagePart::Ptr mp; | ||
345 | ProcessResult processResult(mNodeHelper); | ||
346 | |||
347 | if (node->contentType()->mimeType() == QByteArrayLiteral("application/octet-stream") && | ||
348 | (node->contentType()->name().endsWith(QLatin1String("p7m")) || | ||
349 | node->contentType()->name().endsWith(QLatin1String("p7s")) || | ||
350 | node->contentType()->name().endsWith(QLatin1String("p7c")) | ||
351 | ) && | ||
352 | processType(node, processResult, "application", "pkcs7-mime", mp, onlyOneMimePart)) { | ||
353 | return mp; | ||
354 | } | ||
355 | |||
356 | const auto _mp = AttachmentMessagePart::Ptr(new AttachmentMessagePart(this, node, false, true, mSource->decryptMessage())); | ||
357 | result.setInlineSignatureState(_mp->signatureState()); | ||
358 | result.setInlineEncryptionState(_mp->encryptionState()); | ||
359 | _mp->setNeverDisplayInline(result.neverDisplayInline()); | ||
360 | _mp->setIsImage(result.isImage()); | ||
361 | mp = _mp; | ||
362 | |||
363 | // always show images in multipart/related when showing in html, not with an additional icon | ||
364 | auto preferredMode = mSource->preferredMode(); | ||
365 | bool isHtmlPreferred = (preferredMode == Util::Html) || (preferredMode == Util::MultipartHtml); | ||
366 | if (result.isImage() && node->parent() && | ||
367 | node->parent()->contentType()->subType() == "related" && isHtmlPreferred && !onlyOneMimePart) { | ||
368 | QString fileName = mNodeHelper->writeNodeToTempFile(node); | ||
369 | QString href = QUrl::fromLocalFile(fileName).url(); | ||
370 | QByteArray cid = node->contentID()->identifier(); | ||
371 | if (htmlWriter()) { | ||
372 | htmlWriter()->embedPart(cid, href); | ||
373 | } | ||
374 | nodeHelper()->setNodeDisplayedEmbedded(node, true); | ||
375 | mNodeHelper->setNodeDisplayedHidden(node, true); | ||
376 | return mp; | ||
377 | } | ||
378 | |||
379 | // Show it inline if showOnlyOneMimePart(), which means the user clicked the image | ||
380 | // in the message structure viewer manually, and therefore wants to see the full image | ||
381 | if (result.isImage() && onlyOneMimePart && !result.neverDisplayInline()) { | ||
382 | mNodeHelper->setNodeDisplayedEmbedded(node, true); | ||
383 | } | ||
384 | |||
385 | return mp; | ||
386 | } | ||
387 | |||
388 | KMMsgSignatureState ProcessResult::inlineSignatureState() const | ||
389 | { | ||
390 | return mInlineSignatureState; | ||
391 | } | ||
392 | |||
393 | void ProcessResult::setInlineSignatureState(KMMsgSignatureState state) | ||
394 | { | ||
395 | mInlineSignatureState = state; | ||
396 | } | ||
397 | |||
398 | KMMsgEncryptionState ProcessResult::inlineEncryptionState() const | ||
399 | { | ||
400 | return mInlineEncryptionState; | ||
401 | } | ||
402 | |||
403 | void ProcessResult::setInlineEncryptionState(KMMsgEncryptionState state) | ||
404 | { | ||
405 | mInlineEncryptionState = state; | ||
406 | } | ||
407 | |||
408 | bool ProcessResult::neverDisplayInline() const | ||
409 | { | ||
410 | return mNeverDisplayInline; | ||
411 | } | ||
412 | |||
413 | void ProcessResult::setNeverDisplayInline(bool display) | ||
414 | { | ||
415 | mNeverDisplayInline = display; | ||
416 | } | ||
417 | |||
418 | bool ProcessResult::isImage() const | ||
419 | { | ||
420 | return mIsImage; | ||
421 | } | ||
422 | |||
423 | void ProcessResult::setIsImage(bool image) | ||
424 | { | ||
425 | mIsImage = image; | ||
426 | } | ||
427 | |||
428 | void ProcessResult::adjustCryptoStatesOfNode(const KMime::Content *node) const | ||
429 | { | ||
430 | if ((inlineSignatureState() != KMMsgNotSigned) || | ||
431 | (inlineEncryptionState() != KMMsgNotEncrypted)) { | ||
432 | mNodeHelper->setSignatureState(node, inlineSignatureState()); | ||
433 | mNodeHelper->setEncryptionState(node, inlineEncryptionState()); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | void ObjectTreeParser::extractNodeInfos(KMime::Content *curNode, bool isFirstTextPart) | ||
438 | { | ||
439 | if (isFirstTextPart) { | ||
440 | mPlainTextContent += curNode->decodedText(); | ||
441 | mPlainTextContentCharset += NodeHelper::charset(curNode); | ||
442 | } | ||
443 | } | ||
444 | |||
445 | void ObjectTreeParser::setPlainTextContent(const QString &plainTextContent) | ||
446 | { | ||
447 | mPlainTextContent = plainTextContent; | ||
448 | } | ||
449 | |||
450 | const QTextCodec *ObjectTreeParser::codecFor(KMime::Content *node) const | ||
451 | { | ||
452 | Q_ASSERT(node); | ||
453 | if (mSource->overrideCodec()) { | ||
454 | return mSource->overrideCodec(); | ||
455 | } | ||
456 | return mNodeHelper->codec(node); | ||
457 | } | ||
458 | |||
459 | QByteArray ObjectTreeParser::plainTextContentCharset() const | ||
460 | { | ||
461 | return mPlainTextContentCharset; | ||
462 | } | ||
463 | |||
464 | QByteArray ObjectTreeParser::htmlContentCharset() const | ||
465 | { | ||
466 | return mHtmlContentCharset; | ||
467 | } | ||
468 | |||
469 | bool ObjectTreeParser::showOnlyOneMimePart() const | ||
470 | { | ||
471 | return mShowOnlyOneMimePart; | ||
472 | } | ||
473 | |||
474 | void ObjectTreeParser::setShowOnlyOneMimePart(bool show) | ||
475 | { | ||
476 | mShowOnlyOneMimePart = show; | ||
477 | } | ||
478 | |||
479 | const AttachmentStrategy *ObjectTreeParser::attachmentStrategy() const | ||
480 | { | ||
481 | return mAttachmentStrategy; | ||
482 | } | ||
483 | |||
484 | HtmlWriter *ObjectTreeParser::htmlWriter() const | ||
485 | { | ||
486 | if (mHtmlWriter) { | ||
487 | return mHtmlWriter; | ||
488 | } | ||
489 | return mSource->htmlWriter(); | ||
490 | } | ||
491 | |||
492 | MimeTreeParser::NodeHelper *ObjectTreeParser::nodeHelper() const | ||
493 | { | ||
494 | return mNodeHelper; | ||
495 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/objecttreeparser.h b/framework/src/domain/mime/mimetreeparser/otp/objecttreeparser.h new file mode 100644 index 00000000..3f29a673 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/objecttreeparser.h | |||
@@ -0,0 +1,406 @@ | |||
1 | /* | ||
2 | objecttreeparser.h | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | Copyright (C) 2002-2003, 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
7 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
8 | |||
9 | KMail is free software; you can redistribute it and/or modify it | ||
10 | under the terms of the GNU General Public License, version 2, as | ||
11 | published by the Free Software Foundation. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #ifndef __MIMETREEPARSER_OBJECTTREEPARSER_H__ | ||
35 | #define __MIMETREEPARSER_OBJECTTREEPARSER_H__ | ||
36 | |||
37 | #include "nodehelper.h" | ||
38 | #include "objecttreesource.h" | ||
39 | |||
40 | #include <gpgme++/verificationresult.h> | ||
41 | |||
42 | class QString; | ||
43 | |||
44 | namespace KMime | ||
45 | { | ||
46 | class Content; | ||
47 | } | ||
48 | |||
49 | namespace MimeTreeParser | ||
50 | { | ||
51 | |||
52 | namespace Interface | ||
53 | { | ||
54 | class MessagePart; | ||
55 | typedef QSharedPointer<MessagePart> MessagePartPtr; | ||
56 | } | ||
57 | |||
58 | class PartMetaData; | ||
59 | class ViewerPrivate; | ||
60 | class HtmlWriter; | ||
61 | class AttachmentStrategy; | ||
62 | class NodeHelper; | ||
63 | class MessagePart; | ||
64 | class MimeMessagePart; | ||
65 | |||
66 | typedef QSharedPointer<MessagePart> MessagePartPtr; | ||
67 | typedef QSharedPointer<MimeMessagePart> MimeMessagePartPtr; | ||
68 | |||
69 | class ProcessResult | ||
70 | { | ||
71 | public: | ||
72 | explicit ProcessResult(NodeHelper *nodeHelper, KMMsgSignatureState inlineSignatureState = KMMsgNotSigned, | ||
73 | KMMsgEncryptionState inlineEncryptionState = KMMsgNotEncrypted, | ||
74 | bool neverDisplayInline = false, | ||
75 | bool isImage = false) | ||
76 | : mInlineSignatureState(inlineSignatureState), | ||
77 | mInlineEncryptionState(inlineEncryptionState), | ||
78 | mNeverDisplayInline(neverDisplayInline), | ||
79 | mIsImage(isImage), | ||
80 | mNodeHelper(nodeHelper) {} | ||
81 | |||
82 | KMMsgSignatureState inlineSignatureState() const; | ||
83 | void setInlineSignatureState(KMMsgSignatureState state); | ||
84 | |||
85 | KMMsgEncryptionState inlineEncryptionState() const; | ||
86 | void setInlineEncryptionState(KMMsgEncryptionState state); | ||
87 | |||
88 | bool neverDisplayInline() const; | ||
89 | void setNeverDisplayInline(bool display); | ||
90 | |||
91 | bool isImage() const; | ||
92 | void setIsImage(bool image); | ||
93 | |||
94 | void adjustCryptoStatesOfNode(const KMime::Content *node) const; | ||
95 | |||
96 | private: | ||
97 | KMMsgSignatureState mInlineSignatureState; | ||
98 | KMMsgEncryptionState mInlineEncryptionState; | ||
99 | bool mNeverDisplayInline : 1; | ||
100 | bool mIsImage : 1; | ||
101 | NodeHelper *mNodeHelper; | ||
102 | }; | ||
103 | |||
104 | /** | ||
105 | \brief Parses messages and generates HTML display code out of them | ||
106 | |||
107 | \par Introduction | ||
108 | |||
109 | First, have a look at the documentation in Mainpage.dox and at the documentation of ViewerPrivate | ||
110 | to understand the broader picture. | ||
111 | |||
112 | Just a note on the terminology: 'Node' refers to a MIME part here, which in KMime is a | ||
113 | KMime::Content. | ||
114 | |||
115 | \par Basics | ||
116 | |||
117 | The ObjectTreeParser basically has two modes: Generating the HTML code for the Viewer, or only | ||
118 | extracting the plainTextContent() for situations where only the message text is needed, for example | ||
119 | when inline forwarding a message. The mode depends on the Interface::ObjectTreeSource passed to the | ||
120 | constructor: If Interface::ObjectTreeSource::htmlWriter() is not 0, then the HTML code generation mode is | ||
121 | used. | ||
122 | |||
123 | Basically, all the ObjectTreeParser does is going through the tree of MIME parts and operating on | ||
124 | those nodes. Operating here means creating the HTML code for the node or extracting the textual | ||
125 | content from it. This process is started with parseObjectTree(), where we loop over the subnodes | ||
126 | of the current root node. For each of those subnodes, we try to find a BodyPartFormatter that can | ||
127 | handle the type of the node. This can either be an internal function, such as | ||
128 | processMultiPartAlternativeSubtype() or processTextHtmlSubtype(), or it can be an external plugin. | ||
129 | More on external plugins later. When no matching formatter is found, defaultHandling() is called | ||
130 | for that node. | ||
131 | |||
132 | \par Multipart Nodes | ||
133 | |||
134 | Those nodes that are of type multipart have subnodes. If one of those children needs to be | ||
135 | processed normally, the processMultipartXXX() functions call stdChildHandling() for the node that | ||
136 | should be handled normally. stdChildHandling() creates its own ObjectTreeParser, which is a clone | ||
137 | of the current ObjectTreeParser, and processes the node. stdChildHandling() is not called for all | ||
138 | children of the multipart node, for example processMultiPartAlternativeSubtype() only calls it on | ||
139 | one of the children, as the other one doesn't need to be displayed. Similary, | ||
140 | processMultiPartSignedSubtype() doesn't call stdChildHandling() for the signature node, only for the | ||
141 | signed node. | ||
142 | |||
143 | \par Processed and Unprocessed Nodes | ||
144 | |||
145 | When a BodyPartFormatter has finished processing a node, it is processed. Nodes are set to being | ||
146 | not processed at the beginning of parseObjectTree(). The processed state of a node is saved in a | ||
147 | list in NodeHelper, see NodeHelper::setNodeProcessed(), NodeHelper::nodeProcessed() and the other | ||
148 | related helper functions. | ||
149 | |||
150 | It is the responsibility of the BodyPartFormatter to correctly call setNodeProcessed() and the | ||
151 | related functions. This is important so that processing the same node twice can be prevented. The | ||
152 | check that prevents duplicate processing is in parseObjectTree(). | ||
153 | |||
154 | An example where duplicate processing would happen if we didn't check for it is in stdChildHandling(), | ||
155 | which is for example called from processMultiPartAlternativeSubtype(). Let's say the setting is to | ||
156 | prefer HTML over plain text. In this case, processMultiPartAlternativeSubtype() would call | ||
157 | stdChildHandling() on the HTML node, which would create a new ObjectTreeParser and call | ||
158 | parseObjectTree() on it. parseObjectTree() processes the node and all its siblings, and one of the | ||
159 | siblings is the plain text node, which shouldn't be processed! Therefore | ||
160 | processMultiPartAlternativeSubtype() sets the plain text node as been processed already. | ||
161 | |||
162 | \par Plain Text Output | ||
163 | |||
164 | Various nodes have plain text that should be displayed. This plain text is usually processed though | ||
165 | writeBodyString() first. That method checks if the provided text is an inline PGP text and decrypts | ||
166 | it if necessary. It also pushes the text through quotedHTML(), which does a number of things like | ||
167 | coloring quoted lines or detecting links and creating real link tags for them. | ||
168 | |||
169 | \par Modifying the Message | ||
170 | |||
171 | The ObjectTreeParser does not only parse its message, in some circumstances it also modifies it | ||
172 | before displaying. This is for example the case when displaying a decrypted message: The original | ||
173 | message only contains a binary blob of crypto data, and processMultiPartEncryptedSubtype() decrypts | ||
174 | that blob. After decryption, the current node is replaced with the decrypted node, which happens | ||
175 | in insertAndParseNewChildNode(). | ||
176 | |||
177 | \par Crypto Operations | ||
178 | |||
179 | For signature and decryption handling, there are functions which help with generating the HTML code | ||
180 | for the signature header and footer. These are writeDeferredDecryptionBlock(), writeSigstatFooter() | ||
181 | and writeSigstatHeader(). As the name writeDeferredDecryptionBlock() suggests, a setting can cause | ||
182 | the message to not be decrypted unless the user clicks a link. Whether the message should be | ||
183 | decrypted or not can be controlled by Interface::ObjectTreeSource::decryptMessage(). When the user clicks the | ||
184 | decryption link, the URLHandler for 'kmail:' URLs sets that variable to true and triggers an update | ||
185 | of the Viewer, which will cause parseObjectTree() to be called again. | ||
186 | |||
187 | \par Async Crypto Operations | ||
188 | |||
189 | The above case describes decryption the message in place. However, decryption and also verifying of | ||
190 | the signature can take a long time, so synchronous decryption and verifing would cause the Viewer to | ||
191 | block. Therefore it is possible to run these operations in async mode, see allowAsync(). | ||
192 | In the first run of the async mode, all the ObjectTreeParser does is starting the decrypt or the | ||
193 | verify job, and informing the user that the operation is in progress with | ||
194 | writeDecryptionInProgressBlock() or with writeSigstatHeader(). Then, it creates and associates a | ||
195 | BodyPartMemento with the current node, for example a VerifyDetachedBodyPartMemento. Each node can | ||
196 | have multiple mementos associated with it, which are differeniated by name. | ||
197 | |||
198 | NodeHelper::setBodyPartMemento() and NodeHelper::bodyPartMemento() provide means to store and | ||
199 | retrieve these mementos. A memento is basically a thin wrapper around the crypto job, it stores the | ||
200 | job pointer, the job input data and the job result. Mementos can be used for any async situation, | ||
201 | not just for crypto jobs, but I'll describe crypto jobs here. | ||
202 | |||
203 | So in the first run of decrypting or verifying a message, the BodyPartFormatter only starts the | ||
204 | crypto job, creates the BodyPartMemento and writes the HTML code that tells the user that the | ||
205 | operation is in progress. parseObjectTree() thus finishes without waiting for anything, and the | ||
206 | message is displayed. | ||
207 | |||
208 | At some point, the crypto jobs then finish, which will cause slotResult() of the BodyPartMemento | ||
209 | to be called. slotResult() then saves the result to some member variable and calls | ||
210 | BodyPartMemento::notify(), which in the end will trigger an update of the Viewer. That update | ||
211 | will, in ViewerPrivate::parseMsg(), create a new ObjectTreeParser and call parseObjectTree() on it. | ||
212 | This is where the second run begins. | ||
213 | |||
214 | The functions that deal with decrypting of verifying, like processMultiPartSignedSubtype() or | ||
215 | processMultiPartEncryptedSubtype() will look if they find a BodyPartMemento that is associated with | ||
216 | the current node. Now it finds that memento, since it was created in the first run. It checks if the | ||
217 | memento's job has finished, and if so, the result can be written out (either the decrypted data or | ||
218 | the verified signature). | ||
219 | |||
220 | When dealing with encrypted nodes, new nodes are created with the decrypted data. It is important to | ||
221 | note that the original MIME tree is never modified, and remains the same as the original one. The method | ||
222 | createAndParseTempNode is called with the newly decrypted data, and it generates a new temporary node to | ||
223 | store the decrypted data. When these nodes are created, it is important to keep track of them as otherwise | ||
224 | some mementos that are added to the newly created temporary nodes will be constantly regenerated. As the | ||
225 | regeneration triggers a viewer update when complete, it results in an infinite refresh loop. The function | ||
226 | NodeHelper::linkAsPermanentDecrypted will create a link between the newly created node and the original parent. | ||
227 | Conversely, the function NodeHelper::attachExtraContent will create a link in the other direction, from the parent | ||
228 | node to the newly created temporary node. | ||
229 | |||
230 | When generating some mementos for nodes that may be temporary nodes (for example, contact photo mementos), the | ||
231 | function NodeHelper::setBodyPartMementoForPermanentParent is used. This will save the given body part memento for | ||
232 | the closest found permanent parent node, rather than the transient node itself. Then when checking for the existence | ||
233 | of a certain memento in a node, NodeHelper::findPermanentParentBodyPartMemento will check to see if any parent of the | ||
234 | given temporary node is a permanent (encrypted) node that has been used to generate the asked-for node. | ||
235 | |||
236 | To conclude: For async operations, parseObjectTree() is called twice: The first call starts the | ||
237 | crypto operation and creates the BodyPartMemento, the second calls sees that the BodyPartMemento is | ||
238 | there and can use its result for writing out the HTML. | ||
239 | |||
240 | \par PartMetaData and ProcessResult | ||
241 | |||
242 | For crypto operations, the class PartMetaData is used a lot, mainly to pass around info about the | ||
243 | crypto state of a node. A PartMetaData can also be associated with a node by using | ||
244 | NodeHelper::setPartMetaData(). The only user of that however is MessageAnalyzer::processPart() of | ||
245 | the Nepomuk E-Mail Feeder, which also uses the ObjectTreeParser to analyze the message. | ||
246 | |||
247 | You'll notice that a ProcessResult is passed to each formatter. The formatter is supposed to modify | ||
248 | the ProcessResult to tell the callers something about the state of the nodes that were processed. | ||
249 | One example for its use is to tell the caller about the crypto state of the node. | ||
250 | |||
251 | \par BodyPartFormatter Plugins | ||
252 | |||
253 | As mentioned way earlier, BodyPartFormatter can either be plugins or be internal. bodypartformatter.cpp | ||
254 | contains some trickery so that the processXXX() methods of the ObjectTreeParser are called from | ||
255 | a BodyPartFormatter associated with them, see the CREATE_BODY_PART_FORMATTER macro. | ||
256 | |||
257 | The BodyPartFormatter code is work in progress, it was supposed to be refactored, but that has not | ||
258 | yet happened at the time of writing. Therefore the code can seem a bit chaotic. | ||
259 | |||
260 | External plugins are loaded with loadPlugins() in bodypartformatterfactory.cpp. External plugins | ||
261 | can only use the classes in the interfaces/ directory, they include BodyPart, BodyPartMemento, | ||
262 | BodyPartFormatterPlugin, BodyPartFormatter, BodyPartURLHandler, HtmlWriter and URLHandler. Therefore | ||
263 | external plugins have powerful capabilities, which are needed for example in the iCal formatter or | ||
264 | in the vCard formatter. | ||
265 | |||
266 | \par Special HTML tags | ||
267 | |||
268 | As also mentioned in the documentation of ViewerPrivate, the ObjectTreeParser writes out special | ||
269 | links that are only understood by the viewer, for example 'kmail:' URLs or 'attachment:' URLs. | ||
270 | Also, some special HTML tags are created, which the Viewer later uses for post-processing. For | ||
271 | example a div with the id 'attachmentInjectionPoint', or a div with the id 'attachmentDiv', which | ||
272 | is used to mark an attachment in the body with a yellow border when the user clicks the attachment | ||
273 | in the header. Finally, parseObjectTree() creates an anchor with the id 'att%1', which is used in | ||
274 | the Viewer to scroll to the attachment. | ||
275 | */ | ||
276 | class ObjectTreeParser | ||
277 | { | ||
278 | /** | ||
279 | * @internal | ||
280 | * Copies the context of @p other, but not it's rawDecryptedBody, plainTextContent or htmlContent. | ||
281 | */ | ||
282 | ObjectTreeParser(const ObjectTreeParser &other); | ||
283 | |||
284 | public: | ||
285 | explicit ObjectTreeParser(Interface::ObjectTreeSource *source, | ||
286 | NodeHelper *nodeHelper = nullptr, | ||
287 | bool showOneMimePart = false, | ||
288 | const AttachmentStrategy *attachmentStrategy = nullptr); | ||
289 | |||
290 | explicit ObjectTreeParser(const ObjectTreeParser *topLevelParser, | ||
291 | bool showOneMimePart = false, | ||
292 | const AttachmentStrategy *attachmentStrategy = nullptr); | ||
293 | virtual ~ObjectTreeParser(); | ||
294 | |||
295 | void setAllowAsync(bool allow); | ||
296 | bool allowAsync() const; | ||
297 | |||
298 | bool hasPendingAsyncJobs() const; | ||
299 | |||
300 | /** | ||
301 | * The text of the message, ie. what would appear in the | ||
302 | * composer's text editor if this was edited or replied to. | ||
303 | * This is usually the content of the first text/plain MIME part. | ||
304 | */ | ||
305 | QString plainTextContent() const; | ||
306 | |||
307 | /** | ||
308 | * Similar to plainTextContent(), but returns the HTML source of the first text/html MIME part. | ||
309 | * | ||
310 | * Not to be consfused with the HTML code that the message viewer widget displays, that HTML | ||
311 | * is written out by htmlWriter() and a totally different pair of shoes. | ||
312 | */ | ||
313 | QString htmlContent() const; | ||
314 | |||
315 | /** | ||
316 | * The original charset of MIME part the plain text was extracted from. | ||
317 | * | ||
318 | * If there were more than one text/plain MIME parts in the mail, the this is the charset | ||
319 | * of the last MIME part processed. | ||
320 | */ | ||
321 | QByteArray plainTextContentCharset() const; | ||
322 | QByteArray htmlContentCharset() const; | ||
323 | |||
324 | bool showOnlyOneMimePart() const; | ||
325 | void setShowOnlyOneMimePart(bool show); | ||
326 | |||
327 | const AttachmentStrategy *attachmentStrategy() const; | ||
328 | |||
329 | HtmlWriter *htmlWriter() const; | ||
330 | |||
331 | NodeHelper *nodeHelper() const; | ||
332 | |||
333 | /** Parse beginning at a given node and recursively parsing | ||
334 | the children of that node and it's next sibling. */ | ||
335 | void parseObjectTree(KMime::Content *node); | ||
336 | MessagePartPtr parsedPart() const; | ||
337 | |||
338 | private: | ||
339 | void extractNodeInfos(KMime::Content *curNode, bool isFirstTextPart); | ||
340 | void setPlainTextContent(const QString &plainTextContent); | ||
341 | |||
342 | /** | ||
343 | * Does the actual work for parseObjectTree. Unlike parseObjectTree(), this does not change the | ||
344 | * top-level content. | ||
345 | */ | ||
346 | MessagePartPtr parseObjectTreeInternal(KMime::Content *node, bool mOnlyOneMimePart); | ||
347 | bool processType(KMime::Content *node, MimeTreeParser::ProcessResult &processResult, const QByteArray &mediaType, const QByteArray &subType, Interface::MessagePartPtr &mpRet, bool onlyOneMimePart); | ||
348 | |||
349 | Interface::MessagePartPtr defaultHandling(KMime::Content *node, MimeTreeParser::ProcessResult &result, bool onlyOneMimePart); | ||
350 | |||
351 | private: | ||
352 | |||
353 | /** ctor helper */ | ||
354 | void init(); | ||
355 | |||
356 | const QTextCodec *codecFor(KMime::Content *node) const; | ||
357 | |||
358 | void copyContentFrom(const ObjectTreeParser *other); | ||
359 | |||
360 | private: | ||
361 | Interface::ObjectTreeSource *mSource; | ||
362 | NodeHelper *mNodeHelper; | ||
363 | HtmlWriter *mHtmlWriter; | ||
364 | QByteArray mPlainTextContentCharset; | ||
365 | QByteArray mHtmlContentCharset; | ||
366 | QString mPlainTextContent; | ||
367 | QString mHtmlContent; | ||
368 | KMime::Content *mTopLevelContent; | ||
369 | MessagePartPtr mParsedPart; | ||
370 | |||
371 | /// Show only one mime part means that the user has selected some node in the message structure | ||
372 | /// viewer that is not the root, which means the user wants to only see the selected node and its | ||
373 | /// children. If that is the case, this variable is set to true. | ||
374 | /// The code needs to behave differently if this is set. For example, it should not process the | ||
375 | /// siblings. Also, consider inline images: Normally, those nodes are completely hidden, as the | ||
376 | /// HTML node embedds them. However, when showing only the node of the image, one has to show them, | ||
377 | /// as their is no HTML node in which they are displayed. There are many more cases where this | ||
378 | /// variable needs to be obeyed. | ||
379 | /// This variable is set to false again when processing the children in stdChildHandling(), as | ||
380 | /// the children can be completely displayed again. | ||
381 | bool mShowOnlyOneMimePart; | ||
382 | |||
383 | bool mHasPendingAsyncJobs; | ||
384 | bool mAllowAsync; | ||
385 | const AttachmentStrategy *mAttachmentStrategy; | ||
386 | // DataUrl Icons cache | ||
387 | QString mCollapseIcon; | ||
388 | QString mExpandIcon; | ||
389 | bool mDeleteNodeHelper; | ||
390 | |||
391 | friend class PartNodeBodyPart; | ||
392 | friend class MessagePart; | ||
393 | friend class EncryptedMessagePart; | ||
394 | friend class SignedMessagePart; | ||
395 | friend class EncapsulatedRfc822MessagePart; | ||
396 | friend class TextMessagePart; | ||
397 | friend class HtmlMessagePart; | ||
398 | friend class TextPlainBodyPartFormatter; | ||
399 | friend class MultiPartSignedBodyPartFormatter; | ||
400 | friend class ApplicationPkcs7MimeBodyPartFormatter; | ||
401 | }; | ||
402 | |||
403 | } | ||
404 | |||
405 | #endif // __MIMETREEPARSER_OBJECTTREEPARSER_H__ | ||
406 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/objecttreesource.cpp b/framework/src/domain/mime/mimetreeparser/otp/objecttreesource.cpp new file mode 100644 index 00000000..45f96c58 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/objecttreesource.cpp | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
3 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along | ||
16 | with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #include "objecttreesource.h" | ||
21 | #include "bodypartformatter.h" | ||
22 | #include "messagepart.h" | ||
23 | |||
24 | using namespace MimeTreeParser; | ||
25 | |||
26 | Interface::ObjectTreeSource::~ObjectTreeSource() | ||
27 | { | ||
28 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/objecttreesource.h b/framework/src/domain/mime/mimetreeparser/otp/objecttreesource.h new file mode 100644 index 00000000..afada4c4 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/objecttreesource.h | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
3 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along | ||
16 | with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef __MIMETREEPARSER_OBJECTTREESOURCE_IF_H__ | ||
21 | #define __MIMETREEPARSER_OBJECTTREESOURCE_IF_H__ | ||
22 | |||
23 | #include "util.h" | ||
24 | |||
25 | #include <KMime/Message> | ||
26 | |||
27 | #include <QSharedPointer> | ||
28 | class QTextCodec; | ||
29 | |||
30 | namespace MimeTreeParser | ||
31 | { | ||
32 | class HtmlWriter; | ||
33 | class AttachmentStrategy; | ||
34 | class BodyPartFormatterBaseFactory; | ||
35 | namespace Interface | ||
36 | { | ||
37 | class MessagePart; | ||
38 | typedef QSharedPointer<MessagePart> MessagePartPtr; | ||
39 | class MessagePartRenderer; | ||
40 | typedef QSharedPointer<MessagePartRenderer> MessagePartRendererPtr; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | namespace MimeTreeParser | ||
45 | { | ||
46 | namespace Interface | ||
47 | { | ||
48 | |||
49 | /** | ||
50 | * Interface for object tree sources. | ||
51 | * @author Andras Mantia <amantia@kdab.net> | ||
52 | */ | ||
53 | class ObjectTreeSource | ||
54 | { | ||
55 | |||
56 | public: | ||
57 | virtual ~ObjectTreeSource(); | ||
58 | |||
59 | /** | ||
60 | * Sets the type of mail that is currently displayed. Applications can display this | ||
61 | * information to the user, for example KMail displays a HTML status bar. | ||
62 | * Note: This is not called when the mode is "Normal". | ||
63 | */ | ||
64 | virtual void setHtmlMode(MimeTreeParser::Util::HtmlMode mode, const QList<MimeTreeParser::Util::HtmlMode> &availableModes) = 0; | ||
65 | |||
66 | /** Return the mode that is the preferred to display */ | ||
67 | virtual MimeTreeParser::Util::HtmlMode preferredMode() const = 0; | ||
68 | |||
69 | /** Return true if an encrypted mail should be decrypted */ | ||
70 | virtual bool decryptMessage() const = 0; | ||
71 | |||
72 | /** Return true if external sources should be loaded in a html mail */ | ||
73 | virtual bool htmlLoadExternal() const = 0; | ||
74 | |||
75 | /** Return true to include the signature details in the generated html */ | ||
76 | virtual bool showSignatureDetails() const = 0; | ||
77 | |||
78 | virtual int levelQuote() const = 0; | ||
79 | |||
80 | /** The override codec that should be used for the mail */ | ||
81 | virtual const QTextCodec *overrideCodec() = 0; | ||
82 | |||
83 | virtual QString createMessageHeader(KMime::Message *message) = 0; | ||
84 | |||
85 | /** Return the wanted attachment startegy */ | ||
86 | virtual const AttachmentStrategy *attachmentStrategy() = 0; | ||
87 | |||
88 | /** Return the html write object */ | ||
89 | virtual HtmlWriter *htmlWriter() = 0; | ||
90 | |||
91 | /** The source object behind the interface. */ | ||
92 | virtual QObject *sourceObject() = 0; | ||
93 | |||
94 | /** should keys be imported automatically **/ | ||
95 | virtual bool autoImportKeys() const = 0; | ||
96 | |||
97 | virtual bool showEmoticons() const = 0; | ||
98 | |||
99 | virtual bool showExpandQuotesMark() const = 0; | ||
100 | |||
101 | virtual const BodyPartFormatterBaseFactory *bodyPartFormatterFactory() = 0; | ||
102 | |||
103 | virtual MessagePartRendererPtr messagePartTheme(MessagePartPtr msgPart) = 0; | ||
104 | |||
105 | virtual bool isPrinting() const = 0; | ||
106 | }; | ||
107 | } | ||
108 | } | ||
109 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/partmetadata.h b/framework/src/domain/mime/mimetreeparser/otp/partmetadata.h new file mode 100644 index 00000000..41399837 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/partmetadata.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* -*- c++ -*- | ||
2 | partmetadata.h | ||
3 | |||
4 | KMail, the KDE mail client. | ||
5 | Copyright (c) 2002-2003 Karl-Heinz Zimmer <khz@kde.org> | ||
6 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
7 | |||
8 | This program is free software; you can redistribute it and/or | ||
9 | modify it under the terms of the GNU General Public License, | ||
10 | version 2.0, as published by the Free Software Foundation. | ||
11 | You should have received a copy of the GNU General Public License | ||
12 | along with this program; if not, write to the Free Software Foundation, | ||
13 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US | ||
14 | */ | ||
15 | |||
16 | #ifndef __MIMETREEPARSER_PARTMETADATA_H__ | ||
17 | #define __MIMETREEPARSER_PARTMETADATA_H__ | ||
18 | |||
19 | #include <gpgme++/verificationresult.h> | ||
20 | #include <gpgme++/context.h> | ||
21 | |||
22 | #include <QStringList> | ||
23 | #include <QDateTime> | ||
24 | |||
25 | namespace MimeTreeParser | ||
26 | { | ||
27 | |||
28 | class PartMetaData | ||
29 | { | ||
30 | public: | ||
31 | PartMetaData() | ||
32 | : sigSummary(GpgME::Signature::None), | ||
33 | isSigned(false), | ||
34 | isGoodSignature(false), | ||
35 | isEncrypted(false), | ||
36 | isDecryptable(false), | ||
37 | inProgress(false), | ||
38 | technicalProblem(false), | ||
39 | isEncapsulatedRfc822Message(false) | ||
40 | { | ||
41 | } | ||
42 | GpgME::Signature::Summary sigSummary; | ||
43 | QString signClass; | ||
44 | QString signer; | ||
45 | QStringList signerMailAddresses; | ||
46 | QByteArray keyId; | ||
47 | GpgME::Signature::Validity keyTrust; | ||
48 | QString status; // to be used for unknown plug-ins | ||
49 | int status_code; // to be used for i18n of OpenPGP and S/MIME CryptPlugs | ||
50 | QString errorText; | ||
51 | QDateTime creationTime; | ||
52 | QString decryptionError; | ||
53 | QString auditLog; | ||
54 | GpgME::Error auditLogError; | ||
55 | bool isSigned : 1; | ||
56 | bool isGoodSignature : 1; | ||
57 | bool isEncrypted : 1; | ||
58 | bool isDecryptable : 1; | ||
59 | bool inProgress : 1; | ||
60 | bool technicalProblem : 1; | ||
61 | bool isEncapsulatedRfc822Message : 1; | ||
62 | }; | ||
63 | |||
64 | } | ||
65 | |||
66 | #endif // __MIMETREEPARSER_PARTMETADATA_H__ | ||
67 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/partnodebodypart.cpp b/framework/src/domain/mime/mimetreeparser/otp/partnodebodypart.cpp new file mode 100644 index 00000000..ec509787 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/partnodebodypart.cpp | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | partnodebodypart.cpp | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2004 Marc Mutz <mutz@kde.org>, | ||
6 | Ingo Kloecker <kloecker@kde.org> | ||
7 | |||
8 | KMail is free software; you can redistribute it and/or modify it | ||
9 | under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #include "partnodebodypart.h" | ||
35 | #include "nodehelper.h" | ||
36 | #include "objecttreeparser.h" | ||
37 | #include "mimetreeparser_debug.h" | ||
38 | #include <KMime/Content> | ||
39 | |||
40 | #include <QTextCodec> | ||
41 | #include <QUrl> | ||
42 | |||
43 | using namespace MimeTreeParser; | ||
44 | |||
45 | static int serial = 0; | ||
46 | |||
47 | PartNodeBodyPart::PartNodeBodyPart(ObjectTreeParser *otp, ProcessResult *result, KMime::Content *topLevelContent, KMime::Content *content, | ||
48 | NodeHelper *nodeHelper) | ||
49 | : Interface::BodyPart(), mTopLevelContent(topLevelContent), mContent(content), | ||
50 | mDefaultDisplay(Interface::BodyPart::None), mNodeHelper(nodeHelper) | ||
51 | , mObjectTreeParser(otp) | ||
52 | , mProcessResult(result) | ||
53 | {} | ||
54 | |||
55 | QString PartNodeBodyPart::makeLink(const QString &path) const | ||
56 | { | ||
57 | // FIXME: use a PRNG for the first arg, instead of a serial number | ||
58 | return QStringLiteral("x-kmail:/bodypart/%1/%2/%3") | ||
59 | .arg(serial++).arg(mContent->index().toString()) | ||
60 | .arg(QString::fromLatin1(QUrl::toPercentEncoding(path, "/"))); | ||
61 | } | ||
62 | |||
63 | QString PartNodeBodyPart::asText() const | ||
64 | { | ||
65 | if (!mContent->contentType()->isText()) { | ||
66 | return QString(); | ||
67 | } | ||
68 | return mContent->decodedText(); | ||
69 | } | ||
70 | |||
71 | QByteArray PartNodeBodyPart::asBinary() const | ||
72 | { | ||
73 | return mContent->decodedContent(); | ||
74 | } | ||
75 | |||
76 | QString PartNodeBodyPart::contentTypeParameter(const char *param) const | ||
77 | { | ||
78 | return mContent->contentType()->parameter(QString::fromLatin1(param)); | ||
79 | } | ||
80 | |||
81 | QString PartNodeBodyPart::contentDescription() const | ||
82 | { | ||
83 | return mContent->contentDescription()->asUnicodeString(); | ||
84 | } | ||
85 | |||
86 | QString PartNodeBodyPart::contentDispositionParameter(const char *param) const | ||
87 | { | ||
88 | return mContent->contentDisposition()->parameter(QString::fromLatin1(param)); | ||
89 | } | ||
90 | |||
91 | bool PartNodeBodyPart::hasCompleteBody() const | ||
92 | { | ||
93 | qCWarning(MIMETREEPARSER_LOG) << "Sorry, not yet implemented."; | ||
94 | return true; | ||
95 | } | ||
96 | |||
97 | Interface::BodyPartMemento *PartNodeBodyPart::memento() const | ||
98 | { | ||
99 | /*TODO(Andras) Volker suggests to use a ContentIndex->Mememnto mapping | ||
100 | Also review if the reader's bodyPartMemento should be returned or the NodeHelper's one | ||
101 | */ | ||
102 | return mNodeHelper->bodyPartMemento(mContent, "__plugin__"); | ||
103 | } | ||
104 | |||
105 | void PartNodeBodyPart::setBodyPartMemento(Interface::BodyPartMemento *memento) | ||
106 | { | ||
107 | /*TODO(Andras) Volker suggests to use a ContentIndex->Memento mapping | ||
108 | Also review if the reader's bodyPartMemento should be set or the NodeHelper's one */ | ||
109 | mNodeHelper->setBodyPartMemento(mContent, "__plugin__", memento); | ||
110 | } | ||
111 | |||
112 | Interface::BodyPart::Display PartNodeBodyPart::defaultDisplay() const | ||
113 | { | ||
114 | return mDefaultDisplay; | ||
115 | } | ||
116 | |||
117 | void PartNodeBodyPart::setDefaultDisplay(Interface::BodyPart::Display d) | ||
118 | { | ||
119 | mDefaultDisplay = d; | ||
120 | } | ||
121 | |||
122 | Interface::ObjectTreeSource *PartNodeBodyPart::source() const | ||
123 | { | ||
124 | return mObjectTreeParser->mSource; | ||
125 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/partnodebodypart.h b/framework/src/domain/mime/mimetreeparser/otp/partnodebodypart.h new file mode 100644 index 00000000..ded0ee2c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/partnodebodypart.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | partnodebodypart.h | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2004 Marc Mutz <mutz@kde.org>, | ||
6 | Ingo Kloecker <kloecker@kde.org> | ||
7 | |||
8 | KMail is free software; you can redistribute it and/or modify it | ||
9 | under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | KMail is distributed in the hope that it will be useful, but | ||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | |||
22 | In addition, as a special exception, the copyright holders give | ||
23 | permission to link the code of this program with any edition of | ||
24 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
25 | of Qt that use the same license as Qt), and distribute linked | ||
26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | ||
32 | */ | ||
33 | |||
34 | #ifndef __MIMETREEPARSER_PARTNODEBODYPART_H__ | ||
35 | #define __MIMETREEPARSER_PARTNODEBODYPART_H__ | ||
36 | |||
37 | #include "bodypart.h" | ||
38 | |||
39 | namespace KMime | ||
40 | { | ||
41 | class Content; | ||
42 | } | ||
43 | |||
44 | namespace MimeTreeParser | ||
45 | { | ||
46 | class NodeHelper; | ||
47 | } | ||
48 | |||
49 | namespace MimeTreeParser | ||
50 | { | ||
51 | |||
52 | /** | ||
53 | @short an implementation of the BodyPart interface using KMime::Content's | ||
54 | */ | ||
55 | class PartNodeBodyPart : public Interface::BodyPart | ||
56 | { | ||
57 | public: | ||
58 | explicit PartNodeBodyPart(ObjectTreeParser *otp, ProcessResult *result, KMime::Content *topLevelContent, KMime::Content *content, | ||
59 | NodeHelper *nodeHelper); | ||
60 | |||
61 | QString makeLink(const QString &path) const Q_DECL_OVERRIDE; | ||
62 | QString asText() const Q_DECL_OVERRIDE; | ||
63 | QByteArray asBinary() const Q_DECL_OVERRIDE; | ||
64 | QString contentTypeParameter(const char *param) const Q_DECL_OVERRIDE; | ||
65 | QString contentDescription() const Q_DECL_OVERRIDE; | ||
66 | QString contentDispositionParameter(const char *param) const Q_DECL_OVERRIDE; | ||
67 | bool hasCompleteBody() const Q_DECL_OVERRIDE; | ||
68 | |||
69 | Interface::BodyPartMemento *memento() const Q_DECL_OVERRIDE; | ||
70 | void setBodyPartMemento(Interface::BodyPartMemento *memento) Q_DECL_OVERRIDE; | ||
71 | BodyPart::Display defaultDisplay() const Q_DECL_OVERRIDE; | ||
72 | void setDefaultDisplay(BodyPart::Display); | ||
73 | KMime::Content *content() const Q_DECL_OVERRIDE | ||
74 | { | ||
75 | return mContent; | ||
76 | } | ||
77 | KMime::Content *topLevelContent() const Q_DECL_OVERRIDE | ||
78 | { | ||
79 | return mTopLevelContent; | ||
80 | } | ||
81 | NodeHelper *nodeHelper() const Q_DECL_OVERRIDE | ||
82 | { | ||
83 | return mNodeHelper; | ||
84 | } | ||
85 | |||
86 | ObjectTreeParser *objectTreeParser() const Q_DECL_OVERRIDE | ||
87 | { | ||
88 | return mObjectTreeParser; | ||
89 | } | ||
90 | |||
91 | ProcessResult *processResult() const Q_DECL_OVERRIDE | ||
92 | { | ||
93 | return mProcessResult; | ||
94 | } | ||
95 | |||
96 | Interface::ObjectTreeSource *source() const Q_DECL_OVERRIDE; | ||
97 | private: | ||
98 | KMime::Content *mTopLevelContent; | ||
99 | KMime::Content *mContent; | ||
100 | BodyPart::Display mDefaultDisplay; | ||
101 | NodeHelper *mNodeHelper; | ||
102 | ObjectTreeParser *mObjectTreeParser; | ||
103 | ProcessResult *mProcessResult; | ||
104 | }; | ||
105 | |||
106 | } | ||
107 | |||
108 | #endif // __MIMETREEPARSER_PARTNODEBODYPART_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/qgpgmejobexecutor.cpp b/framework/src/domain/mime/mimetreeparser/otp/qgpgmejobexecutor.cpp new file mode 100644 index 00000000..1f453342 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/qgpgmejobexecutor.cpp | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | Copyright (c) 2008 Volker Krause <vkrause@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
17 | */ | ||
18 | |||
19 | #include "qgpgmejobexecutor.h" | ||
20 | #include "mimetreeparser_debug.h" | ||
21 | |||
22 | #include <QGpgME/DecryptVerifyJob> | ||
23 | #include <QGpgME/ImportJob> | ||
24 | #include <QGpgME/VerifyDetachedJob> | ||
25 | #include <QGpgME/VerifyOpaqueJob> | ||
26 | |||
27 | #include <QEventLoop> | ||
28 | |||
29 | #include <cassert> | ||
30 | |||
31 | using namespace GpgME; | ||
32 | using namespace MimeTreeParser; | ||
33 | |||
34 | QGpgMEJobExecutor::QGpgMEJobExecutor(QObject *parent) : QObject(parent) | ||
35 | { | ||
36 | setObjectName(QStringLiteral("KleoJobExecutor")); | ||
37 | mEventLoop = new QEventLoop(this); | ||
38 | } | ||
39 | |||
40 | GpgME::VerificationResult QGpgMEJobExecutor::exec( | ||
41 | QGpgME::VerifyDetachedJob *job, | ||
42 | const QByteArray &signature, | ||
43 | const QByteArray &signedData) | ||
44 | { | ||
45 | qCDebug(MIMETREEPARSER_LOG) << "Starting detached verification job"; | ||
46 | connect(job, SIGNAL(result(GpgME::VerificationResult)), SLOT(verificationResult(GpgME::VerificationResult))); | ||
47 | GpgME::Error err = job->start(signature, signedData); | ||
48 | if (err) { | ||
49 | return VerificationResult(err); | ||
50 | } | ||
51 | mEventLoop->exec(QEventLoop::ExcludeUserInputEvents); | ||
52 | return mVerificationResult; | ||
53 | } | ||
54 | |||
55 | GpgME::VerificationResult QGpgMEJobExecutor::exec( | ||
56 | QGpgME::VerifyOpaqueJob *job, | ||
57 | const QByteArray &signedData, | ||
58 | QByteArray &plainText) | ||
59 | { | ||
60 | qCDebug(MIMETREEPARSER_LOG) << "Starting opaque verification job"; | ||
61 | connect(job, SIGNAL(result(GpgME::VerificationResult,QByteArray)), SLOT(verificationResult(GpgME::VerificationResult,QByteArray))); | ||
62 | GpgME::Error err = job->start(signedData); | ||
63 | if (err) { | ||
64 | plainText.clear(); | ||
65 | return VerificationResult(err); | ||
66 | } | ||
67 | mEventLoop->exec(QEventLoop::ExcludeUserInputEvents); | ||
68 | plainText = mData; | ||
69 | return mVerificationResult; | ||
70 | } | ||
71 | |||
72 | std::pair< GpgME::DecryptionResult, GpgME::VerificationResult > QGpgMEJobExecutor::exec( | ||
73 | QGpgME::DecryptVerifyJob *job, | ||
74 | const QByteArray &cipherText, | ||
75 | QByteArray &plainText) | ||
76 | { | ||
77 | qCDebug(MIMETREEPARSER_LOG) << "Starting decryption job"; | ||
78 | connect(job, &QGpgME::DecryptVerifyJob::result, this, &QGpgMEJobExecutor::decryptResult); | ||
79 | GpgME::Error err = job->start(cipherText); | ||
80 | if (err) { | ||
81 | plainText.clear(); | ||
82 | return std::make_pair(DecryptionResult(err), VerificationResult(err)); | ||
83 | } | ||
84 | mEventLoop->exec(QEventLoop::ExcludeUserInputEvents); | ||
85 | plainText = mData; | ||
86 | return std::make_pair(mDecryptResult, mVerificationResult); | ||
87 | } | ||
88 | |||
89 | GpgME::ImportResult QGpgMEJobExecutor::exec(QGpgME::ImportJob *job, const QByteArray &certData) | ||
90 | { | ||
91 | connect(job, SIGNAL(result(GpgME::ImportResult)), SLOT(importResult(GpgME::ImportResult))); | ||
92 | GpgME::Error err = job->start(certData); | ||
93 | if (err) { | ||
94 | return ImportResult(err); | ||
95 | } | ||
96 | mEventLoop->exec(QEventLoop::ExcludeUserInputEvents); | ||
97 | return mImportResult; | ||
98 | } | ||
99 | |||
100 | Error QGpgMEJobExecutor::auditLogError() const | ||
101 | { | ||
102 | return mAuditLogError; | ||
103 | } | ||
104 | |||
105 | void QGpgMEJobExecutor::verificationResult(const GpgME::VerificationResult &result) | ||
106 | { | ||
107 | qCDebug(MIMETREEPARSER_LOG) << "Detached verification job finished"; | ||
108 | QGpgME::Job *job = qobject_cast<QGpgME::Job *>(sender()); | ||
109 | assert(job); | ||
110 | mVerificationResult = result; | ||
111 | mAuditLogError = job->auditLogError(); | ||
112 | mAuditLog = job->auditLogAsHtml(); | ||
113 | mEventLoop->quit(); | ||
114 | } | ||
115 | |||
116 | void QGpgMEJobExecutor::verificationResult(const GpgME::VerificationResult &result, const QByteArray &plainText) | ||
117 | { | ||
118 | qCDebug(MIMETREEPARSER_LOG) << "Opaque verification job finished"; | ||
119 | QGpgME::Job *job = qobject_cast<QGpgME::Job *>(sender()); | ||
120 | assert(job); | ||
121 | mVerificationResult = result; | ||
122 | mData = plainText; | ||
123 | mAuditLogError = job->auditLogError(); | ||
124 | mAuditLog = job->auditLogAsHtml(); | ||
125 | mEventLoop->quit(); | ||
126 | } | ||
127 | |||
128 | void QGpgMEJobExecutor::decryptResult( | ||
129 | const GpgME::DecryptionResult &decryptionresult, | ||
130 | const GpgME::VerificationResult &verificationresult, | ||
131 | const QByteArray &plainText) | ||
132 | { | ||
133 | qCDebug(MIMETREEPARSER_LOG) << "Decryption job finished"; | ||
134 | QGpgME::Job *job = qobject_cast<QGpgME::Job *>(sender()); | ||
135 | assert(job); | ||
136 | mVerificationResult = verificationresult; | ||
137 | mDecryptResult = decryptionresult; | ||
138 | mData = plainText; | ||
139 | mAuditLogError = job->auditLogError(); | ||
140 | mAuditLog = job->auditLogAsHtml(); | ||
141 | mEventLoop->quit(); | ||
142 | } | ||
143 | |||
144 | void QGpgMEJobExecutor::importResult(const GpgME::ImportResult &result) | ||
145 | { | ||
146 | QGpgME::Job *job = qobject_cast<QGpgME::Job *>(sender()); | ||
147 | assert(job); | ||
148 | mImportResult = result; | ||
149 | mAuditLogError = job->auditLogError(); | ||
150 | mAuditLog = job->auditLogAsHtml(); | ||
151 | mEventLoop->quit(); | ||
152 | } | ||
153 | |||
154 | QString QGpgMEJobExecutor::auditLogAsHtml() const | ||
155 | { | ||
156 | return mAuditLog; | ||
157 | } | ||
158 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/qgpgmejobexecutor.h b/framework/src/domain/mime/mimetreeparser/otp/qgpgmejobexecutor.h new file mode 100644 index 00000000..8a81b078 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/qgpgmejobexecutor.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | Copyright (c) 2008 Volker Krause <vkrause@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef __MIMETREEPARSER_KLEOJOBEXECUTOR_H__ | ||
20 | #define __MIMETREEPARSER_KLEOJOBEXECUTOR_H__ | ||
21 | |||
22 | #include <gpgme++/decryptionresult.h> | ||
23 | #include <gpgme++/importresult.h> | ||
24 | #include <gpgme++/verificationresult.h> | ||
25 | |||
26 | #include <QObject> | ||
27 | |||
28 | #include <utility> | ||
29 | |||
30 | class QEventLoop; | ||
31 | |||
32 | namespace QGpgME | ||
33 | { | ||
34 | class DecryptVerifyJob; | ||
35 | class ImportJob; | ||
36 | class VerifyDetachedJob; | ||
37 | class VerifyOpaqueJob; | ||
38 | } | ||
39 | |||
40 | namespace MimeTreeParser | ||
41 | { | ||
42 | |||
43 | /** | ||
44 | Helper class for synchronous execution of Kleo crypto jobs. | ||
45 | */ | ||
46 | class QGpgMEJobExecutor : public QObject | ||
47 | { | ||
48 | Q_OBJECT | ||
49 | public: | ||
50 | explicit QGpgMEJobExecutor(QObject *parent = nullptr); | ||
51 | |||
52 | GpgME::VerificationResult exec(QGpgME::VerifyDetachedJob *job, | ||
53 | const QByteArray &signature, | ||
54 | const QByteArray &signedData); | ||
55 | GpgME::VerificationResult exec(QGpgME::VerifyOpaqueJob *job, | ||
56 | const QByteArray &signedData, | ||
57 | QByteArray &plainText); | ||
58 | std::pair<GpgME::DecryptionResult, GpgME::VerificationResult> exec(QGpgME::DecryptVerifyJob *job, | ||
59 | const QByteArray &cipherText, | ||
60 | QByteArray &plainText); | ||
61 | GpgME::ImportResult exec(QGpgME::ImportJob *job, const QByteArray &certData); | ||
62 | |||
63 | GpgME::Error auditLogError() const; | ||
64 | QString auditLogAsHtml() const; | ||
65 | |||
66 | private Q_SLOTS: | ||
67 | void verificationResult(const GpgME::VerificationResult &result); | ||
68 | void verificationResult(const GpgME::VerificationResult &result, const QByteArray &plainText); | ||
69 | void decryptResult(const GpgME::DecryptionResult &decryptionresult, | ||
70 | const GpgME::VerificationResult &verificationresult, | ||
71 | const QByteArray &plainText); | ||
72 | void importResult(const GpgME::ImportResult &result); | ||
73 | |||
74 | private: | ||
75 | QEventLoop *mEventLoop; | ||
76 | GpgME::VerificationResult mVerificationResult; | ||
77 | GpgME::DecryptionResult mDecryptResult; | ||
78 | GpgME::ImportResult mImportResult; | ||
79 | QByteArray mData; | ||
80 | GpgME::Error mAuditLogError; | ||
81 | QString mAuditLog; | ||
82 | }; | ||
83 | |||
84 | } | ||
85 | |||
86 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/queuehtmlwriter.cpp b/framework/src/domain/mime/mimetreeparser/otp/queuehtmlwriter.cpp new file mode 100644 index 00000000..ea17bf5c --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/queuehtmlwriter.cpp | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | Copyright (c) 2015 Sandro Knauß <sknauss@kde.org> | ||
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 "queuehtmlwriter.h" | ||
21 | |||
22 | #include "mimetreeparser_debug.h" | ||
23 | |||
24 | #include<QByteArray> | ||
25 | #include<QString> | ||
26 | |||
27 | using namespace MimeTreeParser; | ||
28 | |||
29 | QueueHtmlWriter::QueueHtmlWriter(HtmlWriter *base) | ||
30 | : HtmlWriter() | ||
31 | , mBase(base) | ||
32 | { | ||
33 | } | ||
34 | |||
35 | QueueHtmlWriter::~QueueHtmlWriter() | ||
36 | { | ||
37 | } | ||
38 | |||
39 | void QueueHtmlWriter::setBase(HtmlWriter *base) | ||
40 | { | ||
41 | mBase = base; | ||
42 | } | ||
43 | |||
44 | void QueueHtmlWriter::begin(const QString &css) | ||
45 | { | ||
46 | Command cmd; | ||
47 | cmd.type = Command::Begin; | ||
48 | cmd.s = css; | ||
49 | mQueue.append(cmd); | ||
50 | } | ||
51 | |||
52 | void QueueHtmlWriter::end() | ||
53 | { | ||
54 | Command cmd; | ||
55 | cmd.type = Command::End; | ||
56 | mQueue.append(cmd); | ||
57 | } | ||
58 | |||
59 | void QueueHtmlWriter::reset() | ||
60 | { | ||
61 | Command cmd; | ||
62 | cmd.type = Command::Reset; | ||
63 | mQueue.append(cmd); | ||
64 | } | ||
65 | |||
66 | void QueueHtmlWriter::write(const QString &str) | ||
67 | { | ||
68 | Command cmd; | ||
69 | cmd.type = Command::Write; | ||
70 | cmd.s = str; | ||
71 | mQueue.append(cmd); | ||
72 | } | ||
73 | |||
74 | void QueueHtmlWriter::queue(const QString &str) | ||
75 | { | ||
76 | Command cmd; | ||
77 | cmd.type = Command::Queue; | ||
78 | cmd.s = str; | ||
79 | mQueue.append(cmd); | ||
80 | } | ||
81 | |||
82 | void QueueHtmlWriter::flush() | ||
83 | { | ||
84 | Command cmd; | ||
85 | cmd.type = Command::Flush; | ||
86 | mQueue.append(cmd); | ||
87 | } | ||
88 | |||
89 | void QueueHtmlWriter::replay() | ||
90 | { | ||
91 | foreach (const auto &entry, mQueue) { | ||
92 | switch (entry.type) { | ||
93 | case Command::Begin: | ||
94 | mBase->begin(entry.s); | ||
95 | break; | ||
96 | case Command::End: | ||
97 | mBase->end(); | ||
98 | break; | ||
99 | case Command::Reset: | ||
100 | mBase->reset(); | ||
101 | break; | ||
102 | case Command::Write: | ||
103 | mBase->write(entry.s); | ||
104 | break; | ||
105 | case Command::Queue: | ||
106 | mBase->queue(entry.s); | ||
107 | break; | ||
108 | case Command::Flush: | ||
109 | mBase->flush(); | ||
110 | break; | ||
111 | case Command::EmbedPart: | ||
112 | mBase->embedPart(entry.b, entry.s); | ||
113 | break; | ||
114 | case Command::ExtraHead: | ||
115 | mBase->extraHead(entry.s); | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | |||
121 | void QueueHtmlWriter::embedPart(const QByteArray &contentId, const QString &url) | ||
122 | { | ||
123 | Command cmd; | ||
124 | cmd.type = Command::EmbedPart; | ||
125 | cmd.s = url; | ||
126 | cmd.b = contentId; | ||
127 | mQueue.append(cmd); | ||
128 | } | ||
129 | void QueueHtmlWriter::extraHead(const QString &extra) | ||
130 | { | ||
131 | Command cmd; | ||
132 | cmd.type = Command::ExtraHead; | ||
133 | cmd.s = extra; | ||
134 | mQueue.append(cmd); | ||
135 | } | ||
136 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/queuehtmlwriter.h b/framework/src/domain/mime/mimetreeparser/otp/queuehtmlwriter.h new file mode 100644 index 00000000..9e7a4659 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/queuehtmlwriter.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | Copyright (c) 2015 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_QUEUEHTMLWRITER_H__ | ||
21 | #define __MIMETREEPARSER_QUEUEHTMLWRITER_H__ | ||
22 | |||
23 | #include "htmlwriter.h" | ||
24 | |||
25 | #include<QVector> | ||
26 | #include<QVariant> | ||
27 | |||
28 | class QString; | ||
29 | class QByteArray; | ||
30 | |||
31 | namespace MimeTreeParser | ||
32 | { | ||
33 | /** | ||
34 | \brief Cache HTML output and not write them directy. | ||
35 | |||
36 | This class is needed to make it possible to first process the mime tree and | ||
37 | afterwards render the HTML. | ||
38 | |||
39 | Please do not use this class - it is only added to make it possible to slowly | ||
40 | move ObjectTreeParser to a process fist / render later. | ||
41 | |||
42 | */ | ||
43 | struct Command { | ||
44 | enum { Begin, End, Reset, Write, Queue, Flush, EmbedPart, ExtraHead } type; | ||
45 | QString s; | ||
46 | QByteArray b; | ||
47 | }; | ||
48 | |||
49 | class QueueHtmlWriter : public HtmlWriter | ||
50 | { | ||
51 | public: | ||
52 | explicit QueueHtmlWriter(MimeTreeParser::HtmlWriter *base); | ||
53 | virtual ~QueueHtmlWriter(); | ||
54 | |||
55 | void setBase(HtmlWriter *base); | ||
56 | |||
57 | void begin(const QString &cssDefs) Q_DECL_OVERRIDE; | ||
58 | void end() Q_DECL_OVERRIDE; | ||
59 | void reset() Q_DECL_OVERRIDE; | ||
60 | void write(const QString &str) Q_DECL_OVERRIDE; | ||
61 | void queue(const QString &str) Q_DECL_OVERRIDE; | ||
62 | void flush() Q_DECL_OVERRIDE; | ||
63 | void embedPart(const QByteArray &contentId, const QString &url) Q_DECL_OVERRIDE; | ||
64 | void extraHead(const QString &str) Q_DECL_OVERRIDE; | ||
65 | |||
66 | void replay(); | ||
67 | |||
68 | private: | ||
69 | HtmlWriter *mBase; | ||
70 | QVector<Command> mQueue; | ||
71 | }; | ||
72 | |||
73 | } // namespace MimeTreeParser | ||
74 | |||
75 | #endif // __MIMETREEPARSER_QUEUEHTMLWRITER_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/texthtml.cpp b/framework/src/domain/mime/mimetreeparser/otp/texthtml.cpp new file mode 100644 index 00000000..51332cff --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/texthtml.cpp | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "texthtml.h" | ||
21 | |||
22 | #include "attachmentstrategy.h" | ||
23 | #include "objecttreeparser.h" | ||
24 | #include "messagepart.h" | ||
25 | |||
26 | #include <KMime/Content> | ||
27 | |||
28 | #include "mimetreeparser_debug.h" | ||
29 | |||
30 | using namespace MimeTreeParser; | ||
31 | |||
32 | const TextHtmlBodyPartFormatter *TextHtmlBodyPartFormatter::self; | ||
33 | |||
34 | const Interface::BodyPartFormatter *TextHtmlBodyPartFormatter::create() | ||
35 | { | ||
36 | if (!self) { | ||
37 | self = new TextHtmlBodyPartFormatter(); | ||
38 | } | ||
39 | return self; | ||
40 | } | ||
41 | Interface::BodyPartFormatter::Result TextHtmlBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
42 | { | ||
43 | Q_UNUSED(writer) | ||
44 | const auto p = process(*part); | ||
45 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
46 | if (mp) { | ||
47 | mp->html(false); | ||
48 | return Ok; | ||
49 | } | ||
50 | return Failed; | ||
51 | } | ||
52 | |||
53 | Interface::MessagePart::Ptr TextHtmlBodyPartFormatter::process(Interface::BodyPart &part) const | ||
54 | { | ||
55 | KMime::Content *node = part.content(); | ||
56 | HtmlMessagePart::Ptr mp(new HtmlMessagePart(part.objectTreeParser(), node, part.source())); | ||
57 | return mp; | ||
58 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/texthtml.h b/framework/src/domain/mime/mimetreeparser/otp/texthtml.h new file mode 100644 index 00000000..a03cfe50 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/texthtml.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_TEXTHTML_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_TEXTHTML_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "bodypart.h" | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class TextHtmlBodyPartFormatter : public Interface::BodyPartFormatter | ||
30 | { | ||
31 | static const TextHtmlBodyPartFormatter *self; | ||
32 | public: | ||
33 | Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; | ||
34 | Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
35 | using Interface::BodyPartFormatter::format; | ||
36 | static const Interface::BodyPartFormatter *create(); | ||
37 | }; | ||
38 | |||
39 | } | ||
40 | |||
41 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/textplain.cpp b/framework/src/domain/mime/mimetreeparser/otp/textplain.cpp new file mode 100644 index 00000000..d3437f04 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/textplain.cpp | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "textplain.h" | ||
21 | |||
22 | #include "attachmentstrategy.h" | ||
23 | #include "objecttreeparser.h" | ||
24 | #include "messagepart.h" | ||
25 | |||
26 | #include <KMime/Content> | ||
27 | |||
28 | #include "mimetreeparser_debug.h" | ||
29 | |||
30 | using namespace MimeTreeParser; | ||
31 | |||
32 | const TextPlainBodyPartFormatter *TextPlainBodyPartFormatter::self; | ||
33 | |||
34 | const Interface::BodyPartFormatter *TextPlainBodyPartFormatter::create() | ||
35 | { | ||
36 | if (!self) { | ||
37 | self = new TextPlainBodyPartFormatter(); | ||
38 | } | ||
39 | return self; | ||
40 | } | ||
41 | Interface::BodyPartFormatter::Result TextPlainBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const | ||
42 | { | ||
43 | Q_UNUSED(writer) | ||
44 | const auto p = process(*part); | ||
45 | const auto mp = static_cast<MessagePart *>(p.data()); | ||
46 | if (mp) { | ||
47 | mp->html(false); | ||
48 | return Ok; | ||
49 | } | ||
50 | return Failed; | ||
51 | } | ||
52 | |||
53 | Interface::MessagePart::Ptr TextPlainBodyPartFormatter::process(Interface::BodyPart &part) const | ||
54 | { | ||
55 | KMime::Content *node = part.content(); | ||
56 | const bool isFirstTextPart = (node->topLevel()->textContent() == node); | ||
57 | |||
58 | QString label = NodeHelper::fileName(node); | ||
59 | |||
60 | const bool bDrawFrame = !isFirstTextPart | ||
61 | && !part.objectTreeParser()->showOnlyOneMimePart() | ||
62 | && !label.isEmpty(); | ||
63 | const QString fileName = part.nodeHelper()->writeNodeToTempFile(node); | ||
64 | |||
65 | TextMessagePart::Ptr mp; | ||
66 | if (isFirstTextPart) { | ||
67 | mp = TextMessagePart::Ptr(new TextMessagePart(part.objectTreeParser(), node, bDrawFrame, fileName.isEmpty(), part.source()->decryptMessage())); | ||
68 | } else { | ||
69 | mp = TextMessagePart::Ptr(new AttachmentMessagePart(part.objectTreeParser(), node, bDrawFrame, fileName.isEmpty(), part.source()->decryptMessage())); | ||
70 | } | ||
71 | |||
72 | part.processResult()->setInlineSignatureState(mp->signatureState()); | ||
73 | part.processResult()->setInlineEncryptionState(mp->encryptionState()); | ||
74 | |||
75 | part.nodeHelper()->setNodeDisplayedEmbedded(node, true); | ||
76 | |||
77 | return mp; | ||
78 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/textplain.h b/framework/src/domain/mime/mimetreeparser/otp/textplain.h new file mode 100644 index 00000000..c97a6aec --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/textplain.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_TEXTPLAIN_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_TEXTPLAIN_H__ | ||
22 | |||
23 | #include "bodypartformatter.h" | ||
24 | #include "bodypart.h" | ||
25 | |||
26 | namespace MimeTreeParser | ||
27 | { | ||
28 | |||
29 | class TextPlainBodyPartFormatter : public Interface::BodyPartFormatter | ||
30 | { | ||
31 | static const TextPlainBodyPartFormatter *self; | ||
32 | public: | ||
33 | Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; | ||
34 | Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; | ||
35 | using Interface::BodyPartFormatter::format; | ||
36 | static const Interface::BodyPartFormatter *create(); | ||
37 | }; | ||
38 | |||
39 | } | ||
40 | |||
41 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/util.cpp b/framework/src/domain/mime/mimetreeparser/otp/util.cpp new file mode 100644 index 00000000..5ca8d828 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/util.cpp | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along | ||
15 | with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
17 | */ | ||
18 | |||
19 | #include "util.h" | ||
20 | |||
21 | #include "mimetreeparser_debug.h" | ||
22 | |||
23 | #include "nodehelper.h" | ||
24 | |||
25 | #include <KMime/Content> | ||
26 | |||
27 | #include <QMimeDatabase> | ||
28 | #include <QString> | ||
29 | |||
30 | using namespace MimeTreeParser::Util; | ||
31 | |||
32 | bool MimeTreeParser::Util::isTypeBlacklisted(KMime::Content *node) | ||
33 | { | ||
34 | const QByteArray mediaTypeLower = node->contentType()->mediaType().toLower(); | ||
35 | bool typeBlacklisted = mediaTypeLower == "multipart"; | ||
36 | if (!typeBlacklisted) { | ||
37 | typeBlacklisted = KMime::isCryptoPart(node); | ||
38 | } | ||
39 | typeBlacklisted = typeBlacklisted || node == node->topLevel(); | ||
40 | const bool firstTextChildOfEncapsulatedMsg = | ||
41 | mediaTypeLower == "text" && | ||
42 | node->contentType()->subType().toLower() == "plain" && | ||
43 | node->parent() && node->parent()->contentType()->mediaType().toLower() == "message"; | ||
44 | return typeBlacklisted || firstTextChildOfEncapsulatedMsg; | ||
45 | } | ||
46 | |||
47 | QString MimeTreeParser::Util::labelForContent(KMime::Content *node) | ||
48 | { | ||
49 | const QString name = node->contentType()->name(); | ||
50 | QString label = name.isEmpty() ? NodeHelper::fileName(node) : name; | ||
51 | if (label.isEmpty()) { | ||
52 | label = node->contentDescription()->asUnicodeString(); | ||
53 | } | ||
54 | return label; | ||
55 | } | ||
56 | |||
57 | QMimeType MimeTreeParser::Util::mimetype(const QString &name) | ||
58 | { | ||
59 | QMimeDatabase db; | ||
60 | // consider the filename if mimetype cannot be found by content-type | ||
61 | const auto mimeTypes = db.mimeTypesForFileName(name); | ||
62 | for (const auto &mt : mimeTypes) { | ||
63 | if (mt.name() != QLatin1String("application/octet-stream")) { | ||
64 | return mt; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | // consider the attachment's contents if neither the Content-Type header | ||
69 | // nor the filename give us a clue | ||
70 | return db.mimeTypeForFile(name); | ||
71 | } | ||
72 | |||
73 | QString MimeTreeParser::Util::iconNameForMimetype(const QString &mimeType, | ||
74 | const QString &fallbackFileName1, | ||
75 | const QString &fallbackFileName2) | ||
76 | { | ||
77 | QString fileName; | ||
78 | QString tMimeType = mimeType; | ||
79 | |||
80 | // convert non-registered types to registered types | ||
81 | if (mimeType == QLatin1String("application/x-vnd.kolab.contact")) { | ||
82 | tMimeType = QStringLiteral("text/x-vcard"); | ||
83 | } else if (mimeType == QLatin1String("application/x-vnd.kolab.event")) { | ||
84 | tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.event"); | ||
85 | } else if (mimeType == QLatin1String("application/x-vnd.kolab.task")) { | ||
86 | tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.todo"); | ||
87 | } else if (mimeType == QLatin1String("application/x-vnd.kolab.journal")) { | ||
88 | tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.journal"); | ||
89 | } else if (mimeType == QLatin1String("application/x-vnd.kolab.note")) { | ||
90 | tMimeType = QStringLiteral("application/x-vnd.akonadi.note"); | ||
91 | } else if (mimeType == QLatin1String("image/jpg")) { | ||
92 | tMimeType = QStringLiteral("image/jpeg"); | ||
93 | } | ||
94 | QMimeDatabase mimeDb; | ||
95 | auto mime = mimeDb.mimeTypeForName(tMimeType); | ||
96 | if (mime.isValid()) { | ||
97 | fileName = mime.iconName(); | ||
98 | } else { | ||
99 | fileName = QStringLiteral("unknown"); | ||
100 | if (!tMimeType.isEmpty()) { | ||
101 | qCWarning(MIMETREEPARSER_LOG) << "unknown mimetype" << tMimeType; | ||
102 | } | ||
103 | } | ||
104 | //WorkAround for #199083 | ||
105 | if (fileName == QLatin1String("text-vcard")) { | ||
106 | fileName = QStringLiteral("text-x-vcard"); | ||
107 | } | ||
108 | |||
109 | if (fileName.isEmpty()) { | ||
110 | fileName = fallbackFileName1; | ||
111 | if (fileName.isEmpty()) { | ||
112 | fileName = fallbackFileName2; | ||
113 | } | ||
114 | if (!fileName.isEmpty()) { | ||
115 | fileName = mimeDb.mimeTypeForFile(QLatin1String("/tmp/") + fileName).iconName(); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | return fileName; | ||
120 | } | ||
121 | |||
122 | QString MimeTreeParser::Util::iconNameForContent(KMime::Content *node) | ||
123 | { | ||
124 | if (!node) { | ||
125 | return QString(); | ||
126 | } | ||
127 | |||
128 | QByteArray mimeType = node->contentType()->mimeType(); | ||
129 | if (mimeType.isNull() || mimeType == "application/octet-stream") { | ||
130 | const QString mime = mimetype(node->contentDisposition()->filename()).name(); | ||
131 | mimeType = mime.toLatin1(); | ||
132 | } | ||
133 | mimeType = mimeType.toLower(); | ||
134 | return iconNameForMimetype(QLatin1String(mimeType), node->contentDisposition()->filename(), | ||
135 | node->contentType()->name()); | ||
136 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/util.h b/framework/src/domain/mime/mimetreeparser/otp/util.h new file mode 100644 index 00000000..099c647a --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/util.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along | ||
15 | with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef __MIMETREEPARSER_UTILS_UTIL_H__ | ||
20 | #define __MIMETREEPARSER_UTILS_UTIL_H__ | ||
21 | |||
22 | #include <QString> | ||
23 | |||
24 | class QMimeType; | ||
25 | |||
26 | namespace KMime | ||
27 | { | ||
28 | class Content; | ||
29 | } | ||
30 | |||
31 | namespace MimeTreeParser | ||
32 | { | ||
33 | |||
34 | /** | ||
35 | * The Util namespace contains a collection of helper functions use in | ||
36 | * various places. | ||
37 | */ | ||
38 | namespace Util | ||
39 | { | ||
40 | |||
41 | /** | ||
42 | * Describes the type of the displayed message. This depends on the MIME structure | ||
43 | * of the mail and on whether HTML mode is enabled (which is decided by htmlMail()) | ||
44 | */ | ||
45 | enum HtmlMode { | ||
46 | Normal, ///< A normal plaintext message, non-multipart | ||
47 | Html, ///< A HTML message, non-multipart | ||
48 | MultipartPlain, ///< A multipart/alternative message, the plain text part is currently displayed | ||
49 | MultipartHtml, ///< A multipart/altervative message, the HTML part is currently displayed | ||
50 | MultipartIcal ///< A multipart/altervative message, the ICal part is currently displayed | ||
51 | }; | ||
52 | |||
53 | bool isTypeBlacklisted(KMime::Content *node); | ||
54 | |||
55 | QString labelForContent(KMime::Content *node); | ||
56 | |||
57 | QMimeType mimetype(const QString &name); | ||
58 | |||
59 | QString iconNameForMimetype(const QString &mimeType, | ||
60 | const QString &fallbackFileName1 = QString(), | ||
61 | const QString &fallbackFileName2 = QString()); | ||
62 | |||
63 | QString iconNameForContent(KMime::Content *node); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/utils.cpp b/framework/src/domain/mime/mimetreeparser/otp/utils.cpp new file mode 100644 index 00000000..8f718143 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/utils.cpp | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 "utils.h" | ||
21 | |||
22 | using namespace MimeTreeParser; | ||
23 | |||
24 | MimeMessagePart::Ptr MimeTreeParser::createAndParseTempNode(Interface::BodyPart &part, KMime::Content *parentNode, const char *content, const char *cntDesc) | ||
25 | { | ||
26 | KMime::Content *newNode = new KMime::Content(); | ||
27 | newNode->setContent(KMime::CRLFtoLF(content)); | ||
28 | newNode->parse(); | ||
29 | |||
30 | if (!newNode->head().isEmpty()) { | ||
31 | newNode->contentDescription()->from7BitString(cntDesc); | ||
32 | } | ||
33 | part.nodeHelper()->attachExtraContent(parentNode, newNode); | ||
34 | |||
35 | return MimeMessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), newNode, false)); | ||
36 | } | ||
37 | |||
38 | KMime::Content *MimeTreeParser::findTypeInDirectChilds(KMime::Content *content, const QByteArray &mimeType) | ||
39 | { | ||
40 | if (mimeType.isEmpty()) { | ||
41 | return content; | ||
42 | } | ||
43 | |||
44 | foreach (auto child, content->contents()) { | ||
45 | if ((!child->contentType()->isEmpty()) | ||
46 | && (mimeType == child->contentType()->mimeType())) { | ||
47 | return child; | ||
48 | } | ||
49 | } | ||
50 | return nullptr; | ||
51 | } | ||
52 | |||
53 | MessagePart::Ptr MimeTreeParser::toplevelTextNode(MessagePart::Ptr messageTree) | ||
54 | { | ||
55 | foreach (const auto &mp, messageTree->subParts()) { | ||
56 | auto text = mp.dynamicCast<TextMessagePart>(); | ||
57 | auto attach = mp.dynamicCast<AttachmentMessagePart>(); | ||
58 | if (text && !attach) { | ||
59 | return text; | ||
60 | } else if (const auto alternative = mp.dynamicCast<AlternativeMessagePart>()) { | ||
61 | return alternative; | ||
62 | } else if (const auto m = mp.dynamicCast<MessagePart>()) { | ||
63 | auto ret = toplevelTextNode(m); | ||
64 | if (ret) { | ||
65 | return ret; | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | return MessagePart::Ptr(); | ||
70 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/utils.h b/framework/src/domain/mime/mimetreeparser/otp/utils.h new file mode 100644 index 00000000..d4aaa43a --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/utils.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
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 | #ifndef __MIMETREEPARSER_BODYFORAMATTER_UTILS_H__ | ||
21 | #define __MIMETREEPARSER_BODYFORAMATTER_UTILS_H__ | ||
22 | |||
23 | #include "bodypart.h" | ||
24 | #include "messagepart.h" | ||
25 | |||
26 | #include <KMime/Content> | ||
27 | |||
28 | namespace MimeTreeParser | ||
29 | { | ||
30 | /** | ||
31 | 1. Create a new partNode using 'content' data and Content-Description | ||
32 | found in 'cntDesc'. | ||
33 | 2. Parse the 'node' to display the content. | ||
34 | */ | ||
35 | MimeMessagePart::Ptr createAndParseTempNode(Interface::BodyPart &part, KMime::Content *parentNode, const char *content, const char *cntDesc); | ||
36 | |||
37 | KMime::Content *findTypeInDirectChilds(KMime::Content *content, const QByteArray &mimeType); | ||
38 | |||
39 | MessagePart::Ptr toplevelTextNode(MessagePart::Ptr messageTree); | ||
40 | } | ||
41 | |||
42 | #endif | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/verifydetachedbodypartmemento.cpp b/framework/src/domain/mime/mimetreeparser/otp/verifydetachedbodypartmemento.cpp new file mode 100644 index 00000000..56c1d1a7 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/verifydetachedbodypartmemento.cpp | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | Copyright (c) 2014-2017 Montel Laurent <montel@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License, version 2, as | ||
6 | published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, but | ||
9 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along | ||
14 | with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
16 | */ | ||
17 | |||
18 | #include "verifydetachedbodypartmemento.h" | ||
19 | #include "mimetreeparser_debug.h" | ||
20 | |||
21 | #include <QGpgME/VerifyDetachedJob> | ||
22 | #include <QGpgME/KeyListJob> | ||
23 | |||
24 | #include <gpgme++/keylistresult.h> | ||
25 | |||
26 | #include <qstringlist.h> | ||
27 | |||
28 | #include <cassert> | ||
29 | |||
30 | using namespace QGpgME; | ||
31 | using namespace GpgME; | ||
32 | using namespace MimeTreeParser; | ||
33 | |||
34 | VerifyDetachedBodyPartMemento::VerifyDetachedBodyPartMemento(VerifyDetachedJob *job, | ||
35 | KeyListJob *klj, | ||
36 | const QByteArray &signature, | ||
37 | const QByteArray &plainText) | ||
38 | : CryptoBodyPartMemento(), | ||
39 | m_signature(signature), | ||
40 | m_plainText(plainText), | ||
41 | m_job(job), | ||
42 | m_keylistjob(klj) | ||
43 | { | ||
44 | assert(m_job); | ||
45 | } | ||
46 | |||
47 | VerifyDetachedBodyPartMemento::~VerifyDetachedBodyPartMemento() | ||
48 | { | ||
49 | if (m_job) { | ||
50 | m_job->slotCancel(); | ||
51 | } | ||
52 | if (m_keylistjob) { | ||
53 | m_keylistjob->slotCancel(); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | bool VerifyDetachedBodyPartMemento::start() | ||
58 | { | ||
59 | assert(m_job); | ||
60 | #ifdef DEBUG_SIGNATURE | ||
61 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyDetachedBodyPartMemento started"; | ||
62 | #endif | ||
63 | connect(m_job, SIGNAL(result(GpgME::VerificationResult)), | ||
64 | this, SLOT(slotResult(GpgME::VerificationResult))); | ||
65 | if (const Error err = m_job->start(m_signature, m_plainText)) { | ||
66 | m_vr = VerificationResult(err); | ||
67 | #ifdef DEBUG_SIGNATURE | ||
68 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyDetachedBodyPartMemento stopped with error"; | ||
69 | #endif | ||
70 | return false; | ||
71 | } | ||
72 | setRunning(true); | ||
73 | return true; | ||
74 | } | ||
75 | |||
76 | void VerifyDetachedBodyPartMemento::exec() | ||
77 | { | ||
78 | assert(m_job); | ||
79 | setRunning(true); | ||
80 | #ifdef DEBUG_SIGNATURE | ||
81 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyDetachedBodyPartMemento execed"; | ||
82 | #endif | ||
83 | saveResult(m_job->exec(m_signature, m_plainText)); | ||
84 | m_job->deleteLater(); // exec'ed jobs don't delete themselves | ||
85 | m_job = nullptr; | ||
86 | #ifdef DEBUG_SIGNATURE | ||
87 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyDetachedBodyPartMemento after execed"; | ||
88 | #endif | ||
89 | if (canStartKeyListJob()) { | ||
90 | std::vector<GpgME::Key> keys; | ||
91 | m_keylistjob->exec(keyListPattern(), /*secretOnly=*/false, keys); | ||
92 | if (!keys.empty()) { | ||
93 | m_key = keys.back(); | ||
94 | } | ||
95 | } | ||
96 | if (m_keylistjob) { | ||
97 | m_keylistjob->deleteLater(); // exec'ed jobs don't delete themselves | ||
98 | } | ||
99 | m_keylistjob = nullptr; | ||
100 | setRunning(false); | ||
101 | } | ||
102 | |||
103 | bool VerifyDetachedBodyPartMemento::canStartKeyListJob() const | ||
104 | { | ||
105 | if (!m_keylistjob) { | ||
106 | return false; | ||
107 | } | ||
108 | const char *const fpr = m_vr.signature(0).fingerprint(); | ||
109 | return fpr && *fpr; | ||
110 | } | ||
111 | |||
112 | QStringList VerifyDetachedBodyPartMemento::keyListPattern() const | ||
113 | { | ||
114 | assert(canStartKeyListJob()); | ||
115 | return QStringList(QString::fromLatin1(m_vr.signature(0).fingerprint())); | ||
116 | } | ||
117 | |||
118 | void VerifyDetachedBodyPartMemento::saveResult(const VerificationResult &vr) | ||
119 | { | ||
120 | assert(m_job); | ||
121 | #ifdef DEBUG_SIGNATURE | ||
122 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyDetachedBodyPartMemento::saveResult called"; | ||
123 | #endif | ||
124 | m_vr = vr; | ||
125 | setAuditLog(m_job->auditLogError(), m_job->auditLogAsHtml()); | ||
126 | } | ||
127 | |||
128 | void VerifyDetachedBodyPartMemento::slotResult(const VerificationResult &vr) | ||
129 | { | ||
130 | #ifdef DEBUG_SIGNATURE | ||
131 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyDetachedBodyPartMemento::slotResult called"; | ||
132 | #endif | ||
133 | saveResult(vr); | ||
134 | m_job = nullptr; | ||
135 | if (canStartKeyListJob() && startKeyListJob()) { | ||
136 | #ifdef DEBUG_SIGNATURE | ||
137 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyDetachedBodyPartMemento: canStartKeyListJob && startKeyListJob"; | ||
138 | #endif | ||
139 | return; | ||
140 | } | ||
141 | if (m_keylistjob) { | ||
142 | m_keylistjob->deleteLater(); | ||
143 | } | ||
144 | m_keylistjob = nullptr; | ||
145 | setRunning(false); | ||
146 | notify(); | ||
147 | } | ||
148 | |||
149 | bool VerifyDetachedBodyPartMemento::startKeyListJob() | ||
150 | { | ||
151 | assert(canStartKeyListJob()); | ||
152 | if (const GpgME::Error err = m_keylistjob->start(keyListPattern())) { | ||
153 | return false; | ||
154 | } | ||
155 | connect(m_keylistjob, SIGNAL(done()), this, SLOT(slotKeyListJobDone())); | ||
156 | connect(m_keylistjob, SIGNAL(nextKey(GpgME::Key)), | ||
157 | this, SLOT(slotNextKey(GpgME::Key))); | ||
158 | return true; | ||
159 | } | ||
160 | |||
161 | void VerifyDetachedBodyPartMemento::slotNextKey(const GpgME::Key &key) | ||
162 | { | ||
163 | #ifdef DEBUG_SIGNATURE | ||
164 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyDetachedBodyPartMemento::slotNextKey called"; | ||
165 | #endif | ||
166 | m_key = key; | ||
167 | } | ||
168 | |||
169 | void VerifyDetachedBodyPartMemento::slotKeyListJobDone() | ||
170 | { | ||
171 | #ifdef DEBUG_SIGNATURE | ||
172 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyDetachedBodyPartMemento::slotKeyListJobDone called"; | ||
173 | #endif | ||
174 | m_keylistjob = nullptr; | ||
175 | setRunning(false); | ||
176 | notify(); | ||
177 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/verifydetachedbodypartmemento.h b/framework/src/domain/mime/mimetreeparser/otp/verifydetachedbodypartmemento.h new file mode 100644 index 00000000..f37dfe81 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/verifydetachedbodypartmemento.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | Copyright (c) 2014-2016 Montel Laurent <montel@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License, version 2, as | ||
6 | published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, but | ||
9 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along | ||
14 | with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef __MIMETREEPARSER_VERIFYDETACHEDBODYPARTMEMENTO_H__ | ||
19 | #define __MIMETREEPARSER_VERIFYDETACHEDBODYPARTMEMENTO_H__ | ||
20 | |||
21 | #include "cryptobodypartmemento.h" | ||
22 | #include <gpgme++/verificationresult.h> | ||
23 | #include <gpgme++/key.h> | ||
24 | |||
25 | #include <QString> | ||
26 | #include <QPointer> | ||
27 | |||
28 | #include "bodypart.h" | ||
29 | |||
30 | namespace QGpgME | ||
31 | { | ||
32 | class VerifyDetachedJob; | ||
33 | class KeyListJob; | ||
34 | } | ||
35 | |||
36 | class QStringList; | ||
37 | |||
38 | namespace MimeTreeParser | ||
39 | { | ||
40 | |||
41 | class VerifyDetachedBodyPartMemento | ||
42 | : public CryptoBodyPartMemento | ||
43 | { | ||
44 | Q_OBJECT | ||
45 | public: | ||
46 | VerifyDetachedBodyPartMemento(QGpgME::VerifyDetachedJob *job, | ||
47 | QGpgME::KeyListJob *klj, | ||
48 | const QByteArray &signature, | ||
49 | const QByteArray &plainText); | ||
50 | ~VerifyDetachedBodyPartMemento(); | ||
51 | |||
52 | bool start() Q_DECL_OVERRIDE; | ||
53 | void exec() Q_DECL_OVERRIDE; | ||
54 | |||
55 | const GpgME::VerificationResult &verifyResult() const | ||
56 | { | ||
57 | return m_vr; | ||
58 | } | ||
59 | const GpgME::Key &signingKey() const | ||
60 | { | ||
61 | return m_key; | ||
62 | } | ||
63 | |||
64 | private Q_SLOTS: | ||
65 | void slotResult(const GpgME::VerificationResult &vr); | ||
66 | void slotKeyListJobDone(); | ||
67 | void slotNextKey(const GpgME::Key &); | ||
68 | |||
69 | private: | ||
70 | void saveResult(const GpgME::VerificationResult &); | ||
71 | bool canStartKeyListJob() const; | ||
72 | QStringList keyListPattern() const; | ||
73 | bool startKeyListJob(); | ||
74 | private: | ||
75 | // input: | ||
76 | const QByteArray m_signature; | ||
77 | const QByteArray m_plainText; | ||
78 | QPointer<QGpgME::VerifyDetachedJob> m_job; | ||
79 | QPointer<QGpgME::KeyListJob> m_keylistjob; | ||
80 | // output: | ||
81 | GpgME::VerificationResult m_vr; | ||
82 | GpgME::Key m_key; | ||
83 | }; | ||
84 | |||
85 | } | ||
86 | |||
87 | #endif // __MIMETREEPARSER_VERIFYDETACHEDBODYPARTMEMENTO_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/verifyopaquebodypartmemento.cpp b/framework/src/domain/mime/mimetreeparser/otp/verifyopaquebodypartmemento.cpp new file mode 100644 index 00000000..99eb8b8e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/verifyopaquebodypartmemento.cpp | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | Copyright (c) 2014-2017 Montel Laurent <montel@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License, version 2, as | ||
6 | published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, but | ||
9 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along | ||
14 | with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
16 | */ | ||
17 | |||
18 | #include "verifyopaquebodypartmemento.h" | ||
19 | #include "mimetreeparser_debug.h" | ||
20 | |||
21 | #include <QGpgME/VerifyOpaqueJob> | ||
22 | #include <QGpgME/KeyListJob> | ||
23 | |||
24 | #include <gpgme++/keylistresult.h> | ||
25 | |||
26 | #include <qstringlist.h> | ||
27 | |||
28 | #include <cassert> | ||
29 | |||
30 | using namespace QGpgME; | ||
31 | using namespace GpgME; | ||
32 | using namespace MimeTreeParser; | ||
33 | |||
34 | VerifyOpaqueBodyPartMemento::VerifyOpaqueBodyPartMemento(VerifyOpaqueJob *job, | ||
35 | KeyListJob *klj, | ||
36 | const QByteArray &signature) | ||
37 | : CryptoBodyPartMemento(), | ||
38 | m_signature(signature), | ||
39 | m_job(job), | ||
40 | m_keylistjob(klj) | ||
41 | { | ||
42 | assert(m_job); | ||
43 | } | ||
44 | |||
45 | VerifyOpaqueBodyPartMemento::~VerifyOpaqueBodyPartMemento() | ||
46 | { | ||
47 | if (m_job) { | ||
48 | m_job->slotCancel(); | ||
49 | } | ||
50 | if (m_keylistjob) { | ||
51 | m_keylistjob->slotCancel(); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | bool VerifyOpaqueBodyPartMemento::start() | ||
56 | { | ||
57 | assert(m_job); | ||
58 | #ifdef DEBUG_SIGNATURE | ||
59 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyOpaqueBodyPartMemento started"; | ||
60 | #endif | ||
61 | if (const Error err = m_job->start(m_signature)) { | ||
62 | m_vr = VerificationResult(err); | ||
63 | #ifdef DEBUG_SIGNATURE | ||
64 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyOpaqueBodyPartMemento stopped with error"; | ||
65 | #endif | ||
66 | return false; | ||
67 | } | ||
68 | connect(m_job, SIGNAL(result(GpgME::VerificationResult,QByteArray)), | ||
69 | this, SLOT(slotResult(GpgME::VerificationResult,QByteArray))); | ||
70 | setRunning(true); | ||
71 | return true; | ||
72 | } | ||
73 | |||
74 | void VerifyOpaqueBodyPartMemento::exec() | ||
75 | { | ||
76 | assert(m_job); | ||
77 | setRunning(true); | ||
78 | QByteArray plainText; | ||
79 | #ifdef DEBUG_SIGNATURE | ||
80 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyOpaqueBodyPartMemento execed"; | ||
81 | #endif | ||
82 | saveResult(m_job->exec(m_signature, plainText), plainText); | ||
83 | #ifdef DEBUG_SIGNATURE | ||
84 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyOpaqueBodyPartMemento after execed"; | ||
85 | #endif | ||
86 | m_job->deleteLater(); // exec'ed jobs don't delete themselves | ||
87 | m_job = nullptr; | ||
88 | if (canStartKeyListJob()) { | ||
89 | std::vector<GpgME::Key> keys; | ||
90 | m_keylistjob->exec(keyListPattern(), /*secretOnly=*/false, keys); | ||
91 | if (!keys.empty()) { | ||
92 | m_key = keys.back(); | ||
93 | } | ||
94 | } | ||
95 | if (m_keylistjob) { | ||
96 | m_keylistjob->deleteLater(); // exec'ed jobs don't delete themselves | ||
97 | } | ||
98 | m_keylistjob = nullptr; | ||
99 | setRunning(false); | ||
100 | } | ||
101 | |||
102 | bool VerifyOpaqueBodyPartMemento::canStartKeyListJob() const | ||
103 | { | ||
104 | if (!m_keylistjob) { | ||
105 | return false; | ||
106 | } | ||
107 | const char *const fpr = m_vr.signature(0).fingerprint(); | ||
108 | return fpr && *fpr; | ||
109 | } | ||
110 | |||
111 | QStringList VerifyOpaqueBodyPartMemento::keyListPattern() const | ||
112 | { | ||
113 | assert(canStartKeyListJob()); | ||
114 | return QStringList(QString::fromLatin1(m_vr.signature(0).fingerprint())); | ||
115 | } | ||
116 | |||
117 | void VerifyOpaqueBodyPartMemento::saveResult(const VerificationResult &vr, | ||
118 | const QByteArray &plainText) | ||
119 | { | ||
120 | assert(m_job); | ||
121 | #ifdef DEBUG_SIGNATURE | ||
122 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyOpaqueBodyPartMemento::saveResult called"; | ||
123 | #endif | ||
124 | m_vr = vr; | ||
125 | m_plainText = plainText; | ||
126 | setAuditLog(m_job->auditLogError(), m_job->auditLogAsHtml()); | ||
127 | } | ||
128 | |||
129 | void VerifyOpaqueBodyPartMemento::slotResult(const VerificationResult &vr, | ||
130 | const QByteArray &plainText) | ||
131 | { | ||
132 | #ifdef DEBUG_SIGNATURE | ||
133 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyOpaqueBodyPartMemento::slotResult called"; | ||
134 | #endif | ||
135 | saveResult(vr, plainText); | ||
136 | m_job = nullptr; | ||
137 | if (canStartKeyListJob() && startKeyListJob()) { | ||
138 | #ifdef DEBUG_SIGNATURE | ||
139 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyOpaqueBodyPartMemento: canStartKeyListJob && startKeyListJob"; | ||
140 | #endif | ||
141 | return; | ||
142 | } | ||
143 | if (m_keylistjob) { | ||
144 | m_keylistjob->deleteLater(); | ||
145 | } | ||
146 | m_keylistjob = nullptr; | ||
147 | setRunning(false); | ||
148 | notify(); | ||
149 | } | ||
150 | |||
151 | bool VerifyOpaqueBodyPartMemento::startKeyListJob() | ||
152 | { | ||
153 | assert(canStartKeyListJob()); | ||
154 | if (const GpgME::Error err = m_keylistjob->start(keyListPattern())) { | ||
155 | return false; | ||
156 | } | ||
157 | connect(m_keylistjob, SIGNAL(done()), this, SLOT(slotKeyListJobDone())); | ||
158 | connect(m_keylistjob, SIGNAL(nextKey(GpgME::Key)), | ||
159 | this, SLOT(slotNextKey(GpgME::Key))); | ||
160 | return true; | ||
161 | } | ||
162 | |||
163 | void VerifyOpaqueBodyPartMemento::slotNextKey(const GpgME::Key &key) | ||
164 | { | ||
165 | #ifdef DEBUG_SIGNATURE | ||
166 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyOpaqueBodyPartMemento::slotNextKey called"; | ||
167 | #endif | ||
168 | m_key = key; | ||
169 | } | ||
170 | |||
171 | void VerifyOpaqueBodyPartMemento::slotKeyListJobDone() | ||
172 | { | ||
173 | #ifdef DEBUG_SIGNATURE | ||
174 | qCDebug(MIMETREEPARSER_LOG) << "tokoe: VerifyOpaqueBodyPartMemento::slotKeyListJobDone called"; | ||
175 | #endif | ||
176 | m_keylistjob = nullptr; | ||
177 | setRunning(false); | ||
178 | notify(); | ||
179 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/otp/verifyopaquebodypartmemento.h b/framework/src/domain/mime/mimetreeparser/otp/verifyopaquebodypartmemento.h new file mode 100644 index 00000000..02d30a13 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/otp/verifyopaquebodypartmemento.h | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | Copyright (c) 2014-2016 Montel Laurent <montel@kde.org> | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License, version 2, as | ||
6 | published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, but | ||
9 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along | ||
14 | with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef __MIMETREEPARSER_VERIFYOPAQUEBODYPARTMEMENTO_H__ | ||
19 | #define __MIMETREEPARSER_VERIFYOPAQUEBODYPARTMEMENTO_H__ | ||
20 | |||
21 | #include "cryptobodypartmemento.h" | ||
22 | #include <gpgme++/verificationresult.h> | ||
23 | #include <gpgme++/decryptionresult.h> | ||
24 | #include <gpgme++/key.h> | ||
25 | |||
26 | #include <QString> | ||
27 | #include <QPointer> | ||
28 | |||
29 | #include "bodypart.h" | ||
30 | |||
31 | namespace QGpgME | ||
32 | { | ||
33 | class VerifyOpaqueJob; | ||
34 | class KeyListJob; | ||
35 | } | ||
36 | |||
37 | class QStringList; | ||
38 | |||
39 | namespace MimeTreeParser | ||
40 | { | ||
41 | |||
42 | class VerifyOpaqueBodyPartMemento | ||
43 | : public CryptoBodyPartMemento | ||
44 | { | ||
45 | Q_OBJECT | ||
46 | public: | ||
47 | VerifyOpaqueBodyPartMemento(QGpgME::VerifyOpaqueJob *job, | ||
48 | QGpgME::KeyListJob *klj, | ||
49 | const QByteArray &signature); | ||
50 | ~VerifyOpaqueBodyPartMemento(); | ||
51 | |||
52 | bool start() Q_DECL_OVERRIDE; | ||
53 | void exec() Q_DECL_OVERRIDE; | ||
54 | |||
55 | const QByteArray &plainText() const | ||
56 | { | ||
57 | return m_plainText; | ||
58 | } | ||
59 | const GpgME::VerificationResult &verifyResult() const | ||
60 | { | ||
61 | return m_vr; | ||
62 | } | ||
63 | const GpgME::Key &signingKey() const | ||
64 | { | ||
65 | return m_key; | ||
66 | } | ||
67 | |||
68 | private Q_SLOTS: | ||
69 | void slotResult(const GpgME::VerificationResult &vr, | ||
70 | const QByteArray &plainText); | ||
71 | void slotKeyListJobDone(); | ||
72 | void slotNextKey(const GpgME::Key &); | ||
73 | |||
74 | private: | ||
75 | void saveResult(const GpgME::VerificationResult &, | ||
76 | const QByteArray &); | ||
77 | bool canStartKeyListJob() const; | ||
78 | QStringList keyListPattern() const; | ||
79 | bool startKeyListJob(); | ||
80 | private: | ||
81 | // input: | ||
82 | const QByteArray m_signature; | ||
83 | QPointer<QGpgME::VerifyOpaqueJob> m_job; | ||
84 | QPointer<QGpgME::KeyListJob> m_keylistjob; | ||
85 | // output: | ||
86 | GpgME::VerificationResult m_vr; | ||
87 | QByteArray m_plainText; | ||
88 | GpgME::Key m_key; | ||
89 | }; | ||
90 | |||
91 | } | ||
92 | |||
93 | #endif // __MIMETREEPARSER_VERIFYOPAQUEBODYPARTMEMENTO_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/stringhtmlwriter.cpp b/framework/src/domain/mime/mimetreeparser/stringhtmlwriter.cpp new file mode 100644 index 00000000..88034492 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/stringhtmlwriter.cpp | |||
@@ -0,0 +1,150 @@ | |||
1 | /* -*- c++ -*- | ||
2 | filehtmlwriter.cpp | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | |||
7 | KMail is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License, version 2, as | ||
9 | published by the Free Software Foundation. | ||
10 | |||
11 | KMail is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | |||
20 | In addition, as a special exception, the copyright holders give | ||
21 | permission to link the code of this program with any edition of | ||
22 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
23 | of Qt that use the same license as Qt), and distribute linked | ||
24 | combinations including the two. You must obey the GNU General | ||
25 | Public License in all respects for all of the code used other than | ||
26 | Qt. If you modify this file, you may extend this exception to | ||
27 | your version of the file, but you are not obligated to do so. If | ||
28 | you do not wish to do so, delete this exception statement from | ||
29 | your version. | ||
30 | */ | ||
31 | |||
32 | #include "stringhtmlwriter.h" | ||
33 | |||
34 | #include <QDebug> | ||
35 | #include <QTextStream> | ||
36 | #include <QUrl> | ||
37 | |||
38 | StringHtmlWriter::StringHtmlWriter() | ||
39 | : MimeTreeParser::HtmlWriter() | ||
40 | , mState(Ended) | ||
41 | { | ||
42 | } | ||
43 | |||
44 | StringHtmlWriter::~StringHtmlWriter() | ||
45 | { | ||
46 | } | ||
47 | |||
48 | void StringHtmlWriter::begin(const QString &css) | ||
49 | { | ||
50 | if (mState != Ended) { | ||
51 | qWarning() << "begin() called on non-ended session!"; | ||
52 | reset(); | ||
53 | } | ||
54 | |||
55 | mState = Begun; | ||
56 | mExtraHead.clear(); | ||
57 | mHtml.clear(); | ||
58 | |||
59 | if (!css.isEmpty()) { | ||
60 | write(QLatin1String("<!-- CSS Definitions \n") + css + QLatin1String("-->\n")); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void StringHtmlWriter::end() | ||
65 | { | ||
66 | if (mState != Begun) { | ||
67 | qWarning() << "Called on non-begun or queued session!"; | ||
68 | } | ||
69 | |||
70 | if (!mExtraHead.isEmpty()) { | ||
71 | insertExtraHead(); | ||
72 | mExtraHead.clear(); | ||
73 | } | ||
74 | resolveCidUrls(); | ||
75 | mState = Ended; | ||
76 | } | ||
77 | |||
78 | void StringHtmlWriter::reset() | ||
79 | { | ||
80 | if (mState != Ended) { | ||
81 | mHtml.clear(); | ||
82 | mExtraHead.clear(); | ||
83 | mState = Begun; // don't run into end()'s warning | ||
84 | end(); | ||
85 | mState = Ended; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | void StringHtmlWriter::write(const QString &str) | ||
90 | { | ||
91 | if (mState != Begun) { | ||
92 | qWarning() << "Called in Ended or Queued state!"; | ||
93 | } | ||
94 | mHtml.append(str); | ||
95 | } | ||
96 | |||
97 | void StringHtmlWriter::queue(const QString &str) | ||
98 | { | ||
99 | write(str); | ||
100 | } | ||
101 | |||
102 | void StringHtmlWriter::flush() | ||
103 | { | ||
104 | mState = Begun; // don't run into end()'s warning | ||
105 | end(); | ||
106 | } | ||
107 | |||
108 | void StringHtmlWriter::embedPart(const QByteArray &contentId, const QString &url) | ||
109 | { | ||
110 | write("<!-- embedPart(contentID=" + contentId + ", url=" + url + ") -->\n"); | ||
111 | mEmbeddedPartMap.insert(contentId, url); | ||
112 | } | ||
113 | |||
114 | void StringHtmlWriter::resolveCidUrls() | ||
115 | { | ||
116 | for (const auto &cid : mEmbeddedPartMap.keys()) { | ||
117 | mHtml.replace(QString("src=\"cid:%1\"").arg(QString(cid)), QString("src=\"%1\"").arg(mEmbeddedPartMap.value(cid).toString())); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | void StringHtmlWriter::extraHead(const QString &extraHead) | ||
122 | { | ||
123 | if (mState != Ended) { | ||
124 | qWarning() << "Called on non-started session!"; | ||
125 | } | ||
126 | mExtraHead.append(extraHead); | ||
127 | } | ||
128 | |||
129 | |||
130 | void StringHtmlWriter::insertExtraHead() | ||
131 | { | ||
132 | const QString headTag(QStringLiteral("<head>")); | ||
133 | const int index = mHtml.indexOf(headTag); | ||
134 | if (index != -1) { | ||
135 | mHtml.insert(index + headTag.length(), mExtraHead); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | QMap<QByteArray, QUrl> StringHtmlWriter::embeddedParts() const | ||
140 | { | ||
141 | return mEmbeddedPartMap; | ||
142 | } | ||
143 | |||
144 | QString StringHtmlWriter::html() const | ||
145 | { | ||
146 | if (mState != Ended) { | ||
147 | qWarning() << "Called on non-ended session!"; | ||
148 | } | ||
149 | return mHtml; | ||
150 | } | ||
diff --git a/framework/src/domain/mime/mimetreeparser/stringhtmlwriter.h b/framework/src/domain/mime/mimetreeparser/stringhtmlwriter.h new file mode 100644 index 00000000..20f6763e --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/stringhtmlwriter.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* -*- c++ -*- | ||
2 | |||
3 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
4 | |||
5 | Kube is free software; you can redistribute it and/or modify it | ||
6 | under the terms of the GNU General Public License, version 2, as | ||
7 | published by the Free Software Foundation. | ||
8 | |||
9 | Kube is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | |||
18 | In addition, as a special exception, the copyright holders give | ||
19 | permission to link the code of this program with any edition of | ||
20 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
21 | of Qt that use the same license as Qt), and distribute linked | ||
22 | combinations including the two. You must obey the GNU General | ||
23 | Public License in all respects for all of the code used other than | ||
24 | Qt. If you modify this file, you may extend this exception to | ||
25 | your version of the file, but you are not obligated to do so. If | ||
26 | you do not wish to do so, delete this exception statement from | ||
27 | your version. | ||
28 | */ | ||
29 | |||
30 | #ifndef __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ | ||
31 | #define __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ | ||
32 | |||
33 | #include <otp/htmlwriter.h> | ||
34 | |||
35 | #include <QFile> | ||
36 | #include <QTextStream> | ||
37 | |||
38 | class QString; | ||
39 | |||
40 | class StringHtmlWriter : public MimeTreeParser::HtmlWriter | ||
41 | { | ||
42 | public: | ||
43 | explicit StringHtmlWriter(); | ||
44 | virtual ~StringHtmlWriter(); | ||
45 | |||
46 | void begin(const QString &cssDefs) Q_DECL_OVERRIDE; | ||
47 | void end() Q_DECL_OVERRIDE; | ||
48 | void reset() Q_DECL_OVERRIDE; | ||
49 | void write(const QString &str) Q_DECL_OVERRIDE; | ||
50 | void queue(const QString &str) Q_DECL_OVERRIDE; | ||
51 | void flush() Q_DECL_OVERRIDE; | ||
52 | void embedPart(const QByteArray &contentId, const QString &url) Q_DECL_OVERRIDE; | ||
53 | void extraHead(const QString &str) Q_DECL_OVERRIDE; | ||
54 | |||
55 | QString html() const; | ||
56 | QMap<QByteArray, QUrl> embeddedParts() const; | ||
57 | private: | ||
58 | void insertExtraHead(); | ||
59 | void resolveCidUrls(); | ||
60 | |||
61 | QString mHtml; | ||
62 | QString mExtraHead; | ||
63 | enum State { | ||
64 | Begun, | ||
65 | Queued, | ||
66 | Ended | ||
67 | } mState; | ||
68 | QMap<QByteArray, QUrl> mEmbeddedPartMap; | ||
69 | }; | ||
70 | |||
71 | #endif // __MESSAGEVIEWER_FILEHTMLWRITER_H__ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/CMakeLists.txt b/framework/src/domain/mime/mimetreeparser/tests/CMakeLists.txt new file mode 100644 index 00000000..a7f28bb1 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/CMakeLists.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | add_subdirectory(gnupg_home) | ||
2 | add_definitions( -DMAIL_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" ) | ||
3 | include(${CMAKE_CURRENT_SOURCE_DIR}/kdepim_add_gpg_crypto_test.cmake) | ||
4 | include_directories( | ||
5 | ${CMAKE_CURRENT_BINARY_DIR} | ||
6 | ${CMAKE_CURRENT_SOURCE_DIR}/.. | ||
7 | ) | ||
8 | |||
9 | include(ECMAddTests) | ||
10 | |||
11 | add_executable(mimetreeparsertest interfacetest.cpp) | ||
12 | add_gpg_crypto_test(mimetreeparsertest mimetreeparsertest) | ||
13 | qt5_use_modules(mimetreeparsertest Core Test) | ||
14 | target_link_libraries(mimetreeparsertest mimetreeparser kube_otp) | ||
15 | |||
16 | #find_package(Gpgmepp 1.7.1 CONFIG) | ||
17 | #find_package(QGpgme 1.7.1 CONFIG) | ||
18 | # | ||
19 | #ecm_add_test(gpgerrortest.cpp | ||
20 | # TEST_NAME "gpgerrortest" | ||
21 | # NAME_PREFIX "mimetreeparser-" | ||
22 | # LINK_LIBRARIES Qt5::Core Qt5::Test mimetreeparser Gpgmepp QGpgme | ||
23 | #) | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/data/alternative.mbox b/framework/src/domain/mime/mimetreeparser/tests/data/alternative.mbox new file mode 100644 index 00000000..6522c34b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/data/alternative.mbox | |||
@@ -0,0 +1,28 @@ | |||
1 | Return-Path: <konqi@example.org> | ||
2 | Date: Wed, 8 Jun 2016 20:34:44 -0700 | ||
3 | From: Konqi <konqi@example.org> | ||
4 | To: konqi@kde.org | ||
5 | Subject: A random subject with alternative contenttype | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: multipart/alternative; | ||
8 | boundary="----=_Part_12345678_12345678" | ||
9 | |||
10 | |||
11 | ------=_Part_12345678_12345678 | ||
12 | Content-Type: text/plain; charset=utf-8 | ||
13 | Content-Transfer-Encoding: quoted-printable | ||
14 | |||
15 | If you can see this text it means that your email client couldn't display o= | ||
16 | ur newsletter properly. | ||
17 | Please visit this link to view the newsletter on our website: http://www.go= | ||
18 | g.com/newsletter/ | ||
19 | |||
20 | |||
21 | ------=_Part_12345678_12345678 | ||
22 | Content-Transfer-Encoding: 7Bit | ||
23 | Content-Type: text/html; charset="windows-1252" | ||
24 | |||
25 | <html><body><p><span>HTML</span> text</p></body></html> | ||
26 | |||
27 | |||
28 | ------=_Part_12345678_12345678-- | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/data/cid-links.mbox b/framework/src/domain/mime/mimetreeparser/tests/data/cid-links.mbox new file mode 100644 index 00000000..40ff5282 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/data/cid-links.mbox | |||
@@ -0,0 +1,1384 @@ | |||
1 | Message-ID: <851f01d15e53$31734730$790bc9ad@info> | ||
2 | From: "OculusLab" <info@findermanze.co.ua> | ||
3 | To: <info@example.org> | ||
4 | Subject: CID links for images | ||
5 | Date: Wed, 03 Feb 2016 07:19:17 +0200 | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: multipart/related; | ||
8 | type="multipart/alternative"; | ||
9 | boundary="----=_NextPart_000_000F_01D15E52.0BD654A0" | ||
10 | X-MSMail-Priority: Normal | ||
11 | X-Mailer: Microsoft Windows Live Mail 14.0.8117.416 | ||
12 | X-MimeOLE: Produced By Microsoft MimeOLE V14.0.8117.416 | ||
13 | |||
14 | This is a multi-part message in MIME format. | ||
15 | |||
16 | ------=_NextPart_000_000F_01D15E52.0BD654A0 | ||
17 | Content-Type: multipart/alternative; | ||
18 | boundary="----=_NextPart_000_0010_01D15E52.0BD654A0" | ||
19 | |||
20 | ------=_NextPart_000_0010_01D15E52.0BD654A0 | ||
21 | Content-Type: text/plain; | ||
22 | charset="windows-1251" | ||
23 | Content-Transfer-Encoding: quoted-printable | ||
24 | |||
25 | =0D=0A=0D=0A=0D=0A=0D=0ASuperkombipackung für nur 45 Euro=0D= | ||
26 | =0A=0D=0A | ||
27 | ------=_NextPart_000_0010_01D15E52.0BD654A0 | ||
28 | Content-Type: text/html; | ||
29 | charset="windows-1251" | ||
30 | Content-Transfer-Encoding: quoted-printable | ||
31 | |||
32 | <HTML><HEAD>=0D=0A<META http-equiv=3D"Content-Type" content=3D"te= | ||
33 | xt/html; charset=3Dwindows-1251">=0D=0A</HEAD>=0D=0A<BODY bgColor= | ||
34 | =3D#ffffff>=0D=0A<DIV align=3Dcenter><FONT size=3D2 face=3DArial>= | ||
35 | <A =0D=0Ahref=3D"http://intenices.co.ua/drugs-store/index.html"><= | ||
36 | STRONG><FONT =0D=0Asize=3D4>Superkombipackung für nur 45 Eur= | ||
37 | o</FONT></STRONG></A><BR><BR><A =0D=0Ahref=3D"http://intenices.co= | ||
38 | .ua/drugs-store/index.html"><IMG border=3D0 hspace=3D0 alt=3D""=20= | ||
39 | src=3D"cid:9359201d15e53f31a68c307b3369b6@info" width=3D650 heigh= | ||
40 | t=3D763></A></FONT></DIV></BODY></HTML> | ||
41 | |||
42 | ------=_NextPart_000_0010_01D15E52.0BD654A0-- | ||
43 | |||
44 | ------=_NextPart_000_000F_01D15E52.0BD654A0 | ||
45 | Content-Type: image/jpeg; | ||
46 | name="aqnaozisxya.jpeg" | ||
47 | Content-Transfer-Encoding: base64 | ||
48 | Content-ID: <9359201d15e53f31a68c307b3369b6@info> | ||
49 | |||
50 | /9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMqaHR0cDov | ||
51 | L25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENl | ||
52 | aGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4 | ||
53 | OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjUtYzAxNCA3OS4xNTE0ODEsIDIwMTMvMDMvMTMtMTI6 | ||
54 | MDk6MTUgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5 | ||
55 | OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHht | ||
56 | bG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6 | ||
57 | Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUu | ||
58 | Y29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBo | ||
59 | b3Rvc2hvcCBDQyAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjdCRTg5MTBD | ||
60 | OUNGMTFFNUJBOTdEMkQyNzU0ODI3RDciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjdCRTg5 | ||
61 | MTFDOUNGMTFFNUJBOTdEMkQyNzU0ODI3RDciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5z | ||
62 | dGFuY2VJRD0ieG1wLmlpZDpCN0JFODkwRUM5Q0YxMUU1QkE5N0QyRDI3NTQ4MjdENyIgc3RSZWY6 | ||
63 | ZG9jdW1lbnRJRD0ieG1wLmRpZDpCN0JFODkwRkM5Q0YxMUU1QkE5N0QyRDI3NTQ4MjdENyIvPiA8 | ||
64 | L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0i | ||
65 | ciI/Pv/uAA5BZG9iZQBkwAAAAAH/2wCEAAYEBAQFBAYFBQYJBgUGCQsIBgYICwwKCgsKCgwQDAwM | ||
66 | DAwMEAwODxAPDgwTExQUExMcGxsbHB8fHx8fHx8fHx8BBwcHDQwNGBAQGBoVERUaHx8fHx8fHx8f | ||
67 | Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fH//AABEIAvsCigMBEQACEQED | ||
68 | EQH/xADJAAEAAgMBAQEAAAAAAAAAAAAAAwQBAgUGBwgBAQEBAQEBAQAAAAAAAAAAAAABAgMEBQYQ | ||
69 | AAEEAgEDAgQCBAgKCQMACwIAAQMEEQUSIRMGMUFRIjIUYXGBQhUHkaGxUiMzFhfB0WJy0+OkZZVW | ||
70 | 8ILSsyQ0lFU24UN1U4MlssJzhLQ1djcRAQABAgMEBQkFBwQBBAIDAAABEQIhMQNBUWEScYGRoQTw | ||
71 | scHRIjJSYhPhQpKyFfFygqIzUwXCI2Nzk9JDsxSDNPLD0//aAAwDAQACEQMRAD8A/VKAgICAgICA | ||
72 | gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA | ||
73 | gICAgICAgICAgICAgICAgICAg1y6Bl0DLoGXQMugZdBrIZMBOz9WZBpWkM68Zk+SIWd3QS8nQOTo | ||
74 | HJ0Dk6BydA5OgcnQOToGXQMugZdAy6Bl0DLoGXQMugOT4dAYnwyA7ughaWTPqgkIyaNnz16INQkN | ||
75 | 3bL+6BJIbHhn6INozJ2fL+6DbLoI5JDYmZn6KDJGTR8s9VQiM39Xyg1GWRy6v0ygkMiYXdn6sghG | ||
76 | aRxd8/yItGAnldupfxMoUZ70nx/kQO9J8f5EKAzSO3r/ABMhRnuyfH+RCg0snXqgNNI/v/Igd2T4 | ||
77 | /wAiDLSyfFCjDSyfH+RUZ7snx/kUBpTz6oMd2TPr/Igz3JPj/Igy0knx/kQY7smX6oMd2T4/yIMj | ||
78 | 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 | ||
302 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
303 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
304 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
305 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
306 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
307 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
308 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
309 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
310 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
311 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
312 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
313 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
314 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
315 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
316 | 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 | ||
484 | AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgION5nsL2u8V2l6g/G3Xrmc | ||
485 | R45cMN1k4v68GyWPwUwmYicIm62J6JmInuWK40is0mkb5phHXLx/kwjrquz19C/Zu07vjuxtWgs2 | ||
486 | JLeCjABhmE5SNwaRpDbiLsL46N0V1MromKcs29VZnDu27uLWh71k1xm7tjfwph2tNtJd00FiGnet | ||
487 | 8bfjF66by2JZHCzVGFo5YeRYhfEz9I+LenToumvnqcLre+bq+aHLwsf0p34T2W+XnN1sdx48xy62 | ||
488 | 3ZszWtBZvSNamksM1iucAtMAydwY8DOTkICwvj6VdSI5r4yiL7I6IuuuiceiOpnSmZtsuzmYu66W | ||
489 | xMd+HGubt+JU9/X2wzTzwfsu1UeRoW2tnaSSysYOE8b2YYe2HEiYmB+PUejJdSImJzrGzLOvHdnu | ||
490 | IrNJ8p9H7XK8mtWNLutvqKhPHL5dHC+rJv1bhENS0Tf5kJRy/od1zssi+OScou/kmt135buu6HW6 | ||
491 | 7kmNThT+KPd7a06LUVvlU1HkloL9ija8ZJq2mpxTyRwxxw14yrCdcSaOfvkX/wBwSznA4wt88zy3 | ||
492 | Zzffj+OlOHs0nfjXczZZETyThbbbGP8ADWbuqa8PZ6Vye92rXl+z2dq+0GreLs1q1iSNou7Qi59s | ||
493 | GIQzykd255ES+bo/VZiPZimMzfNvfbTy3LF2MTOyyLp6pvr5striW9hvtZftUCmlpwsOqtFD+07G | ||
494 | xkjaTYhHIRzTsJxscb4IGJwx+lb06TdSdl8Rlvtuw44xGbN2Vd9l89lMeGc5eh293a3F7yPyHXan | ||
495 | YM0kFfU4qlZKAXI5rBTwhIHJ4ZZohZuQjy9PwdYs92JnH257OS3zTjTpavwmNnsf6vKHm9luNpBs | ||
496 | aBaitdju0G2cF+G5O9+esDDSOc60hnL9w4RnzASP6untxWraYzM+zNueX36eeM8cMcUpNKRHtRfF | ||
497 | I2TPJdMfsw6s3U8kvxyUrRaK1bsNqNVFabZzbexVhYZBkOGZmBpfupC45LujwfDD8Vi+Zt5rqUpd | ||
498 | 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 | ||
680 | ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDiec//AArf/wD463/3BrnqZdnnddD+ | ||
681 | pb0w8/O3llX93t2zNsaxhHpjOo1KrNWsRyNBkC7z2p8uLN7A3Xr0Xp8RMRfNfj/1YuHg4rFm6keZ | ||
682 | X8u3lkLUkdO+YkPi2zuOEMzs7SN2OzPgX+pvm4H+eFjUin1OF1nnur6GvD4/SrtntwhZCmUu41On | ||
683 | tX7wUblCW/LI1yxHLYtD2QcWmAwMBACc+3G4i+c4XS+I57/lpTrm6s8aUiMcq9DlZdM2WT8WfVEU | ||
684 | jrxnfPL0ut4bugm01YLt4ZppbNytr5ZjFpbUVaeQYzH07hdoGJ3Fuv1LE4xE7ZtiZ7se/vdJik3b | ||
685 | oup9nVNY6npFhRAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ | ||
686 | EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBpPBBYgkgnjGaCUXCWKRmIDAmwQkL9HZ29WdJh | ||
687 | YmmMObrvEvFdZO9jXaajSsOLg81etDEbgXqPIBF8P8FZumYozyxWrev4x43WjKKtqacEZhJEYR14 | ||
688 | gEo5sd0HYRbIycW5N746pMzMU8sF212pr+m1GxqjU2FGvcqA7OFexEEsbOLYZ2A2cWwpM412kYRS | ||
689 | Mkj67XuVY3qwuVLP2Zdscw5Hg/afHyZD5fl9uitZrXalMKbFhRRAQEBAQEBAQEBAQEBAQEBAQEBA | ||
690 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
691 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
692 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
693 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
694 | 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 | ||
834 | 0bkDbJqkdTZ3ZTijEasgQyWP/CyGfIjL5my4ceTlhlrTnGZjPl3fPuyypE8eLN9s8tNnNG35Lq49 | ||
835 | VY3Y0b2r22raDZbSK5Odo95PrnkntyxQQVD2Hbdmw0oRszNxaXtkQM/TDLFkVjTj4ox405qds0jj | ||
836 | ludL5pN8/Dy067bK9lZnvpnWeCPybVb7VQXLQwa+xsYWClHsrOxkHnUtcmlmsxwyPHIYA4AXJuTP | ||
837 | hbtmJmm2l2z93vjGd9GJieWZ/d/Nn30bQbq5L5IbR35JKY+TvUdhlJ42jbUs/Z6Px49/rx9Of4qa | ||
838 | cYW8bb/zzTu7l1MJu4fT9FUU+yuXtvPWi2Vhqp+UjScq85jiFtWxHAJC/wAo91nyzehdehdVNOKx | ||
839 | ZXbbqfmup9i3zSb+EaffNtW0Fu8+0fxqS9aDVftuWn9y9iX7nsjrwtx1/unLvfNKb/Nz5YbjlW2O | ||
840 | aImfhvnri/lj+XzY7Wb55ZmI32dVbce+Ij+Lodrw7YVarbuGzsikrQ7gqVKS5ZKZ8vDCwQDJMRET | ||
841 | 8ydmHOc/ipnZbvnm66XXeiOwmKX3bo5fy2+l65YaEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ | ||
842 | EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBpPBBYgkgnjGaCUXCWKRmIDAmwQkL9HZ29WdJh | ||
843 | YmmMIj1uukKsUlWEyp5+0Ioxd4cjwft5b5Pl6dPZWZrNdssxFIpsV6njvj9OCzXqaypXr3Mtbhig | ||
844 | jAJmJnZ+4IizHlnduqkzWKbFjCa7Vn7Cj3Hk+3i7jxdhz4Dnst17ecfR1+n0Sca1258SMKU2ZcPK | ||
845 | jiTeDaGzvW2VunVs14qcFOpRlrRmEPYkkMTj5ZYeknFmYWxhatvmKztma1SYikRsivfTzUdXY6TS | ||
846 | 7PtftKhWvdh+UH3MMcvAviHNi4v09lImk1jNdlNjYtRqT2AbI6UBbGMHijuvEDzCD5yDSY5sPX0y | ||
847 | pGFeOfEmMuGSGt4147VjmiraqnBFYMZbAR14gGSSMuQGbCLMRCTZZ39HVrOHDImMZnesTazWzvYe | ||
848 | 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 | ||
1072 | uuiminiqwxzwRfbwyjGLGEOWftCTNlgyLfK3TorWceKUwpuWFFEBAQEBAQEBAQEBAQEBAQEBAQEB | ||
1073 | AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB | ||
1074 | AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB | ||
1075 | AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB | ||
1076 | AQEBAQEBAQEBAQEBAQEBAQEBBX2Owqa6hYv3JGiqVYymnlfL8QBuRPhuvoykysRWXJi8qleGeezp | ||
1077 | b9KvFAdkJrL1AjMI25O3NrBDE7t1/puH44w61dFM/L0Jb7UxTb5dPcvyb/SQ2KtWxfrV7lwRKrUl | ||
1078 | miGWTl6cA5ZP/q5V5ZrMRsZi7CJ2Ss3b1KjWO1dsR1asTZlnmMY4xb0yRE7MyzVuIVD8l8cCpFcP | ||
1079 | a0xqTAUkNh7ETRmEbsJkJ8uLiLkzO7emVeWa02+vJImsVhuO+0ZSyQjsapSwjJJLG00bkAQlwlIm | ||
1080 | zlmAvlJ39H9VNldh6f2oYvJtNZjqy0LUF+vbsfahPWnrnG0nAjxl5B5PgfpDkX4Yy7XlmtOFexKx | ||
1081 | SZ3fsVdz5jqaNK1NVnr37FKevBbqRThziexOEGZGHm4ceecO3XCWxWbd100qs4V3xbM9kVdGpu9L | ||
1082 | cqzW6d+tZq13IZ7EM0ZxxuDZJjMXcR4t65UnCKzkRjNNqKLybxuamN2La05KZG8Q2QsRFE8gi5uD | ||
1083 | GxceTCLu7Z9FZiYzIxyW6GwobCqFuhZit1ZM9uxAYyxlh8PgwdxfDpMTGaRMS1/ams7Pf+7h7Pd+ | ||
1084 | 37vcDj3ufa7XLOOfc+Tj68unqkRlxWcK8EIeQaE7wUA2VUr0jmIVGnjeUiid2kZo+XJ3Bxdi6dEi | ||
1085 | K5E4Zsx77Ry7I9XFsap7OPLyURmjecWZsvmJn5t/AkRWKxkTNJpKz93U78lfvR9+IGllh5NzGMnd | ||
1086 | hMhzlhdxfD/g6lcK7Fp3qNjyjxqtFHNY21KGKUI5YpJLEQiUcue2Yu5MzifF+L+/sryzWm1K4V2K | ||
1087 | 5+ZeOx+Sf2dluxRbJ4opowkliHuPMRCMYM58yk+Xlx4+js/ults3Vps/b3bUumLaV+99nnrh0Sth | ||
1088 | 5F4+c9qANnUKeiJSXomnjc4AD6ilHlkGH3clNldi0xptbRb3STEIxbCtIRzPWARmjJ3nYO48TYfq | ||
1089 | fD5uPrjqryz5cM+xKx5u/Lt2LyiiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC | ||
1090 | AgICAgICAgICAgICAgICAgICAgICAgICAgp7mOrLqrcVuqV2rJEQT1AHmUgE2CFhy2css3RE5tWz | ||
1091 | MTg+eXK20OltaOgfb2dGeovR2KmzgsM4WHiYa0dV7cYWpCL5mdmchxj3wt31m2ebhTfWuOWym80a | ||
1092 | RfZTD2sd1P20yRj47dkl2ut21jcwR7Y4jgjoVa8sM0X28YAJWDqzFXkiKNx/pJQZuhMu3NHNhnbf | ||
1093 | M/zTdE8cKccKbnCyJi2K5TZEfy0mKdNZ3Y76vTeeUNjMekt15LYVKFspbhUYorFkGKE4wlCGWKw0 | ||
1094 | nAi6sMblh8t6LjZNL6z8Mx11j0RMfZV0mPYpG+OyK+mk9W+jl6XQDF5XqdhCOwuV5v2lamubGuEJ | ||
1095 | DNMFUGfthDX7PPtlhijEnfk/XOVu2aVjCPY/119KXYxX5o7rbo9XcgtaHbSeKbMK9eeGZ/IJr08c | ||
1096 | McbWJqwXnk5RjOJBI/BmIGIXYsYWbJpGnXZGPD3vTMTv2w3fFZviNsW0/DZWOvGN2/ahtaGzat09 | ||
1097 | jrrG2uWrV+EZ7mwqjV7XZqWwCTshXqGzCUosUhhh/lZn6KXRNKRSK239s2xHoS2YznGnL2RfbPrT | ||
1098 | WKr2f3f1NGGnsjsNf+z4bcB1ZOLOFqDv8JHHhMJcCMijcmx1LC63XROrbfHu80dUbursYtibbLrZ | ||
1099 | xu5buueWcevtxZ8u0e5s7ndHRhsDWcNLPI9eMHKYa1icpxhaYThkkAGAuLs+cM2OrLnpzSImf7l0 | ||
1100 | 9tkRE/i82GMNXxXCPgp/NWnXFY68cGv7CazttZtIS2uzebaVSuTbKoFZhGtWtMJ9ka1Qm4vILPIY | ||
1101 | Yf5WYui3ZPLdGUR7c9c2xHoScbZ30tj+eJ9b0/ilWzX2Xk3dhOGGbaPLWchcRMCqV+RhlvmZ5GLq | ||
1102 | 3vlYj+nbH7357lu9+Z4W+Z5axFsIta2kbXXZLgeSRXDkCvK8DVj2jWWmabHbIe2/zMLuQ/rMzM7r | ||
1103 | WjnZPw2zE9PJdHl6zWyv+aIp/KmfT3h0U3CjKNovKht9IiaR4f2oLvN0bPDs5fl6cfwU0p/p12W3 | ||
1104 | flv+w1cfqcYtp1RZ6YWNBFfp+Rw0deNqxqHs2rFuDY0DhemUvcNzr3XGMJecp8eLOZcS+rDJpzW3 | ||
1105 | HZbERv2YTHR5jU97DObsd3T5b9i9tTsa7yzYWypWrMOx1kNeo9WCSZnngknIozIGcYstMOCkcR/F | ||
1106 | cborp327Zx/lp5bdzrbPtWTsivnhyPDtJcjep95QkBx8UoUyeaImxKzy92H5m6G2W5B6+mV38XNY | ||
1107 | 1qbbsOOEuXh8J067Ju89rXxqttqRatrNe3BPe8ao0IrH280nZuQ9xyGdwEuy491nzJhvXqr4mOad | ||
1108 | WLc7prHZdtTRpbGnMxhbN1eubaeZyg8ctTeKfZznu5dvqdZbiDWyVII6wTSU5ICGOeKrF9wJkXys | ||
1109 | ExkT8XJvVTWuia3W7cONKxNKcKbqbmtCJi62Lpyuiftr1znNccX0FhpVKugrzaqSwbFHHWKOuJjT | ||
1110 | kaAv6U3fHZHDOHJvd8e6upNdWafNj6OvvcdOKaVtY+HDjv6ncXJ2EBAQEBAQEBAQEBAQEBAQEBAQ | ||
1111 | EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ | ||
1112 | EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ | ||
1113 | EBAQEBAQEBAQEBAQEHLk8m00E1kLdqGpHWk7Tzzz1xApBi70gt/SOQlGHzExiL46+nVemPCakxE2 | ||
1114 | xN1caRE76Rs2zlSu7NOaK08q506aY9DleSfvH8X02toXG2VGd9sbR6lztwxQTZ9ZO+7kLRB+sbM/ | ||
1115 | szM5OzP6fC/4rX1b7reW6OT3vZmZjhTfOyMOyJlJvti3mrh5R+3dDqavyGhasNrbFyiO/jj7lzVV | ||
1116 | bY2Dib44cYZXH/KKMV5tbwt1sc8Rf9KuF020r5475SLt9Kyjv+SjDLLX1+vt7m1XdhsQ0WhZo3fr | ||
1117 | xKWzLWg5Y6uDScmbDu2HZXS8LzRE33W6ds5TdXHqti67rpTi1M7NqTXeS6u5rJ9hIb0YqZnFfC5x | ||
1118 | hKvJHhzGbLuLYZ2fkxOLs7Ozuz5U1fC323xbHtc3u8uPNXd5Vrglt1ZmNseqvmxUtf51othsrMVS | ||
1119 | 3Wm1VaKs/wC1wsRlAdi0ZiFcCbIkXEGf6v1mbC7av+O1dOyJui6L5m72eWa0tiK3eW6U+pbWkT5V | ||
1120 | pHbNfKXVrbzSWoJJ6uwrTwQxtNLLFNGYBEXLEhELuzC/Aur9Oj/Bea/w+pbNLrbomZplOe7vatmJ | ||
1121 | mkZ+UeeJjqRX/J/G9f8Ab/tDbU6f3bcqnfsRRd0cZzHzJubY69FrT8JraleSy67lzpEzTp3HNFIn | ||
1122 | ZLNnyTx2raq1LO0pwWrzM9KvLPEEkzF6doCJiPPtxSzwmrdbN1tl0xbnNJw6dyTfFK1wlavX6NCr | ||
1123 | JbvWIqlSJuUticxjjBvTJGTsLfpXLT07r7ottibrp2RjLTz837y/Bo9rrNY26pSz7cCkpnHZgeMh | ||
1124 | EmAfm7nV5DfjGw5cnZ8ejr3W/wCJ8TNl9/JdTTz9mfVsjGd2G9idS2IrXb6+7CnS7MO+0c2zl1MO | ||
1125 | xqybSEec1AJoysAP84omfmzfi7LyT4bUiyNSbbuSfvUmnbk1MxE02tR8i8fLvcdnUf7cClsYnjft | ||
1126 | xgbxkZ/N8oiYuLu/u2FZ8Lq4ezdjhGE4zn5iJiZptx7s+zam1m11e1phd1lyC/Tky0dmtIE0RYfD | ||
1127 | 4MHIXx+azraN+ndy32zbdumKT3kXROSCv5J47YvDr6+0qTXzEyCpHPEUxDEThI7RsTk7AQuxdOjr | ||
1128 | V3hdW23nmy6Ld9JpjljxTmjf5Rn2NJ/KvGILVmnPt6UVulEVi5WOxEMsMItkpJAcuQAzepO2FbfB | ||
1129 | 611sXRZdNt00ieWaTO6N8rXGm1F4n5dofKtRHtdLajs1j6GInGZxljLBKMZHwPi7PxLq2erLfjfA | ||
1130 | 6vhtTk1ImJ68eiufSlt8TM02eXfsdleRoQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB | ||
1131 | AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBFan+3qzT8Dk7IFJ24xczLi2eIiOXJ39mZat | ||
1132 | trMRvW2KzR838b1OyqTFuttrZ5bGo1819oe2chy7TaGVu0MI8cmUIBHCDj8XFff8XrWXR9PTuil9 | ||
1133 | 8W50pZZ7Ntd3NMzdNd1XKyOe6K1iJ9qa024Wx02WxTrjNBDoPKaWrmanWkbZaXSTHVMBwMu32plP | ||
1134 | bOFiwJFDw+Tr+u4rd3idG++OafY1NWInhp6eFtenb+7Vi3mwmI9r2r6TlzXV5ba8PaicsJhcvRSS | ||
1135 | a+nsPHtXZgpeK0btug1qvLVnnulWOGOFoZxCZ2wZFIRjgi445dccbJiL7rdW+2bta622aTF0RbzR | ||
1136 | MzW2sboiInCK5N6WnF02W44XVmvRMdczWsz34uZsfHZ9nrrcTePF5NrJGp/sO8E1KWNqZjG9qWJr | ||
1137 | U8TjcMzmMpMNy+X5+mF6dLxMad8T9T6N/tc8UviebHlieW2fYiOWKbMfZc4mbrMMa2/zTWs9ONY6 | ||
1138 | NjrnVuU/JNdY22usnTtPa2RVqteS1GGw/oYakczwtIAPDVB2Yydo+eXYugryxfbdo3RZdbzW8ttZ | ||
1139 | mLfY9qbpitJnmunL3uXCmazE1jClszjw5Yti2MNk43TnETEdKDx7R3tns9XZ2eskrxW7FryXYxzx | ||
1140 | ODDZPFbXV5WduLyw1vmMc5EwZ/gt+J8Rbp2X22XRM2226VtJ2e9qXRwm7LfF0rMc05e9d/LZEREf | ||
1141 | xTS7qnrgMdnsau41J6u8F/yTdyVdrMdaYa8OujftMTTmwgQS0a2BKNyZjPD4d1uOSybL+e3l0tLm | ||
1142 | txis3zjlnWL7ttPZtwa1Jmt9K1wtjoyrE8Jm67fVCZybDXT+P29faDdeSbSSttzsVJQiHXwzGbhH | ||
1143 | KYiEkTUou2DxETMRZfBF11ERp3xq23W/T0tOLraXRXnmIzjOJ55rPNTCN0MXYRdFMZ9iP3Zwik/u | ||
1144 | 1vp8VXS0tbZ2vKLU2qK4Gm2sp2N1X2uuevJUnjgCOAqk08YNK4nGHFuMoMzP8zdM8Ne6y3RiL+X6 | ||
1145 | lkUsmy+vNE3TM80RM0wmfhnhu1OF3s8ImNnLEUw7sOMzgz5VrtjAVGqG33d7eUZSv6q6etht1zlO | ||
1146 | I4WryvVrV64YZ3dikIHbl9fweD1bLua7k0rdO6OW6OebZpWJ5o5r7rp6ubL3WrrcKTM5+bhEce7Y | ||
1147 | rRl5Sz+VTvr5a/lUerhg17Vq8rVDJoe/PLWmIewRnbsm3B5Ob8Gd/itzGhTSjmidGdSZurMc2fLE | ||
1148 | XR71OS2MaU9qaMW3X1iZiJvizDdzcZ6rYx3YJdhFNLR193xvU2o6vjdaxJrRsVp6089+xCVWKPsz | ||
1149 | AE/Bu6Uk0hjh3w+S+Z2zpzEXXW619vNqzbF1LouiLInmmaxPLsiLYid8YYVWxFLcJnlnmnfNInDH | ||
1150 | Obq5168Ue68bm1JeLaaGbY0tDrq8hHe1NQL0h7IXjGM7ERVrv1MUp9x4/r6uTPha8P4qNX6upMWX | ||
1151 | al0xhfdyxyY15Z5rPlilctiTbdFsRONZrdO2vRumazlnFuTqQnc8f1m/ra2rtdluZYf2l9/chhYZ | ||
1152 | 7llvt4ohKqEUfIOyDyMEeBHqT5dea6Lde/Tm+dOzTry0tmcLY9qZ9qZnbNKzjOEOlkRZdN01ur7U | ||
1153 | /wAMRFNmMxGEdrlbrxnba6pU1vjtMyk8Z01mxSstHh5tnZjetGQSEzAcvDvGbZ+ohz6r06Hi9PUu | ||
1154 | uv1Zw1tS2JjdZE804ZxHuxHCJoxFl0W2x712N08bojCv7113c5uy8ad/EgnoXPIdjDSb7aCtaoRV | ||
1155 | pIBuO1S3OEMNGrdmkjrzSHluXJ+vzEvTpeK/36XW6Nk3YzMXzdE8vtW21nUusiJuiI2U4QzbbPLW | ||
1156 | JnmtrdH71JiJxzzrtq+s0Pt/sa/2wFFW7QdmMwKIhDi3EXjNhMHZv1SZnZfmNSvNPNjNenv2uunE | ||
1157 | RbERknWGxAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE | ||
1158 | BAQEBAQEBAQEBAQEFbZavWbSlJQ2dSG9Rm496rZjCaI+JMY8gNiF8ELO2W9V00ta/Tui6yZtujbE | ||
1159 | 0nthJiubhf3Yfu1/5S03/D6v+jXt/WPGf3tX8d3rZ+nbug/uw/dr/wApab/h9X/Rp+seM/vav47v | ||
1160 | WfTt3Qf3Yfu1/wCUtN/w+r/o0/WPGf3tX8d3rPp27oP7sP3a/wDKWm/4fV/0afrHjP72r+O71n07 | ||
1161 | d0H92H7tf+UtN/w+r/o0/WPGf3tX8d3rPp27oP7sP3a/8pab/h9X/Rp+seM/vav47vWfTt3QP+6/ | ||
1162 | 92js7P4npsP06a+q38kafrHjP72r+O71n07d0Iav7pf3X1gIY/FNUTE+X7tSGZ8/g8gm7Ld/+b8b | ||
1163 | dnran4pjzH0rdyb+7D92v/KWm/4fV/0ax+seM/vav47vWfTt3Qf3Yfu1/wCUtN/w+r/o0/WPGf3t | ||
1164 | X8d3rPp27oP7sP3a/wDKWm/4fV/0afrHjP72r+O71n07d0H92H7tf+UtN/w+r/o0/WPGf3tX8d3r | ||
1165 | Pp27oP7sP3a/8pab/h9X/Rp+seM/vav47vWfTt3Qf3Yfu1/5S03/AA+r/o0/WPGf3tX8d3rPp27o | ||
1166 | P7sP3a/8pab/AIfV/wBGn6x4z+9q/ju9Z9O3dB/dh+7X/lLTf8Pq/wCjT9Y8Z/e1fx3es+nbuhf0 | ||
1167 | /h3iGlsla02j1+stGDxHPTqwwSPG7sTg5RiLuLuLPj8Fx1/H6+tHLqal98Z0uumfPKxbEZQ668jQ | ||
1168 | gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA | ||
1169 | gICAgICAgqjttUQAY3IHCScqoE0oOxWAJxKFnz1kEgJnH1yzrp9G/wCGcq5bN/RxJmnV5emGo7rT | ||
1170 | FLahG/XKWgPO9G0oOUAdfmlbOQb5C6l8HVnQ1KRPLNLssM+jeRjNNvl647QtzqAsVq5Xq42Lrcqc | ||
1171 | LygxzNxcsxDnJtxF3+X2SNDUmJnlmlueGXTuZ5opE1z8vTHa3baax2y1uF2ab7V37gf1+cdn1/rM | ||
1172 | 9OPqp9G/dOVctm/o4rMxHV6cvPHaj2m70uoiCba7Ctr4pTaOOS1NHCJG/oIvI4s7/gtaPh9TVmll | ||
1173 | t10xuiZ8xM0is5OZqPNtNd17Xrdivr4ZpZ2pd+xGLzV4p/twsDy4/LKXFx9fqHr1Xo1vAall3LbE | ||
1174 | 3TERWkThM283L0x6JZ+pGOOEV/l97snDv2uuO01hRRTDcgeKeV4IJGkBxOVncXjB84I+QE3FuvR1 | ||
1175 | 5fo31mKTWIrls39DXNHZ66efDpVv7TeN/tMtV+1af7UF2EqH3EX3DOX0s8XLnl/boun/ANTW5Ofk | ||
1176 | u5PipNO3Im6IwlvV8g0NvYz6yrsqtjZVmzZpRTxnPG2cfPGJOY9fiyl/htW2yL7rbosnKaTSeiSb | ||
1177 | oiabTa7/AEWoaJ9tsquvacuED25o4GMv5odwh5P19GU0fDaurX6dt11M6RM+YmYiKzk52p898T2u | ||
1178 | 62Wmo7KvLf1T4sxDNC7vgWKRwFjc3GLkwmXHDF09WdejW/xuvpadupdbMW35YT1bKY7N8YpzRzcu | ||
1179 | 39uHTgvVPJfHLlGe/U2tOzRqu42bcViI4onH6mkkEnEXb3y643+E1bLotusui67KJiaz0Qc8Y45Z | ||
1180 | 8GtryvxepUe5a3FGvUaV672JbMIRtML4KLmRMPNvcfVWzwetddy22XTdStItmtN/RxXmjHgvT3ad | ||
1181 | eodyxPHDUAe4diQxGMQxnk5u7CzfiuNundddyxEzdu2nNFK7EFHd6XYPZahfrW3pn27jQTRydk2b | ||
1182 | PGTg78Hx7Et6nh9SynNbdbzZViYr0byJrNNrjbb95Xg+t057c9zTsUgsBU517MBs88hMLR8ubAxC | ||
1183 | z8iyXQWd36MvXo/4nxOpqRpxZdF1K42zlvy6uM4JN0Umfh8qdM7HoadypdqxW6c8dmpODSQWISGS | ||
1184 | MwJsiQGLuJM7ejsvDqad1l023RMXRnE5rExOSVYUQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA | ||
1185 | QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQfH6+m8obU6vZx6yb7+LdWS1tKYH | ||
1186 | /ovvJ7MklywOP6MXOQer9Wjbp1NxX6m7X0ee6yb45Z0reaY28ttkRbbvnCf4uFtXGYml9fapfWOP | ||
1187 | t4dXLSInZ7U5UWLvht4bfkuvgqWD1oamAZrZA7lfsRjZn7YiLZkeSxZeSbDYd8D15Ozc9Px1vLpX | ||
1188 | zMc/1JpHwR7FteFLbaW9uyG9O2fqxWaxMRX8V3N2+zHC3D4Up6DyOSz4xsGpShubk5STTOLOOurx | ||
1189 | 0Za9cZXfLM8QWDPh15Sk7fT1aR4jSiNWzmj6dsfjmb7brqdPLEV2WRE5uFsXcls7ptinCLbs8vvU | ||
1190 | uu/DnEJ/HdbY081izZ1V2XXanaTwaanFC8k8012ftFedicfkCKT+tJ/R5SfPR35+J1Y1YiIvti+/ | ||
1191 | TibpmaREWxXk6ZmPdjdZDrdbSbt0Uu/enljt9c7OVJtru4jt+VlHrLtjyC0ceu0krVJTrxU5o444 | ||
1192 | 5Rn49ngM8hyzMxcunVsCymjp6c26VbrY0ordf7UVm6JmZimdeWIttwpunFZvm2+bqV5Y9njhXqmb | ||
1193 | sJ4RGaSppb2po+SbTV6wyt6jXjp/F6xA7SFBRruTPExMz/01g3bp9TAP4LOpr26t2nZfd7Opfz6k | ||
1194 | 8brtvRbHVWTR04tuiJxiyIjpnOZ68LZrtiXLvQ7UtRTq+Pa++NbxfTST66xYqywyzX5onqxFHFMw | ||
1195 | SFLFH3yISFnciH4r02XWfUuu1brK62rEXRF0TEWRPNNZjCkzyxExOUTuYtm7kikVuxumuFbojCJ/ | ||
1196 | eumu7DDhbafU2NjSipa/YBo/GKJTNwpWBuPav5rBIEJg1h5I4e8cmY+T8mLr78uW+2y6brrPqa11 | ||
1197 | Pet5eW32piZieWkzyxGNMKYLb92Ixp7c14ViK76zMz0wueF6HyAtTJrm2dqpqqIQQ6Da/YwU9l2W | ||
1198 | H+mjlhtwSiwZEG5FABE7P09Hfl4/xOl9Tn5Lbr7qzfbzzdZXZMTbdHH70xHcacTGEe7TbnWs16cN | ||
1199 | vGVeWvty8s7+pkv3LBtX12+rbfXca01OsUnOeK00deHlIxk7DE5C5O2QFs43F1n0KXxZbGN1k2X+ | ||
1200 | 1F00pE21unCmd1JpHvTtt0TExSfaikcKVxyymk9dIzVKB2S8V0Ut/W7D7Wzs5bnllT7G0c7TSDJY | ||
1201 | GJ4Gi7s0AWCjDlGBC4i36uV11LbY174tusrbpxbpzz20pFLa1rS26beaaTMTWd7M1mLsM7sf3dlN | ||
1202 | +EW2zStba5rl/QX9zvClsa+SGhv7lQLcJg7M2t1InOD2GZnESs2DYOBde30fqzi3LS8TbpadIuib | ||
1203 | tK26Y/f1KW+z+7bjWPvZbJm3xWsxti2zqrN108ImK2+qrWfVbS75lugtXt1rJZXCrrI6FKrNTPXj | ||
1204 | CD9LVmnZiiIpSk5g8oO+G+V8MrbrWWeHspbpXxndzXXRdz1n7tt9szhSk8s9OazMxfXKlOWnf0TX | ||
1205 | DZhEL1imO00ui8aqay7Bpo7rVbn30Tg70tS7uJH65CzLDGI8scwd3xhcbdT6epqa111s6nLzRyz9 | ||
1206 | 7U9NsTNae7MJFnJp/Ttrst6ts9FIm2u+cN7h+R6va2rdzYyQX6WrvbWOpckoVO/bHXayCRq7/anD | ||
1207 | ZeSOS65F0hLIOPTj1Xr8JrWW222RNl19unN0c11Lee+Yr7XNbSYs+aPartNW2azSPht/hxumY655 | ||
1208 | ZjGsRK4OkOr5ho7lqTb7OveN7E+wtVQd2mqRvDRhlio1oBhD/wAZLJzmAcODcnbouf8A9jm0NS22 | ||
1209 | NOybYpFsXbLprfMTfdPNPsWxS2ZwnDazdbldjNZiJw2W1ujClfemOzc+mL889AgICAgICAgICAgI | ||
1210 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgrbLV6 | ||
1211 | zaUpKGzqQ3qM3HvVbMYTRHxJjHkBsQvghZ2y3qumlrX6d0XWTNt0bYmk9sJMVzcL+7D92v8Aylpv | ||
1212 | +H1f9Gvb+seM/vav47vWz9O3dB/dh+7X/lLTf8Pq/wCjT9Y8Z/e1fx3es+nbug/uw/dr/wApab/h | ||
1213 | 9X/Rp+seM/vav47vWfTt3Qf3Yfu1/wCUtN/w+r/o0/WPGf3tX8d3rPp27oP7sP3a/wDKWm/4fV/0 | ||
1214 | afrHjP72r+O71n07d0H92H7tf+UtN/w+r/o0/WPGf3tX8d3rPp27oR2P3UfuxsRPFJ4pqRF/V46U | ||
1215 | ERdP8qMBL+Nat/zXjLZrGtqfiun0n07d0Nov3WfuzijGMfE9O4i2Gc6NYy/SRA5P+l1J/wAz4yZr | ||
1216 | 9bU/Hd6yNO3c2/uw/dr/AMpab/h9X/RqfrHjP72r+O71n07d0H92H7tf+UtN/wAPq/6NP1jxn97V | ||
1217 | /Hd6z6du6D+7D92v/KWm/wCH1f8ARp+seM/vav47vWfTt3Qf3Yfu1/5S03/D6v8Ao0/WPGf3tX8d | ||
1218 | 3rPp27oP7sP3a/8AKWm/4fV/0afrHjP72r+O71n07d0H92H7tf8AlLTf8Pq/6NP1jxn97V/Hd6z6 | ||
1219 | du6D+7D92v8Aylpv+H1f9Gn6x4z+9q/ju9Z9O3dCWr+7r931SzDaq+MamvarmMsE8VGsEkcgPyEw | ||
1220 | IQZxIXbLOyzf/lfFXRNt2rqTE4TE33Y968lu56FeBoQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE | ||
1221 | BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE | ||
1222 | BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE | ||
1223 | BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE | ||
1224 | BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE | ||
1225 | BAQEBAQEHwOx5Z5NPMcpbS0Lm7u4xzGAtn2YRdmZl+ijw+nEU5YfBnXvmc5R/wBpvJP/AHa5/wCo | ||
1226 | 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 | ||
1268 | 7M5dwc/wL6cf5KaY29750/4+K4Sj/ub/AN7/AOz/AOtV/Uvl7/sT9P8Am7vtP7m/97/7P/rU/Uvl | ||
1269 | 7/sP0/5u77T+5v8A3v8A7P8A61P1L5e/7D9P+bu+0/ub/wB7/wCz/wCtT9S+Xv8AsP0/5u77T+5v | ||
1270 | /e/+z/61P1L5e/7D9P8Am7vtP7m/97/7P/rU/Uvl7/sP0/5u77T+5v8A3v8A7P8A61P1L5e/7D9P | ||
1271 | +bu+0/ub/wB7/wCz/wCtT9S+Xv8AsP0/5u77T+5v/e/+z/61P1L5e/7D9P8Am7vtP7m/97/7P/rU | ||
1272 | /Uvl7/sP0/5u77T+5v8A3v8A7P8A61P1L5e/7D9P+bu+0/ub/wB7/wCz/wCtT9S+Xv8AsP0/5u77 | ||
1273 | T+5v/e/+z/61P1L5e/7D9P8Am7vtP7m/97/7P/rU/Uvl7/sP0/5u77T+5v8A3v8A7P8A61P1L5e/ | ||
1274 | 7D9P+bu+0/ub/wB7/wCz/wCtT9S+Xv8AsP0/5u77T+5v/e/+z/61P1L5e/7D9P8Am7vtdbxj928O | ||
1275 | k2obE7z2pIhJogaPtszmLi7v8x5+V3XHX8bOpby0o7aPg4surWr2a8L2CAgICAgICAgICAgICAgI | ||
1276 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI | ||
1277 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI | ||
1278 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI | ||
1279 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI | ||
1280 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI | ||
1281 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI | ||
1282 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI | ||
1283 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI | ||
1284 | CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI | ||
1285 | CAg81e2k4bO1Bc2MmpjEhGiXaB4ZGcWdzOWQDbPJ8cWIVLcemq3YTwWp/IJ42tzQ1WsUte/C3Y7n | ||
1286 | A3cWYpHij4kxcGfrkm/BWu2cImfs86RGzOaObb2F79sSDBMZB+0K4RxvIQg4lTc+D4zgSLq/T8VL | ||
1287 | axH/AJO6PQzM17LfzJaHk9uHSUbGxaD7i5gYJDnaICwzuRyu8YjGzM36vLK3dnEcPRDUbZ4+mU1b | ||
1288 | yyW5NDWp1Yp7EhzAZDYZ4WeFgLIyiBchIZG/Vz+CzGPZXvokzTy4OrrNi9/XDaGLhI/MShd84kjJ | ||
1289 | wIeXTLch9VLpwrG6rUZ0nZLj6baTWZoQtbSSHYvkrGrlhjib0fIxcgE34+vLmSXTERMxjgzPHDFF | ||
1290 | B5pG1ODrCU/24zzfd2Y4CflniIYjZjN+P80W9Fq7Du81ViPPPno7w3pbGthu0YwkaYBlAZzeJmAm | ||
1291 | 5dSEJerN+Cl8csls1UNV5FPdsV4pagwjaGY4ZQleQSCFxFjbIRvg+XT8PzVjHsie1JmnbRQs+TMN | ||
1292 | 3W2jY44j+9h+1AnJ5ZIpBijZm+VnIn9PhlZsmteNsU65W7CZj4bvRLo/tC5PalrSMdOavUaxIMRx | ||
1293 | yNyl5Mw5OJ+ocOjt0+LOpdNIun4f2/YtsVutjf8AsQQ+SXZghatSGUyox3jeSbhhj5Nw6Rvkvl+D | ||
1294 | N+S1dNOadlv7WbMaRtmvc5m122ztzy2qeQrQ6wb1dvuJInZz5FzMABxkceGOBPx/hUuw5uExC2zW | ||
1295 | kb6+h0ZfILNIaUuxHg0leaYxgNjEu2MbjnlEBcic8MzOzN+Ptu6PauiNn/qozZNYifLKq7T2189m | ||
1296 | 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 | ||
1366 | t3AM6tgZxaOHtg7CBDjDmZZfn1fl7eiRhNenvJisU8s6oz1uxr2DelNhrt0bFmTiP9HCMbCQMxcu | ||
1367 | Tk8bNlm91LcKRsx/Z39y3Y1nbSI+1Z22pi2TVRldu1XmaY4yHkxswEDg/VvXmpTGvCe82eW9zj8U | ||
1368 | kOAK5XnKKGGzWr8o8kMVgREWIuXzdvj+lJxrXOYjumpGE4ZVqtUtLZpSm1W2wVZnE54ii5F3GFhI | ||
1369 | oz5YFj4tlnEvwVv9qvGvekRSI6PMpQeGQQ1RrDYdopIPt7zCDD3uOXjkbr8hg/v16dFZn0dsUxX7 | ||
1370 | eydi3Y02yt0nq3L4yNmJxIIOGe3IMmTyZZJ+GPl4t19Eifaid01SYwpwXIdf29pZv9zP3McUfbxj | ||
1371 | j2nN85z1zz+CkYV6fQt2Mxwj0q2x1ezuR2Kz3gGlZZxMHg5SiBNghCTmw/k7g6lK5rWmSu/i7BaK | ||
1372 | 3Vs9mwMkclYnDmwMELQEBtybmxC3xZ1qs9899PUzEYU4R3V9br1orQRO1mZppSd3cgDtg34COSfH | ||
1373 | 5k6zdFYosOTrvHLFcKMNm4M9bXZKvGEXbdzcXFiMnM88WJ8MzMrdj00okx56+lnW+OT6+WqcFsS7 | ||
1374 | Ncathjid+4Am5s44NuBfM/ryVnGsbJp3RQp5575aweN2oKtWKO6LSa83KhN2eogTOxBK3PEjOL46 | ||
1375 | cUrOE7aU83qXf01dMfvYKkhzO92x1fhCIRZ9uICZ4b/rH+lZvisUIeaqUNhXq6aD9mXS/ZBEXL/w | ||
1376 | TdzlGcfp92/H68+6t/tT/Dy+b1GyY33V75lX1ms3mqCL9nU7YSdgILXdjpyBJ2nfgYi10HAmYnb6 | ||
1377 | nb8FZmvd5oj0H2981drRRXYtlemnp2o2vPGZSz/aswvFEMfXszSO7lxz0BmSMLacZntSmNeHr9bu | ||
1378 | qKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC | ||
1379 | AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC | ||
1380 | AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC | ||
1381 | D//Z | ||
1382 | ------=_NextPart_000_000F_01D15E52.0BD654A0-- | ||
1383 | |||
1384 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/data/html.mbox b/framework/src/domain/mime/mimetreeparser/tests/data/html.mbox new file mode 100644 index 00000000..bf5c685d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/data/html.mbox | |||
@@ -0,0 +1,15 @@ | |||
1 | From foo@example.com Thu, 26 May 2011 01:16:54 +0100 | ||
2 | From: Thomas McGuire <foo@example.com> | ||
3 | Subject: HTML test | ||
4 | Date: Thu, 26 May 2011 01:16:54 +0100 | ||
5 | Message-ID: <1501334.pROlBb7MZF@herrwackelpudding.localhost> | ||
6 | X-KMail-Transport: GMX | ||
7 | X-KMail-Fcc: 28 | ||
8 | X-KMail-Drafts: 7 | ||
9 | X-KMail-Templates: 9 | ||
10 | User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) | ||
11 | MIME-Version: 1.0 | ||
12 | Content-Transfer-Encoding: 7Bit | ||
13 | Content-Type: text/html; charset="windows-1252" | ||
14 | |||
15 | <html><body><p><span>HTML</span> text</p></body></html> \ No newline at end of file | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox b/framework/src/domain/mime/mimetreeparser/tests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox new file mode 100644 index 00000000..2d9726ea --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox | |||
@@ -0,0 +1,115 @@ | |||
1 | From test@kolab.org Fri May 01 15:12:47 2015 | ||
2 | From: testkey <test@kolab.org> | ||
3 | To: you@you.com | ||
4 | Subject: enc & non enc attachment | ||
5 | Date: Fri, 01 May 2015 17:12:47 +0200 | ||
6 | Message-ID: <13897561.XENKdJMSlR@tabin.local> | ||
7 | X-KMail-Identity: 1197256126 | ||
8 | User-Agent: KMail/4.13.0.1 (Linux/3.19.1-towo.1-siduction-amd64; KDE/4.14.2; x86_64; git-cd33034; 2015-04-11) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: multipart/mixed; boundary="nextPart1939768.sIoLGH0PD8" | ||
11 | Content-Transfer-Encoding: 7Bit | ||
12 | |||
13 | This is a multi-part message in MIME format. | ||
14 | |||
15 | --nextPart1939768.sIoLGH0PD8 | ||
16 | Content-Type: multipart/encrypted; boundary="nextPart2814166.CHKktCGlQ3"; protocol="application/pgp-encrypted" | ||
17 | |||
18 | |||
19 | --nextPart2814166.CHKktCGlQ3 | ||
20 | Content-Type: application/pgp-encrypted | ||
21 | Content-Disposition: attachment | ||
22 | Content-Transfer-Encoding: 7Bit | ||
23 | |||
24 | Version: 1 | ||
25 | --nextPart2814166.CHKktCGlQ3 | ||
26 | Content-Type: application/octet-stream | ||
27 | Content-Disposition: inline; filename="msg.asc" | ||
28 | Content-Transfer-Encoding: 7Bit | ||
29 | |||
30 | -----BEGIN PGP MESSAGE----- | ||
31 | Version: GnuPG v2 | ||
32 | |||
33 | hIwDGJlthTT7oq0BA/9cXFQ6mN9Vxnc2B9M10odS3/6z1tsIY9oJdsiOjpfxqapX | ||
34 | P7nOzR/jNWdFQanXoG1SjAcY2FeZEN0c3SkxEM6R5QVF1vMh/Xsni1clI+peZyVT | ||
35 | Z4OSU74YCfYLg+cgDnPCF3kyNPVe6Z1pnfWOCZNCG3rpApw6UVLN63ScWC6eQIUB | ||
36 | DAMMzkNap8zaOwEIANKHn1svvj+hBOIZYf8R+q2Bw7cd4xEChiJ7uQLnD98j0Fh1 | ||
37 | 85v7/8JbZx6rEDDenPp1mCciDodb0aCmi0XLuzJz2ANGTVflfq+ZA+v1pwLksWCs | ||
38 | 0YcHLEjOJzjr3KKmvu6wqnun5J2yV69K3OW3qTTGhNvcYZulqQ617pPa48+sFCgh | ||
39 | nM8TMAD0ElVEwmMtrS3AWoJz52Af+R3YzpAnX8NzV317/JG+b6e2ksl3tR7TWp1q | ||
40 | 2FOqC1sXAxuv+DIz4GgRfaK1+xYr2ckkg+H/3HJqa5LmJ7rGCyv+Epfp9u+OvdBG | ||
41 | PBvuCtO3tm0crmnttMw57Gy35BKutRf/8MpBj/nS6QFX0t7XOLeL4Me7/a2H20wz | ||
42 | HZsuRGDXMCh0lL0FYCBAwdbbYvvy0gz/5iaNvoADtaIu+VtbFNrTUN0SwuL+AIFS | ||
43 | +WIiaSbFt4Ng3t9YmqL6pqB7fjxI10S+PK0s7ABqe4pgbzUWWt1yzBcxfk8l/47Q | ||
44 | JrlvcE7HuDOhNOHfZIgUP2Dbeu+pVvHIJbmLsNWpl4s+nHhoxc9HrVhYG/MTZtQ3 | ||
45 | kkUWviegO6mwEZjQvgBxjWib7090sCxkO847b8A93mfQNHnuy2ZEEJ+9xyk7nIWs | ||
46 | 4RsiNR8pYc/SMvdocyAvQMH/qSvmn/IFJ+jHhtT8UJlXJ0bHvXTHjHMqBp6fP69z | ||
47 | Jh1ERadWQdMaTkzQ+asl+kl/x3p6RZP8MEVbZIl/3pcV+xiFCYcFu2TETKMtbW+b | ||
48 | NYOlrltFxFDvyu3WeNNp0g9k0nFpD/T1OXHRBRcbUDWE4QF6NWTm6NO9wy2UYHCi | ||
49 | 7QTSecBWgMaw7cUdwvnW6chIVoov1pm69BI9D0PoV76zCI7KzpiDsTFxdilKwbQf | ||
50 | K/PDnv9Adx3ERh0/F8llBHrj2UGsRs4aHSEBDBJIHDCp8+lqtsRcINQBKEU3qIjt | ||
51 | wf5vizdaVIgQnsD2z8QmBQ7QCCipI0ur6GKl+YWDDOSDLDUs9dK4A6xo/4Q0bsnI | ||
52 | rH63ti5HslGq6uArfFkewH2MWff/8Li3uGEqzpK5NhP5UpbArelK+QaQQP5SdsmW | ||
53 | XFwUqDS4QTCKNJXw/5SQMl8UE10l2Xaav3TkiOYTcBcvPNDovYgnMyRff/tTeFa8 | ||
54 | 83STkvpGtkULkCntp22fydv5rg6DZ7eJrYfC2oZXdM87hHhUALUO6Y/VtVmNdNYw | ||
55 | F3Uim4PDuLIKt+mFqRtFqnWm+5X/AslC31qLkjH+Fbb83TY+mC9gbIn7CZGJRCjn | ||
56 | zzzMX2h15V/VHzNUgx9V/h28T0/z25FxoozZiJxpmhOtqoxMHp+y6nXXfMoIAD1D | ||
57 | 963Pc7u1HS0ny54A7bqc6KKd4W9IF7HkXn3SoBwCyn0IOPoKQTDD8mW3lbBI6+h9 | ||
58 | vP+MAQpfD8s+3VZ9r7OKYCVmUv47ViTRlf428Co6WT7rTHjGM09tqz826fTOXA== | ||
59 | =6Eu9 | ||
60 | -----END PGP MESSAGE----- | ||
61 | |||
62 | --nextPart2814166.CHKktCGlQ3-- | ||
63 | |||
64 | --nextPart1939768.sIoLGH0PD8 | ||
65 | Content-Disposition: attachment; filename="image.png" | ||
66 | Content-Transfer-Encoding: base64 | ||
67 | Content-Type: image/png; name="image.png" | ||
68 | |||
69 | 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 | ||
112 | o/0d59+Lh3Y1HHcAAAAASUVORK5CYII= | ||
113 | |||
114 | --nextPart1939768.sIoLGH0PD8-- | ||
115 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/data/openpgp-inline-charset-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/tests/data/openpgp-inline-charset-encrypted.mbox new file mode 100644 index 00000000..8bd06910 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/data/openpgp-inline-charset-encrypted.mbox | |||
@@ -0,0 +1,40 @@ | |||
1 | From test@example.com Thu, 17 Oct 2013 02:13:03 +0200 | ||
2 | Return-Path: <test@example.com> | ||
3 | Delivered-To: you@you.com | ||
4 | Received: from localhost (localhost [127.0.0.1]) | ||
5 | by test@example.com (Postfix) with ESMTP id B30D8120030 | ||
6 | for <you@you.com>; Thu, 17 Oct 2013 02:13:05 +0200 (CEST) | ||
7 | From: test <test@example.com> | ||
8 | To: you@you.com | ||
9 | Subject: charset | ||
10 | Date: Thu, 17 Oct 2013 02:13:03 +0200 | ||
11 | Message-ID: <4081645.yGjUJ4o4Se@example.local> | ||
12 | User-Agent: KMail/4.12 pre (Linux/3.11-4.towo-siduction-amd64; KDE/4.11.2; x86_64; git-f7f14e3; 2013-10-15) | ||
13 | MIME-Version: 1.0 | ||
14 | Content-Transfer-Encoding: 7Bit | ||
15 | Content-Type: text/plain; charset="ISO-8859-15" | ||
16 | |||
17 | -----BEGIN PGP MESSAGE----- | ||
18 | Version: GnuPG v2.0.22 (GNU/Linux) | ||
19 | |||
20 | hIwDGJlthTT7oq0BBACbaRZudMigMTetPZNRgkfEXv4QQowR1jborw0dcgKKqMQ1 | ||
21 | 6o67NkpxvmXKGJTfTVCLBX3nk6FKYo6NwlPCyU7X9X0DDk8hvaBdR9wGfrdm5YWX | ||
22 | GKOzcqJY1EypiMsspXeZvjzEW7O8I956c3vBb/2pM3xqYEK1kh8+d9bVH+cjf4UB | ||
23 | DAMMzkNap8zaOwEH/1rPShyYL8meJN+/GGgS8+Nf1BW5pSHdAPCg0dnX4QCLEx7u | ||
24 | GkBU6N4JGYayaCBofibOLacQPhYZdnR5Xb/Pvrx03GrzyzyDp0WyeI9nGNfkani7 | ||
25 | sCRWbzlMPsEvGEvJVnMLNRSk4xhPIWumL4APkw+Mgi6mf+Br8z0RhfnGwyMA53Mr | ||
26 | pG9VQKlq3v7/aaN40pMjAsxiytcHS515jXrb3Ko4pWbTlAr/eytOEfkLRJgSOpQT | ||
27 | BY7lWs+UQJqiG8Yn65vS9LMDNJgX9EOGx77Z4u9wvv4ZieOxzgbHGg5kYCoae7ba | ||
28 | hxZeNjYKscH+E6epbOxM/wlTdr4UTiiW9dMsH0zSwMUB891gToeXq+LDGEPTKVSX | ||
29 | tsJm4HS/kISJBwrCI4EUqWZML6xQ427NkZGmF2z/sD3kmL66GjspIKnb4zHmXacp | ||
30 | 84n2KrI9s7p6AnKnQjsxvB/4/lpXPCIY5GH7KjySEJiMsHECzeN1dJSL6keykBsx | ||
31 | DtmYDA+dhZ6UWbwzx/78+mjNREhyp/UiSAmLzlJh89OH/xelAPvKcIosYwz4cY9N | ||
32 | wjralTmL+Y0aHKeZJOeqPLaXADcPFiZrCNPCH65Ey5GEtDpjLpEbjVbykPV9+YkK | ||
33 | 7JKW6bwMraOl5zmAoR77PWMo3IoYb9q4GuqDr1V2ZGlb7eMH1gj1nfgfVintKC1X | ||
34 | 3jFfy7aK6LIQDVKEwbi0SxVXTKStuliVUy5oX4woDOxmTEotJf1QlKZpn5oF20UP | ||
35 | tumYrp0SPoP8Bo4EVRVaLupduI5cYce1q/kFj9Iho/wk56MoG9PxMMfsH7oKg3AA | ||
36 | CqQ6/kM4oJNdN5xIf1EH5HeaNFkDy1jlLznnhwVAZKPo/9ffpg== | ||
37 | =bPqu | ||
38 | -----END PGP MESSAGE----- | ||
39 | |||
40 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/data/openpgp-inline-encrypted+nonenc.mbox b/framework/src/domain/mime/mimetreeparser/tests/data/openpgp-inline-encrypted+nonenc.mbox new file mode 100644 index 00000000..b98dc336 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/data/openpgp-inline-encrypted+nonenc.mbox | |||
@@ -0,0 +1,31 @@ | |||
1 | From test@kolab.org Wed, 25 May 2011 23:49:40 +0100 | ||
2 | From: OpenPGP Test <test@kolab.org> | ||
3 | To: test@kolab.org | ||
4 | Subject: inlinepgpencrypted + non enc text | ||
5 | Date: Wed, 25 May 2011 23:49:40 +0100 | ||
6 | Message-ID: <1786696.yKXrOjjflF@herrwackelpudding.localhost> | ||
7 | X-KMail-Transport: GMX | ||
8 | X-KMail-Fcc: 28 | ||
9 | X-KMail-Drafts: 7 | ||
10 | X-KMail-Templates: 9 | ||
11 | User-Agent: KMail/4.6 beta5 (Linux/2.6.34.7-0.7-desktop; KDE/4.6.41; x86_64; git-0269848; 2011-04-19) | ||
12 | MIME-Version: 1.0 | ||
13 | Content-Transfer-Encoding: 7Bit | ||
14 | Content-Type: text/plain; charset="us-ascii" | ||
15 | |||
16 | Not encrypted not signed :( | ||
17 | |||
18 | -----BEGIN PGP MESSAGE----- | ||
19 | Version: GnuPG v2.0.15 (GNU/Linux) | ||
20 | |||
21 | hQEMAwzOQ1qnzNo7AQf/a3aNTLpQBfcUr+4AKsZQLj4h6z7e7a5AaCW8AG0wrbxN | ||
22 | kBYB7E5jdZh45DX/99gvoZslthWryUCX2kKZ3LtIllxKVjqNuK5hSt+SAuKkwiMR | ||
23 | Xcbf1KFKENKupgGSO9B2NJRbjoExdJ+fC3mGXnO3dT7xJJAo3oLE8Nivu+Bj1peY | ||
24 | E1wCf+vcTwVHFrA7SV8eMRb9Z9wBXmU8Q8e9ekJ7ZsRX3tMeBs6jvscVvfMf6DYY | ||
25 | N14snZBZuGNKT9a3DPny7IC1S0lHcaam34ogWwMi3FxPGJt/Lg52kARlkF5TDhcP | ||
26 | N6H0EB/iqDRjOOUoEVm8um5XOSR1FpEiAdD0DON3y9JPATnrYq7sgYZz3BVImYY+ | ||
27 | N/jV8fEiN0a34pcOq8NQedMuOsJHNBS5MtbQH/kJLq0MXBpXekGlHo4MKw0trISc | ||
28 | Rw3pW6/BFfhPJLni29g9tw== | ||
29 | =fRFW | ||
30 | -----END PGP MESSAGE----- | ||
31 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/data/plaintext.mbox b/framework/src/domain/mime/mimetreeparser/tests/data/plaintext.mbox new file mode 100644 index 00000000..d185b1c1 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/data/plaintext.mbox | |||
@@ -0,0 +1,13 @@ | |||
1 | Return-Path: <konqi@example.org> | ||
2 | Date: Wed, 8 Jun 2016 20:34:44 -0700 | ||
3 | From: Konqi <konqi@example.org> | ||
4 | To: konqi@kde.org | ||
5 | Subject: A random subject with alternative contenttype | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: text/plain; charset=utf-8 | ||
8 | Content-Transfer-Encoding: quoted-printable | ||
9 | |||
10 | If you can see this text it means that your email client couldn't display o= | ||
11 | ur newsletter properly. | ||
12 | Please visit this link to view the newsletter on our website: http://www.go= | ||
13 | g.com/newsletter/ | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/data/smime-encrypted.mbox b/framework/src/domain/mime/mimetreeparser/tests/data/smime-encrypted.mbox new file mode 100644 index 00000000..6b6d6a0d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/data/smime-encrypted.mbox | |||
@@ -0,0 +1,22 @@ | |||
1 | From test@example.com Sat, 13 Apr 2013 01:54:30 +0200 | ||
2 | From: test <test@example.com> | ||
3 | To: you@you.com | ||
4 | Subject: test | ||
5 | Date: Sat, 13 Apr 2013 01:54:30 +0200 | ||
6 | Message-ID: <1576646.QQxzHWx8dA@tabin> | ||
7 | X-KMail-Identity: 505942601 | ||
8 | User-Agent: KMail/4.10.2 (Linux/3.9.0-rc4-experimental-amd64; KDE/4.10.60; x86_64; git-fc9b82c; 2013-04-11) | ||
9 | MIME-Version: 1.0 | ||
10 | Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type="enveloped-data" | ||
11 | Content-Transfer-Encoding: base64 | ||
12 | Content-Disposition: attachment; filename="smime.p7m" | ||
13 | |||
14 | MIAGCSqGSIb3DQEHA6CAMIACAQAxgfwwgfkCAQAwYjBVMQswCQYDVQQGEwJVUzENMAsGA1UECgwE | ||
15 | S0RBQjEWMBQGA1UEAwwNdW5pdHRlc3QgY2VydDEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxl | ||
16 | LmNvbQIJANNFIDoYY4XJMA0GCSqGSIb3DQEBAQUABIGAJwmmaOeidXUHSQGOf2OBIsPYafVqdORe | ||
17 | y54pEXbXiAfSVUWgI4a9CsiWwcDX8vlaX9ZLLr+L2VmOfr6Yc5214yxzausZVvnUFjy6LUXotuEX | ||
18 | tSar4EW7XI9DjaZc1l985naMsTx9JUa5GyQ9J6PGqhosAKpKMGgKkFAHaOwE1/IwgAYJKoZIhvcN | ||
19 | AQcBMBQGCCqGSIb3DQMHBAieDfmz3WGbN6CABHgEpsLrNn0PAZTDUfNomDypvSCl5bQH+9cKm80m | ||
20 | upMV2r8RBiXS7OaP4SpCxq18afDTTPatvboHIoEX92taTbq8soiAgEs6raSGtEYZNvFL0IYqm7MA | ||
21 | o5HCOmjiEcInyPf14lL3HnPk10FaP3hh58qTHUh4LPYtL7UECOZELYnUfUVhAAAAAAAAAAAAAA== | ||
22 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/CMakeLists.txt b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/CMakeLists.txt new file mode 100644 index 00000000..9c64a008 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/CMakeLists.txt | |||
@@ -0,0 +1,10 @@ | |||
1 | configure_file( gpg-agent.conf.in | ||
2 | "${CMAKE_CURRENT_BINARY_DIR}/gpg-agent.conf" @ONLY ) | ||
3 | |||
4 | configure_file( gpgsm.conf.in | ||
5 | "${CMAKE_CURRENT_BINARY_DIR}/gpgsm.conf" @ONLY ) | ||
6 | |||
7 | file( COPY | ||
8 | ${CMAKE_CURRENT_SOURCE_DIR} | ||
9 | DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/../" | ||
10 | ) | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/DIR.txt b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/DIR.txt new file mode 100644 index 00000000..1a45a6b3 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/DIR.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | v:1: | ||
2 | c:4E31CEB57DDD4A7B9991AB05507B1ED4293FF952:CN=Test-ZS 7,O=Intevation GmbH,C=DE:ldap%3A//ca.intevation.org/cn=Test-ZS 7, o=Intevation GmbH, c=DE?certificateRevocationList:20100615T181523:20100707T181523:72FEF3FD88455A1D4C6796A6499D4422:::: | ||
3 | c:7F2A402CBB016A9146D613568C89D3596A4111AA:CN=Wurzel ZS 3,O=Intevation GmbH,C=DE:ldap%3A//ca.intevation.org/cn=Wurzel ZS 3, o=Intevation GmbH, c=DE?certificateRevocationList:20100625T102134:20100814T102134:44E60EEC02EF2FBF7A5C77E9BD565667:::: | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-4E31CEB57DDD4A7B9991AB05507B1ED4293FF952.db b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-4E31CEB57DDD4A7B9991AB05507B1ED4293FF952.db new file mode 100644 index 00000000..0b7e2dd4 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-4E31CEB57DDD4A7B9991AB05507B1ED4293FF952.db | |||
Binary files differ | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-7F2A402CBB016A9146D613568C89D3596A4111AA.db b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-7F2A402CBB016A9146D613568C89D3596A4111AA.db new file mode 100644 index 00000000..47474a26 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-7F2A402CBB016A9146D613568C89D3596A4111AA.db | |||
Binary files differ | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr.conf b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr.conf new file mode 100644 index 00000000..a17a0354 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/dirmngr.conf | |||
@@ -0,0 +1,8 @@ | |||
1 | |||
2 | ###+++--- GPGConf ---+++### | ||
3 | debug-level basic | ||
4 | log-file socket:///home/leo/kde/src/kdepim/messagecomposer/tests/gnupg_home/log-socket | ||
5 | ###+++--- GPGConf ---+++### Tue 29 Jun 2010 10:23:13 AM EDT | ||
6 | # GPGConf edited this configuration file. | ||
7 | # It will disable options before this marked block, but it will | ||
8 | # never change anything below these lines. | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/gpg-agent.conf.in b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/gpg-agent.conf.in new file mode 100644 index 00000000..ece69255 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/gpg-agent.conf.in | |||
@@ -0,0 +1,10 @@ | |||
1 | pinentry-program @CMAKE_CURRENT_BINARY_DIR@/pinentry-fake.sh | ||
2 | ###+++--- GPGConf ---+++### | ||
3 | allow-mark-trusted | ||
4 | debug-level basic | ||
5 | faked-system-time 20130110T154812 | ||
6 | log-file @CMAKE_CURRENT_BINARY_DIR@/gpg-agent.log | ||
7 | ###+++--- GPGConf ---+++### Tue 29 Jun 2010 10:23:13 AM EDT | ||
8 | # GPGConf edited this configuration file. | ||
9 | # It will disable options before this marked block, but it will | ||
10 | # never change anything below these lines. | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/gpg.conf b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/gpg.conf new file mode 100644 index 00000000..f1760823 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/gpg.conf | |||
@@ -0,0 +1,244 @@ | |||
1 | # Options for GnuPG | ||
2 | # Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # This file is free software; as a special exception the author gives | ||
5 | # unlimited permission to copy and/or distribute it, with or without | ||
6 | # modifications, as long as this notice is preserved. | ||
7 | # | ||
8 | # This file is distributed in the hope that it will be useful, but | ||
9 | # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the | ||
10 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
11 | # | ||
12 | # Unless you specify which option file to use (with the command line | ||
13 | # option "--options filename"), GnuPG uses the file ~/.gnupg/gpg.conf | ||
14 | # by default. | ||
15 | # | ||
16 | # An options file can contain any long options which are available in | ||
17 | # GnuPG. If the first non white space character of a line is a '#', | ||
18 | # this line is ignored. Empty lines are also ignored. | ||
19 | # | ||
20 | # See the man page for a list of options. | ||
21 | |||
22 | # Uncomment the following option to get rid of the copyright notice | ||
23 | |||
24 | #no-greeting | ||
25 | |||
26 | # If you have more than 1 secret key in your keyring, you may want to | ||
27 | # uncomment the following option and set your preferred keyid. | ||
28 | |||
29 | #default-key 621CC013 | ||
30 | |||
31 | # If you do not pass a recipient to gpg, it will ask for one. Using | ||
32 | # this option you can encrypt to a default key. Key validation will | ||
33 | # not be done in this case. The second form uses the default key as | ||
34 | # default recipient. | ||
35 | |||
36 | #default-recipient some-user-id | ||
37 | #default-recipient-self | ||
38 | |||
39 | # Use --encrypt-to to add the specified key as a recipient to all | ||
40 | # messages. This is useful, for example, when sending mail through a | ||
41 | # mail client that does not automatically encrypt mail to your key. | ||
42 | # In the example, this option allows you to read your local copy of | ||
43 | # encrypted mail that you've sent to others. | ||
44 | |||
45 | #encrypt-to some-key-id | ||
46 | |||
47 | # By default GnuPG creates version 3 signatures for data files. This | ||
48 | # is not strictly OpenPGP compliant but PGP 6 and most versions of PGP | ||
49 | # 7 require them. To disable this behavior, you may use this option | ||
50 | # or --openpgp. | ||
51 | |||
52 | #no-force-v3-sigs | ||
53 | |||
54 | # Because some mailers change lines starting with "From " to ">From " | ||
55 | # it is good to handle such lines in a special way when creating | ||
56 | # cleartext signatures; all other PGP versions do it this way too. | ||
57 | |||
58 | #no-escape-from-lines | ||
59 | |||
60 | # If you do not use the Latin-1 (ISO-8859-1) charset, you should tell | ||
61 | # GnuPG which is the native character set. Please check the man page | ||
62 | # for supported character sets. This character set is only used for | ||
63 | # metadata and not for the actual message which does not undergo any | ||
64 | # translation. Note that future version of GnuPG will change to UTF-8 | ||
65 | # as default character set. In most cases this option is not required | ||
66 | # as GnuPG is able to figure out the correct charset at runtime. | ||
67 | |||
68 | #charset utf-8 | ||
69 | |||
70 | # Group names may be defined like this: | ||
71 | # group mynames = paige 0x12345678 joe patti | ||
72 | # | ||
73 | # Any time "mynames" is a recipient (-r or --recipient), it will be | ||
74 | # expanded to the names "paige", "joe", and "patti", and the key ID | ||
75 | # "0x12345678". Note there is only one level of expansion - you | ||
76 | # cannot make an group that points to another group. Note also that | ||
77 | # if there are spaces in the recipient name, this will appear as two | ||
78 | # recipients. In these cases it is better to use the key ID. | ||
79 | |||
80 | #group mynames = paige 0x12345678 joe patti | ||
81 | |||
82 | # Lock the file only once for the lifetime of a process. If you do | ||
83 | # not define this, the lock will be obtained and released every time | ||
84 | # it is needed, which is usually preferable. | ||
85 | |||
86 | #lock-once | ||
87 | |||
88 | # GnuPG can send and receive keys to and from a keyserver. These | ||
89 | # servers can be HKP, email, or LDAP (if GnuPG is built with LDAP | ||
90 | # support). | ||
91 | # | ||
92 | # Example HKP keyserver: | ||
93 | # hkp://keys.gnupg.net | ||
94 | # hkp://subkeys.pgp.net | ||
95 | # | ||
96 | # Example email keyserver: | ||
97 | # mailto:pgp-public-keys@keys.pgp.net | ||
98 | # | ||
99 | # Example LDAP keyservers: | ||
100 | # ldap://keyserver.pgp.com | ||
101 | # | ||
102 | # Regular URL syntax applies, and you can set an alternate port | ||
103 | # through the usual method: | ||
104 | # hkp://keyserver.example.net:22742 | ||
105 | # | ||
106 | # Most users just set the name and type of their preferred keyserver. | ||
107 | # Note that most servers (with the notable exception of | ||
108 | # ldap://keyserver.pgp.com) synchronize changes with each other. Note | ||
109 | # also that a single server name may actually point to multiple | ||
110 | # servers via DNS round-robin. hkp://keys.gnupg.net is an example of | ||
111 | # such a "server", which spreads the load over a number of physical | ||
112 | # servers. To see the IP address of the server actually used, you may use | ||
113 | # the "--keyserver-options debug". | ||
114 | |||
115 | keyserver hkp://keys.gnupg.net | ||
116 | #keyserver mailto:pgp-public-keys@keys.nl.pgp.net | ||
117 | #keyserver ldap://keyserver.pgp.com | ||
118 | |||
119 | # Common options for keyserver functions: | ||
120 | # | ||
121 | # include-disabled : when searching, include keys marked as "disabled" | ||
122 | # on the keyserver (not all keyservers support this). | ||
123 | # | ||
124 | # no-include-revoked : when searching, do not include keys marked as | ||
125 | # "revoked" on the keyserver. | ||
126 | # | ||
127 | # verbose : show more information as the keys are fetched. | ||
128 | # Can be used more than once to increase the amount | ||
129 | # of information shown. | ||
130 | # | ||
131 | # use-temp-files : use temporary files instead of a pipe to talk to the | ||
132 | # keyserver. Some platforms (Win32 for one) always | ||
133 | # have this on. | ||
134 | # | ||
135 | # keep-temp-files : do not delete temporary files after using them | ||
136 | # (really only useful for debugging) | ||
137 | # | ||
138 | # http-proxy="proxy" : set the proxy to use for HTTP and HKP keyservers. | ||
139 | # This overrides the "http_proxy" environment variable, | ||
140 | # if any. | ||
141 | # | ||
142 | # auto-key-retrieve : automatically fetch keys as needed from the keyserver | ||
143 | # when verifying signatures or when importing keys that | ||
144 | # have been revoked by a revocation key that is not | ||
145 | # present on the keyring. | ||
146 | # | ||
147 | # no-include-attributes : do not include attribute IDs (aka "photo IDs") | ||
148 | # when sending keys to the keyserver. | ||
149 | |||
150 | #keyserver-options auto-key-retrieve | ||
151 | |||
152 | # Display photo user IDs in key listings | ||
153 | |||
154 | # list-options show-photos | ||
155 | |||
156 | # Display photo user IDs when a signature from a key with a photo is | ||
157 | # verified | ||
158 | |||
159 | # verify-options show-photos | ||
160 | |||
161 | # Use this program to display photo user IDs | ||
162 | # | ||
163 | # %i is expanded to a temporary file that contains the photo. | ||
164 | # %I is the same as %i, but the file isn't deleted afterwards by GnuPG. | ||
165 | # %k is expanded to the key ID of the key. | ||
166 | # %K is expanded to the long OpenPGP key ID of the key. | ||
167 | # %t is expanded to the extension of the image (e.g. "jpg"). | ||
168 | # %T is expanded to the MIME type of the image (e.g. "image/jpeg"). | ||
169 | # %f is expanded to the fingerprint of the key. | ||
170 | # %% is %, of course. | ||
171 | # | ||
172 | # If %i or %I are not present, then the photo is supplied to the | ||
173 | # viewer on standard input. If your platform supports it, standard | ||
174 | # input is the best way to do this as it avoids the time and effort in | ||
175 | # generating and then cleaning up a secure temp file. | ||
176 | # | ||
177 | # If no photo-viewer is provided, GnuPG will look for xloadimage, eog, | ||
178 | # or display (ImageMagick). On Mac OS X and Windows, the default is | ||
179 | # to use your regular JPEG image viewer. | ||
180 | # | ||
181 | # Some other viewers: | ||
182 | # photo-viewer "qiv %i" | ||
183 | # photo-viewer "ee %i" | ||
184 | # | ||
185 | # This one saves a copy of the photo ID in your home directory: | ||
186 | # photo-viewer "cat > ~/photoid-for-key-%k.%t" | ||
187 | # | ||
188 | # Use your MIME handler to view photos: | ||
189 | # photo-viewer "metamail -q -d -b -c %T -s 'KeyID 0x%k' -f GnuPG" | ||
190 | |||
191 | # Passphrase agent | ||
192 | # | ||
193 | # We support the old experimental passphrase agent protocol as well as | ||
194 | # the new Assuan based one (currently available in the "newpg" package | ||
195 | # at ftp.gnupg.org/gcrypt/alpha/aegypten/). To make use of the agent, | ||
196 | # you have to run an agent as daemon and use the option | ||
197 | # | ||
198 | # use-agent | ||
199 | # | ||
200 | # which tries to use the agent but will fallback to the regular mode | ||
201 | # if there is a problem connecting to the agent. The normal way to | ||
202 | # locate the agent is by looking at the environment variable | ||
203 | # GPG_AGENT_INFO which should have been set during gpg-agent startup. | ||
204 | # In certain situations the use of this variable is not possible, thus | ||
205 | # the option | ||
206 | # | ||
207 | # --gpg-agent-info=<path>:<pid>:1 | ||
208 | # | ||
209 | # may be used to override it. | ||
210 | |||
211 | # Automatic key location | ||
212 | # | ||
213 | # GnuPG can automatically locate and retrieve keys as needed using the | ||
214 | # auto-key-locate option. This happens when encrypting to an email | ||
215 | # address (in the "user@example.com" form), and there are no | ||
216 | # user@example.com keys on the local keyring. This option takes the | ||
217 | # following arguments, in the order they are to be tried: | ||
218 | # | ||
219 | # cert = locate a key using DNS CERT, as specified in RFC-4398. | ||
220 | # GnuPG can handle both the PGP (key) and IPGP (URL + fingerprint) | ||
221 | # CERT methods. | ||
222 | # | ||
223 | # pka = locate a key using DNS PKA. | ||
224 | # | ||
225 | # ldap = locate a key using the PGP Universal method of checking | ||
226 | # "ldap://keys.(thedomain)". For example, encrypting to | ||
227 | # user@example.com will check ldap://keys.example.com. | ||
228 | # | ||
229 | # keyserver = locate a key using whatever keyserver is defined using | ||
230 | # the keyserver option. | ||
231 | # | ||
232 | # You may also list arbitrary keyservers here by URL. | ||
233 | # | ||
234 | # Try CERT, then PKA, then LDAP, then hkp://subkeys.net: | ||
235 | #auto-key-locate cert pka ldap hkp://subkeys.pgp.net | ||
236 | |||
237 | ###+++--- GPGConf ---+++### | ||
238 | utf8-strings | ||
239 | #debug-level basic | ||
240 | #log-file socket:///home/leo/kde/src/kdepim/messagecomposer/tests/gnupg_home/log-socket | ||
241 | ###+++--- GPGConf ---+++### Tue 29 Jun 2010 10:23:13 AM EDT | ||
242 | # GPGConf edited this configuration file. | ||
243 | # It will disable options before this marked block, but it will | ||
244 | # never change anything below these lines. | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/gpgsm.conf.in b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/gpgsm.conf.in new file mode 100644 index 00000000..92b6119d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/gpgsm.conf.in | |||
@@ -0,0 +1,10 @@ | |||
1 | |||
2 | ###+++--- GPGConf ---+++### | ||
3 | disable-crl-checks | ||
4 | debug-level basic | ||
5 | faked-system-time 20130110T154812 | ||
6 | log-file @CMAKE_CURRENT_BINARY_DIR@/gpgsm.log | ||
7 | ###+++--- GPGConf ---+++### Tue 29 Jun 2010 10:23:13 AM EDT | ||
8 | # GPGConf edited this configuration file. | ||
9 | # It will disable options before this marked block, but it will | ||
10 | # never change anything below these lines. | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/pinentry-fake.sh b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/pinentry-fake.sh new file mode 100755 index 00000000..7135a942 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/pinentry-fake.sh | |||
@@ -0,0 +1,9 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | echo "OK Your orders please" | ||
4 | while : | ||
5 | do | ||
6 | read cmd | ||
7 | echo "OK" | ||
8 | [ "$cmd" = "BYE" ] && break | ||
9 | done | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/private-keys-v1.d/1AA8BA52430E51AE249AF0DA97D59F869E4101A8.key b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/private-keys-v1.d/1AA8BA52430E51AE249AF0DA97D59F869E4101A8.key new file mode 100644 index 00000000..39ac307b --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/private-keys-v1.d/1AA8BA52430E51AE249AF0DA97D59F869E4101A8.key | |||
Binary files differ | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/pubring.gpg b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/pubring.gpg new file mode 100644 index 00000000..2e00fa24 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/pubring.gpg | |||
Binary files differ | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/pubring.kbx b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/pubring.kbx new file mode 100644 index 00000000..0230f313 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/pubring.kbx | |||
Binary files differ | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/scdaemon.conf b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/scdaemon.conf new file mode 100644 index 00000000..a17a0354 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/scdaemon.conf | |||
@@ -0,0 +1,8 @@ | |||
1 | |||
2 | ###+++--- GPGConf ---+++### | ||
3 | debug-level basic | ||
4 | log-file socket:///home/leo/kde/src/kdepim/messagecomposer/tests/gnupg_home/log-socket | ||
5 | ###+++--- GPGConf ---+++### Tue 29 Jun 2010 10:23:13 AM EDT | ||
6 | # GPGConf edited this configuration file. | ||
7 | # It will disable options before this marked block, but it will | ||
8 | # never change anything below these lines. | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/secring.gpg b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/secring.gpg new file mode 100644 index 00000000..cfd3387d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/secring.gpg | |||
Binary files differ | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/trustdb.gpg b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/trustdb.gpg new file mode 100644 index 00000000..70089c15 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/trustdb.gpg | |||
Binary files differ | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/trustlist.txt b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/trustlist.txt new file mode 100644 index 00000000..bbb0442d --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gnupg_home/trustlist.txt | |||
@@ -0,0 +1,11 @@ | |||
1 | 5E:7C:B2:F4:9F:70:05:43:42:32:5D:75:74:70:00:09:B9:D8:08:61 S | ||
2 | |||
3 | |||
4 | |||
5 | # CN=unittest cert | ||
6 | # O=KDAB | ||
7 | # C=US | ||
8 | # EMail=test@example.com | ||
9 | 24:D2:FC:A2:2E:B3:B8:0A:1E:37:71:D1:4C:C6:58:E3:21:2B:49:DC S | ||
10 | |||
11 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/gpgerrortest.cpp b/framework/src/domain/mime/mimetreeparser/tests/gpgerrortest.cpp new file mode 100644 index 00000000..4254d972 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/gpgerrortest.cpp | |||
@@ -0,0 +1,214 @@ | |||
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 <QGpgME/Protocol> | ||
24 | #include <gpgme++/context.h> | ||
25 | #include <gpgme++/engineinfo.h> | ||
26 | #include <gpgme.h> | ||
27 | |||
28 | #include <QDebug> | ||
29 | #include <QDir> | ||
30 | #include <QProcess> | ||
31 | #include <QTest> | ||
32 | |||
33 | QByteArray readMailFromFile(const QString &mailFile) | ||
34 | { | ||
35 | QFile file(QLatin1String(MAIL_DATA_DIR) + QLatin1Char('/') + mailFile); | ||
36 | file.open(QIODevice::ReadOnly); | ||
37 | Q_ASSERT(file.isOpen()); | ||
38 | return file.readAll(); | ||
39 | } | ||
40 | |||
41 | void killAgent(const QString& dir) | ||
42 | { | ||
43 | QProcess proc; | ||
44 | proc.setProgram(QStringLiteral("gpg-connect-agent")); | ||
45 | QStringList arguments; | ||
46 | arguments << "-S " << dir + "/S.gpg-agent"; | ||
47 | proc.start(); | ||
48 | proc.waitForStarted(); | ||
49 | proc.write("KILLAGENT\n"); | ||
50 | proc.write("BYE\n"); | ||
51 | proc.closeWriteChannel(); | ||
52 | proc.waitForFinished(); | ||
53 | } | ||
54 | |||
55 | class GpgErrorTest : public QObject | ||
56 | { | ||
57 | Q_OBJECT | ||
58 | |||
59 | private slots: | ||
60 | |||
61 | void testGpgConfiguredCorrectly() | ||
62 | { | ||
63 | setEnv("GNUPGHOME", GNUPGHOME); | ||
64 | |||
65 | Parser parser(readMailFromFile("openpgp-inline-charset-encrypted.mbox")); | ||
66 | |||
67 | auto contentPartList = parser.collectContentParts(); | ||
68 | QCOMPARE(contentPartList.size(), 1); | ||
69 | auto contentPart = contentPartList[0]; | ||
70 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "plaintext"); | ||
71 | auto contentList = contentPart->content("plaintext"); | ||
72 | QVERIFY(contentList[0]->content().startsWith("asdasd")); | ||
73 | QCOMPARE(contentList[0]->encryptions().size(), 1); | ||
74 | auto enc = contentList[0]->encryptions()[0]; | ||
75 | QCOMPARE(enc->errorType(), Encryption::NoError); | ||
76 | QCOMPARE(enc->errorString(), QString()); | ||
77 | QCOMPARE((int) enc->recipients().size(), 2); | ||
78 | } | ||
79 | |||
80 | void testNoGPGInstalled_data() | ||
81 | { | ||
82 | QTest::addColumn<QString>("mailFileName"); | ||
83 | |||
84 | QTest::newRow("openpgp-inline-charset-encrypted") << "openpgp-inline-charset-encrypted.mbox"; | ||
85 | QTest::newRow("openpgp-encrypted-attachment-and-non-encrypted-attachment") << "openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox"; | ||
86 | QTest::newRow("smime-encrypted") << "smime-encrypted.mbox"; | ||
87 | } | ||
88 | |||
89 | void testNoGPGInstalled() | ||
90 | { | ||
91 | QFETCH(QString, mailFileName); | ||
92 | |||
93 | setEnv("PATH", "/nonexististing"); | ||
94 | setGpgMEfname("/nonexisting/gpg", ""); | ||
95 | |||
96 | Parser parser(readMailFromFile(mailFileName)); | ||
97 | auto contentPartList = parser.collectContentParts(); | ||
98 | |||
99 | QCOMPARE(contentPartList.size(), 1); | ||
100 | auto contentPart = contentPartList[0]; | ||
101 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "plaintext"); | ||
102 | auto contentList = contentPart->content("plaintext"); | ||
103 | QCOMPARE(contentList[0]->encryptions().size(), 1); | ||
104 | QVERIFY(contentList[0]->content().isEmpty()); | ||
105 | auto enc = contentList[0]->encryptions()[0]; | ||
106 | qDebug() << "HUHU"<< enc->errorType(); | ||
107 | QCOMPARE(enc->errorType(), Encryption::UnknownError); | ||
108 | QCOMPARE(enc->errorString(), QString("Crypto plug-in \"OpenPGP\" could not decrypt the data.<br />Error: No data")); | ||
109 | QCOMPARE((int) enc->recipients().size(), 0); | ||
110 | } | ||
111 | |||
112 | void testGpgIncorrectGPGHOME_data() | ||
113 | { | ||
114 | QTest::addColumn<QString>("mailFileName"); | ||
115 | |||
116 | QTest::newRow("openpgp-inline-charset-encrypted") << "openpgp-inline-charset-encrypted.mbox"; | ||
117 | QTest::newRow("openpgp-encrypted-attachment-and-non-encrypted-attachment") << "openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox"; | ||
118 | QTest::newRow("smime-encrypted") << "smime-encrypted.mbox"; | ||
119 | } | ||
120 | |||
121 | void testGpgIncorrectGPGHOME() | ||
122 | { | ||
123 | QFETCH(QString, mailFileName); | ||
124 | setEnv("GNUPGHOME", QByteArray(GNUPGHOME) + QByteArray("noexist")); | ||
125 | |||
126 | Parser parser(readMailFromFile(mailFileName)); | ||
127 | |||
128 | auto contentPartList = parser.collectContentParts(); | ||
129 | QCOMPARE(contentPartList.size(), 1); | ||
130 | auto contentPart = contentPartList[0]; | ||
131 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "plaintext"); | ||
132 | auto contentList = contentPart->content("plaintext"); | ||
133 | QCOMPARE(contentList[0]->encryptions().size(), 1); | ||
134 | QCOMPARE(contentList[0]->signatures().size(), 0); | ||
135 | QVERIFY(contentList[0]->content().isEmpty()); | ||
136 | auto enc = contentList[0]->encryptions()[0]; | ||
137 | qDebug() << enc->errorType(); | ||
138 | QCOMPARE(enc->errorType(), Encryption::KeyMissing); | ||
139 | QCOMPARE(enc->errorString(), QString("Crypto plug-in \"OpenPGP\" could not decrypt the data.<br />Error: Decryption failed")); | ||
140 | QCOMPARE((int) enc->recipients().size(), 2); | ||
141 | } | ||
142 | |||
143 | public Q_SLOTS: | ||
144 | void init() | ||
145 | { | ||
146 | mResetGpgmeEngine = false; | ||
147 | mModifiedEnv.clear(); | ||
148 | { | ||
149 | QGpgME::openpgp(); // We need to intialize it, otherwise ctx will be a nullpointer | ||
150 | const GpgME::Context *ctx = GpgME::Context::createForProtocol(GpgME::Protocol::OpenPGP); | ||
151 | const auto engineinfo = ctx->engineInfo(); | ||
152 | mGpgmeEngine_fname = engineinfo.fileName(); | ||
153 | } | ||
154 | mEnv = QProcessEnvironment::systemEnvironment(); | ||
155 | unsetEnv("GNUPGHOME"); | ||
156 | } | ||
157 | |||
158 | void cleanup() | ||
159 | { | ||
160 | QCoreApplication::sendPostedEvents(); | ||
161 | |||
162 | const QString &gnupghome = qgetenv("GNUPGHOME"); | ||
163 | if (!gnupghome.isEmpty()) { | ||
164 | killAgent(gnupghome); | ||
165 | } | ||
166 | |||
167 | resetGpgMfname(); | ||
168 | resetEnv(); | ||
169 | } | ||
170 | private: | ||
171 | void unsetEnv(const QByteArray &name) | ||
172 | { | ||
173 | mModifiedEnv << name; | ||
174 | unsetenv(name); | ||
175 | } | ||
176 | |||
177 | void setEnv(const QByteArray &name, const QByteArray &value) | ||
178 | { | ||
179 | mModifiedEnv << name; | ||
180 | setenv(name, value , 1); | ||
181 | } | ||
182 | |||
183 | void resetEnv() | ||
184 | { | ||
185 | foreach(const auto &i, mModifiedEnv) { | ||
186 | if (mEnv.contains(i)) { | ||
187 | setenv(i, mEnv.value(i).toUtf8(), 1); | ||
188 | } else { | ||
189 | unsetenv(i); | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | |||
194 | void resetGpgMfname() | ||
195 | { | ||
196 | if (mResetGpgmeEngine) { | ||
197 | gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, mGpgmeEngine_fname, NULL); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | void setGpgMEfname(const QByteArray &fname, const QByteArray &homedir) | ||
202 | { | ||
203 | mResetGpgmeEngine = true; | ||
204 | gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, fname, homedir); | ||
205 | } | ||
206 | |||
207 | QSet<QByteArray> mModifiedEnv; | ||
208 | QProcessEnvironment mEnv; | ||
209 | bool mResetGpgmeEngine; | ||
210 | QByteArray mGpgmeEngine_fname; | ||
211 | }; | ||
212 | |||
213 | QTEST_GUILESS_MAIN(GpgErrorTest) | ||
214 | #include "gpgerrortest.moc" | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp b/framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp new file mode 100644 index 00000000..3ae32a4a --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp | |||
@@ -0,0 +1,310 @@ | |||
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 <QTest> | ||
24 | |||
25 | QByteArray readMailFromFile(const QString &mailFile) | ||
26 | { | ||
27 | QFile file(QLatin1String(MAIL_DATA_DIR) + QLatin1Char('/') + mailFile); | ||
28 | file.open(QIODevice::ReadOnly); | ||
29 | Q_ASSERT(file.isOpen()); | ||
30 | return file.readAll(); | ||
31 | } | ||
32 | |||
33 | QByteArray join(QVector<QByteArray> vec, QByteArray sep) | ||
34 | { | ||
35 | QByteArray ret; | ||
36 | bool bInit = true; | ||
37 | foreach(const auto &entry, vec) { | ||
38 | if (!bInit) { | ||
39 | ret += sep; | ||
40 | } | ||
41 | bInit = false; | ||
42 | ret += entry; | ||
43 | } | ||
44 | return ret; | ||
45 | } | ||
46 | |||
47 | class InterfaceTest : public QObject | ||
48 | { | ||
49 | Q_OBJECT | ||
50 | private: | ||
51 | void printTree(const Part::Ptr &start, QString pre) | ||
52 | { | ||
53 | foreach (const auto &part, start->subParts()) { | ||
54 | qWarning() << QStringLiteral("%1* %2(%3)") | ||
55 | .arg(pre) | ||
56 | .arg(QString::fromLatin1(part->type())) | ||
57 | .arg(QString::fromLatin1(join(part->availableContents(),", "))); | ||
58 | printTree(part,pre + QStringLiteral(" ")); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | private slots: | ||
63 | |||
64 | void testTextMail() | ||
65 | { | ||
66 | Parser parser(readMailFromFile("plaintext.mbox")); | ||
67 | printTree(parser.d->mTree,QString()); | ||
68 | auto contentPartList = parser.collectContentParts(); | ||
69 | QCOMPARE(contentPartList.size(), 1); | ||
70 | auto contentPart = contentPartList[0]; | ||
71 | QVERIFY((bool)contentPart); | ||
72 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "plaintext"); | ||
73 | auto contentList = contentPart->content("plaintext"); | ||
74 | QCOMPARE(contentList.size(), 1); | ||
75 | QCOMPARE(contentList[0]->content(), QStringLiteral("If you can see this text it means that your email client couldn't display our newsletter properly.\nPlease visit this link to view the newsletter on our website: http://www.gog.com/newsletter/").toLocal8Bit()); | ||
76 | QCOMPARE(contentList[0]->charset(), QStringLiteral("utf-8").toLocal8Bit()); | ||
77 | QCOMPARE(contentList[0]->encryptions().size(), 0); | ||
78 | QCOMPARE(contentList[0]->signatures().size(), 0); | ||
79 | |||
80 | contentList = contentPart->content("html"); | ||
81 | QCOMPARE(contentList.size(), 0); | ||
82 | auto contentAttachmentList = parser.collectAttachmentParts(); | ||
83 | QCOMPARE(contentAttachmentList.size(), 0); | ||
84 | } | ||
85 | |||
86 | void testTextAlternative() | ||
87 | { | ||
88 | Parser parser(readMailFromFile("alternative.mbox")); | ||
89 | printTree(parser.d->mTree,QString()); | ||
90 | auto contentPartList = parser.collectContentParts(); | ||
91 | QCOMPARE(contentPartList.size(), 1); | ||
92 | auto contentPart = contentPartList[0]; | ||
93 | QVERIFY((bool)contentPart); | ||
94 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "html" << "plaintext"); | ||
95 | auto contentList = contentPart->content("plaintext"); | ||
96 | QCOMPARE(contentList.size(), 1); | ||
97 | QCOMPARE(contentList[0]->content(), QStringLiteral("If you can see this text it means that your email client couldn't display our newsletter properly.\nPlease visit this link to view the newsletter on our website: http://www.gog.com/newsletter/\n").toLocal8Bit()); | ||
98 | QCOMPARE(contentList[0]->charset(), QStringLiteral("utf-8").toLocal8Bit()); | ||
99 | QCOMPARE(contentList[0]->encryptions().size(), 0); | ||
100 | QCOMPARE(contentList[0]->signatures().size(), 0); | ||
101 | |||
102 | contentList = contentPart->content("html"); | ||
103 | QCOMPARE(contentList.size(), 1); | ||
104 | QCOMPARE(contentList[0]->content(), QStringLiteral("<html><body><p><span>HTML</span> text</p></body></html>\n\n").toLocal8Bit()); | ||
105 | QCOMPARE(contentList[0]->charset(), QStringLiteral("utf-8").toLocal8Bit()); | ||
106 | QCOMPARE(contentList[0]->encryptions().size(), 0); | ||
107 | QCOMPARE(contentList[0]->signatures().size(), 0); | ||
108 | auto contentAttachmentList = parser.collectAttachmentParts(); | ||
109 | QCOMPARE(contentAttachmentList.size(), 0); | ||
110 | } | ||
111 | |||
112 | void testTextHtml() | ||
113 | { | ||
114 | Parser parser(readMailFromFile("html.mbox")); | ||
115 | printTree(parser.d->mTree,QString()); | ||
116 | auto contentPartList = parser.collectContentParts(); | ||
117 | QCOMPARE(contentPartList.size(), 1); | ||
118 | auto contentPart = contentPartList[0]; | ||
119 | QVERIFY((bool)contentPart); | ||
120 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "html"); | ||
121 | |||
122 | auto contentList = contentPart->content("plaintext"); | ||
123 | QCOMPARE(contentList.size(), 0); | ||
124 | |||
125 | contentList = contentPart->content("html"); | ||
126 | QCOMPARE(contentList.size(), 1); | ||
127 | QCOMPARE(contentList[0]->content(), QStringLiteral("<html><body><p><span>HTML</span> text</p></body></html>").toLocal8Bit()); | ||
128 | QCOMPARE(contentList[0]->charset(), QStringLiteral("utf-8").toLocal8Bit()); | ||
129 | QCOMPARE(contentList[0]->encryptions().size(), 0); | ||
130 | QCOMPARE(contentList[0]->signatures().size(), 0); | ||
131 | auto contentAttachmentList = parser.collectAttachmentParts(); | ||
132 | QCOMPARE(contentAttachmentList.size(), 0); | ||
133 | } | ||
134 | |||
135 | void testSMimeEncrypted() | ||
136 | { | ||
137 | Parser parser(readMailFromFile("smime-encrypted.mbox")); | ||
138 | printTree(parser.d->mTree,QString()); | ||
139 | auto contentPartList = parser.collectContentParts(); | ||
140 | QCOMPARE(contentPartList.size(), 1); | ||
141 | auto contentPart = contentPartList[0]; | ||
142 | QVERIFY((bool)contentPart); | ||
143 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "plaintext"); | ||
144 | auto contentList = contentPart->content("plaintext"); | ||
145 | QCOMPARE(contentList.size(), 1); | ||
146 | QCOMPARE(contentList[0]->content(), QStringLiteral("The quick brown fox jumped over the lazy dog.").toLocal8Bit()); | ||
147 | QCOMPARE(contentList[0]->charset(), QStringLiteral("us-ascii").toLocal8Bit()); | ||
148 | QCOMPARE(contentList[0]->encryptions().size(), 1); | ||
149 | QCOMPARE(contentList[0]->signatures().size(), 0); | ||
150 | auto contentAttachmentList = parser.collectAttachmentParts(); | ||
151 | QCOMPARE(contentAttachmentList.size(), 0); | ||
152 | } | ||
153 | |||
154 | void testOpenPGPEncryptedAttachment() | ||
155 | { | ||
156 | Parser parser(readMailFromFile("openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox")); | ||
157 | printTree(parser.d->mTree,QString()); | ||
158 | auto contentPartList = parser.collectContentParts(); | ||
159 | QCOMPARE(contentPartList.size(), 1); | ||
160 | auto contentPart = contentPartList[0]; | ||
161 | QVERIFY((bool)contentPart); | ||
162 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "plaintext"); | ||
163 | auto contentList = contentPart->content("plaintext"); | ||
164 | QCOMPARE(contentList.size(), 1); | ||
165 | QCOMPARE(contentList[0]->content(), QStringLiteral("test text").toLocal8Bit()); | ||
166 | QCOMPARE(contentList[0]->charset(), QStringLiteral("us-ascii").toLocal8Bit()); | ||
167 | QCOMPARE(contentList[0]->encryptions().size(), 1); | ||
168 | QCOMPARE(contentList[0]->signatures().size(), 1); | ||
169 | auto contentAttachmentList = parser.collectAttachmentParts(); | ||
170 | QCOMPARE(contentAttachmentList.size(), 2); | ||
171 | QCOMPARE(contentAttachmentList[0]->availableContents(), QVector<QByteArray>() << "text/plain"); | ||
172 | QCOMPARE(contentAttachmentList[0]->content().size(), 1); | ||
173 | QCOMPARE(contentAttachmentList[0]->encryptions().size(), 1); | ||
174 | QCOMPARE(contentAttachmentList[0]->signatures().size(), 1); | ||
175 | QCOMPARE(contentAttachmentList[1]->availableContents(), QVector<QByteArray>() << "image/png"); | ||
176 | QCOMPARE(contentAttachmentList[1]->content().size(), 1); | ||
177 | QCOMPARE(contentAttachmentList[1]->encryptions().size(), 0); | ||
178 | QCOMPARE(contentAttachmentList[1]->signatures().size(), 0); | ||
179 | } | ||
180 | |||
181 | void testOpenPGPInline() | ||
182 | { | ||
183 | Parser parser(readMailFromFile("openpgp-inline-charset-encrypted.mbox")); | ||
184 | printTree(parser.d->mTree,QString()); | ||
185 | auto contentPartList = parser.collectContentParts(); | ||
186 | QCOMPARE(contentPartList.size(), 1); | ||
187 | auto contentPart = contentPartList[0]; | ||
188 | QVERIFY((bool)contentPart); | ||
189 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "plaintext"); | ||
190 | QCOMPARE(contentPart->encryptions().size(), 0); | ||
191 | QCOMPARE(contentPart->signatures().size(), 0); | ||
192 | auto contentList = contentPart->content("plaintext"); | ||
193 | QCOMPARE(contentList.size(), 1); | ||
194 | QCOMPARE(contentList[0]->content(), QStringLiteral("asdasd asd asd asdf sadf sdaf sadf äöü").toLocal8Bit()); | ||
195 | QCOMPARE(contentList[0]->charset(), QStringLiteral("ISO-8859-15").toLocal8Bit()); | ||
196 | QCOMPARE(contentList[0]->encryptions().size(), 1); | ||
197 | QCOMPARE(contentList[0]->signatures().size(), 1); | ||
198 | auto contentAttachmentList = parser.collectAttachmentParts(); | ||
199 | QCOMPARE(contentAttachmentList.size(), 0); | ||
200 | } | ||
201 | |||
202 | void testOpenPPGInlineWithNonEncText() | ||
203 | { | ||
204 | Parser parser(readMailFromFile("openpgp-inline-encrypted+nonenc.mbox")); | ||
205 | printTree(parser.d->mTree,QString()); | ||
206 | auto contentPartList = parser.collectContentParts(); | ||
207 | QCOMPARE(contentPartList.size(), 1); | ||
208 | auto contentPart = contentPartList[0]; | ||
209 | QVERIFY((bool)contentPart); | ||
210 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "plaintext"); | ||
211 | QCOMPARE(contentPart->encryptions().size(), 0); | ||
212 | QCOMPARE(contentPart->signatures().size(), 0); | ||
213 | auto contentList = contentPart->content("plaintext"); | ||
214 | QCOMPARE(contentList.size(), 2); | ||
215 | QCOMPARE(contentList[0]->content(), QStringLiteral("Not encrypted not signed :(\n\n").toLocal8Bit()); | ||
216 | QCOMPARE(contentList[0]->charset(), QStringLiteral("us-ascii").toLocal8Bit()); | ||
217 | QCOMPARE(contentList[0]->encryptions().size(), 0); | ||
218 | QCOMPARE(contentList[0]->signatures().size(), 0); | ||
219 | QCOMPARE(contentList[1]->content(), QStringLiteral("some random text").toLocal8Bit()); | ||
220 | QCOMPARE(contentList[1]->charset(), QStringLiteral("us-ascii").toLocal8Bit()); | ||
221 | QCOMPARE(contentList[1]->encryptions().size(), 1); | ||
222 | QCOMPARE(contentList[1]->signatures().size(), 0); | ||
223 | auto contentAttachmentList = parser.collectAttachmentParts(); | ||
224 | QCOMPARE(contentAttachmentList.size(), 0); | ||
225 | } | ||
226 | |||
227 | void testEncryptionBlock() | ||
228 | { | ||
229 | Parser parser(readMailFromFile("openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox")); | ||
230 | auto contentPartList = parser.collectContentParts(); | ||
231 | auto contentPart = contentPartList[0]; | ||
232 | auto contentList = contentPart->content("plaintext"); | ||
233 | QCOMPARE(contentList.size(), 1); | ||
234 | QCOMPARE(contentList[0]->encryptions().size(), 1); | ||
235 | auto enc = contentList[0]->encryptions()[0]; | ||
236 | QCOMPARE((int) enc->recipients().size(), 2); | ||
237 | |||
238 | auto r = enc->recipients()[0]; | ||
239 | QCOMPARE(r->keyid(),QStringLiteral("14B79E26050467AA")); | ||
240 | QCOMPARE(r->name(),QStringLiteral("kdetest")); | ||
241 | QCOMPARE(r->email(),QStringLiteral("you@you.com")); | ||
242 | QCOMPARE(r->comment(),QStringLiteral("")); | ||
243 | |||
244 | r = enc->recipients()[1]; | ||
245 | QCOMPARE(r->keyid(),QStringLiteral("8D9860C58F246DE6")); | ||
246 | QCOMPARE(r->name(),QStringLiteral("unittest key")); | ||
247 | QCOMPARE(r->email(),QStringLiteral("test@kolab.org")); | ||
248 | QCOMPARE(r->comment(),QStringLiteral("no password")); | ||
249 | } | ||
250 | |||
251 | void testSignatureBlock() | ||
252 | { | ||
253 | Parser parser(readMailFromFile("openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox")); | ||
254 | auto contentPartList = parser.collectContentParts(); | ||
255 | auto contentPart = contentPartList[0]; | ||
256 | auto contentList = contentPart->content("plaintext"); | ||
257 | QCOMPARE(contentList.size(), 1); | ||
258 | QCOMPARE(contentList[0]->signatures().size(), 1); | ||
259 | auto sig = contentList[0]->signatures()[0]; | ||
260 | QCOMPARE(sig->creationDateTime(), QDateTime(QDate(2015,05,01),QTime(15,12,47))); | ||
261 | QCOMPARE(sig->expirationDateTime(), QDateTime()); | ||
262 | QCOMPARE(sig->neverExpires(), true); | ||
263 | |||
264 | auto key = sig->key(); | ||
265 | QCOMPARE(key->keyid(),QStringLiteral("8D9860C58F246DE6")); | ||
266 | QCOMPARE(key->name(),QStringLiteral("unittest key")); | ||
267 | QCOMPARE(key->email(),QStringLiteral("test@kolab.org")); | ||
268 | QCOMPARE(key->comment(),QStringLiteral("no password")); | ||
269 | } | ||
270 | |||
271 | void testRelatedAlternative() | ||
272 | { | ||
273 | Parser parser(readMailFromFile("cid-links.mbox")); | ||
274 | printTree(parser.d->mTree,QString()); | ||
275 | auto contentPartList = parser.collectContentParts(); | ||
276 | QCOMPARE(contentPartList.size(), 1); | ||
277 | auto contentPart = contentPartList[0]; | ||
278 | QVERIFY((bool)contentPart); | ||
279 | QCOMPARE(contentPart->availableContents(), QVector<QByteArray>() << "html" << "plaintext"); | ||
280 | QCOMPARE(contentPart->encryptions().size(), 0); | ||
281 | QCOMPARE(contentPart->signatures().size(), 0); | ||
282 | auto contentList = contentPart->content("plaintext"); | ||
283 | QCOMPARE(contentList.size(), 1); | ||
284 | auto contentAttachmentList = parser.collectAttachmentParts(); | ||
285 | QCOMPARE(contentAttachmentList.size(), 0); | ||
286 | } | ||
287 | |||
288 | void testAttachmentPart() | ||
289 | { | ||
290 | Parser parser(readMailFromFile("cid-links.mbox")); | ||
291 | const auto relatedImage = parser.d->mTree->subParts().at(1); | ||
292 | QCOMPARE(relatedImage->availableContents(), QVector<QByteArray>() << "image/jpeg"); | ||
293 | auto contentList = relatedImage->content(); | ||
294 | QCOMPARE(contentList.size(), 1); | ||
295 | contentList = relatedImage->content("image/jpeg"); | ||
296 | QCOMPARE(contentList.size(), 1); | ||
297 | } | ||
298 | |||
299 | void testCidLink() | ||
300 | { | ||
301 | Parser parser(readMailFromFile("cid-links.mbox")); | ||
302 | printTree(parser.d->mTree,QString()); | ||
303 | QCOMPARE(parser.getPart(QUrl("cid:9359201d15e53f31a68c307b3369b6@info")), parser.d->mTree->subParts().at(1)); | ||
304 | QVERIFY(!parser.getPart(QUrl("cid:"))); | ||
305 | QVERIFY(!parser.getPart(QUrl("cid:unknown"))); | ||
306 | } | ||
307 | }; | ||
308 | |||
309 | QTEST_GUILESS_MAIN(InterfaceTest) | ||
310 | #include "interfacetest.moc" | ||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/kdepim_add_gpg_crypto_test.cmake b/framework/src/domain/mime/mimetreeparser/tests/kdepim_add_gpg_crypto_test.cmake new file mode 100644 index 00000000..ea0ab8d2 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/kdepim_add_gpg_crypto_test.cmake | |||
@@ -0,0 +1,61 @@ | |||
1 | # Copyright (c) 2013 Sandro Knauß <mail@sandroknauss.de> | ||
2 | # | ||
3 | # Redistribution and use is allowed according to the terms of the BSD license. | ||
4 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. | ||
5 | |||
6 | set( MIMETREEPARSERRELPATH framework/src/domain/mimetreeparser) | ||
7 | set( GNUPGHOME ${CMAKE_BINARY_DIR}/${MIMETREEPARSERRELPATH}/tests/gnupg_home ) | ||
8 | add_definitions( -DGNUPGHOME="${GNUPGHOME}" ) | ||
9 | |||
10 | macro (ADD_GPG_CRYPTO_TEST _target _testname) | ||
11 | if (UNIX) | ||
12 | if (APPLE) | ||
13 | set(_library_path_variable "DYLD_LIBRARY_PATH") | ||
14 | elseif (CYGWIN) | ||
15 | set(_library_path_variable "PATH") | ||
16 | else (APPLE) | ||
17 | set(_library_path_variable "LD_LIBRARY_PATH") | ||
18 | endif (APPLE) | ||
19 | |||
20 | if (APPLE) | ||
21 | # DYLD_LIBRARY_PATH does not work like LD_LIBRARY_PATH | ||
22 | # OSX already has the RPATH in libraries and executables, putting runtime directories in | ||
23 | # DYLD_LIBRARY_PATH actually breaks things | ||
24 | set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/") | ||
25 | else (APPLE) | ||
26 | set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/:${LIB_INSTALL_DIR}:${QT_LIBRARY_DIR}") | ||
27 | endif (APPLE) | ||
28 | set(_executable "$<TARGET_FILE:${_target}>") | ||
29 | |||
30 | # use add_custom_target() to have the sh-wrapper generated during build time instead of cmake time | ||
31 | add_custom_command(TARGET ${_target} POST_BUILD | ||
32 | COMMAND ${CMAKE_COMMAND} | ||
33 | -D_filename=${_executable}.shell -D_library_path_variable=${_library_path_variable} | ||
34 | -D_ld_library_path="${_ld_library_path}" -D_executable=$<TARGET_FILE:${_target}> | ||
35 | -D_gnupghome="${GNUPGHOME}" | ||
36 | -P ${CMAKE_SOURCE_DIR}/${MIMETREEPARSERRELPATH}/tests/kdepim_generate_crypto_test_wrapper.cmake | ||
37 | ) | ||
38 | |||
39 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${_executable}.shell" ) | ||
40 | add_test(NAME ${_testname} COMMAND ${_executable}.shell) | ||
41 | |||
42 | else (UNIX) | ||
43 | # under windows, set the property WRAPPER_SCRIPT just to the name of the executable | ||
44 | # maybe later this will change to a generated batch file (for setting the PATH so that the Qt libs are found) | ||
45 | set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}\;${LIB_INSTALL_DIR}\;${QT_LIBRARY_DIR}") | ||
46 | set(_executable "$<TARGET_FILE:${_target}>") | ||
47 | |||
48 | # use add_custom_target() to have the batch-file-wrapper generated during build time instead of cmake time | ||
49 | add_custom_command(TARGET ${_target} POST_BUILD | ||
50 | COMMAND ${CMAKE_COMMAND} | ||
51 | -D_filename="${_executable}.bat" | ||
52 | -D_ld_library_path="${_ld_library_path}" -D_executable="${_executable}" | ||
53 | -D_gnupghome="${GNUPGHOME}" | ||
54 | -P ${CMAKE_SOURCE_DIR}/${MIMETREEPARSERRELPATH}/tests/kdepim_generate_crypto_test_wrapper.cmake | ||
55 | ) | ||
56 | |||
57 | add_test(NAME ${_testname} COMMAND ${_executable}.bat) | ||
58 | |||
59 | endif (UNIX) | ||
60 | endmacro (ADD_GPG_CRYPTO_TEST) | ||
61 | |||
diff --git a/framework/src/domain/mime/mimetreeparser/tests/kdepim_generate_crypto_test_wrapper.cmake b/framework/src/domain/mime/mimetreeparser/tests/kdepim_generate_crypto_test_wrapper.cmake new file mode 100644 index 00000000..e1412f37 --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/tests/kdepim_generate_crypto_test_wrapper.cmake | |||
@@ -0,0 +1,45 @@ | |||
1 | # Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org> | ||
2 | # Copyright (c) 2013, Sandro Knauß <mail@sandroknauss.de> | ||
3 | # | ||
4 | # Redistribution and use is allowed according to the terms of the BSD license. | ||
5 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. | ||
6 | |||
7 | |||
8 | if (UNIX) | ||
9 | |||
10 | file(WRITE "${_filename}" | ||
11 | "#!/bin/sh | ||
12 | # created by cmake, don't edit, changes will be lost | ||
13 | |||
14 | # don't mess with a gpg-agent already running on the system | ||
15 | unset GPG_AGENT_INFO | ||
16 | |||
17 | ${_library_path_variable}=${_ld_library_path}\${${_library_path_variable}:+:\$${_library_path_variable}} GNUPGHOME=${_gnupghome} gpg-agent --daemon \"${_executable}\" \"$@\" | ||
18 | _result=$? | ||
19 | _pid=`echo GETINFO pid | GNUPGHOME=${_gnupghome} gpg-connect-agent | grep 'D' | cut -d' ' -f2` | ||
20 | if [ ! -z \"\$_pid\" ]; then | ||
21 | echo \"Waiting for gpg-agent to terminate (PID: $_pid)...\" | ||
22 | while kill -0 \"\$_pid\"; do | ||
23 | sleep 1 | ||
24 | done | ||
25 | fi | ||
26 | exit \$_result | ||
27 | ") | ||
28 | |||
29 | # make it executable | ||
30 | # since this is only executed on UNIX, it is safe to call chmod | ||
31 | exec_program(chmod ARGS ug+x \"${_filename}\" OUTPUT_VARIABLE _dummy ) | ||
32 | |||
33 | else (UNIX) | ||
34 | |||
35 | file(TO_NATIVE_PATH "${_ld_library_path}" win_path) | ||
36 | file(TO_NATIVE_PATH "${_gnupghome}" win_gnupghome) | ||
37 | |||
38 | file(WRITE "${_filename}" | ||
39 | " | ||
40 | set PATH=${win_path};$ENV{PATH} | ||
41 | set GNUPGHOME=${win_gnupghome};$ENV{GNUPGHOME} | ||
42 | gpg-agent --daemon \"${_executable}\" %* | ||
43 | ") | ||
44 | |||
45 | endif (UNIX) | ||
diff --git a/framework/src/domain/mime/mimetreeparser/thoughts.txt b/framework/src/domain/mime/mimetreeparser/thoughts.txt new file mode 100644 index 00000000..3340347a --- /dev/null +++ b/framework/src/domain/mime/mimetreeparser/thoughts.txt | |||
@@ -0,0 +1,148 @@ | |||
1 | Usecases: | ||
2 | |||
3 | # plaintext msg + attachment | ||
4 | * ContentPart => cp1 | ||
5 | * AttachmentPart => ap1 | ||
6 | |||
7 | (cp1) == collect<ContentPart>(select=NoEncapsulatedMessages) | ||
8 | (ap1) == collect<AttachmentParts>(select=NoEncapsulatedMessages) | ||
9 | |||
10 | (PlainText) == cp1.availableContent() | ||
11 | |||
12 | # html msg + related attachment + normal attachment | ||
13 | * ContentPart => cp1 | ||
14 | * AttachmentPart(mimetype="*/related", cid="12345678") => ap1 | ||
15 | * AttachmentPart => ap2 | ||
16 | |||
17 | (cp1) == collect<ContentPart>(select=NoEncapsulatedMessages) | ||
18 | (ap1, ap2) == collect<AttachmentParts>(select=NoEncapsulatedMessages) | ||
19 | (ap2) == collect<AttachmentParts>(select=NoEncapsulatedMessages, filter=filterelated) | ||
20 | |||
21 | ap1 == getPart("cid:12345678") | ||
22 | |||
23 | (Html) == cp1.availableContent() | ||
24 | |||
25 | # alternative msg + attachment | ||
26 | * ContentPart(html=[Content("HTML"),], plaintext=[Content("Text"),]) => cp1 | ||
27 | * AttachmentPart => ap1 | ||
28 | |||
29 | (cp1) == collect<ContentPart>(select=NoEncapsulatedMessages) | ||
30 | (ap1) == collect<AttachmentParts>(select=NoEncapsulatedMessages) | ||
31 | |||
32 | (Html, PlainText) == cp1.availableContent() | ||
33 | [Content("HTML"),] == cp1.content(Html) | ||
34 | [Content("Text"),] == cp1.content(Plaintext) | ||
35 | |||
36 | # alternative msg with GPGInlin | ||
37 | * ContentPart( | ||
38 | plaintext=[Content("Text"), Content("foo", encryption=(enc1))], | ||
39 | html=[Content("HTML"),] | ||
40 | ) => cp1 | ||
41 | |||
42 | (Html, PlainText) == cp1.availableContent() | ||
43 | |||
44 | [Content("HTML"),] == cp1.content(Html) | ||
45 | [Content("Text"),Content("foo", encryption=(enc1))] == cp1.content(Plaintext) | ||
46 | |||
47 | |||
48 | # encrypted msg (not encrypted/error) with unencrypted attachment | ||
49 | * EncryptionErrorPart => cp1 | ||
50 | * AttachmentPart => ap1 | ||
51 | |||
52 | (cp1) == collect<ContentPart>(select=NoEncapsulatedMessages) | ||
53 | (ap1) == collect<AttachmentParts>(select=NoEncapsulatedMessages) | ||
54 | |||
55 | #encrypted msg (decrypted with attachment) + unencrypted attachment | ||
56 | * encrytion=(rec1,rec2) => enc1 | ||
57 | * ContentPart(encrytion = (enc1,)) => cp1 | ||
58 | * AttachmentPart(encryption = (enc1,)) => ap1 | ||
59 | * AttachmentPart => ap2 | ||
60 | |||
61 | (cp1) == collect<ContentPart>(select=NoEncapsulatedMessages) | ||
62 | (ap1, ap2) == collect<AttachmentParts>(select=NoEncapsulatedMessages) | ||
63 | |||
64 | #INLINE GPG encrypted msg + attachment | ||
65 | * ContentPart => cp1 with | ||
66 | plaintext=[Content, Content(encrytion = (enc1(rec1,rec2),)), Content(signed = (sig1,)), Content] | ||
67 | * AttachmentPart => ap1 | ||
68 | |||
69 | (cp1) == collect<ContentPart>(select=NoEncapsulatedMessages) | ||
70 | (ap1) == collect<AttachmentParts>(select=NoEncapsulatedMessages) | ||
71 | |||
72 | [Content, Content(encrytion = (enc1(rec1,rec2),)), Content(signed = (sig1,)), Content] == cp1.content(Plaintext) | ||
73 | |||
74 | #forwared encrypted msg + attachments | ||
75 | * ContentPart => cp1 | ||
76 | * EncapsulatedPart => ep1 | ||
77 | * Encrytion=(rec1,rec2) => enc1 | ||
78 | * Signature => sig1 | ||
79 | * ContentPart(encrytion = (enc1,), signature = (sig1,)) => cp2 | ||
80 | * Content(encrytion = (enc1,), signature = (sig1,)) | ||
81 | * Content(encrytion = (enc1, enc2(rec3,rec4),), signature = (sig1,)) | ||
82 | * AttachmentPart(encrytion = (enc1,), signature = (sig1,)) => ap1 | ||
83 | * AttachmentPart => ap2 | ||
84 | |||
85 | (cp1) = collect<ContentPart>(select=NoEncapsulatedMessages) | ||
86 | (ap2) = collect<AttachmentParts>(select=NoEncapsulatedMessages) | ||
87 | |||
88 | (cp2) = collect<ContentPart>(ep1, select=NoEncapsulatedMessages) | ||
89 | (ap1) = collect<AttachmentParts>(ep1, select=NoEncapsulatedMessages) | ||
90 | |||
91 | (cp1, cp2) == collect<ContentPart>() | ||
92 | (ap1, ap2) == collect<AttachmentParts>()[Content, Content(encrytion = (enc1(rec1,rec2),)), Content(signed = (sig1,)), Content] | ||
93 | |||
94 | |||
95 | # plaintext msg + attachment + cert | ||
96 | * ContentPart => cp1 | ||
97 | * AttachmentPart => ap1 | ||
98 | * CertPart => cep1 | ||
99 | |||
100 | (cp1) == collect<ContentPart>(select=NoEncapsulatedMessages) | ||
101 | (ap1, cep1) == collect<AttachmentPart>(select=NoEncapsulatedMessages) | ||
102 | (ap1) == collect<AttachmentPart>(select=NoEncapsulatedMessages, filter=filterSubAttachmentParts) | ||
103 | |||
104 | (cep1) == collect<CertPart>(select=NoEncapsulatedMessages) | ||
105 | |||
106 | |||
107 | collect function: | ||
108 | |||
109 | bool noEncapsulatedMessages(Part part) | ||
110 | { | ||
111 | if (is<EncapsulatedPart>(part)) { | ||
112 | return false; | ||
113 | } | ||
114 | return true; | ||
115 | } | ||
116 | |||
117 | bool filterRelated(T part) | ||
118 | { | ||
119 | if (part.mimetype == related && !part.cid.isEmpty()) { | ||
120 | return false; //filter out related parts | ||
121 | } | ||
122 | return true; | ||
123 | } | ||
124 | |||
125 | bool filterSubAttachmentParts(AttachmentPart part) | ||
126 | { | ||
127 | if (isSubPart<AttachmentPart>(part)) { | ||
128 | return false; // filter out CertPart f.ex. | ||
129 | } | ||
130 | return true; | ||
131 | } | ||
132 | |||
133 | List<T> collect<T>(Part start, std::function<bool(const Part &)> select, std::function<bool(const std::shared_ptr<T> &)> filter) { | ||
134 | List<T> col; | ||
135 | if (!select(start)) { | ||
136 | return col; | ||
137 | } | ||
138 | |||
139 | if(isOrSubTypeIs<T>(start) && filter(start.staticCast<T>)){ | ||
140 | col.append(p); | ||
141 | } | ||
142 | foreach(childs as child) { | ||
143 | if (select(child)) { | ||
144 | col.expand(collect(child,select,filter); | ||
145 | } | ||
146 | } | ||
147 | return col; | ||
148 | } \ No newline at end of file | ||
diff --git a/framework/src/domain/mime/objecttreesource.cpp b/framework/src/domain/mime/objecttreesource.cpp new file mode 100644 index 00000000..186fdf80 --- /dev/null +++ b/framework/src/domain/mime/objecttreesource.cpp | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
3 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along | ||
16 | with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #include "objecttreesource.h" | ||
21 | |||
22 | #include <otp/attachmentstrategy.h> | ||
23 | #include <otp/bodypartformatterbasefactory.h> | ||
24 | #include <otp/messagepart.h> | ||
25 | #include <otp/messagepartrenderer.h> | ||
26 | |||
27 | class ObjectSourcePrivate | ||
28 | { | ||
29 | public: | ||
30 | ObjectSourcePrivate() | ||
31 | : mWriter(0) | ||
32 | , mAllowDecryption(true) | ||
33 | , mHtmlLoadExternal(true) | ||
34 | , mPreferredMode(MimeTreeParser::Util::Html) | ||
35 | { | ||
36 | |||
37 | } | ||
38 | MimeTreeParser::HtmlWriter *mWriter; | ||
39 | MimeTreeParser::BodyPartFormatterBaseFactory mBodyPartFormatterBaseFactory; | ||
40 | bool mAllowDecryption; | ||
41 | bool mHtmlLoadExternal; | ||
42 | MimeTreeParser::Util::HtmlMode mPreferredMode; | ||
43 | }; | ||
44 | |||
45 | ObjectTreeSource::ObjectTreeSource(MimeTreeParser::HtmlWriter *writer) | ||
46 | : MimeTreeParser::Interface::ObjectTreeSource() | ||
47 | , d(new ObjectSourcePrivate) | ||
48 | { | ||
49 | d->mWriter = writer; | ||
50 | } | ||
51 | |||
52 | ObjectTreeSource::~ObjectTreeSource() | ||
53 | { | ||
54 | delete d; | ||
55 | } | ||
56 | |||
57 | void ObjectTreeSource::setAllowDecryption(bool allowDecryption) | ||
58 | { | ||
59 | d->mAllowDecryption = allowDecryption; | ||
60 | } | ||
61 | |||
62 | MimeTreeParser::HtmlWriter *ObjectTreeSource::htmlWriter() | ||
63 | { | ||
64 | return d->mWriter; | ||
65 | } | ||
66 | |||
67 | bool ObjectTreeSource::htmlLoadExternal() const | ||
68 | { | ||
69 | return d->mHtmlLoadExternal; | ||
70 | } | ||
71 | |||
72 | void ObjectTreeSource::setHtmlLoadExternal(bool loadExternal) | ||
73 | { | ||
74 | d->mHtmlLoadExternal = loadExternal; | ||
75 | } | ||
76 | |||
77 | bool ObjectTreeSource::decryptMessage() const | ||
78 | { | ||
79 | return d->mAllowDecryption; | ||
80 | } | ||
81 | |||
82 | bool ObjectTreeSource::showSignatureDetails() const | ||
83 | { | ||
84 | return true; | ||
85 | } | ||
86 | |||
87 | int ObjectTreeSource::levelQuote() const | ||
88 | { | ||
89 | return 1; | ||
90 | } | ||
91 | |||
92 | const QTextCodec *ObjectTreeSource::overrideCodec() | ||
93 | { | ||
94 | return Q_NULLPTR; | ||
95 | } | ||
96 | |||
97 | QString ObjectTreeSource::createMessageHeader(KMime::Message *message) | ||
98 | { | ||
99 | return QString(); | ||
100 | } | ||
101 | |||
102 | const MimeTreeParser::AttachmentStrategy *ObjectTreeSource::attachmentStrategy() | ||
103 | { | ||
104 | return MimeTreeParser::AttachmentStrategy::smart(); | ||
105 | } | ||
106 | |||
107 | QObject *ObjectTreeSource::sourceObject() | ||
108 | { | ||
109 | return Q_NULLPTR; | ||
110 | } | ||
111 | |||
112 | void ObjectTreeSource::setHtmlMode(MimeTreeParser::Util::HtmlMode mode, const QList<MimeTreeParser::Util::HtmlMode> &availableModes) | ||
113 | { | ||
114 | Q_UNUSED(mode); | ||
115 | Q_UNUSED(availableModes); | ||
116 | } | ||
117 | |||
118 | MimeTreeParser::Util::HtmlMode ObjectTreeSource::preferredMode() const | ||
119 | { | ||
120 | return d->mPreferredMode; | ||
121 | } | ||
122 | |||
123 | bool ObjectTreeSource::autoImportKeys() const | ||
124 | { | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | bool ObjectTreeSource::showEmoticons() const | ||
129 | { | ||
130 | return false; | ||
131 | } | ||
132 | |||
133 | bool ObjectTreeSource::showExpandQuotesMark() const | ||
134 | { | ||
135 | return false; | ||
136 | } | ||
137 | |||
138 | bool ObjectTreeSource::isPrinting() const | ||
139 | { | ||
140 | return false; | ||
141 | } | ||
142 | |||
143 | const MimeTreeParser::BodyPartFormatterBaseFactory *ObjectTreeSource::bodyPartFormatterFactory() | ||
144 | { | ||
145 | return &(d->mBodyPartFormatterBaseFactory); | ||
146 | } | ||
147 | |||
148 | MimeTreeParser::Interface::MessagePartRenderer::Ptr ObjectTreeSource::messagePartTheme(MimeTreeParser::Interface::MessagePart::Ptr msgPart) | ||
149 | { | ||
150 | Q_UNUSED(msgPart); | ||
151 | return MimeTreeParser::Interface::MessagePartRenderer::Ptr(); | ||
152 | } | ||
diff --git a/framework/src/domain/mime/objecttreesource.h b/framework/src/domain/mime/objecttreesource.h new file mode 100644 index 00000000..2167e06f --- /dev/null +++ b/framework/src/domain/mime/objecttreesource.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net | ||
3 | Copyright (c) 2009 Andras Mantia <andras@kdab.net> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along | ||
16 | with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef MAILVIEWER_OBJECTTREEEMPTYSOURCE_H | ||
21 | #define MAILVIEWER_OBJECTTREEEMPTYSOURCE_H | ||
22 | |||
23 | #include <otp/objecttreesource.h> | ||
24 | |||
25 | class QString; | ||
26 | |||
27 | class ObjectSourcePrivate; | ||
28 | class ObjectTreeSource : public MimeTreeParser::Interface::ObjectTreeSource | ||
29 | { | ||
30 | public: | ||
31 | ObjectTreeSource(MimeTreeParser::HtmlWriter *writer); | ||
32 | virtual ~ObjectTreeSource(); | ||
33 | void setHtmlLoadExternal(bool loadExternal); | ||
34 | bool decryptMessage() const Q_DECL_OVERRIDE; | ||
35 | bool htmlLoadExternal() const Q_DECL_OVERRIDE; | ||
36 | bool showSignatureDetails() const Q_DECL_OVERRIDE; | ||
37 | void setHtmlMode(MimeTreeParser::Util::HtmlMode mode, const QList<MimeTreeParser::Util::HtmlMode> &availableModes) Q_DECL_OVERRIDE; | ||
38 | MimeTreeParser::Util::HtmlMode preferredMode() const Q_DECL_OVERRIDE; | ||
39 | void setAllowDecryption(bool allowDecryption); | ||
40 | int levelQuote() const Q_DECL_OVERRIDE; | ||
41 | const QTextCodec *overrideCodec() Q_DECL_OVERRIDE; | ||
42 | QString createMessageHeader(KMime::Message *message) Q_DECL_OVERRIDE; | ||
43 | const MimeTreeParser::AttachmentStrategy *attachmentStrategy() Q_DECL_OVERRIDE; | ||
44 | MimeTreeParser::HtmlWriter *htmlWriter() Q_DECL_OVERRIDE; | ||
45 | QObject *sourceObject() Q_DECL_OVERRIDE; | ||
46 | bool autoImportKeys() const Q_DECL_OVERRIDE; | ||
47 | bool showEmoticons() const Q_DECL_OVERRIDE; | ||
48 | bool showExpandQuotesMark() const Q_DECL_OVERRIDE; | ||
49 | bool isPrinting() const Q_DECL_OVERRIDE; | ||
50 | const MimeTreeParser::BodyPartFormatterBaseFactory *bodyPartFormatterFactory() Q_DECL_OVERRIDE; | ||
51 | MimeTreeParser::Interface::MessagePartRendererPtr messagePartTheme(MimeTreeParser::Interface::MessagePartPtr msgPart) Q_DECL_OVERRIDE; | ||
52 | private: | ||
53 | ObjectSourcePrivate *const d; | ||
54 | }; | ||
55 | |||
56 | #endif | ||
57 | |||
diff --git a/framework/src/domain/mime/stringhtmlwriter.cpp b/framework/src/domain/mime/stringhtmlwriter.cpp new file mode 100644 index 00000000..88034492 --- /dev/null +++ b/framework/src/domain/mime/stringhtmlwriter.cpp | |||
@@ -0,0 +1,150 @@ | |||
1 | /* -*- c++ -*- | ||
2 | filehtmlwriter.cpp | ||
3 | |||
4 | This file is part of KMail, the KDE mail client. | ||
5 | Copyright (c) 2003 Marc Mutz <mutz@kde.org> | ||
6 | |||
7 | KMail is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License, version 2, as | ||
9 | published by the Free Software Foundation. | ||
10 | |||
11 | KMail is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | |||
20 | In addition, as a special exception, the copyright holders give | ||
21 | permission to link the code of this program with any edition of | ||
22 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
23 | of Qt that use the same license as Qt), and distribute linked | ||
24 | combinations including the two. You must obey the GNU General | ||
25 | Public License in all respects for all of the code used other than | ||
26 | Qt. If you modify this file, you may extend this exception to | ||
27 | your version of the file, but you are not obligated to do so. If | ||
28 | you do not wish to do so, delete this exception statement from | ||
29 | your version. | ||
30 | */ | ||
31 | |||
32 | #include "stringhtmlwriter.h" | ||
33 | |||
34 | #include <QDebug> | ||
35 | #include <QTextStream> | ||
36 | #include <QUrl> | ||
37 | |||
38 | StringHtmlWriter::StringHtmlWriter() | ||
39 | : MimeTreeParser::HtmlWriter() | ||
40 | , mState(Ended) | ||
41 | { | ||
42 | } | ||
43 | |||
44 | StringHtmlWriter::~StringHtmlWriter() | ||
45 | { | ||
46 | } | ||
47 | |||
48 | void StringHtmlWriter::begin(const QString &css) | ||
49 | { | ||
50 | if (mState != Ended) { | ||
51 | qWarning() << "begin() called on non-ended session!"; | ||
52 | reset(); | ||
53 | } | ||
54 | |||
55 | mState = Begun; | ||
56 | mExtraHead.clear(); | ||
57 | mHtml.clear(); | ||
58 | |||
59 | if (!css.isEmpty()) { | ||
60 | write(QLatin1String("<!-- CSS Definitions \n") + css + QLatin1String("-->\n")); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void StringHtmlWriter::end() | ||
65 | { | ||
66 | if (mState != Begun) { | ||
67 | qWarning() << "Called on non-begun or queued session!"; | ||
68 | } | ||
69 | |||
70 | if (!mExtraHead.isEmpty()) { | ||
71 | insertExtraHead(); | ||
72 | mExtraHead.clear(); | ||
73 | } | ||
74 | resolveCidUrls(); | ||
75 | mState = Ended; | ||
76 | } | ||
77 | |||
78 | void StringHtmlWriter::reset() | ||
79 | { | ||
80 | if (mState != Ended) { | ||
81 | mHtml.clear(); | ||
82 | mExtraHead.clear(); | ||
83 | mState = Begun; // don't run into end()'s warning | ||
84 | end(); | ||
85 | mState = Ended; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | void StringHtmlWriter::write(const QString &str) | ||
90 | { | ||
91 | if (mState != Begun) { | ||
92 | qWarning() << "Called in Ended or Queued state!"; | ||
93 | } | ||
94 | mHtml.append(str); | ||
95 | } | ||
96 | |||
97 | void StringHtmlWriter::queue(const QString &str) | ||
98 | { | ||
99 | write(str); | ||
100 | } | ||
101 | |||
102 | void StringHtmlWriter::flush() | ||
103 | { | ||
104 | mState = Begun; // don't run into end()'s warning | ||
105 | end(); | ||
106 | } | ||
107 | |||
108 | void StringHtmlWriter::embedPart(const QByteArray &contentId, const QString &url) | ||
109 | { | ||
110 | write("<!-- embedPart(contentID=" + contentId + ", url=" + url + ") -->\n"); | ||
111 | mEmbeddedPartMap.insert(contentId, url); | ||
112 | } | ||
113 | |||
114 | void StringHtmlWriter::resolveCidUrls() | ||
115 | { | ||
116 | for (const auto &cid : mEmbeddedPartMap.keys()) { | ||
117 | mHtml.replace(QString("src=\"cid:%1\"").arg(QString(cid)), QString("src=\"%1\"").arg(mEmbeddedPartMap.value(cid).toString())); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | void StringHtmlWriter::extraHead(const QString &extraHead) | ||
122 | { | ||
123 | if (mState != Ended) { | ||
124 | qWarning() << "Called on non-started session!"; | ||
125 | } | ||
126 | mExtraHead.append(extraHead); | ||
127 | } | ||
128 | |||
129 | |||
130 | void StringHtmlWriter::insertExtraHead() | ||
131 | { | ||
132 | const QString headTag(QStringLiteral("<head>")); | ||
133 | const int index = mHtml.indexOf(headTag); | ||
134 | if (index != -1) { | ||
135 | mHtml.insert(index + headTag.length(), mExtraHead); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | QMap<QByteArray, QUrl> StringHtmlWriter::embeddedParts() const | ||
140 | { | ||
141 | return mEmbeddedPartMap; | ||
142 | } | ||
143 | |||
144 | QString StringHtmlWriter::html() const | ||
145 | { | ||
146 | if (mState != Ended) { | ||
147 | qWarning() << "Called on non-ended session!"; | ||
148 | } | ||
149 | return mHtml; | ||
150 | } | ||
diff --git a/framework/src/domain/mime/stringhtmlwriter.h b/framework/src/domain/mime/stringhtmlwriter.h new file mode 100644 index 00000000..20f6763e --- /dev/null +++ b/framework/src/domain/mime/stringhtmlwriter.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* -*- c++ -*- | ||
2 | |||
3 | Copyright (c) 2016 Sandro Knauß <sknauss@kde.org> | ||
4 | |||
5 | Kube is free software; you can redistribute it and/or modify it | ||
6 | under the terms of the GNU General Public License, version 2, as | ||
7 | published by the Free Software Foundation. | ||
8 | |||
9 | Kube is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | |||
18 | In addition, as a special exception, the copyright holders give | ||
19 | permission to link the code of this program with any edition of | ||
20 | the Qt library by Trolltech AS, Norway (or with modified versions | ||
21 | of Qt that use the same license as Qt), and distribute linked | ||
22 | combinations including the two. You must obey the GNU General | ||
23 | Public License in all respects for all of the code used other than | ||
24 | Qt. If you modify this file, you may extend this exception to | ||
25 | your version of the file, but you are not obligated to do so. If | ||
26 | you do not wish to do so, delete this exception statement from | ||
27 | your version. | ||
28 | */ | ||
29 | |||
30 | #ifndef __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ | ||
31 | #define __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ | ||
32 | |||
33 | #include <otp/htmlwriter.h> | ||
34 | |||
35 | #include <QFile> | ||
36 | #include <QTextStream> | ||
37 | |||
38 | class QString; | ||
39 | |||
40 | class StringHtmlWriter : public MimeTreeParser::HtmlWriter | ||
41 | { | ||
42 | public: | ||
43 | explicit StringHtmlWriter(); | ||
44 | virtual ~StringHtmlWriter(); | ||
45 | |||
46 | void begin(const QString &cssDefs) Q_DECL_OVERRIDE; | ||
47 | void end() Q_DECL_OVERRIDE; | ||
48 | void reset() Q_DECL_OVERRIDE; | ||
49 | void write(const QString &str) Q_DECL_OVERRIDE; | ||
50 | void queue(const QString &str) Q_DECL_OVERRIDE; | ||
51 | void flush() Q_DECL_OVERRIDE; | ||
52 | void embedPart(const QByteArray &contentId, const QString &url) Q_DECL_OVERRIDE; | ||
53 | void extraHead(const QString &str) Q_DECL_OVERRIDE; | ||
54 | |||
55 | QString html() const; | ||
56 | QMap<QByteArray, QUrl> embeddedParts() const; | ||
57 | private: | ||
58 | void insertExtraHead(); | ||
59 | void resolveCidUrls(); | ||
60 | |||
61 | QString mHtml; | ||
62 | QString mExtraHead; | ||
63 | enum State { | ||
64 | Begun, | ||
65 | Queued, | ||
66 | Ended | ||
67 | } mState; | ||
68 | QMap<QByteArray, QUrl> mEmbeddedPartMap; | ||
69 | }; | ||
70 | |||
71 | #endif // __MESSAGEVIEWER_FILEHTMLWRITER_H__ | ||