summaryrefslogtreecommitdiffstats
path: root/framework/src
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src')
-rw-r--r--framework/src/domain/mime/mimetreeparser/messagepart.cpp15
-rw-r--r--framework/src/domain/mime/mimetreeparser/messagepart.h2
-rw-r--r--framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp38
-rw-r--r--framework/src/domain/mime/mimetreeparser/objecttreeparser.h1
-rw-r--r--framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp18
-rw-r--r--framework/src/domain/mime/mimetreeparser/textplain.cpp7
-rw-r--r--framework/src/domain/mime/partmodel.cpp74
-rw-r--r--framework/src/domain/mime/partmodel.h4
8 files changed, 133 insertions, 26 deletions
diff --git a/framework/src/domain/mime/mimetreeparser/messagepart.cpp b/framework/src/domain/mime/mimetreeparser/messagepart.cpp
index 00abb003..df4dfeac 100644
--- a/framework/src/domain/mime/mimetreeparser/messagepart.cpp
+++ b/framework/src/domain/mime/mimetreeparser/messagepart.cpp
@@ -1292,3 +1292,18 @@ QString EncapsulatedRfc822MessagePart::text() const
1292 return renderInternalText(); 1292 return renderInternalText();
1293} 1293}
1294 1294
1295QString EncapsulatedRfc822MessagePart::from() const
1296{
1297 if (auto from = mMessage->from(false)) {
1298 return from->asUnicodeString();
1299 }
1300 return {};
1301}
1302
1303QDateTime EncapsulatedRfc822MessagePart::date() const
1304{
1305 if (auto date = mMessage->date(false)) {
1306 return date->dateTime();
1307 }
1308 return {};
1309}
diff --git a/framework/src/domain/mime/mimetreeparser/messagepart.h b/framework/src/domain/mime/mimetreeparser/messagepart.h
index dd3a842f..7d266ac5 100644
--- a/framework/src/domain/mime/mimetreeparser/messagepart.h
+++ b/framework/src/domain/mime/mimetreeparser/messagepart.h
@@ -281,6 +281,8 @@ public:
281 virtual ~EncapsulatedRfc822MessagePart(); 281 virtual ~EncapsulatedRfc822MessagePart();
282 282
283 QString text() const Q_DECL_OVERRIDE; 283 QString text() const Q_DECL_OVERRIDE;
284 QString from() const;
285 QDateTime date() const;
284private: 286private:
285 const KMime::Message::Ptr mMessage; 287 const KMime::Message::Ptr mMessage;
286 288
diff --git a/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp b/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp
index b137be87..8d8ddf12 100644
--- a/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp
+++ b/framework/src/domain/mime/mimetreeparser/objecttreeparser.cpp
@@ -190,20 +190,17 @@ KMime::Content *ObjectTreeParser::find(const std::function<bool(KMime::Content *
190 * Filter to avoid evaluating a subtree. 190 * Filter to avoid evaluating a subtree.
191 * Select parts to include it in the result set. Selecting a part in a branch will keep any parent parts from being selected. 191 * Select parts to include it in the result set. Selecting a part in a branch will keep any parent parts from being selected.
192 */ 192 */
193static QVector<MessagePart::Ptr> collect(MessagePart::Ptr start, const std::function<bool(const MessagePartPtr &)> &filter, const std::function<bool(const MessagePartPtr &)> &select) 193static QVector<MessagePart::Ptr> collect(MessagePart::Ptr start, const std::function<bool(const MessagePartPtr &)> &evaluateSubtree, const std::function<bool(const MessagePartPtr &)> &select)
194{ 194{
195 MessagePartPtr ptr = start.dynamicCast<MessagePart>(); 195 MessagePartPtr ptr = start.dynamicCast<MessagePart>();
196 Q_ASSERT(ptr); 196 Q_ASSERT(ptr);
197 if (!filter(ptr)) {
198 return {};
199 }
200
201 QVector<MessagePart::Ptr> list; 197 QVector<MessagePart::Ptr> list;
202 if (ptr) { 198 if (evaluateSubtree(ptr)) {
203 for (const auto &p: ptr->subParts()) { 199 for (const auto &p: ptr->subParts()) {
204 list << ::collect(p, filter, select); 200 list << ::collect(p, evaluateSubtree, select);
205 } 201 }
206 } 202 }
203
207 //Don't consider this part if we already selected a subpart 204 //Don't consider this part if we already selected a subpart
208 if (list.isEmpty()) { 205 if (list.isEmpty()) {
209 if (select(ptr)) { 206 if (select(ptr)) {
@@ -213,14 +210,25 @@ static QVector<MessagePart::Ptr> collect(MessagePart::Ptr start, const std::func
213 return list; 210 return list;
214} 211}
215 212
216QVector<MessagePart::Ptr> ObjectTreeParser::collectContentParts() 213QVector<MessagePartPtr> ObjectTreeParser::collectContentParts()
217{ 214{
218 QVector<MessagePart::Ptr> contentParts = ::collect(mParsedPart, 215 return collectContentParts(mParsedPart);
219 [] (const MessagePartPtr &part) { 216}
220 // return p->type() != "EncapsulatedPart"; 217
218QVector<MessagePart::Ptr> ObjectTreeParser::collectContentParts(MessagePart::Ptr start)
219{
220 return ::collect(start,
221 [start] (const MessagePartPtr &part) {
222 //Ignore the top-level
223 if (start.data() == part.data()) {
224 return true;
225 }
226 if (auto e = part.dynamicCast<MimeTreeParser::EncapsulatedRfc822MessagePart>()) {
227 return false;
228 }
221 return true; 229 return true;
222 }, 230 },
223 [] (const MessagePartPtr &part) { 231 [start] (const MessagePartPtr &part) {
224 if (dynamic_cast<MimeTreeParser::AttachmentMessagePart*>(part.data())) { 232 if (dynamic_cast<MimeTreeParser::AttachmentMessagePart*>(part.data())) {
225 return false; 233 return false;
226 } else if (const auto text = dynamic_cast<MimeTreeParser::TextMessagePart*>(part.data())) { 234 } else if (const auto text = dynamic_cast<MimeTreeParser::TextMessagePart*>(part.data())) {
@@ -233,6 +241,11 @@ QVector<MessagePart::Ptr> ObjectTreeParser::collectContentParts()
233 return true; 241 return true;
234 } else if (dynamic_cast<MimeTreeParser::HtmlMessagePart*>(part.data())) { 242 } else if (dynamic_cast<MimeTreeParser::HtmlMessagePart*>(part.data())) {
235 return true; 243 return true;
244 } else if (dynamic_cast<MimeTreeParser::EncapsulatedRfc822MessagePart*>(part.data())) {
245 if (start.data() == part.data()) {
246 return false;
247 }
248 return true;
236 } else if (const auto enc = dynamic_cast<MimeTreeParser::EncryptedMessagePart*>(part.data())) { 249 } else if (const auto enc = dynamic_cast<MimeTreeParser::EncryptedMessagePart*>(part.data())) {
237 if (enc->error()) { 250 if (enc->error()) {
238 return true; 251 return true;
@@ -247,7 +260,6 @@ QVector<MessagePart::Ptr> ObjectTreeParser::collectContentParts()
247 } 260 }
248 return false; 261 return false;
249 }); 262 });
250 return contentParts;
251} 263}
252 264
253QVector<MessagePart::Ptr> ObjectTreeParser::collectAttachmentParts() 265QVector<MessagePart::Ptr> ObjectTreeParser::collectAttachmentParts()
diff --git a/framework/src/domain/mime/mimetreeparser/objecttreeparser.h b/framework/src/domain/mime/mimetreeparser/objecttreeparser.h
index 398cbcd7..d219a52b 100644
--- a/framework/src/domain/mime/mimetreeparser/objecttreeparser.h
+++ b/framework/src/domain/mime/mimetreeparser/objecttreeparser.h
@@ -285,6 +285,7 @@ public:
285 MessagePartPtr parsedPart() const; 285 MessagePartPtr parsedPart() const;
286 KMime::Content *find(const std::function<bool(KMime::Content *)> &select); 286 KMime::Content *find(const std::function<bool(KMime::Content *)> &select);
287 QVector<MessagePartPtr> collectContentParts(); 287 QVector<MessagePartPtr> collectContentParts();
288 QVector<MessagePartPtr> collectContentParts(MessagePart::Ptr start);
288 QVector<MessagePartPtr> collectAttachmentParts(); 289 QVector<MessagePartPtr> collectAttachmentParts();
289 void decryptParts(); 290 void decryptParts();
290 void importCertificates(); 291 void importCertificates();
diff --git a/framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp b/framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp
index f9b557c9..b9fdd356 100644
--- a/framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp
+++ b/framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp
@@ -319,6 +319,24 @@ private slots:
319 QVERIFY(bool(part)); 319 QVERIFY(bool(part));
320 QVERIFY(part->error()); 320 QVERIFY(part->error());
321 } 321 }
322
323 void testEncapsulated()
324 {
325 MimeTreeParser::ObjectTreeParser otp;
326 otp.parseObjectTree(readMailFromFile("encapsulated-with-attachment.mbox"));
327 otp.decryptParts();
328 auto partList = otp.collectContentParts();
329 QCOMPARE(partList.size(), 2);
330 auto part = partList[1].dynamicCast<MimeTreeParser::EncapsulatedRfc822MessagePart>();
331 QVERIFY(bool(part));
332 QCOMPARE(part->from(), QLatin1String("Thomas McGuire <dontspamme@gmx.net>"));
333 QCOMPARE(part->date().toString(), QLatin1String("Wed Aug 5 10:57:58 2009 GMT+0200"));
334 auto subPartList = otp.collectContentParts(part);
335 QCOMPARE(subPartList.size(), 1);
336 qWarning() << subPartList[0]->metaObject()->className();
337 auto subPart = subPartList[0].dynamicCast<MimeTreeParser::TextMessagePart>();
338 QVERIFY(bool(subPart));
339 }
322}; 340};
323 341
324QTEST_GUILESS_MAIN(InterfaceTest) 342QTEST_GUILESS_MAIN(InterfaceTest)
diff --git a/framework/src/domain/mime/mimetreeparser/textplain.cpp b/framework/src/domain/mime/mimetreeparser/textplain.cpp
index 32201a8a..d62cb2cf 100644
--- a/framework/src/domain/mime/mimetreeparser/textplain.cpp
+++ b/framework/src/domain/mime/mimetreeparser/textplain.cpp
@@ -41,13 +41,12 @@ const Interface::BodyPartFormatter *TextPlainBodyPartFormatter::create()
41MessagePart::Ptr TextPlainBodyPartFormatter::process(Interface::BodyPart &part) const 41MessagePart::Ptr TextPlainBodyPartFormatter::process(Interface::BodyPart &part) const
42{ 42{
43 KMime::Content *node = part.content(); 43 KMime::Content *node = part.content();
44 const bool isFirstTextPart = (node->topLevel()->textContent() == node);
45 44
46 TextMessagePart::Ptr mp; 45 TextMessagePart::Ptr mp;
47 if (isFirstTextPart) { 46 if (KMime::isAttachment(node)) {
48 mp = TextMessagePart::Ptr(new TextMessagePart(part.objectTreeParser(), node)); 47 mp = AttachmentMessagePart::Ptr(new AttachmentMessagePart(part.objectTreeParser(), node));
49 } else { 48 } else {
50 mp = TextMessagePart::Ptr(new AttachmentMessagePart(part.objectTreeParser(), node)); 49 mp = TextMessagePart::Ptr(new TextMessagePart(part.objectTreeParser(), node));
51 } 50 }
52 51
53 return mp; 52 return mp;
diff --git a/framework/src/domain/mime/partmodel.cpp b/framework/src/domain/mime/partmodel.cpp
index ea3e90e1..6ee3d46f 100644
--- a/framework/src/domain/mime/partmodel.cpp
+++ b/framework/src/domain/mime/partmodel.cpp
@@ -35,6 +35,8 @@ public:
35 void createTree(); 35 void createTree();
36 PartModel *q; 36 PartModel *q;
37 QVector<MimeTreeParser::MessagePartPtr> mParts; 37 QVector<MimeTreeParser::MessagePartPtr> mParts;
38 QHash<MimeTreeParser::MessagePart*, QVector<MimeTreeParser::MessagePartPtr>> mEncapsulatedParts;
39 QHash<MimeTreeParser::MessagePart*, MimeTreeParser::MessagePart*> mParents;
38 std::shared_ptr<MimeTreeParser::ObjectTreeParser> mParser; 40 std::shared_ptr<MimeTreeParser::ObjectTreeParser> mParser;
39}; 41};
40 42
@@ -44,6 +46,14 @@ PartModelPrivate::PartModelPrivate(PartModel *q_ptr, const std::shared_ptr<MimeT
44{ 46{
45 mParts = mParser->collectContentParts(); 47 mParts = mParser->collectContentParts();
46 qWarning() << "Collected content parts: " << mParts.size(); 48 qWarning() << "Collected content parts: " << mParts.size();
49 for (auto p : mParts) {
50 if (auto e = p.dynamicCast<MimeTreeParser::EncapsulatedRfc822MessagePart>()) {
51 mEncapsulatedParts[e.data()] = mParser->collectContentParts(e);
52 for (auto subPart : mEncapsulatedParts[e.data()]) {
53 mParents[subPart.data()] = e.data();
54 }
55 }
56 }
47} 57}
48 58
49PartModelPrivate::~PartModelPrivate() 59PartModelPrivate::~PartModelPrivate()
@@ -71,6 +81,8 @@ QHash<int, QByteArray> PartModel::roleNames() const
71 roles[EncryptionErrorType] = "errorType"; 81 roles[EncryptionErrorType] = "errorType";
72 roles[EncryptionErrorString] = "errorString"; 82 roles[EncryptionErrorString] = "errorString";
73 roles[IsErrorRole] = "error"; 83 roles[IsErrorRole] = "error";
84 roles[SenderRole] = "sender";
85 roles[DateRole] = "date";
74 return roles; 86 return roles;
75} 87}
76 88
@@ -79,6 +91,15 @@ QModelIndex PartModel::index(int row, int column, const QModelIndex &parent) con
79 if (row < 0 || column != 0) { 91 if (row < 0 || column != 0) {
80 return QModelIndex(); 92 return QModelIndex();
81 } 93 }
94 if (parent.isValid()) {
95 if (auto e = dynamic_cast<MimeTreeParser::EncapsulatedRfc822MessagePart*>(static_cast<MimeTreeParser::MessagePart*>(parent.internalPointer()))) {
96 const auto parts = d->mEncapsulatedParts[e];
97 if (row < parts.size()) {
98 return createIndex(row, column, parts.at(row).data());
99 }
100 }
101 return QModelIndex();
102 }
82 if (row < d->mParts.size()) { 103 if (row < d->mParts.size()) {
83 return createIndex(row, column, d->mParts.at(row).data()); 104 return createIndex(row, column, d->mParts.at(row).data());
84 } 105 }
@@ -88,26 +109,35 @@ QModelIndex PartModel::index(int row, int column, const QModelIndex &parent) con
88QVariant PartModel::data(const QModelIndex &index, int role) const 109QVariant PartModel::data(const QModelIndex &index, int role) const
89{ 110{
90 if (!index.isValid()) { 111 if (!index.isValid()) {
91 switch (role) {
92 case Qt::DisplayRole:
93 return QString("root");
94 case IsEmbededRole:
95 return false;
96 }
97 return QVariant(); 112 return QVariant();
98 } 113 }
99 114
100 if (index.internalPointer()) { 115 if (index.internalPointer()) {
101 const auto messagePart = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer()); 116 const auto messagePart = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer());
102 qWarning() << "Found message part " << messagePart->metaObject()->className() << messagePart->partMetaData()->status << messagePart->error(); 117 // qWarning() << "Found message part " << messagePart->metaObject()->className() << messagePart->partMetaData()->status << messagePart->error();
103 Q_ASSERT(messagePart); 118 Q_ASSERT(messagePart);
104 switch(role) { 119 switch(role) {
105 case Qt::DisplayRole: 120 case Qt::DisplayRole:
106 return QStringLiteral("Content%1"); 121 return QStringLiteral("Content%1");
122 case SenderRole: {
123 if (auto e = dynamic_cast<MimeTreeParser::EncapsulatedRfc822MessagePart*>(messagePart)) {
124 return e->from();
125 }
126 return {};
127 }
128 case DateRole: {
129 if (auto e = dynamic_cast<MimeTreeParser::EncapsulatedRfc822MessagePart*>(messagePart)) {
130 return e->date();
131 }
132 return {};
133 }
107 case TypeRole: { 134 case TypeRole: {
108 if (messagePart->error()) { 135 if (messagePart->error()) {
109 return "error"; 136 return "error";
110 } 137 }
138 if (dynamic_cast<MimeTreeParser::EncapsulatedRfc822MessagePart*>(messagePart)) {
139 return "encapsulated";
140 }
111 //For simple html we don't need a browser 141 //For simple html we don't need a browser
112 auto complexHtml = [&] { 142 auto complexHtml = [&] {
113 if (messagePart->isHtml()) { 143 if (messagePart->isHtml()) {
@@ -165,11 +195,39 @@ QVariant PartModel::data(const QModelIndex &index, int role) const
165 195
166QModelIndex PartModel::parent(const QModelIndex &index) const 196QModelIndex PartModel::parent(const QModelIndex &index) const
167{ 197{
168 return QModelIndex(); 198 if (index.isValid()) {
199 if (auto e = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer())) {
200 for (const auto &p : d->mParts) {
201 if (p.data() == e) {
202 return QModelIndex();
203 }
204 }
205 const auto parentPart = d->mParents[e];
206 Q_ASSERT(parentPart);
207 int row = 0;
208 const auto parts = d->mEncapsulatedParts[parentPart];
209 for (const auto &p : parts) {
210 if (p.data() == e) {
211 break;
212 }
213 row++;
214 }
215 return createIndex(row, 0, parentPart);
216 }
217 return {};
218 }
219 return {};
169} 220}
170 221
171int PartModel::rowCount(const QModelIndex &parent) const 222int PartModel::rowCount(const QModelIndex &parent) const
172{ 223{
224 if (parent.isValid()) {
225 if (auto e = dynamic_cast<MimeTreeParser::EncapsulatedRfc822MessagePart*>(static_cast<MimeTreeParser::MessagePart*>(parent.internalPointer()))) {
226 const auto parts = d->mEncapsulatedParts[e];
227 return parts.size();
228 }
229 return 0;
230 }
173 return d->mParts.count(); 231 return d->mParts.count();
174} 232}
175 233
diff --git a/framework/src/domain/mime/partmodel.h b/framework/src/domain/mime/partmodel.h
index efbd154b..a0e14b61 100644
--- a/framework/src/domain/mime/partmodel.h
+++ b/framework/src/domain/mime/partmodel.h
@@ -47,7 +47,9 @@ public:
47 IsErrorRole, 47 IsErrorRole,
48 SecurityLevelRole, 48 SecurityLevelRole,
49 EncryptionErrorType, 49 EncryptionErrorType,
50 EncryptionErrorString 50 EncryptionErrorString,
51 SenderRole,
52 DateRole
51 }; 53 };
52 54
53 QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; 55 QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE;