diff options
-rw-r--r-- | components/CMakeLists.txt | 1 | ||||
-rw-r--r-- | components/mailviewer/qml/DummyApp.qml | 55 | ||||
-rw-r--r-- | components/mailviewer/qml/HtmlPart.qml | 2 | ||||
-rw-r--r-- | components/mailviewer/qml/MailPart.qml | 36 | ||||
-rw-r--r-- | components/mailviewer/qml/TextPart.qml | 4 | ||||
-rw-r--r-- | components/mailviewer/qml/dummyapp.qml | 90 | ||||
-rw-r--r-- | components/package/contents/ui/MailViewer.qml | 31 | ||||
-rw-r--r-- | framework/domain/CMakeLists.txt | 2 | ||||
-rw-r--r-- | framework/domain/messageparser.cpp | 123 | ||||
-rw-r--r-- | framework/domain/messageparser.h | 57 | ||||
-rw-r--r-- | framework/domain/messageparser_new.cpp | 148 | ||||
-rw-r--r-- | framework/domain/messageparser_old.cpp | 140 | ||||
-rw-r--r-- | framework/domain/mimetreeparser/CMakeLists.txt | 5 | ||||
-rw-r--r-- | framework/domain/mimetreeparser/interface.cpp | 14 | ||||
-rw-r--r-- | framework/domain/mimetreeparser/interface.h | 2 | ||||
-rw-r--r-- | framework/domain/mimetreeparser/tests/data/openpgp-inline-encrypted+nonenc.mbox | 31 | ||||
-rw-r--r-- | framework/domain/mimetreeparser/tests/interfacetest.cpp | 27 |
17 files changed, 528 insertions, 240 deletions
diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 4fad0387..66e27822 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt | |||
@@ -24,6 +24,7 @@ find_package(KF5 REQUIRED COMPONENTS Package) | |||
24 | 24 | ||
25 | install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kube/components) | 25 | install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kube/components) |
26 | install(DIRECTORY package/contents/ui/ DESTINATION ${QML_INSTALL_DIR}/org/kube/components) | 26 | install(DIRECTORY package/contents/ui/ DESTINATION ${QML_INSTALL_DIR}/org/kube/components) |
27 | install(DIRECTORY mailviewer/qml/ DESTINATION ${QML_INSTALL_DIR}/org/kube/components) | ||
27 | 28 | ||
28 | include(${CMAKE_SOURCE_DIR}/KF5KirigamiMacros.cmake) | 29 | include(${CMAKE_SOURCE_DIR}/KF5KirigamiMacros.cmake) |
29 | kirigami_package_breeze_icons(ICONS applications-graphics view-list-icons folder-sync view-list-details configure document-edit dialog-cancel document-decrypt mail-reply-sender bookmarks folder) | 30 | kirigami_package_breeze_icons(ICONS applications-graphics view-list-icons folder-sync view-list-details configure document-edit dialog-cancel document-decrypt mail-reply-sender bookmarks folder) |
diff --git a/components/mailviewer/qml/DummyApp.qml b/components/mailviewer/qml/DummyApp.qml new file mode 100644 index 00000000..acb91ac1 --- /dev/null +++ b/components/mailviewer/qml/DummyApp.qml | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | Copyright (C) 2016 Michael Bohlender, <michael.bohlender@kdemail.net> | ||
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 | import QtQuick 2.4 | ||
20 | |||
21 | Item { | ||
22 | Column { | ||
23 | anchors { | ||
24 | top: parent.top | ||
25 | left: parent.left | ||
26 | right: parent.right | ||
27 | margins: 20 | ||
28 | } | ||
29 | |||
30 | spacing: 10 | ||
31 | width: parent.width | ||
32 | Repeater { | ||
33 | model: messageParser.newTree | ||
34 | |||
35 | delegate: Column { | ||
36 | id: delegateRoot | ||
37 | |||
38 | width: parent.width | ||
39 | |||
40 | Loader { | ||
41 | id: loader | ||
42 | } | ||
43 | |||
44 | Component.onCompleted: { | ||
45 | switch (model.type) { | ||
46 | case "AlternativePart": | ||
47 | case "SinglePart": | ||
48 | loader.source = "MailPart.qml"; | ||
49 | break; | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | } | ||
diff --git a/components/mailviewer/qml/HtmlPart.qml b/components/mailviewer/qml/HtmlPart.qml index f1add75c..f812ecb4 100644 --- a/components/mailviewer/qml/HtmlPart.qml +++ b/components/mailviewer/qml/HtmlPart.qml | |||
@@ -24,7 +24,7 @@ import QtWebEngine 1.2 | |||
24 | 24 | ||
25 | Item { | 25 | Item { |
26 | id: root | 26 | id: root |
27 | property string content: model.htmlContent | 27 | property string content: model.content |
28 | property int contentHeight: helperView.contentHeight; | 28 | property int contentHeight: helperView.contentHeight; |
29 | //FIXME workaround until QtWebEngine 1.3 with contentsSize | 29 | //FIXME workaround until QtWebEngine 1.3 with contentsSize |
30 | 30 | ||
diff --git a/components/mailviewer/qml/MailPart.qml b/components/mailviewer/qml/MailPart.qml index 966337cd..d47b4c5f 100644 --- a/components/mailviewer/qml/MailPart.qml +++ b/components/mailviewer/qml/MailPart.qml | |||
@@ -21,24 +21,22 @@ import QtQuick 2.4 | |||
21 | Item { | 21 | Item { |
22 | id: root | 22 | id: root |
23 | 23 | ||
24 | height: partColumn.height + 40 | 24 | height: partColumn.height + 20 |
25 | width: delegateRoot.width | 25 | width: delegateRoot.width |
26 | 26 | ||
27 | Column { | 27 | Column { |
28 | id: partColumn | 28 | id: partColumn |
29 | |||
30 | anchors { | 29 | anchors { |
31 | top: parent.top | 30 | top: parent.top |
32 | left: parent.left | 31 | left: parent.left |
33 | right: parent.right | 32 | right: parent.right |
34 | margins: 20 | 33 | margins: 10 |
35 | } | 34 | } |
36 | 35 | ||
37 | spacing: 10 | 36 | spacing: 5 |
38 | 37 | ||
39 | Repeater { | 38 | Repeater { |
40 | model: content | 39 | model: contents |
41 | |||
42 | delegate: Column { | 40 | delegate: Column { |
43 | id: delegateRoot | 41 | id: delegateRoot |
44 | 42 | ||
@@ -49,23 +47,29 @@ Item { | |||
49 | } | 47 | } |
50 | 48 | ||
51 | Component.onCompleted: { | 49 | Component.onCompleted: { |
52 | |||
53 | switch (model.type) { | 50 | switch (model.type) { |
51 | case "AlternativePart": | ||
52 | case "SinglePart": | ||
53 | loader.source = "MailPart.qml"; | ||
54 | break; | ||
55 | |||
56 | case "PlainTextContent": | ||
57 | case "Content": | ||
58 | loader.source = "TextPart.qml"; | ||
59 | break; | ||
60 | case "HtmlContent": | ||
61 | loader.source = "HtmlPart.qml"; | ||
62 | break; | ||
63 | |||
64 | case "alternativeframe": | ||
65 | loader.source = "Frame.qml" | ||
66 | break; | ||
54 | case "encrypted": | 67 | case "encrypted": |
55 | loader.source = "EncryptedPart.qml"; | 68 | loader.source = "EncryptedPart.qml"; |
56 | break; | 69 | break; |
57 | case "embeded": | 70 | case "embeded": |
58 | loader.source = "EmbededPart.qml"; | 71 | loader.source = "EmbededPart.qml"; |
59 | break; | 72 | break; |
60 | case "frame": | ||
61 | loader.source = "Frame.qml" | ||
62 | break; | ||
63 | case "plaintext": | ||
64 | loader.source = "TextPart.qml"; | ||
65 | break; | ||
66 | case "html": | ||
67 | loader.source = "HtmlPart.qml"; | ||
68 | break; | ||
69 | } | 73 | } |
70 | } | 74 | } |
71 | } | 75 | } |
diff --git a/components/mailviewer/qml/TextPart.qml b/components/mailviewer/qml/TextPart.qml index 5f183852..0267682f 100644 --- a/components/mailviewer/qml/TextPart.qml +++ b/components/mailviewer/qml/TextPart.qml | |||
@@ -21,8 +21,8 @@ import QtQuick 2.4 | |||
21 | Text { | 21 | Text { |
22 | width: delegateRoot.width | 22 | width: delegateRoot.width |
23 | 23 | ||
24 | text: model.textContent | 24 | text: model.content |
25 | wrapMode: Text.WordWrap | 25 | wrapMode: Text.WordWrap |
26 | 26 | ||
27 | color: embeded ? "grey" : "black" | 27 | color: model.securityLevel //embeded ? "grey" : "black" |
28 | } | 28 | } |
diff --git a/components/mailviewer/qml/dummyapp.qml b/components/mailviewer/qml/dummyapp.qml deleted file mode 100644 index a186f0f1..00000000 --- a/components/mailviewer/qml/dummyapp.qml +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | /* | ||
2 | Copyright (C) 2016 Michael Bohlender, <michael.bohlender@kdemail.net> | ||
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 | import QtQuick 2.4 | ||
20 | |||
21 | Rectangle { | ||
22 | id: app | ||
23 | |||
24 | width: 1200 | ||
25 | height: 700 | ||
26 | |||
27 | Rectangle { | ||
28 | anchors.fill: parent | ||
29 | |||
30 | color: "black" | ||
31 | |||
32 | opacity: 0.8 | ||
33 | |||
34 | } | ||
35 | |||
36 | Rectangle { | ||
37 | |||
38 | anchors.centerIn: parent | ||
39 | |||
40 | height: mainColumn.height + 50 | ||
41 | width: parent.width * 0.9 | ||
42 | |||
43 | Column { | ||
44 | id: mainColumn | ||
45 | |||
46 | anchors.centerIn: parent | ||
47 | |||
48 | width: parent.width - 50 | ||
49 | |||
50 | spacing: 10 | ||
51 | |||
52 | Repeater { | ||
53 | model: MailModel {} | ||
54 | |||
55 | delegate: Column { | ||
56 | id: delegateRoot | ||
57 | |||
58 | width: mainColumn.width | ||
59 | |||
60 | Loader { | ||
61 | id: loader | ||
62 | } | ||
63 | |||
64 | Component.onCompleted: { | ||
65 | switch (model.type) { | ||
66 | case "red": | ||
67 | loader.source = "Rect2.qml"; | ||
68 | break; | ||
69 | case "green": | ||
70 | loader.source = "Rect1.qml"; | ||
71 | break; | ||
72 | case "encrypted": | ||
73 | loader.source = "EncryptedPart.qml"; | ||
74 | break; | ||
75 | case "frame": | ||
76 | loader.source = "Frame.qml"; | ||
77 | break; | ||
78 | case "plaintext": | ||
79 | loader.source = "TextPart.qml"; | ||
80 | break; | ||
81 | case "html": | ||
82 | loader.source = "HtmlPart.qml"; | ||
83 | break; | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | } | ||
diff --git a/components/package/contents/ui/MailViewer.qml b/components/package/contents/ui/MailViewer.qml index 5365be66..347f30de 100644 --- a/components/package/contents/ui/MailViewer.qml +++ b/components/package/contents/ui/MailViewer.qml | |||
@@ -27,8 +27,8 @@ Item { | |||
27 | id: root | 27 | id: root |
28 | property variant message; | 28 | property variant message; |
29 | property string html; | 29 | property string html; |
30 | property bool enablePartTreeView : false | 30 | property bool enablePartTreeView : true; |
31 | property int desiredHeight: enablePartTreeView ? topPartLoader.height+450 : topPartLoader.height; | 31 | property int desiredHeight: enablePartTreeView ? topPartLoader.height + dummyApp.height + mailStructure.height + 50 : topPartLoader.height + dummyApp.height + 50; |
32 | 32 | ||
33 | Rectangle { | 33 | Rectangle { |
34 | id: rootRectangle | 34 | id: rootRectangle |
@@ -41,6 +41,19 @@ Item { | |||
41 | verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff | 41 | verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff |
42 | Column { | 42 | Column { |
43 | spacing:2 | 43 | spacing:2 |
44 | Text { | ||
45 | text: "New Mailviewer:" | ||
46 | color: "blue" | ||
47 | } | ||
48 | DummyApp { | ||
49 | id: dummyApp | ||
50 | height: 800 | ||
51 | width: rootRectangle.width | ||
52 | } | ||
53 | Text { | ||
54 | text: "Old Mailviewer:" | ||
55 | color: "blue" | ||
56 | } | ||
44 | MessagePartTree { | 57 | MessagePartTree { |
45 | id: topPartLoader | 58 | id: topPartLoader |
46 | // width: rootRectangle.width | 59 | // width: rootRectangle.width |
@@ -48,6 +61,7 @@ Item { | |||
48 | width: topPartLoader.contentWidth >= rootRectangle.width ? topPartLoader.contentWidth : rootRectangle.width | 61 | width: topPartLoader.contentWidth >= rootRectangle.width ? topPartLoader.contentWidth : rootRectangle.width |
49 | } | 62 | } |
50 | TreeView { | 63 | TreeView { |
64 | id: mailStructure | ||
51 | visible: enablePartTreeView | 65 | visible: enablePartTreeView |
52 | width: rootRectangle.width | 66 | width: rootRectangle.width |
53 | height: 400 | 67 | height: 400 |
@@ -57,16 +71,17 @@ Item { | |||
57 | width: 300 | 71 | width: 300 |
58 | } | 72 | } |
59 | TableViewColumn { | 73 | TableViewColumn { |
60 | role: "isHidden" | 74 | role: "embeded" |
61 | title: "Hidden" | 75 | title: "Embeded" |
62 | width: 60 | 76 | width: 60 |
63 | } | 77 | } |
64 | TableViewColumn { | 78 | TableViewColumn { |
65 | role: "text" | 79 | role: "content" |
66 | title: "Text" | 80 | title: "Content" |
67 | width: 600 | 81 | width: 200 |
68 | } | 82 | } |
69 | model: messageParser.partTree | 83 | //model: messageParser.partTree |
84 | model: messageParser.newTree | ||
70 | } | 85 | } |
71 | } | 86 | } |
72 | } | 87 | } |
diff --git a/framework/domain/CMakeLists.txt b/framework/domain/CMakeLists.txt index 07f01367..c41da377 100644 --- a/framework/domain/CMakeLists.txt +++ b/framework/domain/CMakeLists.txt | |||
@@ -7,6 +7,8 @@ set(mailplugin_SRCS | |||
7 | stringhtmlwriter.cpp | 7 | stringhtmlwriter.cpp |
8 | composercontroller.cpp | 8 | composercontroller.cpp |
9 | messageparser.cpp | 9 | messageparser.cpp |
10 | messageparser_new.cpp | ||
11 | messageparser_old.cpp | ||
10 | mailtemplates.cpp | 12 | mailtemplates.cpp |
11 | retriever.cpp | 13 | retriever.cpp |
12 | accountfactory.cpp | 14 | accountfactory.cpp |
diff --git a/framework/domain/messageparser.cpp b/framework/domain/messageparser.cpp index febd1363..ef9fb0d2 100644 --- a/framework/domain/messageparser.cpp +++ b/framework/domain/messageparser.cpp | |||
@@ -33,125 +33,6 @@ | |||
33 | #include <MimeTreeParser/ObjectTreeParser> | 33 | #include <MimeTreeParser/ObjectTreeParser> |
34 | #include <MimeTreeParser/MessagePart> | 34 | #include <MimeTreeParser/MessagePart> |
35 | 35 | ||
36 | PartModel::PartModel(QSharedPointer<MimeTreeParser::MessagePart> partTree, std::shared_ptr<Parser> parser) | ||
37 | : mPartTree(partTree) | ||
38 | , mParser(parser) | ||
39 | { | ||
40 | } | ||
41 | |||
42 | QHash<int, QByteArray> PartModel::roleNames() const | ||
43 | { | ||
44 | QHash<int, QByteArray> roles; | ||
45 | roles[Text] = "text"; | ||
46 | roles[IsHtml] = "isHtml"; | ||
47 | roles[IsHidden] = "isHidden"; | ||
48 | roles[IsEncrypted] = "isEncrypted"; | ||
49 | roles[IsAttachment] = "isAttachment"; | ||
50 | roles[HasContent] = "hasContent"; | ||
51 | roles[Type] = "type"; | ||
52 | roles[IsHidden] = "isHidden"; | ||
53 | return roles; | ||
54 | } | ||
55 | |||
56 | QModelIndex PartModel::index(int row, int column, const QModelIndex &parent) const | ||
57 | { | ||
58 | // qDebug() << "index " << parent << row << column << mPartTree->subParts().size(); | ||
59 | if (!parent.isValid()) { | ||
60 | if (row < mPartTree->subParts().size()) { | ||
61 | auto part = mPartTree->subParts().at(row); | ||
62 | return createIndex(row, column, part.data()); | ||
63 | } | ||
64 | } else { | ||
65 | auto part = static_cast<MimeTreeParser::MessagePart*>(parent.internalPointer()); | ||
66 | auto subPart = part->subParts().at(row); | ||
67 | return createIndex(row, column, subPart.data()); | ||
68 | } | ||
69 | return QModelIndex(); | ||
70 | } | ||
71 | |||
72 | QVariant PartModel::data(const QModelIndex &index, int role) const | ||
73 | { | ||
74 | // qDebug() << "Getting data for index"; | ||
75 | if (index.isValid()) { | ||
76 | auto part = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer()); | ||
77 | switch (role) { | ||
78 | case Text: { | ||
79 | // qDebug() << "Getting text: " << part->property("text").toString(); | ||
80 | // FIXME: we should have a list per part, and not one for all parts. | ||
81 | auto text = part->property("htmlContent").toString(); | ||
82 | auto rx = QRegExp("src=(\"|')cid:([^\1]*)\1"); | ||
83 | int pos = 0; | ||
84 | while ((pos = rx.indexIn(text, pos)) != -1) { | ||
85 | auto repl = mParser->getPart(rx.cap(2).toUtf8()); | ||
86 | if (repl.isValid()) { | ||
87 | text.replace(rx.cap(0), QString("src=\"%1\"").arg(repl.toString())); | ||
88 | } | ||
89 | pos += rx.matchedLength(); | ||
90 | } | ||
91 | return text; | ||
92 | } | ||
93 | case IsAttachment: | ||
94 | return part->property("attachment").toBool(); | ||
95 | case IsEncrypted: | ||
96 | return part->property("isEncrypted").toBool(); | ||
97 | case IsHtml: | ||
98 | return part->property("isHtml").toBool(); | ||
99 | case HasContent: | ||
100 | return !part->property("htmlContent").toString().isEmpty(); | ||
101 | case Type: | ||
102 | return part->metaObject()->className(); | ||
103 | case IsHidden: | ||
104 | return false; | ||
105 | //return part->property("isHidden").toBool(); | ||
106 | |||
107 | } | ||
108 | } | ||
109 | return QVariant(); | ||
110 | } | ||
111 | |||
112 | QModelIndex PartModel::parent(const QModelIndex &index) const | ||
113 | { | ||
114 | // qDebug() << "parent " << index; | ||
115 | if (index.isValid()) { | ||
116 | auto part = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer()); | ||
117 | auto parentPart = static_cast<MimeTreeParser::MessagePart*>(part->parentPart()); | ||
118 | auto row = 0;//get the parents parent to find the index | ||
119 | if (!parentPart) { | ||
120 | parentPart = mPartTree.data(); | ||
121 | } | ||
122 | int i = 0; | ||
123 | for (const auto &p : parentPart->subParts()) { | ||
124 | if (p.data() == part) { | ||
125 | row = i; | ||
126 | break; | ||
127 | } | ||
128 | i++; | ||
129 | } | ||
130 | return createIndex(row, index.column(), parentPart); | ||
131 | } | ||
132 | return QModelIndex(); | ||
133 | } | ||
134 | |||
135 | int PartModel::rowCount(const QModelIndex &parent) const | ||
136 | { | ||
137 | // qDebug() << "Row count " << parent; | ||
138 | if (!parent.isValid()) { | ||
139 | // qDebug() << "Row count " << mPartTree->subParts().size(); | ||
140 | return mPartTree->subParts().size(); | ||
141 | } else { | ||
142 | auto part = static_cast<MimeTreeParser::MessagePart*>(parent.internalPointer()); | ||
143 | if (part) { | ||
144 | return part->subParts().size(); | ||
145 | } | ||
146 | } | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | int PartModel::columnCount(const QModelIndex &parent) const | ||
151 | { | ||
152 | // qDebug() << "Column count " << parent; | ||
153 | return 1; | ||
154 | } | ||
155 | 36 | ||
156 | class MessagePartPrivate | 37 | class MessagePartPrivate |
157 | { | 38 | { |
@@ -217,3 +98,7 @@ QAbstractItemModel *MessageParser::partTree() const | |||
217 | return new PartModel(d->mPartTree, d->mParser); | 98 | return new PartModel(d->mPartTree, d->mParser); |
218 | } | 99 | } |
219 | 100 | ||
101 | QAbstractItemModel *MessageParser::newTree() const | ||
102 | { | ||
103 | return new NewModel(d->mParser); | ||
104 | } | ||
diff --git a/framework/domain/messageparser.h b/framework/domain/messageparser.h index 9469f2b5..b3d7537d 100644 --- a/framework/domain/messageparser.h +++ b/framework/domain/messageparser.h | |||
@@ -32,6 +32,10 @@ | |||
32 | class QAbstractItemModel; | 32 | class QAbstractItemModel; |
33 | 33 | ||
34 | class Parser; | 34 | class Parser; |
35 | class Part; | ||
36 | typedef std::shared_ptr<Part> PartPtr; | ||
37 | class Content; | ||
38 | typedef std::shared_ptr<Content> ContentPtr; | ||
35 | class MessagePartPrivate; | 39 | class MessagePartPrivate; |
36 | 40 | ||
37 | class MessageParser : public QObject | 41 | class MessageParser : public QObject |
@@ -40,6 +44,7 @@ class MessageParser : public QObject | |||
40 | Q_PROPERTY (QVariant message READ message WRITE setMessage) | 44 | Q_PROPERTY (QVariant message READ message WRITE setMessage) |
41 | Q_PROPERTY (QString html READ html NOTIFY htmlChanged) | 45 | Q_PROPERTY (QString html READ html NOTIFY htmlChanged) |
42 | Q_PROPERTY (QAbstractItemModel* partTree READ partTree NOTIFY htmlChanged) | 46 | Q_PROPERTY (QAbstractItemModel* partTree READ partTree NOTIFY htmlChanged) |
47 | Q_PROPERTY (QAbstractItemModel* newTree READ newTree NOTIFY htmlChanged) | ||
43 | 48 | ||
44 | public: | 49 | public: |
45 | explicit MessageParser(QObject *parent = Q_NULLPTR); | 50 | explicit MessageParser(QObject *parent = Q_NULLPTR); |
@@ -50,6 +55,7 @@ public: | |||
50 | QVariant message() const; | 55 | QVariant message() const; |
51 | void setMessage(const QVariant &to); | 56 | void setMessage(const QVariant &to); |
52 | QAbstractItemModel *partTree() const; | 57 | QAbstractItemModel *partTree() const; |
58 | QAbstractItemModel *newTree() const; | ||
53 | 59 | ||
54 | signals: | 60 | signals: |
55 | void htmlChanged(); | 61 | void htmlChanged(); |
@@ -87,3 +93,54 @@ private: | |||
87 | std::shared_ptr<Parser> mParser; | 93 | std::shared_ptr<Parser> mParser; |
88 | }; | 94 | }; |
89 | 95 | ||
96 | |||
97 | class NewContentModel : public QAbstractItemModel { | ||
98 | Q_OBJECT | ||
99 | public: | ||
100 | NewContentModel (const PartPtr &part); | ||
101 | |||
102 | public: | ||
103 | enum Roles { | ||
104 | TypeRole = Qt::UserRole + 1, | ||
105 | ContentRole, | ||
106 | IsEmbededRole, | ||
107 | SecurityLevelRole | ||
108 | }; | ||
109 | |||
110 | QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; | ||
111 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
112 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; | ||
113 | QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; | ||
114 | int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
115 | int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
116 | |||
117 | private: | ||
118 | const PartPtr &mPart; | ||
119 | }; | ||
120 | |||
121 | class NewModel : public QAbstractItemModel { | ||
122 | Q_OBJECT | ||
123 | public: | ||
124 | NewModel(std::shared_ptr<Parser> parser); | ||
125 | |||
126 | public: | ||
127 | enum Roles { | ||
128 | TypeRole = Qt::UserRole + 1, | ||
129 | ContentsRole, | ||
130 | IsEmbededRole, | ||
131 | SecurityLevelRole | ||
132 | }; | ||
133 | |||
134 | QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; | ||
135 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
136 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; | ||
137 | QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; | ||
138 | int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
139 | int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
140 | |||
141 | private: | ||
142 | std::shared_ptr<Parser> mParser; | ||
143 | QVector<PartPtr> mParts; | ||
144 | QMap<Part *, std::shared_ptr<NewContentModel>> mContentMap; | ||
145 | }; | ||
146 | |||
diff --git a/framework/domain/messageparser_new.cpp b/framework/domain/messageparser_new.cpp new file mode 100644 index 00000000..d1b956f5 --- /dev/null +++ b/framework/domain/messageparser_new.cpp | |||
@@ -0,0 +1,148 @@ | |||
1 | |||
2 | /* | ||
3 | This library is free software; you can redistribute it and/or modify it | ||
4 | under the terms of the GNU Library General Public License as published by | ||
5 | the Free Software Foundation; either version 2 of the License, or (at your | ||
6 | option) any later version. | ||
7 | |||
8 | This library is distributed in the hope that it will be useful, but WITHOUT | ||
9 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | ||
11 | License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU Library General Public License | ||
14 | along with this library; see the file COPYING.LIB. If not, write to the | ||
15 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
16 | 02110-1301, USA. | ||
17 | */ | ||
18 | |||
19 | #include "messageparser.h" | ||
20 | #include "mimetreeparser/interface.h" | ||
21 | |||
22 | #include <QDebug> | ||
23 | |||
24 | NewModel::NewModel(std::shared_ptr<Parser> parser) | ||
25 | : mParser(parser) | ||
26 | { | ||
27 | mParts = mParser->collectContentParts(); | ||
28 | foreach(const auto &part, mParts) { | ||
29 | mContentMap.insert(part.get(), std::shared_ptr<NewContentModel>(new NewContentModel(part))); | ||
30 | } | ||
31 | } | ||
32 | |||
33 | QHash<int, QByteArray> NewModel::roleNames() const | ||
34 | { | ||
35 | QHash<int, QByteArray> roles; | ||
36 | roles[TypeRole] = "type"; | ||
37 | roles[ContentsRole] = "contents"; | ||
38 | roles[IsEmbededRole] = "embeded"; | ||
39 | roles[SecurityLevelRole] = "securityLevel"; | ||
40 | return roles; | ||
41 | } | ||
42 | |||
43 | QModelIndex NewModel::index(int row, int column, const QModelIndex &parent) const | ||
44 | { | ||
45 | if (!parent.isValid()) { | ||
46 | if (row < mParts.size()) { | ||
47 | auto part = mParts.at(row); | ||
48 | return createIndex(row, column, part.get()); | ||
49 | } | ||
50 | } | ||
51 | return QModelIndex(); | ||
52 | } | ||
53 | |||
54 | QVariant NewModel::data(const QModelIndex &index, int role) const | ||
55 | { | ||
56 | if (!index.parent().isValid()) { | ||
57 | auto part = static_cast<Part *>(index.internalPointer()); | ||
58 | switch (role) { | ||
59 | case TypeRole: | ||
60 | return QString::fromLatin1(part->type()); | ||
61 | case IsEmbededRole: | ||
62 | return index.parent().isValid(); | ||
63 | case SecurityLevelRole: | ||
64 | return QStringLiteral("GRAY"); | ||
65 | case ContentsRole: | ||
66 | return QVariant::fromValue<QAbstractItemModel *>(mContentMap.value(part).get()); | ||
67 | } | ||
68 | } | ||
69 | return QVariant(); | ||
70 | } | ||
71 | |||
72 | QModelIndex NewModel::parent(const QModelIndex &index) const | ||
73 | { | ||
74 | return QModelIndex(); | ||
75 | } | ||
76 | |||
77 | int NewModel::rowCount(const QModelIndex &parent) const | ||
78 | { | ||
79 | if (!parent.isValid()) { | ||
80 | return mParts.size(); | ||
81 | } | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | int NewModel::columnCount(const QModelIndex &parent) const | ||
86 | { | ||
87 | return 1; | ||
88 | } | ||
89 | |||
90 | NewContentModel::NewContentModel(const Part::Ptr &part) | ||
91 | : mPart(part) | ||
92 | { | ||
93 | } | ||
94 | |||
95 | QHash<int, QByteArray> NewContentModel::roleNames() const | ||
96 | { | ||
97 | QHash<int, QByteArray> roles; | ||
98 | roles[TypeRole] = "type"; | ||
99 | roles[ContentRole] = "content"; | ||
100 | roles[IsEmbededRole] = "embeded"; | ||
101 | roles[SecurityLevelRole] = "securityLevel"; | ||
102 | return roles; | ||
103 | } | ||
104 | |||
105 | QModelIndex NewContentModel::index(int row, int column, const QModelIndex &parent) const | ||
106 | { | ||
107 | if (!parent.isValid()) { | ||
108 | if (row < mPart->content().size()) { | ||
109 | auto part = mPart->content().at(row); | ||
110 | return createIndex(row, column, part.get()); | ||
111 | } | ||
112 | } | ||
113 | return QModelIndex(); | ||
114 | } | ||
115 | |||
116 | QVariant NewContentModel::data(const QModelIndex &index, int role) const | ||
117 | { | ||
118 | auto content = static_cast<Content *>(index.internalPointer()); | ||
119 | switch (role) { | ||
120 | case TypeRole: | ||
121 | return QString::fromLatin1(content->type()); | ||
122 | case IsEmbededRole: | ||
123 | return false; | ||
124 | case ContentRole: | ||
125 | return content->encodedContent(); | ||
126 | case SecurityLevelRole: | ||
127 | return content->encryptions().size() > mPart->encryptions().size() ? "red": "black"; //test for gpg inline | ||
128 | } | ||
129 | return QVariant(); | ||
130 | } | ||
131 | |||
132 | QModelIndex NewContentModel::parent(const QModelIndex &index) const | ||
133 | { | ||
134 | return QModelIndex(); | ||
135 | } | ||
136 | |||
137 | int NewContentModel::rowCount(const QModelIndex &parent) const | ||
138 | { | ||
139 | if (!parent.isValid()) { | ||
140 | return mPart->content().size(); | ||
141 | } | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | int NewContentModel::columnCount(const QModelIndex &parent) const | ||
146 | { | ||
147 | return 1; | ||
148 | } | ||
diff --git a/framework/domain/messageparser_old.cpp b/framework/domain/messageparser_old.cpp new file mode 100644 index 00000000..a364c8ab --- /dev/null +++ b/framework/domain/messageparser_old.cpp | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | This library is free software; you can redistribute it and/or modify it | ||
3 | under the terms of the GNU Library General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or (at your | ||
5 | option) any later version. | ||
6 | |||
7 | This library is distributed in the hope that it will be useful, but WITHOUT | ||
8 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
9 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | ||
10 | License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU Library General Public License | ||
13 | along with this library; see the file COPYING.LIB. If not, write to the | ||
14 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "messageparser.h" | ||
19 | #include "mimetreeparser/interface.h" | ||
20 | |||
21 | PartModel::PartModel(QSharedPointer<MimeTreeParser::MessagePart> partTree, std::shared_ptr<Parser> parser) | ||
22 | : mPartTree(partTree) | ||
23 | , mParser(parser) | ||
24 | { | ||
25 | } | ||
26 | |||
27 | QHash<int, QByteArray> PartModel::roleNames() const | ||
28 | { | ||
29 | QHash<int, QByteArray> roles; | ||
30 | roles[Text] = "text"; | ||
31 | roles[IsHtml] = "isHtml"; | ||
32 | roles[IsHidden] = "isHidden"; | ||
33 | roles[IsEncrypted] = "isEncrypted"; | ||
34 | roles[IsAttachment] = "isAttachment"; | ||
35 | roles[HasContent] = "hasContent"; | ||
36 | roles[Type] = "type"; | ||
37 | roles[IsHidden] = "isHidden"; | ||
38 | return roles; | ||
39 | } | ||
40 | |||
41 | QModelIndex PartModel::index(int row, int column, const QModelIndex &parent) const | ||
42 | { | ||
43 | // qDebug() << "index " << parent << row << column << mPartTree->subParts().size(); | ||
44 | if (!parent.isValid()) { | ||
45 | if (row < mPartTree->subParts().size()) { | ||
46 | auto part = mPartTree->subParts().at(row); | ||
47 | return createIndex(row, column, part.data()); | ||
48 | } | ||
49 | } else { | ||
50 | auto part = static_cast<MimeTreeParser::MessagePart*>(parent.internalPointer()); | ||
51 | auto subPart = part->subParts().at(row); | ||
52 | return createIndex(row, column, subPart.data()); | ||
53 | } | ||
54 | return QModelIndex(); | ||
55 | } | ||
56 | |||
57 | QVariant PartModel::data(const QModelIndex &index, int role) const | ||
58 | { | ||
59 | // qDebug() << "Getting data for index"; | ||
60 | if (index.isValid()) { | ||
61 | auto part = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer()); | ||
62 | switch (role) { | ||
63 | case Text: { | ||
64 | // qDebug() << "Getting text: " << part->property("text").toString(); | ||
65 | // FIXME: we should have a list per part, and not one for all parts. | ||
66 | auto text = part->property("htmlContent").toString(); | ||
67 | auto rx = QRegExp("src=(\"|')cid:([^\1]*)\1"); | ||
68 | int pos = 0; | ||
69 | while ((pos = rx.indexIn(text, pos)) != -1) { | ||
70 | auto repl = mParser->getPart(rx.cap(2).toUtf8()); | ||
71 | if (repl.isValid()) { | ||
72 | text.replace(rx.cap(0), QString("src=\"%1\"").arg(repl.toString())); | ||
73 | } | ||
74 | pos += rx.matchedLength(); | ||
75 | } | ||
76 | return text; | ||
77 | } | ||
78 | case IsAttachment: | ||
79 | return part->property("attachment").toBool(); | ||
80 | case IsEncrypted: | ||
81 | return part->property("isEncrypted").toBool(); | ||
82 | case IsHtml: | ||
83 | return part->property("isHtml").toBool(); | ||
84 | case HasContent: | ||
85 | return !part->property("htmlContent").toString().isEmpty(); | ||
86 | case Type: | ||
87 | return part->metaObject()->className(); | ||
88 | case IsHidden: | ||
89 | return false; | ||
90 | //return part->property("isHidden").toBool(); | ||
91 | |||
92 | } | ||
93 | } | ||
94 | return QVariant(); | ||
95 | } | ||
96 | |||
97 | QModelIndex PartModel::parent(const QModelIndex &index) const | ||
98 | { | ||
99 | // qDebug() << "parent " << index; | ||
100 | if (index.isValid()) { | ||
101 | auto part = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer()); | ||
102 | auto parentPart = static_cast<MimeTreeParser::MessagePart*>(part->parentPart()); | ||
103 | auto row = 0;//get the parents parent to find the index | ||
104 | if (!parentPart) { | ||
105 | parentPart = mPartTree.data(); | ||
106 | } | ||
107 | int i = 0; | ||
108 | for (const auto &p : parentPart->subParts()) { | ||
109 | if (p.data() == part) { | ||
110 | row = i; | ||
111 | break; | ||
112 | } | ||
113 | i++; | ||
114 | } | ||
115 | return createIndex(row, index.column(), parentPart); | ||
116 | } | ||
117 | return QModelIndex(); | ||
118 | } | ||
119 | |||
120 | int PartModel::rowCount(const QModelIndex &parent) const | ||
121 | { | ||
122 | // qDebug() << "Row count " << parent; | ||
123 | if (!parent.isValid()) { | ||
124 | // qDebug() << "Row count " << mPartTree->subParts().size(); | ||
125 | return mPartTree->subParts().size(); | ||
126 | } else { | ||
127 | auto part = static_cast<MimeTreeParser::MessagePart*>(parent.internalPointer()); | ||
128 | if (part) { | ||
129 | return part->subParts().size(); | ||
130 | } | ||
131 | } | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | int PartModel::columnCount(const QModelIndex &parent) const | ||
136 | { | ||
137 | // qDebug() << "Column count " << parent; | ||
138 | return 1; | ||
139 | } | ||
140 | |||
diff --git a/framework/domain/mimetreeparser/CMakeLists.txt b/framework/domain/mimetreeparser/CMakeLists.txt index e1c04893..64da2656 100644 --- a/framework/domain/mimetreeparser/CMakeLists.txt +++ b/framework/domain/mimetreeparser/CMakeLists.txt | |||
@@ -9,4 +9,7 @@ add_library(mimetreeparser SHARED ${mimetreeparser_SRCS}) | |||
9 | qt5_use_modules(mimetreeparser Core Gui) | 9 | qt5_use_modules(mimetreeparser Core Gui) |
10 | target_link_libraries(mimetreeparser KF5::Mime KF5::MimeTreeParser) | 10 | target_link_libraries(mimetreeparser KF5::Mime KF5::MimeTreeParser) |
11 | 11 | ||
12 | add_subdirectory(tests) \ No newline at end of file | 12 | install(TARGETS mimetreeparser |
13 | DESTINATION ${LIB_INSTALL_DIR}) | ||
14 | |||
15 | add_subdirectory(tests) | ||
diff --git a/framework/domain/mimetreeparser/interface.cpp b/framework/domain/mimetreeparser/interface.cpp index c3ecf79c..efa0fd40 100644 --- a/framework/domain/mimetreeparser/interface.cpp +++ b/framework/domain/mimetreeparser/interface.cpp | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #include <QMimeDatabase> | 31 | #include <QMimeDatabase> |
32 | #include <QMimeType> | 32 | #include <QMimeType> |
33 | #include <QTextCodec> | ||
33 | #include <QDebug> | 34 | #include <QDebug> |
34 | 35 | ||
35 | class MailMimePrivate | 36 | class MailMimePrivate |
@@ -356,6 +357,17 @@ QByteArray Content::charset() const | |||
356 | return d->mCodec; | 357 | return d->mCodec; |
357 | } | 358 | } |
358 | 359 | ||
360 | QString Content::encodedContent() const | ||
361 | { | ||
362 | return encodedContent(charset()); | ||
363 | } | ||
364 | |||
365 | QString Content::encodedContent(const QByteArray &charset) const | ||
366 | { | ||
367 | QTextCodec *codec = QTextCodec::codecForName(charset); | ||
368 | return codec->toUnicode(content()); | ||
369 | } | ||
370 | |||
359 | QByteArray Content::type() const | 371 | QByteArray Content::type() const |
360 | { | 372 | { |
361 | return "Content"; | 373 | return "Content"; |
@@ -496,7 +508,7 @@ void SinglePartPrivate::fillFrom(MimeTreeParser::TextMessagePart::Ptr part) | |||
496 | mContent.clear(); | 508 | mContent.clear(); |
497 | foreach (const auto &mp, part->subParts()) { | 509 | foreach (const auto &mp, part->subParts()) { |
498 | auto d_ptr = new ContentPrivate; | 510 | auto d_ptr = new ContentPrivate; |
499 | d_ptr->mContent = part->text().toLocal8Bit(); | 511 | d_ptr->mContent = mp->text().toLocal8Bit(); |
500 | d_ptr->mParent = q; | 512 | d_ptr->mParent = q; |
501 | d_ptr->mCodec = "utf-8"; | 513 | d_ptr->mCodec = "utf-8"; |
502 | const auto enc = mp.dynamicCast<MimeTreeParser::EncryptedMessagePart>(); | 514 | const auto enc = mp.dynamicCast<MimeTreeParser::EncryptedMessagePart>(); |
diff --git a/framework/domain/mimetreeparser/interface.h b/framework/domain/mimetreeparser/interface.h index 7eadc311..67246f37 100644 --- a/framework/domain/mimetreeparser/interface.h +++ b/framework/domain/mimetreeparser/interface.h | |||
@@ -125,7 +125,7 @@ public: | |||
125 | QString encodedContent() const; | 125 | QString encodedContent() const; |
126 | 126 | ||
127 | // overwrite default charset with given charset | 127 | // overwrite default charset with given charset |
128 | QString encodedContent(QByteArray charset) const; | 128 | QString encodedContent(const QByteArray &charset) const; |
129 | 129 | ||
130 | QVector<SignaturePtr> signatures() const; | 130 | QVector<SignaturePtr> signatures() const; |
131 | QVector<EncryptionPtr> encryptions() const; | 131 | QVector<EncryptionPtr> encryptions() const; |
diff --git a/framework/domain/mimetreeparser/tests/data/openpgp-inline-encrypted+nonenc.mbox b/framework/domain/mimetreeparser/tests/data/openpgp-inline-encrypted+nonenc.mbox new file mode 100644 index 00000000..b98dc336 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/interfacetest.cpp b/framework/domain/mimetreeparser/tests/interfacetest.cpp index ac77b025..5a3cbb87 100644 --- a/framework/domain/mimetreeparser/tests/interfacetest.cpp +++ b/framework/domain/mimetreeparser/tests/interfacetest.cpp | |||
@@ -198,7 +198,32 @@ private slots: | |||
198 | auto contentAttachmentList = parser.collectAttachmentParts(); | 198 | auto contentAttachmentList = parser.collectAttachmentParts(); |
199 | QCOMPARE(contentAttachmentList.size(), 0); | 199 | QCOMPARE(contentAttachmentList.size(), 0); |
200 | } | 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("utf-8").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("utf-8").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 | } | ||
201 | }; | 226 | }; |
202 | 227 | ||
203 | QTEST_GUILESS_MAIN(InterfaceTest) | 228 | QTEST_GUILESS_MAIN(InterfaceTest) |
204 | #include "interfacetest.moc" \ No newline at end of file | 229 | #include "interfacetest.moc" |