diff options
author | Sandro Knauß <sknauss@kde.org> | 2016-10-24 13:02:40 +0200 |
---|---|---|
committer | Sandro Knauß <sknauss@kde.org> | 2016-10-24 13:02:40 +0200 |
commit | 6aa695939b63fc7370e5eb80ecf7528aea1bd5e1 (patch) | |
tree | 91e7951411f541d7b71d64f15a2a38c6bbd7c577 | |
parent | 9be2b6515cf538673babda8764219b9af9691f6f (diff) | |
parent | a93a649f34ffa794884019e05c57869bd3bd4672 (diff) | |
download | kube-6aa695939b63fc7370e5eb80ecf7528aea1bd5e1.tar.gz kube-6aa695939b63fc7370e5eb80ecf7528aea1bd5e1.zip |
Merge branch 'dev/mimetreeinterface' into develop
58 files changed, 6163 insertions, 427 deletions
diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 4fad0387..30a9d09c 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/mailviewer) | ||
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/EncryptionPart.qml b/components/mailviewer/qml/EncryptionPart.qml new file mode 100644 index 00000000..a1adea43 --- /dev/null +++ b/components/mailviewer/qml/EncryptionPart.qml | |||
@@ -0,0 +1,68 @@ | |||
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 | id: encryption | ||
23 | property alias rootIndex: visualModel.rootIndex | ||
24 | property bool debug: true | ||
25 | height: partListView.height | ||
26 | width: parent.width | ||
27 | |||
28 | MailDataModel { | ||
29 | id: visualModel | ||
30 | debug: encryption.debug | ||
31 | model: messageParser.newTree | ||
32 | } | ||
33 | |||
34 | Column { | ||
35 | id: partListView | ||
36 | anchors { | ||
37 | top: parent.top | ||
38 | left: parent.left | ||
39 | } | ||
40 | width: parent.width | ||
41 | spacing: 5 | ||
42 | Text { | ||
43 | width: parent.width | ||
44 | visible: encryption.debug | ||
45 | text: model.type | ||
46 | } | ||
47 | BorderImage { | ||
48 | width: parent.width | ||
49 | height: childrenRect.height + 40 | ||
50 | border { left: 10; top: 10; right: 10; bottom: 10 } | ||
51 | horizontalTileMode: BorderImage.Round | ||
52 | verticalTileMode: BorderImage.Round | ||
53 | |||
54 | source: "securityborders"+ model.securityLevel +".png" | ||
55 | ListView { | ||
56 | model: visualModel | ||
57 | anchors { | ||
58 | top: parent.top | ||
59 | left: parent.left | ||
60 | margins: 20 | ||
61 | } | ||
62 | spacing: 20 | ||
63 | height: contentHeight | ||
64 | width: parent.width - 40 | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | } | ||
diff --git a/components/mailviewer/qml/HtmlPart.qml b/components/mailviewer/qml/HtmlContent.qml index f1add75c..15bd1915 100644 --- a/components/mailviewer/qml/HtmlPart.qml +++ b/components/mailviewer/qml/HtmlContent.qml | |||
@@ -24,12 +24,12 @@ 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 | ||
31 | height: contentHeight | 31 | height: contentHeight |
32 | width: delegateRoot.width | 32 | width: partColumn.width |
33 | 33 | ||
34 | WebView { | 34 | WebView { |
35 | id: helperView | 35 | id: helperView |
diff --git a/components/mailviewer/qml/MailDataModel.qml b/components/mailviewer/qml/MailDataModel.qml new file mode 100644 index 00000000..408d02e8 --- /dev/null +++ b/components/mailviewer/qml/MailDataModel.qml | |||
@@ -0,0 +1,65 @@ | |||
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 | VisualDataModel { | ||
22 | id: mailDataModel | ||
23 | property bool debug: true | ||
24 | delegate: Rectangle { | ||
25 | id: partColumn | ||
26 | width: parent.width | ||
27 | height: childrenRect.height | ||
28 | Loader { | ||
29 | id: partLoader | ||
30 | anchors { | ||
31 | top: parent.top | ||
32 | left: parent.left | ||
33 | } | ||
34 | height: item? item.contentHeight : 0 | ||
35 | width: parent.width | ||
36 | } | ||
37 | Component.onCompleted: { | ||
38 | switch (model.type) { | ||
39 | case "PlainTextContent": | ||
40 | case "Content": | ||
41 | partLoader.source = "TextContent.qml" | ||
42 | partLoader.item.debug = mailDataModel.debug | ||
43 | return; | ||
44 | case "HtmlContent": | ||
45 | partLoader.source = "HtmlContent.qml" | ||
46 | return; | ||
47 | case "Signature": | ||
48 | partLoader.source = "SignaturePart.qml" | ||
49 | partLoader.item.rootIndex = mailDataModel.modelIndex(index) | ||
50 | partLoader.item.debug = mailDataModel.debug | ||
51 | return; | ||
52 | case "Encryption": | ||
53 | partLoader.source = "EncryptionPart.qml" | ||
54 | partLoader.item.rootIndex = mailDataModel.modelIndex(index) | ||
55 | partLoader.item.debug = mailDataModel.debug | ||
56 | return; | ||
57 | } | ||
58 | if (model.hasModelChildren) { | ||
59 | partLoader.source = "MailPart.qml" | ||
60 | partLoader.item.rootIndex = mailDataModel.modelIndex(index) | ||
61 | partLoader.item.debug = mailDataModel.debug | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | } | ||
diff --git a/components/mailviewer/qml/MailModel.qml b/components/mailviewer/qml/MailModel.qml deleted file mode 100644 index d18f5ece..00000000 --- a/components/mailviewer/qml/MailModel.qml +++ /dev/null | |||
@@ -1,50 +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 | ListModel { | ||
22 | |||
23 | ListElement { | ||
24 | type: "encrypted" | ||
25 | securityLevel: "GREEN" | ||
26 | content: [ | ||
27 | ListElement { | ||
28 | type: "plaintext" | ||
29 | textContent: "Moin, \n find the forwarded mail below. \n \n - M" | ||
30 | embeded: false | ||
31 | }, | ||
32 | ListElement { | ||
33 | type: "embeded" | ||
34 | sender: "Senderson" | ||
35 | date: "05/05/2055" | ||
36 | content: [ | ||
37 | ListElement{ | ||
38 | type: "plaintext" | ||
39 | textContent: "sender mc senderson is a sender. sender mc senderson is a sender. sender mc senderson is a mc senderson is a sender sender mc senderson is a sender sender mc senderson is a sender sender mc senderson is a sender sender mc senderson is a sender sender mc a sender sender mc is a sender sender mc senderson is a sendersender mc senderson is a sender" | ||
40 | embeded: true | ||
41 | }] | ||
42 | } | ||
43 | ] | ||
44 | } | ||
45 | ListElement { | ||
46 | type: "plaintext" | ||
47 | textContent: "footer mc footerson" | ||
48 | embeded: false | ||
49 | } | ||
50 | } | ||
diff --git a/components/mailviewer/qml/MailModel2.qml b/components/mailviewer/qml/MailModel2.qml deleted file mode 100644 index 9ea45d57..00000000 --- a/components/mailviewer/qml/MailModel2.qml +++ /dev/null | |||
@@ -1,28 +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 | ListModel { | ||
22 | |||
23 | ListElement { | ||
24 | type: "html" | ||
25 | htmlContent: "<!DOCTYPE html> <html> <body> <h1>Some Heading</h1> <p>My some paragraph.</p> </body> </html>" | ||
26 | } | ||
27 | } | ||
28 | |||
diff --git a/components/mailviewer/qml/MailPart.qml b/components/mailviewer/qml/MailPart.qml index 966337cd..ad51a7ba 100644 --- a/components/mailviewer/qml/MailPart.qml +++ b/components/mailviewer/qml/MailPart.qml | |||
@@ -20,63 +20,27 @@ import QtQuick 2.4 | |||
20 | 20 | ||
21 | Item { | 21 | Item { |
22 | id: root | 22 | id: root |
23 | property alias rootIndex: visualModel.rootIndex | ||
24 | property bool debug: true | ||
25 | height: partListView.height + 10 | ||
26 | width: parent.width | ||
27 | |||
28 | MailDataModel { | ||
29 | id: visualModel | ||
30 | debug: root.debug | ||
31 | model: messageParser.newTree | ||
32 | } | ||
23 | 33 | ||
24 | height: partColumn.height + 40 | 34 | ListView { |
25 | width: delegateRoot.width | 35 | id: partListView |
26 | 36 | model: visualModel | |
27 | Column { | ||
28 | id: partColumn | ||
29 | |||
30 | anchors { | 37 | anchors { |
31 | top: parent.top | 38 | top: parent.top |
32 | left: parent.left | 39 | left: parent.left |
33 | right: parent.right | 40 | margins: 5 |
34 | margins: 20 | ||
35 | } | ||
36 | |||
37 | spacing: 10 | ||
38 | |||
39 | Repeater { | ||
40 | model: content | ||
41 | |||
42 | delegate: Column { | ||
43 | id: delegateRoot | ||
44 | |||
45 | width: partColumn.width | ||
46 | |||
47 | Loader { | ||
48 | id: loader | ||
49 | } | ||
50 | |||
51 | Component.onCompleted: { | ||
52 | |||
53 | switch (model.type) { | ||
54 | case "encrypted": | ||
55 | loader.source = "EncryptedPart.qml"; | ||
56 | break; | ||
57 | case "embeded": | ||
58 | loader.source = "EmbededPart.qml"; | ||
59 | 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 | } | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | |||
74 | |||
75 | Item { | ||
76 | id: footer | ||
77 | |||
78 | height: 5 | ||
79 | width: 10 | ||
80 | } | 41 | } |
42 | spacing: 5 | ||
43 | height: contentHeight | ||
44 | width: parent.width - 10 | ||
81 | } | 45 | } |
82 | } | 46 | } |
diff --git a/components/mailviewer/qml/EncryptedPart.qml b/components/mailviewer/qml/MailViewer.qml index 18a5d588..86a96913 100644 --- a/components/mailviewer/qml/EncryptedPart.qml +++ b/components/mailviewer/qml/MailViewer.qml | |||
@@ -17,27 +17,30 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | import QtQuick 2.4 | 19 | import QtQuick 2.4 |
20 | import QtQuick.Controls 1.5 | ||
21 | 20 | ||
22 | Item { | 21 | Item { |
23 | 22 | id: root | |
24 | height: mailPart.height + 20 | 23 | property alias rootIndex: visualModel.rootIndex |
25 | width: mailPart.width + 20 | 24 | property bool debug: true |
26 | 25 | height: partListView.height + 50 | |
27 | BorderImage { | 26 | width: parent.width * 0.9 |
28 | 27 | ||
29 | anchors.fill: parent | 28 | MailDataModel { |
30 | border { left: 40; top: 40; right: 40; bottom: 40 } | 29 | id: visualModel |
31 | horizontalTileMode: BorderImage.Round | 30 | debug: root.debug |
32 | verticalTileMode: BorderImage.Round | 31 | model: messageParser.newTree |
33 | |||
34 | source: "securityborders" + model.securityLevel + ".png" | ||
35 | } | 32 | } |
36 | 33 | ||
37 | MailPart { | 34 | ListView { |
38 | id: mailPart | 35 | id: partListView |
39 | 36 | model: visualModel | |
40 | anchors.centerIn: parent | 37 | anchors { |
41 | 38 | top: parent.top | |
39 | left: parent.left | ||
40 | margins: 5 | ||
41 | } | ||
42 | spacing: 5 | ||
43 | height: contentHeight | ||
44 | width: parent.width - 10 | ||
42 | } | 45 | } |
43 | } | 46 | } |
diff --git a/components/mailviewer/qml/SignaturePart.qml b/components/mailviewer/qml/SignaturePart.qml new file mode 100644 index 00000000..8a0e33ce --- /dev/null +++ b/components/mailviewer/qml/SignaturePart.qml | |||
@@ -0,0 +1,66 @@ | |||
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 | id: signature | ||
23 | property alias rootIndex: visualModel.rootIndex | ||
24 | property bool debug: true | ||
25 | height: partListView.height | ||
26 | width: parent.width | ||
27 | |||
28 | MailDataModel { | ||
29 | id: visualModel | ||
30 | debug: signature.debug | ||
31 | model: messageParser.newTree | ||
32 | } | ||
33 | Column { | ||
34 | id: partListView | ||
35 | anchors { | ||
36 | top: parent.top | ||
37 | left: parent.left | ||
38 | } | ||
39 | width: parent.width | ||
40 | spacing: 5 | ||
41 | Text { | ||
42 | width: parent.width | ||
43 | visible: signature.debug | ||
44 | text: model.type | ||
45 | } | ||
46 | BorderImage { | ||
47 | width: parent.width | ||
48 | height: childrenRect.height + 40 | ||
49 | border { left: 10; top: 10; right: 10; bottom: 10 } | ||
50 | horizontalTileMode: BorderImage.Round | ||
51 | verticalTileMode: BorderImage.Round | ||
52 | source: "securityborders"+ model.securityLevel +".png" | ||
53 | ListView { | ||
54 | model: visualModel | ||
55 | anchors { | ||
56 | top: parent.top | ||
57 | left: parent.left | ||
58 | margins: 20 | ||
59 | } | ||
60 | spacing: 20 | ||
61 | height: contentHeight | ||
62 | width: parent.width - 40 | ||
63 | } | ||
64 | } | ||
65 | } | ||
66 | } | ||
diff --git a/components/mailviewer/qml/SignedPart.qml b/components/mailviewer/qml/TextContent.qml index f0daedeb..2e0167d4 100644 --- a/components/mailviewer/qml/SignedPart.qml +++ b/components/mailviewer/qml/TextContent.qml | |||
@@ -17,28 +17,31 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | import QtQuick 2.4 | 19 | import QtQuick 2.4 |
20 | import QtQuick.Controls 1.5 | ||
21 | |||
22 | Item { | 20 | Item { |
23 | 21 | id: textItem | |
24 | height: mailPart.height + 20 | 22 | property bool debug: true |
25 | width: mailPart.width + 20 | 23 | width: partColumn.width |
26 | 24 | height: textColumn.height | |
27 | BorderImage { | 25 | Column { |
28 | 26 | id: textColumn | |
29 | anchors.fill: parent | 27 | anchors { |
30 | border { left: 40; top: 40; right: 40; bottom: 40 } | 28 | top: parent.top |
31 | horizontalTileMode: BorderImage.Round | 29 | left: parent.left |
32 | verticalTileMode: BorderImage.Round | 30 | } |
33 | 31 | width: parent.width | |
34 | source: "securityborders" + model.securityLevel + ".png" | 32 | spacing: 5 |
35 | } | 33 | Text { |
36 | 34 | width: parent.width | |
37 | MailPart { | 35 | visible: textItem.debug |
38 | id: mailPart | 36 | text: model.type |
39 | 37 | } | |
40 | anchors.centerIn: parent | 38 | Text { |
41 | 39 | width: parent.width | |
40 | |||
41 | text: model.content | ||
42 | wrapMode: Text.WordWrap | ||
43 | |||
44 | color: model.embeded ? "grey" : "black" | ||
45 | } | ||
42 | } | 46 | } |
43 | } | 47 | } |
44 | |||
diff --git a/components/mailviewer/qml/TextPart.qml b/components/mailviewer/qml/TextPart.qml deleted file mode 100644 index 5f183852..00000000 --- a/components/mailviewer/qml/TextPart.qml +++ /dev/null | |||
@@ -1,28 +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 | Text { | ||
22 | width: delegateRoot.width | ||
23 | |||
24 | text: model.textContent | ||
25 | wrapMode: Text.WordWrap | ||
26 | |||
27 | color: embeded ? "grey" : "black" | ||
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/mailviewer/qml/qmldir b/components/mailviewer/qml/qmldir new file mode 100644 index 00000000..0d87b779 --- /dev/null +++ b/components/mailviewer/qml/qmldir | |||
@@ -0,0 +1,3 @@ | |||
1 | module org.kube.mailviewer | ||
2 | |||
3 | MailViewer 1.0 MailViewer.qml | ||
diff --git a/components/package/contents/ui/MailViewer.qml b/components/package/contents/ui/MailViewer.qml index 5365be66..f8e0a33b 100644 --- a/components/package/contents/ui/MailViewer.qml +++ b/components/package/contents/ui/MailViewer.qml | |||
@@ -22,13 +22,14 @@ import QtQuick.Controls 1.4 | |||
22 | import QtQuick.Layouts 1.1 | 22 | import QtQuick.Layouts 1.1 |
23 | 23 | ||
24 | import org.kube.framework.domain 1.0 as KubeFramework | 24 | import org.kube.framework.domain 1.0 as KubeFramework |
25 | import org.kube.mailviewer 1.0 as MV | ||
25 | 26 | ||
26 | Item { | 27 | Item { |
27 | id: root | 28 | id: root |
28 | property variant message; | 29 | property variant message; |
29 | property string html; | 30 | property string html; |
30 | property bool enablePartTreeView : false | 31 | property bool enablePartTreeView : true; |
31 | property int desiredHeight: enablePartTreeView ? topPartLoader.height+450 : topPartLoader.height; | 32 | property int desiredHeight: enablePartTreeView ? topPartLoader.height + newMailViewer.height + mailStructure.height + 50 : topPartLoader.height + newMailViewer.height + 50; |
32 | 33 | ||
33 | Rectangle { | 34 | Rectangle { |
34 | id: rootRectangle | 35 | id: rootRectangle |
@@ -40,7 +41,20 @@ Item { | |||
40 | anchors.margins: 0 | 41 | anchors.margins: 0 |
41 | verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff | 42 | verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff |
42 | Column { | 43 | Column { |
43 | spacing:2 | 44 | spacing: 2 |
45 | Text { | ||
46 | text: "New Mailviewer:" | ||
47 | color: "blue" | ||
48 | } | ||
49 | MV.MailViewer { | ||
50 | id: newMailViewer | ||
51 | debug: false | ||
52 | width: rootRectangle.width | ||
53 | } | ||
54 | Text { | ||
55 | text: "Old Mailviewer:" | ||
56 | color: "blue" | ||
57 | } | ||
44 | MessagePartTree { | 58 | MessagePartTree { |
45 | id: topPartLoader | 59 | id: topPartLoader |
46 | // width: rootRectangle.width | 60 | // width: rootRectangle.width |
@@ -48,6 +62,7 @@ Item { | |||
48 | width: topPartLoader.contentWidth >= rootRectangle.width ? topPartLoader.contentWidth : rootRectangle.width | 62 | width: topPartLoader.contentWidth >= rootRectangle.width ? topPartLoader.contentWidth : rootRectangle.width |
49 | } | 63 | } |
50 | TreeView { | 64 | TreeView { |
65 | id: mailStructure | ||
51 | visible: enablePartTreeView | 66 | visible: enablePartTreeView |
52 | width: rootRectangle.width | 67 | width: rootRectangle.width |
53 | height: 400 | 68 | height: 400 |
@@ -57,16 +72,22 @@ Item { | |||
57 | width: 300 | 72 | width: 300 |
58 | } | 73 | } |
59 | TableViewColumn { | 74 | TableViewColumn { |
60 | role: "isHidden" | 75 | role: "embeded" |
61 | title: "Hidden" | 76 | title: "Embeded" |
77 | width: 60 | ||
78 | } | ||
79 | TableViewColumn { | ||
80 | role: "securityLevel" | ||
81 | title: "SecurityLevel" | ||
62 | width: 60 | 82 | width: 60 |
63 | } | 83 | } |
64 | TableViewColumn { | 84 | TableViewColumn { |
65 | role: "text" | 85 | role: "content" |
66 | title: "Text" | 86 | title: "Content" |
67 | width: 600 | 87 | width: 200 |
68 | } | 88 | } |
69 | model: messageParser.partTree | 89 | //model: messageParser.partTree |
90 | model: messageParser.newTree | ||
70 | } | 91 | } |
71 | } | 92 | } |
72 | } | 93 | } |
diff --git a/framework/domain/CMakeLists.txt b/framework/domain/CMakeLists.txt index 804b3ccb..a31bb016 100644 --- a/framework/domain/CMakeLists.txt +++ b/framework/domain/CMakeLists.txt | |||
@@ -7,7 +7,10 @@ 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 |
13 | modeltest.cpp | ||
11 | retriever.cpp | 14 | retriever.cpp |
12 | accountfactory.cpp | 15 | accountfactory.cpp |
13 | accountscontroller.cpp | 16 | accountscontroller.cpp |
@@ -20,10 +23,12 @@ find_package(KF5 REQUIRED COMPONENTS Package) | |||
20 | 23 | ||
21 | add_library(mailplugin SHARED ${mailplugin_SRCS}) | 24 | add_library(mailplugin SHARED ${mailplugin_SRCS}) |
22 | 25 | ||
23 | qt5_use_modules(mailplugin Core Quick Qml WebKitWidgets) | 26 | qt5_use_modules(mailplugin Core Quick Qml WebKitWidgets Test) |
24 | target_link_libraries(mailplugin actionplugin settingsplugin sink KF5::MimeTreeParser KF5::Codecs KF5::Package KF5::Async KF5::IconThemes) | 27 | target_link_libraries(mailplugin actionplugin settingsplugin sink mimetreeparser KF5::MimeTreeParser KF5::Codecs KF5::Package KF5::Async KF5::IconThemes) |
25 | 28 | ||
26 | add_subdirectory(actions/tests) | 29 | add_subdirectory(actions/tests) |
27 | 30 | ||
28 | install(TARGETS mailplugin DESTINATION ${QML_INSTALL_DIR}/org/kube/framework/domain) | 31 | install(TARGETS mailplugin DESTINATION ${QML_INSTALL_DIR}/org/kube/framework/domain) |
29 | install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kube/framework/domain) | 32 | install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kube/framework/domain) |
33 | |||
34 | add_subdirectory(mimetreeparser) | ||
diff --git a/framework/domain/messageparser.cpp b/framework/domain/messageparser.cpp index ff763aec..ec79d50b 100644 --- a/framework/domain/messageparser.cpp +++ b/framework/domain/messageparser.cpp | |||
@@ -18,9 +18,14 @@ | |||
18 | */ | 18 | */ |
19 | #include "messageparser.h" | 19 | #include "messageparser.h" |
20 | 20 | ||
21 | #include "modeltest.h" | ||
21 | #include "stringhtmlwriter.h" | 22 | #include "stringhtmlwriter.h" |
22 | #include "objecttreesource.h" | 23 | #include "objecttreesource.h" |
23 | 24 | ||
25 | #include "mimetreeparser/interface.h" | ||
26 | |||
27 | #include <QRegExp> | ||
28 | |||
24 | #include <QFile> | 29 | #include <QFile> |
25 | #include <QImage> | 30 | #include <QImage> |
26 | #include <QDebug> | 31 | #include <QDebug> |
@@ -29,128 +34,32 @@ | |||
29 | #include <MimeTreeParser/ObjectTreeParser> | 34 | #include <MimeTreeParser/ObjectTreeParser> |
30 | #include <MimeTreeParser/MessagePart> | 35 | #include <MimeTreeParser/MessagePart> |
31 | 36 | ||
32 | PartModel::PartModel(QSharedPointer<MimeTreeParser::MessagePart> partTree, QMap<QByteArray, QUrl> embeddedPartMap) : mPartTree(partTree), mEmbeddedPartMap(embeddedPartMap) | ||
33 | { | ||
34 | } | ||
35 | 37 | ||
36 | QHash<int, QByteArray> PartModel::roleNames() const | 38 | class MessagePartPrivate |
37 | { | 39 | { |
38 | QHash<int, QByteArray> roles; | 40 | public: |
39 | roles[Text] = "text"; | 41 | QSharedPointer<MimeTreeParser::MessagePart> mPartTree; |
40 | roles[IsHtml] = "isHtml"; | 42 | QString mHtml; |
41 | roles[IsHidden] = "isHidden"; | 43 | QMap<QByteArray, QUrl> mEmbeddedPartMap; |
42 | roles[IsEncrypted] = "isEncrypted"; | 44 | std::shared_ptr<MimeTreeParser::NodeHelper> mNodeHelper; |
43 | roles[IsAttachment] = "isAttachment"; | 45 | std::shared_ptr<Parser> mParser; |
44 | roles[HasContent] = "hasContent"; | 46 | }; |
45 | roles[Type] = "type"; | ||
46 | roles[IsHidden] = "isHidden"; | ||
47 | return roles; | ||
48 | } | ||
49 | 47 | ||
50 | QModelIndex PartModel::index(int row, int column, const QModelIndex &parent) const | 48 | MessageParser::MessageParser(QObject *parent) |
51 | { | 49 | : QObject(parent) |
52 | // qDebug() << "index " << parent << row << column << mPartTree->subParts().size(); | 50 | , d(std::unique_ptr<MessagePartPrivate>(new MessagePartPrivate)) |
53 | if (!parent.isValid()) { | ||
54 | if (row < mPartTree->subParts().size()) { | ||
55 | auto part = mPartTree->subParts().at(row); | ||
56 | return createIndex(row, column, part.data()); | ||
57 | } | ||
58 | } else { | ||
59 | auto part = static_cast<MimeTreeParser::MessagePart*>(parent.internalPointer()); | ||
60 | auto subPart = part->subParts().at(row); | ||
61 | return createIndex(row, column, subPart.data()); | ||
62 | } | ||
63 | return QModelIndex(); | ||
64 | } | ||
65 | |||
66 | QVariant PartModel::data(const QModelIndex &index, int role) const | ||
67 | { | ||
68 | // qDebug() << "Getting data for index"; | ||
69 | if (index.isValid()) { | ||
70 | auto part = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer()); | ||
71 | switch (role) { | ||
72 | case Text: { | ||
73 | // qDebug() << "Getting text: " << part->property("text").toString(); | ||
74 | // FIXME: we should have a list per part, and not one for all parts. | ||
75 | auto text = part->property("htmlContent").toString(); | ||
76 | for (const auto &cid : mEmbeddedPartMap.keys()) { | ||
77 | text.replace(QString("src=\"cid:%1\"").arg(QString(cid)), QString("src=\"%1\"").arg(mEmbeddedPartMap.value(cid).toString())); | ||
78 | } | ||
79 | return text; | ||
80 | } | ||
81 | case IsAttachment: | ||
82 | return part->property("attachment").toBool(); | ||
83 | case IsEncrypted: | ||
84 | return part->property("isEncrypted").toBool(); | ||
85 | case IsHtml: | ||
86 | return part->property("isHtml").toBool(); | ||
87 | case HasContent: | ||
88 | return !part->property("htmlContent").toString().isEmpty(); | ||
89 | case Type: | ||
90 | return part->metaObject()->className(); | ||
91 | case IsHidden: | ||
92 | return false; | ||
93 | //return part->property("isHidden").toBool(); | ||
94 | |||
95 | } | ||
96 | } | ||
97 | return QVariant(); | ||
98 | } | ||
99 | |||
100 | QModelIndex PartModel::parent(const QModelIndex &index) const | ||
101 | { | ||
102 | // qDebug() << "parent " << index; | ||
103 | if (index.isValid()) { | ||
104 | auto part = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer()); | ||
105 | auto parentPart = static_cast<MimeTreeParser::MessagePart*>(part->parentPart()); | ||
106 | auto row = 0;//get the parents parent to find the index | ||
107 | if (!parentPart) { | ||
108 | parentPart = mPartTree.data(); | ||
109 | } | ||
110 | int i = 0; | ||
111 | for (const auto &p : parentPart->subParts()) { | ||
112 | if (p.data() == part) { | ||
113 | row = i; | ||
114 | break; | ||
115 | } | ||
116 | i++; | ||
117 | } | ||
118 | return createIndex(row, index.column(), parentPart); | ||
119 | } | ||
120 | return QModelIndex(); | ||
121 | } | ||
122 | |||
123 | int PartModel::rowCount(const QModelIndex &parent) const | ||
124 | { | 51 | { |
125 | // qDebug() << "Row count " << parent; | ||
126 | if (!parent.isValid()) { | ||
127 | // qDebug() << "Row count " << mPartTree->subParts().size(); | ||
128 | return mPartTree->subParts().size(); | ||
129 | } else { | ||
130 | auto part = static_cast<MimeTreeParser::MessagePart*>(parent.internalPointer()); | ||
131 | if (part) { | ||
132 | return part->subParts().size(); | ||
133 | } | ||
134 | } | ||
135 | return 0; | ||
136 | } | ||
137 | 52 | ||
138 | int PartModel::columnCount(const QModelIndex &parent) const | ||
139 | { | ||
140 | // qDebug() << "Column count " << parent; | ||
141 | return 1; | ||
142 | } | 53 | } |
143 | 54 | ||
144 | 55 | MessageParser::~MessageParser() | |
145 | MessageParser::MessageParser(QObject *parent) | ||
146 | : QObject(parent) | ||
147 | { | 56 | { |
148 | 57 | ||
149 | } | 58 | } |
150 | 59 | ||
151 | QString MessageParser::html() const | 60 | QString MessageParser::html() const |
152 | { | 61 | { |
153 | return mHtml; | 62 | return d->mHtml; |
154 | } | 63 | } |
155 | 64 | ||
156 | QVariant MessageParser::message() const | 65 | QVariant MessageParser::message() const |
@@ -162,6 +71,8 @@ void MessageParser::setMessage(const QVariant &message) | |||
162 | { | 71 | { |
163 | QTime time; | 72 | QTime time; |
164 | time.start(); | 73 | time.start(); |
74 | d->mParser = std::shared_ptr<Parser>(new Parser(message.toByteArray())); | ||
75 | |||
165 | const auto mailData = KMime::CRLFtoLF(message.toByteArray()); | 76 | const auto mailData = KMime::CRLFtoLF(message.toByteArray()); |
166 | KMime::Message::Ptr msg(new KMime::Message); | 77 | KMime::Message::Ptr msg(new KMime::Message); |
167 | msg->setContent(mailData); | 78 | msg->setContent(mailData); |
@@ -171,20 +82,26 @@ void MessageParser::setMessage(const QVariant &message) | |||
171 | // render the mail | 82 | // render the mail |
172 | StringHtmlWriter htmlWriter; | 83 | StringHtmlWriter htmlWriter; |
173 | //temporary files only have the lifetime of the nodehelper, so we keep it around until the mail changes. | 84 | //temporary files only have the lifetime of the nodehelper, so we keep it around until the mail changes. |
174 | mNodeHelper = std::make_shared<MimeTreeParser::NodeHelper>(); | 85 | d->mNodeHelper = std::make_shared<MimeTreeParser::NodeHelper>(); |
175 | ObjectTreeSource source(&htmlWriter); | 86 | ObjectTreeSource source(&htmlWriter); |
176 | MimeTreeParser::ObjectTreeParser otp(&source, mNodeHelper.get()); | 87 | MimeTreeParser::ObjectTreeParser otp(&source, d->mNodeHelper.get()); |
177 | 88 | ||
178 | otp.parseObjectTree(msg.data()); | 89 | otp.parseObjectTree(msg.data()); |
179 | mPartTree = otp.parsedPart().dynamicCast<MimeTreeParser::MessagePart>(); | 90 | d->mPartTree = otp.parsedPart().dynamicCast<MimeTreeParser::MessagePart>(); |
180 | 91 | ||
181 | mEmbeddedPartMap = htmlWriter.embeddedParts(); | 92 | d->mEmbeddedPartMap = htmlWriter.embeddedParts(); |
182 | mHtml = htmlWriter.html(); | 93 | d->mHtml = htmlWriter.html(); |
183 | emit htmlChanged(); | 94 | emit htmlChanged(); |
184 | } | 95 | } |
185 | 96 | ||
186 | QAbstractItemModel *MessageParser::partTree() const | 97 | QAbstractItemModel *MessageParser::partTree() const |
187 | { | 98 | { |
188 | return new PartModel(mPartTree, mEmbeddedPartMap); | 99 | return new PartModel(d->mPartTree, d->mParser); |
189 | } | 100 | } |
190 | 101 | ||
102 | QAbstractItemModel *MessageParser::newTree() const | ||
103 | { | ||
104 | const auto model = new NewModel(d->mParser); | ||
105 | new ModelTest(model, model); | ||
106 | return model; | ||
107 | } | ||
diff --git a/framework/domain/messageparser.h b/framework/domain/messageparser.h index 3e0255df..559fa6f9 100644 --- a/framework/domain/messageparser.h +++ b/framework/domain/messageparser.h | |||
@@ -29,41 +29,49 @@ | |||
29 | #include <memory> | 29 | #include <memory> |
30 | #include <MimeTreeParser/MessagePart> | 30 | #include <MimeTreeParser/MessagePart> |
31 | 31 | ||
32 | namespace MimeTreeParser { | ||
33 | class NodeHelper; | ||
34 | }; | ||
35 | class QAbstractItemModel; | 32 | class QAbstractItemModel; |
36 | 33 | ||
34 | class Parser; | ||
35 | class Part; | ||
36 | class Encryption; | ||
37 | class Signature; | ||
38 | typedef std::shared_ptr<Part> PartPtr; | ||
39 | class Content; | ||
40 | typedef std::shared_ptr<Content> ContentPtr; | ||
41 | class MessagePartPrivate; | ||
42 | |||
43 | class NewModelPrivate; | ||
44 | |||
37 | class MessageParser : public QObject | 45 | class MessageParser : public QObject |
38 | { | 46 | { |
39 | Q_OBJECT | 47 | Q_OBJECT |
40 | Q_PROPERTY (QVariant message READ message WRITE setMessage) | 48 | Q_PROPERTY (QVariant message READ message WRITE setMessage) |
41 | Q_PROPERTY (QString html READ html NOTIFY htmlChanged) | 49 | Q_PROPERTY (QString html READ html NOTIFY htmlChanged) |
42 | Q_PROPERTY (QAbstractItemModel* partTree READ partTree NOTIFY htmlChanged) | 50 | Q_PROPERTY (QAbstractItemModel* partTree READ partTree NOTIFY htmlChanged) |
51 | Q_PROPERTY (QAbstractItemModel* newTree READ newTree NOTIFY htmlChanged) | ||
43 | 52 | ||
44 | public: | 53 | public: |
45 | explicit MessageParser(QObject *parent = Q_NULLPTR); | 54 | explicit MessageParser(QObject *parent = Q_NULLPTR); |
55 | ~MessageParser(); | ||
46 | 56 | ||
47 | QString html() const; | 57 | QString html() const; |
48 | 58 | ||
49 | QVariant message() const; | 59 | QVariant message() const; |
50 | void setMessage(const QVariant &to); | 60 | void setMessage(const QVariant &to); |
51 | QAbstractItemModel *partTree() const; | 61 | QAbstractItemModel *partTree() const; |
62 | QAbstractItemModel *newTree() const; | ||
52 | 63 | ||
53 | signals: | 64 | signals: |
54 | void htmlChanged(); | 65 | void htmlChanged(); |
55 | 66 | ||
56 | private: | 67 | private: |
57 | QSharedPointer<MimeTreeParser::MessagePart> mPartTree; | 68 | std::unique_ptr<MessagePartPrivate> d; |
58 | QString mHtml; | ||
59 | QMap<QByteArray, QUrl> mEmbeddedPartMap; | ||
60 | std::shared_ptr<MimeTreeParser::NodeHelper> mNodeHelper; | ||
61 | }; | 69 | }; |
62 | 70 | ||
63 | class PartModel : public QAbstractItemModel { | 71 | class PartModel : public QAbstractItemModel { |
64 | Q_OBJECT | 72 | Q_OBJECT |
65 | public: | 73 | public: |
66 | PartModel(QSharedPointer<MimeTreeParser::MessagePart> partTree, QMap<QByteArray, QUrl> embeddedPartMap); | 74 | PartModel(QSharedPointer<MimeTreeParser::MessagePart> partTree, std::shared_ptr<Parser> parser); |
67 | 75 | ||
68 | public: | 76 | public: |
69 | enum Roles { | 77 | enum Roles { |
@@ -86,5 +94,33 @@ public: | |||
86 | private: | 94 | private: |
87 | QSharedPointer<MimeTreeParser::MessagePart> mPartTree; | 95 | QSharedPointer<MimeTreeParser::MessagePart> mPartTree; |
88 | QMap<QByteArray, QUrl> mEmbeddedPartMap; | 96 | QMap<QByteArray, QUrl> mEmbeddedPartMap; |
97 | std::shared_ptr<Parser> mParser; | ||
98 | }; | ||
99 | |||
100 | |||
101 | class NewModel : public QAbstractItemModel { | ||
102 | Q_OBJECT | ||
103 | public: | ||
104 | NewModel(std::shared_ptr<Parser> parser); | ||
105 | ~NewModel(); | ||
106 | |||
107 | public: | ||
108 | enum Roles { | ||
109 | TypeRole = Qt::UserRole + 1, | ||
110 | ContentsRole, | ||
111 | ContentRole, | ||
112 | IsEmbededRole, | ||
113 | SecurityLevelRole | ||
114 | }; | ||
115 | |||
116 | QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; | ||
117 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
118 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; | ||
119 | QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; | ||
120 | int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
121 | int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; | ||
122 | |||
123 | private: | ||
124 | std::unique_ptr<NewModelPrivate> d; | ||
89 | }; | 125 | }; |
90 | 126 | ||
diff --git a/framework/domain/messageparser_new.cpp b/framework/domain/messageparser_new.cpp new file mode 100644 index 00000000..b930f33d --- /dev/null +++ b/framework/domain/messageparser_new.cpp | |||
@@ -0,0 +1,457 @@ | |||
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 | Q_DECLARE_METATYPE(Part *) | ||
25 | Q_DECLARE_METATYPE(Content *) | ||
26 | Q_DECLARE_METATYPE(Signature *) | ||
27 | Q_DECLARE_METATYPE(Encryption *) | ||
28 | |||
29 | class Entry; | ||
30 | |||
31 | class NewModelPrivate | ||
32 | { | ||
33 | public: | ||
34 | NewModelPrivate(NewModel *q_ptr, const std::shared_ptr<Parser> &parser); | ||
35 | ~NewModelPrivate(); | ||
36 | |||
37 | void createTree(); | ||
38 | |||
39 | QSharedPointer<QVariant> getVar(const std::shared_ptr<Signature> &sig); | ||
40 | QSharedPointer<QVariant> getVar(const std::shared_ptr<Encryption> &enc); | ||
41 | QSharedPointer<QVariant> getVar(const std::shared_ptr<Part> &part); | ||
42 | QSharedPointer<QVariant> getVar(Part *part); | ||
43 | QSharedPointer<QVariant> getVar(const std::shared_ptr<Content> &content); | ||
44 | QSharedPointer<QVariant> getVar(Content *content); | ||
45 | |||
46 | int getPos(Signature *sig); | ||
47 | int getPos(Encryption *enc); | ||
48 | int getPos(Part *part); | ||
49 | int getPos(Content *content); | ||
50 | |||
51 | NewModel *q; | ||
52 | QVector<Part::Ptr> mParts; | ||
53 | std::unique_ptr<Entry> mRoot; | ||
54 | |||
55 | std::shared_ptr<Parser> mParser; | ||
56 | private: | ||
57 | QMap<std::shared_ptr<Signature>, QSharedPointer<QVariant>> mSignatureMap; | ||
58 | QMap<std::shared_ptr<Encryption>, QSharedPointer<QVariant>> mEncryptionMap; | ||
59 | QMap<Part *, QSharedPointer<QVariant>> mPartMap; | ||
60 | QMap<Content *, QSharedPointer<QVariant>> mCMap; | ||
61 | }; | ||
62 | |||
63 | class Entry | ||
64 | { | ||
65 | public: | ||
66 | Entry(NewModelPrivate *model) | ||
67 | : mParent(nullptr) | ||
68 | , mNewModelPrivate(model) | ||
69 | { | ||
70 | } | ||
71 | |||
72 | ~Entry() | ||
73 | { | ||
74 | foreach(auto child, mChildren) { | ||
75 | delete child; | ||
76 | } | ||
77 | mChildren.clear(); | ||
78 | } | ||
79 | |||
80 | void addChild(Entry *entry) | ||
81 | { | ||
82 | mChildren.append(entry); | ||
83 | entry->mParent = this; | ||
84 | } | ||
85 | |||
86 | Entry *addSignatures(QVector<Signature::Ptr> signatures) | ||
87 | { | ||
88 | auto ret = this; | ||
89 | foreach(const auto &sig, signatures) { | ||
90 | auto entry = new Entry(mNewModelPrivate); | ||
91 | entry->mData = mNewModelPrivate->getVar(sig); | ||
92 | ret->addChild(entry); | ||
93 | ret = entry; | ||
94 | } | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | Entry *addEncryptions(QVector<Encryption::Ptr> encryptions) | ||
99 | { | ||
100 | auto ret = this; | ||
101 | foreach(const auto &enc, encryptions) { | ||
102 | auto entry = new Entry(mNewModelPrivate); | ||
103 | entry->mData = mNewModelPrivate->getVar(enc); | ||
104 | ret->addChild(entry); | ||
105 | ret = entry; | ||
106 | } | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | Entry *addPart(Part *part) | ||
111 | { | ||
112 | auto entry = new Entry(mNewModelPrivate); | ||
113 | entry->mData = mNewModelPrivate->getVar(part); | ||
114 | addChild(entry); | ||
115 | foreach(const auto &content, part->content()) { | ||
116 | auto _entry = entry; | ||
117 | _entry = _entry->addEncryptions(content->encryptions().mid(part->encryptions().size())); | ||
118 | _entry = _entry->addSignatures(content->signatures().mid(part->signatures().size())); | ||
119 | auto c = new Entry(mNewModelPrivate); | ||
120 | c->mData = mNewModelPrivate->getVar(content); | ||
121 | _entry->addChild(c); | ||
122 | } | ||
123 | foreach(const auto &sp, part->subParts()) { | ||
124 | auto _entry = entry; | ||
125 | _entry = _entry->addEncryptions(sp->encryptions().mid(part->encryptions().size())); | ||
126 | _entry = _entry->addSignatures(sp->signatures().mid(part->signatures().size())); | ||
127 | _entry->addPart(sp.get()); | ||
128 | } | ||
129 | return entry; | ||
130 | } | ||
131 | |||
132 | int pos() | ||
133 | { | ||
134 | if(!mParent) { | ||
135 | return -1; | ||
136 | } | ||
137 | int i=0; | ||
138 | foreach(const auto &child, mParent->mChildren) { | ||
139 | if (child == this) { | ||
140 | return i; | ||
141 | } | ||
142 | i++; | ||
143 | } | ||
144 | return -1; | ||
145 | } | ||
146 | |||
147 | QSharedPointer<QVariant> mData; | ||
148 | |||
149 | Entry *mParent; | ||
150 | QVector<Entry *> mChildren; | ||
151 | NewModelPrivate *mNewModelPrivate; | ||
152 | }; | ||
153 | |||
154 | |||
155 | NewModelPrivate::NewModelPrivate(NewModel *q_ptr, const std::shared_ptr<Parser> &parser) | ||
156 | : q(q_ptr) | ||
157 | , mRoot(std::unique_ptr<Entry>(new Entry(this))) | ||
158 | , mParser(parser) | ||
159 | { | ||
160 | mParts = mParser->collectContentParts(); | ||
161 | createTree(); | ||
162 | } | ||
163 | |||
164 | NewModelPrivate::~NewModelPrivate() | ||
165 | { | ||
166 | } | ||
167 | |||
168 | void NewModelPrivate::createTree() | ||
169 | { | ||
170 | auto root = mRoot.get(); | ||
171 | auto parent = root; | ||
172 | Part *pPart = nullptr; | ||
173 | QVector<Signature::Ptr> signatures; | ||
174 | QVector<Encryption::Ptr> encryptions; | ||
175 | foreach(const auto part, mParts) { | ||
176 | auto _parent = parent; | ||
177 | if (pPart != part->parent()) { | ||
178 | auto _parent = root; | ||
179 | _parent = _parent->addEncryptions(part->parent()->encryptions()); | ||
180 | _parent = _parent->addSignatures(part->parent()->signatures()); | ||
181 | signatures = part->parent()->signatures(); | ||
182 | encryptions = part->parent()->encryptions(); | ||
183 | parent = _parent; | ||
184 | pPart = part->parent(); | ||
185 | } | ||
186 | _parent = _parent->addEncryptions(part->encryptions().mid(encryptions.size())); | ||
187 | _parent = _parent->addSignatures(part->signatures().mid(signatures.size())); | ||
188 | _parent->addPart(part.get()); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | QSharedPointer<QVariant> NewModelPrivate::getVar(const std::shared_ptr<Signature> &sig) | ||
193 | { | ||
194 | if (!mSignatureMap.contains(sig)) { | ||
195 | auto var = new QVariant(); | ||
196 | var->setValue(sig.get()); | ||
197 | mSignatureMap.insert(sig, QSharedPointer<QVariant>(var)); | ||
198 | } | ||
199 | return mSignatureMap.value(sig); | ||
200 | } | ||
201 | |||
202 | QSharedPointer<QVariant> NewModelPrivate::getVar(const std::shared_ptr<Encryption> &enc) | ||
203 | { | ||
204 | if (!mEncryptionMap.contains(enc)) { | ||
205 | auto var = new QVariant(); | ||
206 | var->setValue(enc.get()); | ||
207 | mEncryptionMap.insert(enc, QSharedPointer<QVariant>(var)); | ||
208 | } | ||
209 | return mEncryptionMap.value(enc); | ||
210 | } | ||
211 | |||
212 | QSharedPointer<QVariant> NewModelPrivate::getVar(const std::shared_ptr<Part> &part) | ||
213 | { | ||
214 | return getVar(part.get()); | ||
215 | } | ||
216 | |||
217 | QSharedPointer<QVariant> NewModelPrivate::getVar(Part *part) | ||
218 | { | ||
219 | if (!mPartMap.contains(part)) { | ||
220 | auto var = new QVariant(); | ||
221 | var->setValue(part); | ||
222 | mPartMap.insert(part, QSharedPointer<QVariant>(var)); | ||
223 | } | ||
224 | return mPartMap.value(part); | ||
225 | } | ||
226 | |||
227 | QSharedPointer<QVariant> NewModelPrivate::getVar(const std::shared_ptr<Content> &content) | ||
228 | { | ||
229 | return getVar(content.get()); | ||
230 | } | ||
231 | |||
232 | QSharedPointer<QVariant> NewModelPrivate::getVar(Content *content) | ||
233 | { | ||
234 | if (!mCMap.contains(content)) { | ||
235 | auto var = new QVariant(); | ||
236 | var->setValue(content); | ||
237 | mCMap.insert(content, QSharedPointer<QVariant>(var)); | ||
238 | } | ||
239 | return mCMap.value(content); | ||
240 | } | ||
241 | |||
242 | int NewModelPrivate::getPos(Signature *signature) | ||
243 | { | ||
244 | const auto first = mParts.first(); | ||
245 | int i = 0; | ||
246 | foreach(const auto &sig, first->signatures()) { | ||
247 | if (sig.get() == signature) { | ||
248 | break; | ||
249 | } | ||
250 | i++; | ||
251 | } | ||
252 | return i; | ||
253 | } | ||
254 | |||
255 | int NewModelPrivate::getPos(Encryption *encryption) | ||
256 | { | ||
257 | const auto first = mParts.first(); | ||
258 | int i = 0; | ||
259 | foreach(const auto &enc, first->encryptions()) { | ||
260 | if (enc.get() == encryption) { | ||
261 | break; | ||
262 | } | ||
263 | i++; | ||
264 | } | ||
265 | return i; | ||
266 | } | ||
267 | |||
268 | int NewModelPrivate::getPos(Part *part) | ||
269 | { | ||
270 | int i = 0; | ||
271 | foreach(const auto &p, mParts) { | ||
272 | if (p.get() == part) { | ||
273 | break; | ||
274 | } | ||
275 | i++; | ||
276 | } | ||
277 | return i; | ||
278 | } | ||
279 | |||
280 | int NewModelPrivate::getPos(Content *content) | ||
281 | { | ||
282 | int i = 0; | ||
283 | foreach(const auto &c, content->parent()->content()) { | ||
284 | if (c.get() == content) { | ||
285 | break; | ||
286 | } | ||
287 | i++; | ||
288 | } | ||
289 | return i; | ||
290 | } | ||
291 | |||
292 | NewModel::NewModel(std::shared_ptr<Parser> parser) | ||
293 | : d(std::unique_ptr<NewModelPrivate>(new NewModelPrivate(this, parser))) | ||
294 | { | ||
295 | } | ||
296 | |||
297 | NewModel::~NewModel() | ||
298 | { | ||
299 | } | ||
300 | |||
301 | QHash<int, QByteArray> NewModel::roleNames() const | ||
302 | { | ||
303 | QHash<int, QByteArray> roles; | ||
304 | roles[TypeRole] = "type"; | ||
305 | roles[ContentRole] = "content"; | ||
306 | roles[IsEmbededRole] = "embeded"; | ||
307 | roles[SecurityLevelRole] = "securityLevel"; | ||
308 | return roles; | ||
309 | } | ||
310 | |||
311 | QModelIndex NewModel::index(int row, int column, const QModelIndex &parent) const | ||
312 | { | ||
313 | if (row < 0 || column != 0) { | ||
314 | return QModelIndex(); | ||
315 | } | ||
316 | Entry *entry = d->mRoot.get(); | ||
317 | if (parent.isValid()) { | ||
318 | entry = static_cast<Entry *>(parent.internalPointer()); | ||
319 | } | ||
320 | |||
321 | if (row < entry->mChildren.size()) { | ||
322 | return createIndex(row, column, entry->mChildren.at(row)); | ||
323 | } | ||
324 | return QModelIndex(); | ||
325 | } | ||
326 | |||
327 | QVariant NewModel::data(const QModelIndex &index, int role) const | ||
328 | { | ||
329 | if (!index.isValid()) { | ||
330 | switch (role) { | ||
331 | case Qt::DisplayRole: | ||
332 | return QString("root"); | ||
333 | case IsEmbededRole: | ||
334 | return false; | ||
335 | } | ||
336 | return QVariant(); | ||
337 | } | ||
338 | |||
339 | if (index.internalPointer()) { | ||
340 | const auto entry = static_cast<Entry *>(index.internalPointer()); | ||
341 | const auto _data = entry->mData; | ||
342 | if (entry == d->mRoot.get()|| !_data) { | ||
343 | switch (role) { | ||
344 | case Qt::DisplayRole: | ||
345 | return QString("root"); | ||
346 | case IsEmbededRole: | ||
347 | return false; | ||
348 | } | ||
349 | return QVariant(); | ||
350 | } | ||
351 | if (_data->userType() == qMetaTypeId<Signature *>()) { | ||
352 | const auto signature = _data->value<Signature *>(); | ||
353 | int i = d->getPos(signature); | ||
354 | switch(role) { | ||
355 | case Qt::DisplayRole: | ||
356 | return QStringLiteral("Signature%1").arg(i); | ||
357 | case TypeRole: | ||
358 | return QStringLiteral("Signature"); | ||
359 | case SecurityLevelRole: | ||
360 | return QStringLiteral("RED"); | ||
361 | case IsEmbededRole: | ||
362 | return data(index.parent(), IsEmbededRole); | ||
363 | } | ||
364 | } else if (_data->userType() == qMetaTypeId<Encryption *>()) { | ||
365 | const auto encryption = _data->value<Encryption *>(); | ||
366 | int i = d->getPos(encryption); | ||
367 | switch(role) { | ||
368 | case Qt::DisplayRole: | ||
369 | return QStringLiteral("Encryption%1").arg(i); | ||
370 | case TypeRole: | ||
371 | return QStringLiteral("Encryption"); | ||
372 | case SecurityLevelRole: | ||
373 | return QStringLiteral("GREEN"); | ||
374 | case IsEmbededRole: | ||
375 | return data(index.parent(), IsEmbededRole); | ||
376 | } | ||
377 | } else if (_data->userType() == qMetaTypeId<Part *>()) { | ||
378 | const auto part = _data->value<Part *>(); | ||
379 | switch (role) { | ||
380 | case Qt::DisplayRole: | ||
381 | case TypeRole: | ||
382 | return QString::fromLatin1(part->type()); | ||
383 | case IsEmbededRole: | ||
384 | return data(index.parent(), IsEmbededRole); | ||
385 | } | ||
386 | } else if (_data->userType() == qMetaTypeId<Content *>()) { | ||
387 | const auto content = _data->value<Content *>(); | ||
388 | int i = d->getPos(content); | ||
389 | switch(role) { | ||
390 | case Qt::DisplayRole: | ||
391 | return QStringLiteral("Content%1").arg(i); | ||
392 | case TypeRole: | ||
393 | return QString::fromLatin1(content->type()); | ||
394 | case IsEmbededRole: | ||
395 | return data(index.parent(), IsEmbededRole); | ||
396 | case ContentRole: { | ||
397 | auto text = content->encodedContent(); | ||
398 | if (data(index, TypeRole).toString() == "HtmlContent") { | ||
399 | const auto rx = QRegExp("(src)\\s*=\\s*(\"|')(cid:[^\"']+)\\2"); | ||
400 | int pos = 0; | ||
401 | while ((pos = rx.indexIn(text, pos)) != -1) { | ||
402 | const auto link = QUrl(rx.cap(3).toUtf8()); | ||
403 | pos += rx.matchedLength(); | ||
404 | const auto repl = d->mParser->getPart(link); | ||
405 | if (!repl) { | ||
406 | continue; | ||
407 | } | ||
408 | const auto content = repl->content(); | ||
409 | if(content.size() < 1) { | ||
410 | continue; | ||
411 | } | ||
412 | const auto mailMime = content.first()->mailMime(); | ||
413 | const auto mimetype = mailMime->mimetype().name(); | ||
414 | if (mimetype.startsWith("image/")) { | ||
415 | const auto data = content.first()->content(); | ||
416 | text.replace(rx.cap(0), QString("src=\"data:%1;base64,%2\"").arg(mimetype, QString::fromLatin1(data.toBase64()))); | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | return text; | ||
421 | } | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | return QVariant(); | ||
426 | } | ||
427 | |||
428 | QModelIndex NewModel::parent(const QModelIndex &index) const | ||
429 | { | ||
430 | if (!index.internalPointer()) { | ||
431 | return QModelIndex(); | ||
432 | } | ||
433 | const auto entry = static_cast<Entry *>(index.internalPointer()); | ||
434 | if (entry->mParent && entry->mParent != d->mRoot.get()) { | ||
435 | return createIndex(entry->pos(), 0, entry->mParent); | ||
436 | } | ||
437 | return QModelIndex(); | ||
438 | } | ||
439 | |||
440 | int NewModel::rowCount(const QModelIndex &parent) const | ||
441 | { | ||
442 | if (!parent.isValid()) { | ||
443 | return d->mRoot->mChildren.size(); | ||
444 | } else { | ||
445 | if (!parent.internalPointer()) { | ||
446 | return 0; | ||
447 | } | ||
448 | const auto entry = static_cast<Entry *>(parent.internalPointer()); | ||
449 | return entry->mChildren.size(); | ||
450 | } | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | int NewModel::columnCount(const QModelIndex &parent) const | ||
455 | { | ||
456 | return 1; | ||
457 | } | ||
diff --git a/framework/domain/messageparser_old.cpp b/framework/domain/messageparser_old.cpp new file mode 100644 index 00000000..a4247d8c --- /dev/null +++ b/framework/domain/messageparser_old.cpp | |||
@@ -0,0 +1,151 @@ | |||
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 | const auto rx = QRegExp("(src)\\s*=\\s*(\"|')(cid:[^\"']+)\\2"); | ||
68 | int pos = 0; | ||
69 | while ((pos = rx.indexIn(text, pos)) != -1) { | ||
70 | const auto link = QUrl(rx.cap(3).toUtf8()); | ||
71 | pos += rx.matchedLength(); | ||
72 | const auto repl = mParser->getPart(link); | ||
73 | if (!repl) { | ||
74 | continue; | ||
75 | } | ||
76 | const auto content = repl->content(); | ||
77 | if(content.size() < 1) { | ||
78 | continue; | ||
79 | } | ||
80 | const auto mailMime = content.first()->mailMime(); | ||
81 | const auto mimetype = mailMime->mimetype().name(); | ||
82 | if (mimetype.startsWith("image/")) { | ||
83 | const auto data = content.first()->content(); | ||
84 | text.replace(rx.cap(0), QString("src=\"data:%1;base64,%2\"").arg(mimetype, QString::fromLatin1(data.toBase64()))); | ||
85 | } | ||
86 | } | ||
87 | return text; | ||
88 | } | ||
89 | case IsAttachment: | ||
90 | return part->property("attachment").toBool(); | ||
91 | case IsEncrypted: | ||
92 | return part->property("isEncrypted").toBool(); | ||
93 | case IsHtml: | ||
94 | return part->property("isHtml").toBool(); | ||
95 | case HasContent: | ||
96 | return !part->property("htmlContent").toString().isEmpty(); | ||
97 | case Type: | ||
98 | return part->metaObject()->className(); | ||
99 | case IsHidden: | ||
100 | return false; | ||
101 | //return part->property("isHidden").toBool(); | ||
102 | |||
103 | } | ||
104 | } | ||
105 | return QVariant(); | ||
106 | } | ||
107 | |||
108 | QModelIndex PartModel::parent(const QModelIndex &index) const | ||
109 | { | ||
110 | // qDebug() << "parent " << index; | ||
111 | if (index.isValid()) { | ||
112 | auto part = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer()); | ||
113 | auto parentPart = static_cast<MimeTreeParser::MessagePart*>(part->parentPart()); | ||
114 | auto row = 0;//get the parents parent to find the index | ||
115 | if (!parentPart) { | ||
116 | parentPart = mPartTree.data(); | ||
117 | } | ||
118 | int i = 0; | ||
119 | for (const auto &p : parentPart->subParts()) { | ||
120 | if (p.data() == part) { | ||
121 | row = i; | ||
122 | break; | ||
123 | } | ||
124 | i++; | ||
125 | } | ||
126 | return createIndex(row, index.column(), parentPart); | ||
127 | } | ||
128 | return QModelIndex(); | ||
129 | } | ||
130 | |||
131 | int PartModel::rowCount(const QModelIndex &parent) const | ||
132 | { | ||
133 | // qDebug() << "Row count " << parent; | ||
134 | if (!parent.isValid()) { | ||
135 | // qDebug() << "Row count " << mPartTree->subParts().size(); | ||
136 | return mPartTree->subParts().size(); | ||
137 | } else { | ||
138 | auto part = static_cast<MimeTreeParser::MessagePart*>(parent.internalPointer()); | ||
139 | if (part) { | ||
140 | return part->subParts().size(); | ||
141 | } | ||
142 | } | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | int PartModel::columnCount(const QModelIndex &parent) const | ||
147 | { | ||
148 | // qDebug() << "Column count " << parent; | ||
149 | return 1; | ||
150 | } | ||
151 | |||
diff --git a/framework/domain/mimetreeparser/CMakeLists.txt b/framework/domain/mimetreeparser/CMakeLists.txt new file mode 100644 index 00000000..64da2656 --- /dev/null +++ b/framework/domain/mimetreeparser/CMakeLists.txt | |||
@@ -0,0 +1,15 @@ | |||
1 | set(mimetreeparser_SRCS | ||
2 | interface.cpp | ||
3 | objecttreesource.cpp | ||
4 | stringhtmlwriter.cpp | ||
5 | ) | ||
6 | |||
7 | add_library(mimetreeparser SHARED ${mimetreeparser_SRCS}) | ||
8 | |||
9 | qt5_use_modules(mimetreeparser Core Gui) | ||
10 | target_link_libraries(mimetreeparser KF5::Mime KF5::MimeTreeParser) | ||
11 | |||
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 new file mode 100644 index 00000000..0bcbfec4 --- /dev/null +++ b/framework/domain/mimetreeparser/interface.cpp | |||
@@ -0,0 +1,1089 @@ | |||
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 <Libkleo/KeyListJob> | ||
27 | #include <gpgme++/key.h> | ||
28 | #include <gpgme++/keylistresult.h> | ||
29 | |||
30 | #include <KMime/Content> | ||
31 | #include <MimeTreeParser/ObjectTreeParser> | ||
32 | #include <MimeTreeParser/MessagePart> | ||
33 | #include <MimeTreeParser/NodeHelper> | ||
34 | |||
35 | #include <QMimeDatabase> | ||
36 | #include <QMimeType> | ||
37 | #include <QTextCodec> | ||
38 | #include <QDebug> | ||
39 | |||
40 | class MailMimePrivate | ||
41 | { | ||
42 | public: | ||
43 | MailMimePrivate(MailMime *p); | ||
44 | |||
45 | MailMime *q; | ||
46 | KMime::Content *mNode; | ||
47 | std::shared_ptr<MailMime> parent; | ||
48 | }; | ||
49 | |||
50 | MailMimePrivate::MailMimePrivate(MailMime* p) | ||
51 | : q(p) | ||
52 | , mNode(nullptr) | ||
53 | , parent(nullptr) | ||
54 | { | ||
55 | } | ||
56 | |||
57 | |||
58 | MailMime::MailMime() | ||
59 | : d(std::unique_ptr<MailMimePrivate>(new MailMimePrivate(this))) | ||
60 | { | ||
61 | } | ||
62 | |||
63 | QByteArray MailMime::cid() const | ||
64 | { | ||
65 | if (!d->mNode || !d->mNode->contentID()) { | ||
66 | return QByteArray(); | ||
67 | } | ||
68 | return d->mNode->contentID()->identifier(); | ||
69 | } | ||
70 | |||
71 | QByteArray MailMime::charset() const | ||
72 | { | ||
73 | if(!d->mNode || !d->mNode->contentType(false)) { | ||
74 | return QByteArray(); | ||
75 | } | ||
76 | if (d->mNode->contentType(false)) { | ||
77 | return d->mNode->contentType(false)->charset(); | ||
78 | } | ||
79 | return d->mNode->defaultCharset(); | ||
80 | } | ||
81 | |||
82 | bool MailMime::isFirstTextPart() const | ||
83 | { | ||
84 | if (!d->mNode || !d->mNode->topLevel()) { | ||
85 | return false; | ||
86 | } | ||
87 | return (d->mNode->topLevel()->textContent() == d->mNode); | ||
88 | } | ||
89 | |||
90 | bool MailMime::isFirstPart() const | ||
91 | { | ||
92 | if (!d->mNode || !d->mNode->parent()) { | ||
93 | return false; | ||
94 | } | ||
95 | return (d->mNode->parent()->contents().first() == d->mNode); | ||
96 | } | ||
97 | |||
98 | bool MailMime::isTopLevelPart() const | ||
99 | { | ||
100 | if (!d->mNode) { | ||
101 | return false; | ||
102 | } | ||
103 | return (d->mNode->topLevel() == d->mNode); | ||
104 | } | ||
105 | |||
106 | MailMime::Disposition MailMime::disposition() const | ||
107 | { | ||
108 | if (!d->mNode) { | ||
109 | return Invalid; | ||
110 | } | ||
111 | const auto cd = d->mNode->contentDisposition(false); | ||
112 | if (!cd) { | ||
113 | return Invalid; | ||
114 | } | ||
115 | switch (cd->disposition()){ | ||
116 | case KMime::Headers::CDinline: | ||
117 | return Inline; | ||
118 | case KMime::Headers::CDattachment: | ||
119 | return Attachment; | ||
120 | default: | ||
121 | return Invalid; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | QString MailMime::filename() const | ||
126 | { | ||
127 | if (!d->mNode) { | ||
128 | return QString(); | ||
129 | } | ||
130 | const auto cd = d->mNode->contentDisposition(false); | ||
131 | if (!cd) { | ||
132 | return QString(); | ||
133 | } | ||
134 | return cd->filename(); | ||
135 | } | ||
136 | |||
137 | QMimeType MailMime::mimetype() const | ||
138 | { | ||
139 | if (!d->mNode) { | ||
140 | return QMimeType(); | ||
141 | } | ||
142 | |||
143 | const auto ct = d->mNode->contentType(false); | ||
144 | if (!ct) { | ||
145 | return QMimeType(); | ||
146 | } | ||
147 | |||
148 | QMimeDatabase mimeDb; | ||
149 | return mimeDb.mimeTypeForName(ct->mimeType()); | ||
150 | } | ||
151 | |||
152 | MailMime::Ptr MailMime::parent() const | ||
153 | { | ||
154 | if (!d->parent) { | ||
155 | d->parent = std::shared_ptr<MailMime>(new MailMime()); | ||
156 | d->parent->d->mNode = d->mNode->parent(); | ||
157 | } | ||
158 | return d->parent; | ||
159 | } | ||
160 | |||
161 | QByteArray MailMime::decodedContent() const | ||
162 | { | ||
163 | if (!d->mNode) { | ||
164 | return QByteArray(); | ||
165 | } | ||
166 | return d->mNode->decodedContent(); | ||
167 | } | ||
168 | |||
169 | class KeyPrivate | ||
170 | { | ||
171 | public: | ||
172 | Key *q; | ||
173 | GpgME::Key mKey; | ||
174 | }; | ||
175 | |||
176 | Key::Key() | ||
177 | :d(std::unique_ptr<KeyPrivate>(new KeyPrivate)) | ||
178 | { | ||
179 | d->q = this; | ||
180 | } | ||
181 | |||
182 | |||
183 | Key::Key(KeyPrivate *d_ptr) | ||
184 | :d(std::unique_ptr<KeyPrivate>(d_ptr)) | ||
185 | { | ||
186 | d->q = this; | ||
187 | } | ||
188 | |||
189 | Key::~Key() | ||
190 | { | ||
191 | |||
192 | } | ||
193 | |||
194 | QString Key::keyid() const | ||
195 | { | ||
196 | return d->mKey.keyID(); | ||
197 | } | ||
198 | |||
199 | QString Key::name() const | ||
200 | { | ||
201 | //FIXME: is this the correct way to get the primary UID? | ||
202 | return d->mKey.userID(0).name(); | ||
203 | } | ||
204 | |||
205 | QString Key::email() const | ||
206 | { | ||
207 | return d->mKey.userID(0).email(); | ||
208 | } | ||
209 | |||
210 | QString Key::comment() const | ||
211 | { | ||
212 | return d->mKey.userID(0).comment(); | ||
213 | } | ||
214 | |||
215 | class SignaturePrivate | ||
216 | { | ||
217 | public: | ||
218 | Signature *q; | ||
219 | GpgME::Signature mSignature; | ||
220 | Key::Ptr mKey; | ||
221 | }; | ||
222 | |||
223 | Signature::Signature() | ||
224 | :d(std::unique_ptr<SignaturePrivate>(new SignaturePrivate)) | ||
225 | { | ||
226 | d->q = this; | ||
227 | } | ||
228 | |||
229 | |||
230 | Signature::Signature(SignaturePrivate *d_ptr) | ||
231 | :d(std::unique_ptr<SignaturePrivate>(d_ptr)) | ||
232 | { | ||
233 | d->q = this; | ||
234 | |||
235 | } | ||
236 | |||
237 | Signature::~Signature() | ||
238 | { | ||
239 | |||
240 | } | ||
241 | |||
242 | QDateTime Signature::creationDateTime() const | ||
243 | { | ||
244 | QDateTime dt; | ||
245 | dt.setTime_t(d->mSignature.creationTime()); | ||
246 | return dt; | ||
247 | } | ||
248 | |||
249 | QDateTime Signature::expirationDateTime() const | ||
250 | { | ||
251 | QDateTime dt; | ||
252 | dt.setTime_t(d->mSignature.expirationTime()); | ||
253 | return dt; | ||
254 | } | ||
255 | |||
256 | bool Signature::neverExpires() const | ||
257 | { | ||
258 | return d->mSignature.neverExpires(); | ||
259 | } | ||
260 | |||
261 | Key::Ptr Signature::key() const | ||
262 | { | ||
263 | return d->mKey; | ||
264 | } | ||
265 | |||
266 | class EncryptionPrivate | ||
267 | { | ||
268 | public: | ||
269 | Encryption *q; | ||
270 | std::vector<Key::Ptr> mRecipients; | ||
271 | }; | ||
272 | |||
273 | Encryption::Encryption(EncryptionPrivate *d_ptr) | ||
274 | :d(std::unique_ptr<EncryptionPrivate>(d_ptr)) | ||
275 | { | ||
276 | d->q = this; | ||
277 | } | ||
278 | |||
279 | Encryption::Encryption() | ||
280 | :d(std::unique_ptr<EncryptionPrivate>(new EncryptionPrivate)) | ||
281 | { | ||
282 | d->q = this; | ||
283 | } | ||
284 | |||
285 | Encryption::~Encryption() | ||
286 | { | ||
287 | |||
288 | } | ||
289 | |||
290 | std::vector<Key::Ptr> Encryption::recipients() const | ||
291 | { | ||
292 | return d->mRecipients; | ||
293 | } | ||
294 | |||
295 | class PartPrivate | ||
296 | { | ||
297 | public: | ||
298 | PartPrivate(Part *part); | ||
299 | void appendSubPart(Part::Ptr subpart); | ||
300 | |||
301 | QVector<Part::Ptr> subParts(); | ||
302 | |||
303 | Part *parent() const; | ||
304 | |||
305 | const MailMime::Ptr &mailMime() const; | ||
306 | void createMailMime(const MimeTreeParser::MimeMessagePart::Ptr &part); | ||
307 | void createMailMime(const MimeTreeParser::TextMessagePart::Ptr &part); | ||
308 | void createMailMime(const MimeTreeParser::AlternativeMessagePart::Ptr &part); | ||
309 | void createMailMime(const MimeTreeParser::HtmlMessagePart::Ptr &part); | ||
310 | |||
311 | static Encryption::Ptr createEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part); | ||
312 | void appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr &part); | ||
313 | static QVector<Signature::Ptr> createSignature(const MimeTreeParser::SignedMessagePart::Ptr& part); | ||
314 | void appendSignature(const MimeTreeParser::SignedMessagePart::Ptr &part); | ||
315 | |||
316 | void setSignatures(const QVector<Signature::Ptr> &sigs); | ||
317 | void setEncryptions(const QVector<Encryption::Ptr> &encs); | ||
318 | |||
319 | const QVector<Encryption::Ptr> &encryptions() const; | ||
320 | const QVector<Signature::Ptr> &signatures() const; | ||
321 | private: | ||
322 | Part *q; | ||
323 | Part *mParent; | ||
324 | QVector<Part::Ptr> mSubParts; | ||
325 | QVector<Encryption::Ptr> mEncryptions; | ||
326 | QVector<Signature::Ptr> mSignatures; | ||
327 | MailMime::Ptr mMailMime; | ||
328 | }; | ||
329 | |||
330 | PartPrivate::PartPrivate(Part* part) | ||
331 | : q(part) | ||
332 | , mParent(Q_NULLPTR) | ||
333 | { | ||
334 | |||
335 | } | ||
336 | |||
337 | void PartPrivate::createMailMime(const MimeTreeParser::HtmlMessagePart::Ptr& part) | ||
338 | { | ||
339 | mMailMime = MailMime::Ptr(new MailMime); | ||
340 | mMailMime->d->mNode = part->mNode; | ||
341 | } | ||
342 | |||
343 | void PartPrivate::createMailMime(const MimeTreeParser::AlternativeMessagePart::Ptr& part) | ||
344 | { | ||
345 | mMailMime = MailMime::Ptr(new MailMime); | ||
346 | mMailMime->d->mNode = part->mNode; | ||
347 | } | ||
348 | |||
349 | void PartPrivate::createMailMime(const MimeTreeParser::TextMessagePart::Ptr& part) | ||
350 | { | ||
351 | mMailMime = MailMime::Ptr(new MailMime); | ||
352 | mMailMime->d->mNode = part->mNode; | ||
353 | } | ||
354 | |||
355 | void PartPrivate::createMailMime(const MimeTreeParser::MimeMessagePart::Ptr& part) | ||
356 | { | ||
357 | mMailMime = MailMime::Ptr(new MailMime); | ||
358 | mMailMime->d->mNode = part->mNode; | ||
359 | } | ||
360 | |||
361 | void PartPrivate::appendSubPart(Part::Ptr subpart) | ||
362 | { | ||
363 | subpart->d->mParent = q; | ||
364 | mSubParts.append(subpart); | ||
365 | } | ||
366 | |||
367 | Encryption::Ptr PartPrivate::createEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part) | ||
368 | { | ||
369 | Kleo::KeyListJob *job = part->mCryptoProto->keyListJob(false); // local, no sigs | ||
370 | if (!job) { | ||
371 | qWarning() << "The Crypto backend does not support listing keys. "; | ||
372 | return Encryption::Ptr(); | ||
373 | } | ||
374 | |||
375 | auto encpriv = new EncryptionPrivate(); | ||
376 | foreach(const auto &recipient, part->mDecryptRecipients) { | ||
377 | std::vector<GpgME::Key> found_keys; | ||
378 | const auto &keyid = recipient.keyID(); | ||
379 | GpgME::KeyListResult res = job->exec(QStringList(QLatin1String(keyid)), false, found_keys); | ||
380 | if (res.error()) { | ||
381 | qWarning() << "Error while searching key for Fingerprint: " << keyid; | ||
382 | continue; | ||
383 | } | ||
384 | if (found_keys.size() > 1) { | ||
385 | // Should not Happen | ||
386 | qWarning() << "Oops: Found more then one Key for Fingerprint: " << keyid; | ||
387 | } | ||
388 | if (found_keys.size() != 1) { | ||
389 | // Should not Happen at this point | ||
390 | qWarning() << "Oops: Found no Key for Fingerprint: " << keyid; | ||
391 | } else { | ||
392 | auto key = found_keys[0]; | ||
393 | auto keypriv = new KeyPrivate; | ||
394 | keypriv->mKey = key; | ||
395 | encpriv->mRecipients.push_back(Key::Ptr(new Key(keypriv))); | ||
396 | } | ||
397 | } | ||
398 | return Encryption::Ptr(new Encryption(encpriv)); | ||
399 | } | ||
400 | |||
401 | void PartPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part) | ||
402 | { | ||
403 | mEncryptions.append(createEncryption(part)); | ||
404 | } | ||
405 | |||
406 | void PartPrivate::setEncryptions(const QVector< Encryption::Ptr >& encs) | ||
407 | { | ||
408 | mEncryptions = encs; | ||
409 | } | ||
410 | |||
411 | QVector<Signature::Ptr> PartPrivate::createSignature(const MimeTreeParser::SignedMessagePart::Ptr& part) | ||
412 | { | ||
413 | QVector<Signature::Ptr> sigs; | ||
414 | Kleo::KeyListJob *job = part->mCryptoProto->keyListJob(false); // local, no sigs | ||
415 | if (!job) { | ||
416 | qWarning() << "The Crypto backend does not support listing keys. "; | ||
417 | return sigs; | ||
418 | } | ||
419 | |||
420 | foreach(const auto &sig, part->mSignatures) { | ||
421 | auto sigpriv = new SignaturePrivate(); | ||
422 | sigpriv->mSignature = sig; | ||
423 | auto signature = std::make_shared<Signature>(sigpriv); | ||
424 | sigs.append(signature); | ||
425 | |||
426 | std::vector<GpgME::Key> found_keys; | ||
427 | const auto &keyid = sig.fingerprint(); | ||
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 | continue; | ||
437 | } | ||
438 | if (found_keys.size() != 1) { | ||
439 | // Should not Happen at this point | ||
440 | qWarning() << "Oops: Found no Key for Fingerprint: " << keyid; | ||
441 | continue; | ||
442 | } else { | ||
443 | auto key = found_keys[0]; | ||
444 | auto keypriv = new KeyPrivate; | ||
445 | keypriv->mKey = key; | ||
446 | sigpriv->mKey = Key::Ptr(new Key(keypriv)); | ||
447 | } | ||
448 | } | ||
449 | return sigs; | ||
450 | } | ||
451 | |||
452 | void PartPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& part) | ||
453 | { | ||
454 | mSignatures.append(createSignature(part)); | ||
455 | } | ||
456 | |||
457 | |||
458 | void PartPrivate::setSignatures(const QVector< Signature::Ptr >& sigs) | ||
459 | { | ||
460 | mSignatures = sigs; | ||
461 | } | ||
462 | |||
463 | Part *PartPrivate::parent() const | ||
464 | { | ||
465 | return mParent; | ||
466 | } | ||
467 | |||
468 | QVector< Part::Ptr > PartPrivate::subParts() | ||
469 | { | ||
470 | return mSubParts; | ||
471 | } | ||
472 | |||
473 | const MailMime::Ptr& PartPrivate::mailMime() const | ||
474 | { | ||
475 | return mMailMime; | ||
476 | } | ||
477 | |||
478 | const QVector< Encryption::Ptr >& PartPrivate::encryptions() const | ||
479 | { | ||
480 | return mEncryptions; | ||
481 | } | ||
482 | |||
483 | const QVector< Signature::Ptr >& PartPrivate::signatures() const | ||
484 | { | ||
485 | return mSignatures; | ||
486 | } | ||
487 | |||
488 | Part::Part() | ||
489 | : d(std::unique_ptr<PartPrivate>(new PartPrivate(this))) | ||
490 | { | ||
491 | |||
492 | } | ||
493 | |||
494 | bool Part::hasSubParts() const | ||
495 | { | ||
496 | return !subParts().isEmpty(); | ||
497 | } | ||
498 | |||
499 | QVector<Part::Ptr> Part::subParts() const | ||
500 | { | ||
501 | return d->subParts(); | ||
502 | } | ||
503 | |||
504 | QByteArray Part::type() const | ||
505 | { | ||
506 | return "Part"; | ||
507 | } | ||
508 | |||
509 | QVector<QByteArray> Part::availableContents() const | ||
510 | { | ||
511 | return QVector<QByteArray>(); | ||
512 | } | ||
513 | |||
514 | QVector<Content::Ptr> Part::content() const | ||
515 | { | ||
516 | return content(availableContents().first()); | ||
517 | } | ||
518 | |||
519 | QVector<Content::Ptr> Part::content(const QByteArray& ct) const | ||
520 | { | ||
521 | return QVector<Content::Ptr>(); | ||
522 | } | ||
523 | |||
524 | QVector<Encryption::Ptr> Part::encryptions() const | ||
525 | { | ||
526 | auto ret = d->encryptions(); | ||
527 | auto parent = d->parent(); | ||
528 | if (parent) { | ||
529 | ret.append(parent->encryptions()); | ||
530 | } | ||
531 | return ret; | ||
532 | } | ||
533 | |||
534 | QVector<Signature::Ptr> Part::signatures() const | ||
535 | { | ||
536 | auto ret = d->signatures(); | ||
537 | auto parent = d->parent(); | ||
538 | if (parent) { | ||
539 | ret.append(parent->signatures()); | ||
540 | } | ||
541 | return ret; | ||
542 | } | ||
543 | |||
544 | MailMime::Ptr Part::mailMime() const | ||
545 | { | ||
546 | return d->mailMime(); | ||
547 | } | ||
548 | |||
549 | Part *Part::parent() const | ||
550 | { | ||
551 | return d->parent(); | ||
552 | } | ||
553 | |||
554 | class ContentPrivate | ||
555 | { | ||
556 | public: | ||
557 | QByteArray mContent; | ||
558 | QByteArray mCodec; | ||
559 | Part *mParent; | ||
560 | Content *q; | ||
561 | MailMime::Ptr mMailMime; | ||
562 | QVector<Encryption::Ptr> mEncryptions; | ||
563 | QVector<Signature::Ptr> mSignatures; | ||
564 | void appendSignature(const MimeTreeParser::SignedMessagePart::Ptr &sig); | ||
565 | void appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr &enc); | ||
566 | }; | ||
567 | |||
568 | void ContentPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& enc) | ||
569 | { | ||
570 | mEncryptions.append(PartPrivate::createEncryption(enc)); | ||
571 | } | ||
572 | |||
573 | void ContentPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& sig) | ||
574 | { | ||
575 | mSignatures.append(PartPrivate::createSignature(sig)); | ||
576 | } | ||
577 | |||
578 | |||
579 | Content::Content(const QByteArray& content, Part *parent) | ||
580 | : d(std::unique_ptr<ContentPrivate>(new ContentPrivate)) | ||
581 | { | ||
582 | d->q = this; | ||
583 | d->mContent = content; | ||
584 | d->mCodec = "utf-8"; | ||
585 | d->mParent = parent; | ||
586 | } | ||
587 | |||
588 | Content::Content(ContentPrivate* d_ptr) | ||
589 | : d(std::unique_ptr<ContentPrivate>(d_ptr)) | ||
590 | { | ||
591 | d->q = this; | ||
592 | } | ||
593 | |||
594 | Content::~Content() | ||
595 | { | ||
596 | } | ||
597 | |||
598 | QVector<Encryption::Ptr> Content::encryptions() const | ||
599 | { | ||
600 | auto ret = d->mEncryptions; | ||
601 | if (d->mParent) { | ||
602 | ret.append(d->mParent->encryptions()); | ||
603 | } | ||
604 | return ret; | ||
605 | } | ||
606 | |||
607 | QVector<Signature::Ptr> Content::signatures() const | ||
608 | { | ||
609 | auto ret = d->mSignatures; | ||
610 | if (d->mParent) { | ||
611 | ret.append(d->mParent->signatures()); | ||
612 | } | ||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | QByteArray Content::content() const | ||
617 | { | ||
618 | return d->mContent; | ||
619 | } | ||
620 | |||
621 | QByteArray Content::charset() const | ||
622 | { | ||
623 | return d->mCodec; | ||
624 | } | ||
625 | |||
626 | QString Content::encodedContent() const | ||
627 | { | ||
628 | return encodedContent(charset()); | ||
629 | } | ||
630 | |||
631 | QString Content::encodedContent(const QByteArray &charset) const | ||
632 | { | ||
633 | QTextCodec *codec = QTextCodec::codecForName(charset); | ||
634 | return codec->toUnicode(content()); | ||
635 | } | ||
636 | |||
637 | QByteArray Content::type() const | ||
638 | { | ||
639 | return "Content"; | ||
640 | } | ||
641 | |||
642 | MailMime::Ptr Content::mailMime() const | ||
643 | { | ||
644 | if (d->mMailMime) { | ||
645 | return d->mMailMime; | ||
646 | } else { | ||
647 | return d->mParent->mailMime(); | ||
648 | } | ||
649 | } | ||
650 | |||
651 | Part *Content::parent() const | ||
652 | { | ||
653 | return d->mParent; | ||
654 | } | ||
655 | |||
656 | HtmlContent::HtmlContent(const QByteArray& content, Part* parent) | ||
657 | : Content(content, parent) | ||
658 | { | ||
659 | |||
660 | } | ||
661 | |||
662 | QByteArray HtmlContent::type() const | ||
663 | { | ||
664 | return "HtmlContent"; | ||
665 | } | ||
666 | |||
667 | PlainTextContent::PlainTextContent(const QByteArray& content, Part* parent) | ||
668 | : Content(content, parent) | ||
669 | { | ||
670 | |||
671 | } | ||
672 | |||
673 | PlainTextContent::PlainTextContent(ContentPrivate* d_ptr) | ||
674 | : Content(d_ptr) | ||
675 | { | ||
676 | |||
677 | } | ||
678 | |||
679 | HtmlContent::HtmlContent(ContentPrivate* d_ptr) | ||
680 | : Content(d_ptr) | ||
681 | { | ||
682 | |||
683 | } | ||
684 | |||
685 | |||
686 | QByteArray PlainTextContent::type() const | ||
687 | { | ||
688 | return "PlainTextContent"; | ||
689 | } | ||
690 | |||
691 | class AlternativePartPrivate | ||
692 | { | ||
693 | public: | ||
694 | void fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part); | ||
695 | |||
696 | QVector<Content::Ptr> content(const QByteArray &ct) const; | ||
697 | |||
698 | AlternativePart *q; | ||
699 | |||
700 | QVector<QByteArray> types() const; | ||
701 | |||
702 | private: | ||
703 | QMap<QByteArray, QVector<Content::Ptr>> mContent; | ||
704 | QVector<QByteArray> mTypes; | ||
705 | }; | ||
706 | |||
707 | void AlternativePartPrivate::fillFrom(MimeTreeParser::AlternativeMessagePart::Ptr part) | ||
708 | { | ||
709 | mTypes = QVector<QByteArray>() << "html" << "plaintext"; | ||
710 | |||
711 | Content::Ptr content = std::make_shared<HtmlContent>(part->htmlContent().toLocal8Bit(), q); | ||
712 | mContent["html"].append(content); | ||
713 | content = std::make_shared<PlainTextContent>(part->plaintextContent().toLocal8Bit(), q); | ||
714 | mContent["plaintext"].append(content); | ||
715 | q->reachParentD()->createMailMime(part); | ||
716 | } | ||
717 | |||
718 | QVector<QByteArray> AlternativePartPrivate::types() const | ||
719 | { | ||
720 | return mTypes; | ||
721 | } | ||
722 | |||
723 | QVector<Content::Ptr> AlternativePartPrivate::content(const QByteArray& ct) const | ||
724 | { | ||
725 | return mContent[ct]; | ||
726 | } | ||
727 | |||
728 | AlternativePart::AlternativePart() | ||
729 | : d(std::unique_ptr<AlternativePartPrivate>(new AlternativePartPrivate)) | ||
730 | { | ||
731 | d->q = this; | ||
732 | } | ||
733 | |||
734 | AlternativePart::~AlternativePart() | ||
735 | { | ||
736 | |||
737 | } | ||
738 | |||
739 | QByteArray AlternativePart::type() const | ||
740 | { | ||
741 | return "AlternativePart"; | ||
742 | } | ||
743 | |||
744 | QVector<QByteArray> AlternativePart::availableContents() const | ||
745 | { | ||
746 | return d->types(); | ||
747 | } | ||
748 | |||
749 | QVector<Content::Ptr> AlternativePart::content(const QByteArray& ct) const | ||
750 | { | ||
751 | return d->content(ct); | ||
752 | } | ||
753 | |||
754 | PartPrivate* AlternativePart::reachParentD() const | ||
755 | { | ||
756 | return Part::d.get(); | ||
757 | } | ||
758 | |||
759 | class SinglePartPrivate | ||
760 | { | ||
761 | public: | ||
762 | void fillFrom(MimeTreeParser::TextMessagePart::Ptr part); | ||
763 | void fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part); | ||
764 | void fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part); | ||
765 | SinglePart *q; | ||
766 | |||
767 | QVector<Content::Ptr> mContent; | ||
768 | QByteArray mType; | ||
769 | }; | ||
770 | |||
771 | void SinglePartPrivate::fillFrom(MimeTreeParser::TextMessagePart::Ptr part) | ||
772 | { | ||
773 | mType = "plaintext"; | ||
774 | mContent.clear(); | ||
775 | foreach (const auto &mp, part->subParts()) { | ||
776 | auto d_ptr = new ContentPrivate; | ||
777 | d_ptr->mContent = mp->text().toLocal8Bit(); | ||
778 | d_ptr->mParent = q; | ||
779 | const auto enc = mp.dynamicCast<MimeTreeParser::EncryptedMessagePart>(); | ||
780 | auto sig = mp.dynamicCast<MimeTreeParser::SignedMessagePart>(); | ||
781 | if (enc) { | ||
782 | d_ptr->appendEncryption(enc); | ||
783 | const auto s = enc->subParts(); | ||
784 | if (s.size() == 1) { | ||
785 | sig = s[0].dynamicCast<MimeTreeParser::SignedMessagePart>(); | ||
786 | } | ||
787 | } | ||
788 | if (sig) { | ||
789 | d_ptr->appendSignature(sig); | ||
790 | } | ||
791 | mContent.append(std::make_shared<PlainTextContent>(d_ptr)); | ||
792 | q->reachParentD()->createMailMime(part); | ||
793 | d_ptr->mCodec = q->mailMime()->charset(); | ||
794 | } | ||
795 | } | ||
796 | |||
797 | void SinglePartPrivate::fillFrom(MimeTreeParser::HtmlMessagePart::Ptr part) | ||
798 | { | ||
799 | mType = "html"; | ||
800 | mContent.clear(); | ||
801 | mContent.append(std::make_shared<HtmlContent>(part->text().toLocal8Bit(), q)); | ||
802 | q->reachParentD()->createMailMime(part); | ||
803 | } | ||
804 | |||
805 | void SinglePartPrivate::fillFrom(MimeTreeParser::AttachmentMessagePart::Ptr part) | ||
806 | { | ||
807 | q->reachParentD()->createMailMime(part.staticCast<MimeTreeParser::TextMessagePart>()); | ||
808 | mType = q->mailMime()->mimetype().name().toUtf8(); | ||
809 | mContent.clear(); | ||
810 | mContent.append(std::make_shared<Content>(q->mailMime()->decodedContent(), q)); | ||
811 | } | ||
812 | |||
813 | SinglePart::SinglePart() | ||
814 | : d(std::unique_ptr<SinglePartPrivate>(new SinglePartPrivate)) | ||
815 | { | ||
816 | d->q = this; | ||
817 | } | ||
818 | |||
819 | SinglePart::~SinglePart() | ||
820 | { | ||
821 | |||
822 | } | ||
823 | |||
824 | QVector<QByteArray> SinglePart::availableContents() const | ||
825 | { | ||
826 | return QVector<QByteArray>() << d->mType; | ||
827 | } | ||
828 | |||
829 | QVector< Content::Ptr > SinglePart::content(const QByteArray &ct) const | ||
830 | { | ||
831 | if (ct == d->mType) { | ||
832 | return d->mContent; | ||
833 | } | ||
834 | return QVector<Content::Ptr>(); | ||
835 | } | ||
836 | |||
837 | QByteArray SinglePart::type() const | ||
838 | { | ||
839 | return "SinglePart"; | ||
840 | } | ||
841 | |||
842 | PartPrivate* SinglePart::reachParentD() const | ||
843 | { | ||
844 | return Part::d.get(); | ||
845 | } | ||
846 | |||
847 | ParserPrivate::ParserPrivate(Parser* parser) | ||
848 | : q(parser) | ||
849 | , mNodeHelper(std::make_shared<MimeTreeParser::NodeHelper>()) | ||
850 | { | ||
851 | |||
852 | } | ||
853 | |||
854 | void ParserPrivate::setMessage(const QByteArray& mimeMessage) | ||
855 | { | ||
856 | const auto mailData = KMime::CRLFtoLF(mimeMessage); | ||
857 | mMsg = KMime::Message::Ptr(new KMime::Message); | ||
858 | mMsg->setContent(mailData); | ||
859 | mMsg->parse(); | ||
860 | |||
861 | // render the mail | ||
862 | StringHtmlWriter htmlWriter; | ||
863 | ObjectTreeSource source(&htmlWriter); | ||
864 | MimeTreeParser::ObjectTreeParser otp(&source, mNodeHelper.get()); | ||
865 | |||
866 | otp.parseObjectTree(mMsg.data()); | ||
867 | mPartTree = otp.parsedPart().dynamicCast<MimeTreeParser::MessagePart>(); | ||
868 | |||
869 | mEmbeddedPartMap = htmlWriter.embeddedParts(); | ||
870 | mHtml = htmlWriter.html(); | ||
871 | |||
872 | mTree = std::make_shared<Part>(); | ||
873 | createTree(mPartTree, mTree); | ||
874 | } | ||
875 | |||
876 | |||
877 | void ParserPrivate::createTree(const MimeTreeParser::MessagePart::Ptr &start, const Part::Ptr &tree) | ||
878 | { | ||
879 | foreach (const auto &mp, start->subParts()) { | ||
880 | const auto m = mp.dynamicCast<MimeTreeParser::MessagePart>(); | ||
881 | const auto text = mp.dynamicCast<MimeTreeParser::TextMessagePart>(); | ||
882 | const auto alternative = mp.dynamicCast<MimeTreeParser::AlternativeMessagePart>(); | ||
883 | const auto html = mp.dynamicCast<MimeTreeParser::HtmlMessagePart>(); | ||
884 | const auto attachment = mp.dynamicCast<MimeTreeParser::AttachmentMessagePart>(); | ||
885 | if (attachment) { | ||
886 | auto part = std::make_shared<SinglePart>(); | ||
887 | part->d->fillFrom(attachment); | ||
888 | tree->d->appendSubPart(part); | ||
889 | } else if (text) { | ||
890 | auto part = std::make_shared<SinglePart>(); | ||
891 | part->d->fillFrom(text); | ||
892 | tree->d->appendSubPart(part); | ||
893 | } else if (alternative) { | ||
894 | auto part = std::make_shared<AlternativePart>(); | ||
895 | part->d->fillFrom(alternative); | ||
896 | tree->d->appendSubPart(part); | ||
897 | } else if (html) { | ||
898 | auto part = std::make_shared<SinglePart>(); | ||
899 | part->d->fillFrom(html); | ||
900 | tree->d->appendSubPart(part); | ||
901 | } else { | ||
902 | const auto enc = mp.dynamicCast<MimeTreeParser::EncryptedMessagePart>(); | ||
903 | const auto sig = mp.dynamicCast<MimeTreeParser::SignedMessagePart>(); | ||
904 | if (enc || sig) { | ||
905 | auto subTree = std::make_shared<Part>(); | ||
906 | if (enc) { | ||
907 | subTree->d->appendEncryption(enc); | ||
908 | } | ||
909 | if (sig) { | ||
910 | subTree->d->appendSignature(sig); | ||
911 | } | ||
912 | createTree(m, subTree); | ||
913 | foreach(const auto &p, subTree->subParts()) { | ||
914 | tree->d->appendSubPart(p); | ||
915 | if (enc) { | ||
916 | p->d->setEncryptions(subTree->d->encryptions()); | ||
917 | } | ||
918 | if (sig) { | ||
919 | p->d->setSignatures(subTree->d->signatures()); | ||
920 | } | ||
921 | } | ||
922 | } else { | ||
923 | createTree(m, tree); | ||
924 | } | ||
925 | } | ||
926 | } | ||
927 | } | ||
928 | |||
929 | Parser::Parser(const QByteArray& mimeMessage) | ||
930 | :d(std::unique_ptr<ParserPrivate>(new ParserPrivate(this))) | ||
931 | { | ||
932 | d->setMessage(mimeMessage); | ||
933 | } | ||
934 | |||
935 | Parser::~Parser() | ||
936 | { | ||
937 | } | ||
938 | |||
939 | Part::Ptr Parser::getPart(const QUrl &url) | ||
940 | { | ||
941 | if (url.scheme() == QStringLiteral("cid") && !url.path().isEmpty()) { | ||
942 | const auto cid = url.path(); | ||
943 | return find(d->mTree, [&cid](const Part::Ptr &p){ | ||
944 | const auto mime = p->mailMime(); | ||
945 | return mime->cid() == cid; | ||
946 | }); | ||
947 | } | ||
948 | return Part::Ptr(); | ||
949 | } | ||
950 | |||
951 | QVector<Part::Ptr> Parser::collectContentParts() const | ||
952 | { | ||
953 | return collect(d->mTree, [](const Part::Ptr &p){return p->type() != "EncapsulatedPart";}, | ||
954 | [](const Content::Ptr &content){ | ||
955 | const auto mime = content->mailMime(); | ||
956 | |||
957 | if (!mime) { | ||
958 | return true; | ||
959 | } | ||
960 | |||
961 | if (mime->isFirstTextPart()) { | ||
962 | return true; | ||
963 | } | ||
964 | |||
965 | { | ||
966 | auto _mime = content->parent()->mailMime(); | ||
967 | while (_mime) { | ||
968 | if (_mime && (_mime->isTopLevelPart() || _mime->isFirstTextPart())) { | ||
969 | return true; | ||
970 | } | ||
971 | if (_mime->isFirstPart()) { | ||
972 | _mime = _mime->parent(); | ||
973 | } else { | ||
974 | break; | ||
975 | } | ||
976 | } | ||
977 | } | ||
978 | const auto cd = mime->disposition(); | ||
979 | if (cd && cd == MailMime::Inline) { | ||
980 | // explict "inline" disposition: | ||
981 | return true; | ||
982 | } | ||
983 | if (cd && cd == MailMime::Attachment) { | ||
984 | // explicit "attachment" disposition: | ||
985 | return false; | ||
986 | } | ||
987 | |||
988 | const auto ct = mime->mimetype(); | ||
989 | if (ct.name().trimmed().toLower() == "text" && ct.name().trimmed().isEmpty() && | ||
990 | (!mime || mime->filename().trimmed().isEmpty())) { | ||
991 | // text/* w/o filename parameter: | ||
992 | return true; | ||
993 | } | ||
994 | return false; | ||
995 | }); | ||
996 | } | ||
997 | |||
998 | |||
999 | QVector<Part::Ptr> Parser::collectAttachmentParts() const | ||
1000 | { | ||
1001 | return collect(d->mTree, [](const Part::Ptr &p){return p->type() != "EncapsulatedPart";}, | ||
1002 | [](const Content::Ptr &content){ | ||
1003 | const auto mime = content->mailMime(); | ||
1004 | |||
1005 | if (!mime) { | ||
1006 | return false; | ||
1007 | } | ||
1008 | |||
1009 | if (mime->isFirstTextPart()) { | ||
1010 | return false; | ||
1011 | } | ||
1012 | |||
1013 | { | ||
1014 | QMimeDatabase mimeDb; | ||
1015 | auto _mime = content->parent()->mailMime(); | ||
1016 | const auto parent = _mime->parent(); | ||
1017 | if (parent) { | ||
1018 | const auto mimetype = parent->mimetype(); | ||
1019 | if (mimetype == mimeDb.mimeTypeForName("multipart/related")) { | ||
1020 | return false; | ||
1021 | } | ||
1022 | } | ||
1023 | while (_mime) { | ||
1024 | if (_mime && (_mime->isTopLevelPart() || _mime->isFirstTextPart())) { | ||
1025 | return false; | ||
1026 | } | ||
1027 | if (_mime->isFirstPart()) { | ||
1028 | _mime = _mime->parent(); | ||
1029 | } else { | ||
1030 | break; | ||
1031 | } | ||
1032 | } | ||
1033 | } | ||
1034 | const auto cd = mime->disposition(); | ||
1035 | if (cd && cd == MailMime::Inline) { | ||
1036 | // explict "inline" disposition: | ||
1037 | return false; | ||
1038 | } | ||
1039 | if (cd && cd == MailMime::Attachment) { | ||
1040 | // explicit "attachment" disposition: | ||
1041 | return true; | ||
1042 | } | ||
1043 | |||
1044 | const auto ct = mime->mimetype(); | ||
1045 | if (ct.name().trimmed().toLower() == "text" && ct.name().trimmed().isEmpty() && | ||
1046 | (!mime || mime->filename().trimmed().isEmpty())) { | ||
1047 | // text/* w/o filename parameter: | ||
1048 | return false; | ||
1049 | } | ||
1050 | return true; | ||
1051 | }); | ||
1052 | } | ||
1053 | |||
1054 | QVector<Part::Ptr> Parser::collect(const Part::Ptr &start, std::function<bool(const Part::Ptr &)> select, std::function<bool(const Content::Ptr &)> filter) const | ||
1055 | { | ||
1056 | QVector<Part::Ptr> ret; | ||
1057 | foreach (const auto &part, start->subParts()) { | ||
1058 | QVector<QByteArray> contents; | ||
1059 | foreach(const auto &ct, part->availableContents()) { | ||
1060 | foreach(const auto &content, part->content(ct)) { | ||
1061 | if (filter(content)) { | ||
1062 | contents.append(ct); | ||
1063 | break; | ||
1064 | } | ||
1065 | } | ||
1066 | } | ||
1067 | if (!contents.isEmpty()) { | ||
1068 | ret.append(part); | ||
1069 | } | ||
1070 | if (select(part)){ | ||
1071 | ret += collect(part, select, filter); | ||
1072 | } | ||
1073 | } | ||
1074 | return ret; | ||
1075 | } | ||
1076 | |||
1077 | Part::Ptr Parser::find(const Part::Ptr &start, std::function<bool(const Part::Ptr &)> select) const | ||
1078 | { | ||
1079 | foreach (const auto &part, start->subParts()) { | ||
1080 | if (select(part)) { | ||
1081 | return part; | ||
1082 | } | ||
1083 | const auto ret = find(part, select); | ||
1084 | if (ret) { | ||
1085 | return ret; | ||
1086 | } | ||
1087 | } | ||
1088 | return Part::Ptr(); | ||
1089 | } | ||
diff --git a/framework/domain/mimetreeparser/interface.h b/framework/domain/mimetreeparser/interface.h new file mode 100644 index 00000000..3ff29d5d --- /dev/null +++ b/framework/domain/mimetreeparser/interface.h | |||
@@ -0,0 +1,381 @@ | |||
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 | |||
25 | #include <QDateTime> | ||
26 | #include <QUrl> | ||
27 | #include <QMimeType> | ||
28 | |||
29 | class Part; | ||
30 | class PartPrivate; | ||
31 | |||
32 | class MailMime; | ||
33 | class MailMimePrivate; | ||
34 | |||
35 | class AlternativePart; | ||
36 | class AlternativePartPrivate; | ||
37 | |||
38 | class SinglePart; | ||
39 | class SinglePartPrivate; | ||
40 | |||
41 | class EncryptionPart; | ||
42 | class EncryptionPartPrivate; | ||
43 | |||
44 | class EncapsulatedPart; | ||
45 | class EncapsulatedPartPrivate; | ||
46 | |||
47 | class Content; | ||
48 | class ContentPrivate; | ||
49 | |||
50 | class CertContent; | ||
51 | class CertContentPrivate; | ||
52 | |||
53 | class EncryptionError; | ||
54 | |||
55 | class Key; | ||
56 | class KeyPrivate; | ||
57 | class Signature; | ||
58 | class SignaturePrivate; | ||
59 | class Encryption; | ||
60 | class EncryptionPrivate; | ||
61 | |||
62 | typedef std::shared_ptr<Signature> SignaturePtr; | ||
63 | typedef std::shared_ptr<Encryption> EncryptionPtr; | ||
64 | |||
65 | class Parser; | ||
66 | class ParserPrivate; | ||
67 | |||
68 | /* | ||
69 | * A MessagePart that is based on a KMime::Content | ||
70 | */ | ||
71 | class MailMime | ||
72 | { | ||
73 | public: | ||
74 | typedef std::shared_ptr<MailMime> Ptr; | ||
75 | /** | ||
76 | * Various possible values for the "Content-Disposition" header. | ||
77 | */ | ||
78 | enum Disposition { | ||
79 | Invalid, ///< Default, invalid value | ||
80 | Inline, ///< inline | ||
81 | Attachment ///< attachment | ||
82 | }; | ||
83 | |||
84 | MailMime(); | ||
85 | |||
86 | // interessting header parts of a KMime::Content | ||
87 | QMimeType mimetype() const; | ||
88 | Disposition disposition() const; | ||
89 | QUrl label() const; | ||
90 | QByteArray cid() const; | ||
91 | QByteArray charset() const; | ||
92 | QString filename() const; | ||
93 | |||
94 | // Unique identifier to ecactly this KMime::Content | ||
95 | QByteArray link() const; | ||
96 | |||
97 | QByteArray content() const; | ||
98 | //Use default charset | ||
99 | QString encodedContent() const; | ||
100 | |||
101 | // overwrite default charset with given charset | ||
102 | QString encodedContent(QByteArray charset) const; | ||
103 | |||
104 | QByteArray decodedContent() const; | ||
105 | |||
106 | bool isFirstTextPart() const; | ||
107 | bool isFirstPart() const; | ||
108 | bool isTopLevelPart() const; | ||
109 | |||
110 | MailMime::Ptr parent() const; | ||
111 | |||
112 | private: | ||
113 | std::unique_ptr<MailMimePrivate> d; | ||
114 | |||
115 | friend class PartPrivate; | ||
116 | }; | ||
117 | |||
118 | class Content | ||
119 | { | ||
120 | public: | ||
121 | typedef std::shared_ptr<Content> Ptr; | ||
122 | Content(const QByteArray &content, Part *parent); | ||
123 | Content(ContentPrivate *d_ptr); | ||
124 | virtual ~Content(); | ||
125 | |||
126 | QByteArray content() const; | ||
127 | |||
128 | QByteArray charset() const; | ||
129 | |||
130 | //Use default charset | ||
131 | QString encodedContent() const; | ||
132 | |||
133 | // overwrite default charset with given charset | ||
134 | QString encodedContent(const QByteArray &charset) const; | ||
135 | |||
136 | QVector<SignaturePtr> signatures() const; | ||
137 | QVector<EncryptionPtr> encryptions() const; | ||
138 | MailMime::Ptr mailMime() const; | ||
139 | virtual QByteArray type() const; | ||
140 | Part* parent() const; | ||
141 | private: | ||
142 | std::unique_ptr<ContentPrivate> d; | ||
143 | }; | ||
144 | |||
145 | class PlainTextContent : public Content | ||
146 | { | ||
147 | public: | ||
148 | PlainTextContent(const QByteArray &content, Part *parent); | ||
149 | PlainTextContent(ContentPrivate *d_ptr); | ||
150 | QByteArray type() const Q_DECL_OVERRIDE; | ||
151 | }; | ||
152 | |||
153 | class HtmlContent : public Content | ||
154 | { | ||
155 | public: | ||
156 | HtmlContent(const QByteArray &content, Part *parent); | ||
157 | HtmlContent(ContentPrivate* d_ptr); | ||
158 | QByteArray type() const Q_DECL_OVERRIDE; | ||
159 | }; | ||
160 | |||
161 | /* | ||
162 | * importing a cert GpgMe::ImportResult | ||
163 | * checking a cert (if it is a valid cert) | ||
164 | */ | ||
165 | |||
166 | class CertContent : public Content | ||
167 | { | ||
168 | public: | ||
169 | typedef std::shared_ptr<CertContent> Ptr; | ||
170 | CertContent(const QByteArray &content, Part *parent); | ||
171 | |||
172 | QByteArray type() const Q_DECL_OVERRIDE; | ||
173 | enum CertType { | ||
174 | Pgp, | ||
175 | SMime | ||
176 | }; | ||
177 | |||
178 | enum CertSubType { | ||
179 | Public, | ||
180 | Private | ||
181 | }; | ||
182 | |||
183 | CertType certType() const; | ||
184 | CertSubType certSubType() const; | ||
185 | int keyLength() const; | ||
186 | |||
187 | private: | ||
188 | std::unique_ptr<CertContentPrivate> d; | ||
189 | }; | ||
190 | |||
191 | class Part | ||
192 | { | ||
193 | public: | ||
194 | typedef std::shared_ptr<Part> Ptr; | ||
195 | Part(); | ||
196 | virtual QByteArray type() const; | ||
197 | |||
198 | virtual QVector<QByteArray> availableContents() const; | ||
199 | virtual QVector<Content::Ptr> content(const QByteArray& ct) const; | ||
200 | QVector<Content::Ptr> content() const; | ||
201 | |||
202 | bool hasSubParts() const; | ||
203 | QVector<Part::Ptr> subParts() const; | ||
204 | Part *parent() const; | ||
205 | |||
206 | QVector<SignaturePtr> signatures() const; | ||
207 | QVector<EncryptionPtr> encryptions() const; | ||
208 | virtual MailMime::Ptr mailMime() const; | ||
209 | protected: | ||
210 | std::unique_ptr<PartPrivate> d; | ||
211 | private: | ||
212 | friend class ParserPrivate; | ||
213 | friend class PartPrivate; | ||
214 | }; | ||
215 | |||
216 | class AlternativePart : public Part | ||
217 | { | ||
218 | public: | ||
219 | typedef std::shared_ptr<AlternativePart> Ptr; | ||
220 | |||
221 | AlternativePart(); | ||
222 | virtual ~AlternativePart(); | ||
223 | |||
224 | QVector<QByteArray> availableContents() const Q_DECL_OVERRIDE; | ||
225 | QVector<Content::Ptr> content(const QByteArray& ct) const Q_DECL_OVERRIDE; | ||
226 | |||
227 | QByteArray type() const Q_DECL_OVERRIDE; | ||
228 | |||
229 | private: | ||
230 | PartPrivate *reachParentD() const; | ||
231 | std::unique_ptr<AlternativePartPrivate> d; | ||
232 | |||
233 | friend class ParserPrivate; | ||
234 | friend class AlternativePartPrivate; | ||
235 | }; | ||
236 | |||
237 | class SinglePart : public Part | ||
238 | { | ||
239 | public: | ||
240 | typedef std::shared_ptr<SinglePart> Ptr; | ||
241 | |||
242 | SinglePart(); | ||
243 | virtual ~SinglePart(); | ||
244 | |||
245 | QVector<Content::Ptr> content(const QByteArray& ct) const Q_DECL_OVERRIDE; | ||
246 | QVector<QByteArray> availableContents() const Q_DECL_OVERRIDE; | ||
247 | |||
248 | QByteArray type() const Q_DECL_OVERRIDE; | ||
249 | private: | ||
250 | PartPrivate *reachParentD() const; | ||
251 | std::unique_ptr<SinglePartPrivate> d; | ||
252 | |||
253 | friend class ParserPrivate; | ||
254 | friend class SinglePartPrivate; | ||
255 | }; | ||
256 | |||
257 | |||
258 | class EncryptionPart : public Part | ||
259 | { | ||
260 | public: | ||
261 | typedef std::shared_ptr<EncryptionPart> Ptr; | ||
262 | QByteArray type() const Q_DECL_OVERRIDE; | ||
263 | |||
264 | EncryptionError error() const; | ||
265 | private: | ||
266 | std::unique_ptr<EncryptionPartPrivate> d; | ||
267 | }; | ||
268 | |||
269 | /* | ||
270 | * we want to request complete headers like: | ||
271 | * from/to... | ||
272 | */ | ||
273 | |||
274 | class EncapsulatedPart : public SinglePart | ||
275 | { | ||
276 | public: | ||
277 | typedef std::shared_ptr<EncapsulatedPart> Ptr; | ||
278 | QByteArray type() const Q_DECL_OVERRIDE; | ||
279 | |||
280 | //template <class T> QByteArray header<T>(); | ||
281 | private: | ||
282 | std::unique_ptr<EncapsulatedPartPrivate> d; | ||
283 | }; | ||
284 | |||
285 | class EncryptionError | ||
286 | { | ||
287 | public: | ||
288 | int errorId() const; | ||
289 | QString errorString() const; | ||
290 | }; | ||
291 | |||
292 | class Key | ||
293 | { | ||
294 | public: | ||
295 | typedef std::shared_ptr<Key> Ptr; | ||
296 | Key(); | ||
297 | Key(KeyPrivate *); | ||
298 | ~Key(); | ||
299 | |||
300 | QString keyid() const; | ||
301 | QString name() const; | ||
302 | QString email() const; | ||
303 | QString comment() const; | ||
304 | QVector<QString> emails() const; | ||
305 | enum KeyTrust { | ||
306 | Unknown, Undefined, Never, Marginal, Full, Ultimate | ||
307 | }; | ||
308 | KeyTrust keyTrust() const; | ||
309 | |||
310 | bool isRevokation() const; | ||
311 | bool isInvalid() const; | ||
312 | bool isExpired() const; | ||
313 | |||
314 | std::vector<Key::Ptr> subkeys(); | ||
315 | Key parentkey() const; | ||
316 | private: | ||
317 | std::unique_ptr<KeyPrivate> d; | ||
318 | }; | ||
319 | |||
320 | class Signature | ||
321 | { | ||
322 | public: | ||
323 | typedef std::shared_ptr<Signature> Ptr; | ||
324 | Signature(); | ||
325 | Signature(SignaturePrivate *); | ||
326 | ~Signature(); | ||
327 | |||
328 | Key::Ptr key() const; | ||
329 | QDateTime creationDateTime() const; | ||
330 | QDateTime expirationDateTime() const; | ||
331 | bool neverExpires() const; | ||
332 | |||
333 | //template <> StatusObject<SignatureVerificationResult> verify() const; | ||
334 | private: | ||
335 | std::unique_ptr<SignaturePrivate> d; | ||
336 | }; | ||
337 | |||
338 | /* | ||
339 | * Normally the Keys for encryption are subkeys | ||
340 | * for clients the parentkeys are "more interessting", because they store the name, email etc. | ||
341 | * but a client may also wants show to what subkey the mail is really encrypted, an if this subkey isRevoked or something else | ||
342 | */ | ||
343 | class Encryption | ||
344 | { | ||
345 | public: | ||
346 | typedef std::shared_ptr<Encryption> Ptr; | ||
347 | Encryption(); | ||
348 | Encryption(EncryptionPrivate *); | ||
349 | ~Encryption(); | ||
350 | std::vector<Key::Ptr> recipients() const; | ||
351 | private: | ||
352 | std::unique_ptr<EncryptionPrivate> d; | ||
353 | }; | ||
354 | |||
355 | class Parser | ||
356 | { | ||
357 | public: | ||
358 | typedef std::shared_ptr<Parser> Ptr; | ||
359 | Parser(const QByteArray &mimeMessage); | ||
360 | ~Parser(); | ||
361 | |||
362 | Part::Ptr getPart(const QUrl &url); | ||
363 | |||
364 | QVector<Part::Ptr> collect(const Part::Ptr &start, std::function<bool(const Part::Ptr &)> select, std::function<bool(const Content::Ptr &)> filter) const; | ||
365 | Part::Ptr find(const Part::Ptr &start, std::function<bool(const Part::Ptr &)> select) const; | ||
366 | QVector<Part::Ptr> collectContentParts() const; | ||
367 | QVector<Part::Ptr> collectAttachmentParts() const; | ||
368 | //template <> QVector<ContentPart::Ptr> collect<ContentPart>() const; | ||
369 | |||
370 | //template <> static StatusObject<SignatureVerificationResult> verifySignature(const Signature signature) const; | ||
371 | //template <> static StatusObject<Part> decrypt(const EncryptedPart part) const; | ||
372 | |||
373 | signals: | ||
374 | void partsChanged(); | ||
375 | |||
376 | private: | ||
377 | std::unique_ptr<ParserPrivate> d; | ||
378 | |||
379 | friend class InterfaceTest; | ||
380 | }; | ||
381 | |||
diff --git a/framework/domain/mimetreeparser/interface_p.h b/framework/domain/mimetreeparser/interface_p.h new file mode 100644 index 00000000..8fab221a --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/objecttreesource.cpp b/framework/domain/mimetreeparser/objecttreesource.cpp new file mode 100644 index 00000000..58667444 --- /dev/null +++ b/framework/domain/mimetreeparser/objecttreesource.cpp | |||
@@ -0,0 +1,147 @@ | |||
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 <MimeTreeParser/AttachmentStrategy> | ||
23 | #include <MimeTreeParser/BodyPartFormatterBaseFactory> | ||
24 | #include <MimeTreeParser/MessagePart> | ||
25 | #include <MimeTreeParser/MessagePartRenderer> | ||
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 | const MimeTreeParser::BodyPartFormatterBaseFactory *ObjectTreeSource::bodyPartFormatterFactory() | ||
139 | { | ||
140 | return &(d->mBodyPartFormatterBaseFactory); | ||
141 | } | ||
142 | |||
143 | MimeTreeParser::Interface::MessagePartRenderer::Ptr ObjectTreeSource::messagePartTheme(MimeTreeParser::Interface::MessagePart::Ptr msgPart) | ||
144 | { | ||
145 | Q_UNUSED(msgPart); | ||
146 | return MimeTreeParser::Interface::MessagePartRenderer::Ptr(); | ||
147 | } | ||
diff --git a/framework/domain/mimetreeparser/objecttreesource.h b/framework/domain/mimetreeparser/objecttreesource.h new file mode 100644 index 00000000..42433e71 --- /dev/null +++ b/framework/domain/mimetreeparser/objecttreesource.h | |||
@@ -0,0 +1,56 @@ | |||
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 <MimeTreeParser/ObjectTreeSource> | ||
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 | const MimeTreeParser::BodyPartFormatterBaseFactory *bodyPartFormatterFactory() Q_DECL_OVERRIDE; | ||
50 | MimeTreeParser::Interface::MessagePartRendererPtr messagePartTheme(MimeTreeParser::Interface::MessagePartPtr msgPart) Q_DECL_OVERRIDE; | ||
51 | private: | ||
52 | ObjectSourcePrivate *const d; | ||
53 | }; | ||
54 | |||
55 | #endif | ||
56 | |||
diff --git a/framework/domain/mimetreeparser/stringhtmlwriter.cpp b/framework/domain/mimetreeparser/stringhtmlwriter.cpp new file mode 100644 index 00000000..88034492 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/stringhtmlwriter.h b/framework/domain/mimetreeparser/stringhtmlwriter.h new file mode 100644 index 00000000..fa5b760e --- /dev/null +++ b/framework/domain/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 <MimeTreeParser/HtmlWriter> | ||
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/domain/mimetreeparser/tests/CMakeLists.txt b/framework/domain/mimetreeparser/tests/CMakeLists.txt new file mode 100644 index 00000000..7945c5a0 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/CMakeLists.txt | |||
@@ -0,0 +1,12 @@ | |||
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 | add_executable(mimetreeparsertest interfacetest.cpp) | ||
10 | add_gpg_crypto_test(mimetreeparsertest mimetreeparsertest) | ||
11 | qt5_use_modules(mimetreeparsertest Core Test) | ||
12 | target_link_libraries(mimetreeparsertest mimetreeparser) | ||
diff --git a/framework/domain/mimetreeparser/tests/data/alternative.mbox b/framework/domain/mimetreeparser/tests/data/alternative.mbox new file mode 100644 index 00000000..6522c34b --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/data/cid-links.mbox b/framework/domain/mimetreeparser/tests/data/cid-links.mbox new file mode 100644 index 00000000..40ff5282 --- /dev/null +++ b/framework/domain/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 | 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 | ||
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 | 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 | ||
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 | l/7Sv0NP4Y7E+tf8U9p/abyT/wB2uf8AqJf+0n0NP4Y7D61/xT2n9pvJP/drn/qJf+0n0NP4Y7D6 | ||
1227 | 1/xT2n9pvJP/AHa5/wCol/7SfQ0/hjsPrX/FPaf2m8k/92uf+ol/7SfQ0/hjsPrX/FPaf2m8k/8A | ||
1228 | drn/AKiX/tJ9DT+GOw+tf8U9p/abyT/3a5/6iX/tJ9DT+GOw+tf8U9p/abyT/wB2uf8AqJf+0n0N | ||
1229 | P4Y7D61/xT2n9pvJP/drn/qJf+0n0NP4Y7D61/xT2n9pvJP/AHa5/wCol/7SfQ0/hjsPrX/FPaf2 | ||
1230 | m8k/92uf+ol/7SfQ0/hjsPrX/FPaf2m8k/8Adrn/AKiX/tJ9DT+GOw+tf8U9q/s7PneraMr9u/XG | ||
1231 | XrGRTyOz++MsTtn8Fzst0b/di2ep0vnVtzme1VLd+WjWGyWwvtXMnAJnmm4OTerMXLGVv6WlWlLa | ||
1232 | 9EMfU1KVrNEX9pvJP/drn/qJf+0r9DT+GOxPrX/FPaf2m8k/92uf+ol/7SfQ0/hjsPrX/FPaf2m8 | ||
1233 | k/8Adrn/AKiX/tJ9DT+GOw+tf8U9r0n7vfI95N5RWqWb09ivYGQZI5pCkb5YyNnbk74fI+y8vjNG | ||
1234 | yNOZiIiYenwmtdN8RM1fXF8Z9YQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE | ||
1235 | BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEH5tX6l+cEBB6zUeI07/iFrbs8534pHiggBx4E+RYWdnF | ||
1236 | y9T+K8Ov4m6zUttilJp53q8PoRfZdM521/LVH5R47pvH9fUrzTSz+QWRY5IAMGhiDPUybg5Y/VHr | ||
1237 | 1f8AJNHxN2pqTFsexG3y8qNanh7dPTrd707PLc69b929WXxRtiUs37VOuViOuxAwP05C3Fx5fTj3 | ||
1238 | 9Vy1fHTbqcuHLE4+lvQ8HF9lds5ehx/GvGdfs9DuNjZOVpddEUkIRkIiTjGR/NyEn9R9l38V4i7T | ||
1239 | m2I2z6nPwPh41tSbZ+Xvr6jR+Ma+94lt9zOczWNeMpRRgQsD8ImNuWRJ/X4Omv4i6zUttjK6Y89G | ||
1240 | dDRi+y6Z2R6F69414nqvHdZttg+xmO+MeY6hV+hnHzfpKwfL0/nLnPiNSdWbLYjCvdLrGhpxpxfd | ||
1241 | M4tNB454ttqe32TtsIKGuFjjAyr98hGJzPLCxhnIvx+ZNbxGppxbWI5pXw/h9PW1Jttmcre2Zu7s | ||
1242 | I73Np1fEtntdfQ10WziezOIWJLZVWZo3Z/o7Tm/LOPVsLrz6sRM3cuET2vNfGnhy1rN1sdUzR6De | ||
1243 | fu3pUthrBqyzyULU417REQOYET9HZ2Bm6/i3qvPoeOm6taVpWOp6fEeEiyIm34oieuY8ux5XyvVV | ||
1244 | dTv7eurEZQ13BhKV2cn5Rib54sLfrfBevwurOpZzS4+K0Y07oiNzsa6ebY+CbWtNIUp6+aGxFzdy | ||
1245 | dgL5SZs+2MrlfEW61sx97BqyZu0ronY6u0teIv8Au+qwQzSE4G516/Ie60755MfT6R5rjp26v1pm | ||
1246 | Y/Y633af0Yh47baKzrKtCawY878TzDA2eYBn5XLP872Xt09WL5mI2PHfpTbETO1zV2cxB6X93P8A | ||
1247 | 8z1//wCu/wC4kXk8b/Snq870+E/qR5bH21fBfaEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB | ||
1248 | AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBB+bV+pfnBAQfT/CtmWr/AHf3NgMbSvXn | ||
1249 | I+2Xo/UGf+VfI8dbXVtjfSO99DwE00753Vnsthr5H4lX8iv6/fat+5X2BxDe69WBsNz/AA4i3F2+ | ||
1250 | KeH1vo81l2zGOn7W/Eaf1rYvt6O/0bXVbyfRj52OtFrn3UcbUWx2WpM7s0v87u8vQfTHsvPZo3Xa | ||
1251 | U3YUnHjhWPW76mrZZfbbtjD8VPVDnaahXp3PKPGe4ME10Sejz6MQTRkw8fjx5suurdN+lZfny59V | ||
1252 | PPRNCml4mZn73LMds18/cphTl8X/AHfberuCCC3se5FVrsYkZlJG0Y44u+f5z/BvVb1dSNXWs5Ma | ||
1253 | THnq46WlOnp382GE+ZY8j3e41Pg3j0urtFUllGEJJBCM3cew5YxKMjerfBLdK3U8RfF2WM98LOpN | ||
1254 | mhbMZ1j0sfu+u7q9qfIrYzlY3EzM8MxNGLvM0RNH0YQjbqze2PinjdO2yLLYyx88M/46/n1rpv8A | ||
1255 | kr/MowQefD5BpJPJpjkrtbEYBL7Rm7js7v0riJeg+66W/RpdyZ8s78nHWnW9nny57d2dXoNXvwbz | ||
1256 | rc6K2/KGWaKany9BkCCMnFvzxyb8WXm+jXQtvjOK9nNL1fVpr3WzldTt5YeD/eH/APMtl+cX/cAv | ||
1257 | f/j/AOlHTPncP8j78fu+tjwrYdjYy0Dqncr7SJ600ETsxuz9eQ5dm6dVvxVlba1pNuLh4e+k0pXm | ||
1258 | d+rofDH3D0I6Wzlv135yVD7WMDh/mfLNxfp7rz3a2ry81baS726WnzUpdV5PybbWtpurNmyDwkxP | ||
1259 | GED/AP2xB8MH6Pf8V7NDTiyyIh5da+brpmXLXZyEHpf3c/8AzPX/AP67/uJF5PG/0p6vO9PhP6ke | ||
1260 | Wx9tXwX2hAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE | ||
1261 | BAQEBAQEBAQEBAQfm1fqX5wQEGhxRGQkYCRA+Qd2Z3Z/wypQqxJXgkJikjEybozkLO/8alIWstgj | ||
1262 | jjHgAsIN6CLMzfwMqjEcMMYuMYCAv6iLMzP/AAJQqxHXgjd3jjEHf1cRZv5EiKEyz2ou53eA9x2x | ||
1263 | zw3LH5pQqSQxSszSgJs3VmJmds/pSYqRLWOrWjLlHCAF6ZEWZ8foSkLWWwRRRhwABAP5oszN1/Bk | ||
1264 | ojMcUUY8YwEB9cCzM38SCxSu2qVqO1VkeKxE/KOQfVn/AEqXWxdFJyW26bZrC5F5Hu4tpJtI7Zjf | ||
1265 | lZ2knwLu7OzNh2duOOjeyxOjZNvLTBuNa6LuauLnyyyTSnLKTnJITkZv1dyd8u7rpEUwc5mrVUEH | ||
1266 | pf3c/wDzPX//AK7/ALiReTxv9KerzvT4T+pHlsfbV8F9oQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB | ||
1267 | AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEHzqf9z0JTGUG0KOJ3dwjKHm4t | ||
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/domain/mimetreeparser/tests/data/html.mbox b/framework/domain/mimetreeparser/tests/data/html.mbox new file mode 100644 index 00000000..bf5c685d --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox b/framework/domain/mimetreeparser/tests/data/openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox new file mode 100644 index 00000000..2d9726ea --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/data/openpgp-inline-charset-encrypted.mbox b/framework/domain/mimetreeparser/tests/data/openpgp-inline-charset-encrypted.mbox new file mode 100644 index 00000000..8bd06910 --- /dev/null +++ b/framework/domain/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/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/data/plaintext.mbox b/framework/domain/mimetreeparser/tests/data/plaintext.mbox new file mode 100644 index 00000000..d185b1c1 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/data/smime-encrypted.mbox b/framework/domain/mimetreeparser/tests/data/smime-encrypted.mbox new file mode 100644 index 00000000..6b6d6a0d --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/gnupg_home/CMakeLists.txt b/framework/domain/mimetreeparser/tests/gnupg_home/CMakeLists.txt new file mode 100644 index 00000000..9c64a008 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/DIR.txt b/framework/domain/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/DIR.txt new file mode 100644 index 00000000..1a45a6b3 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-4E31CEB57DDD4A7B9991AB05507B1ED4293FF952.db b/framework/domain/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-4E31CEB57DDD4A7B9991AB05507B1ED4293FF952.db new file mode 100644 index 00000000..0b7e2dd4 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-4E31CEB57DDD4A7B9991AB05507B1ED4293FF952.db | |||
Binary files differ | |||
diff --git a/framework/domain/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-7F2A402CBB016A9146D613568C89D3596A4111AA.db b/framework/domain/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-7F2A402CBB016A9146D613568C89D3596A4111AA.db new file mode 100644 index 00000000..47474a26 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/gnupg_home/dirmngr-cache.d/crl-7F2A402CBB016A9146D613568C89D3596A4111AA.db | |||
Binary files differ | |||
diff --git a/framework/domain/mimetreeparser/tests/gnupg_home/dirmngr.conf b/framework/domain/mimetreeparser/tests/gnupg_home/dirmngr.conf new file mode 100644 index 00000000..a17a0354 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/gnupg_home/gpg-agent.conf.in b/framework/domain/mimetreeparser/tests/gnupg_home/gpg-agent.conf.in new file mode 100644 index 00000000..ece69255 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/gnupg_home/gpg.conf b/framework/domain/mimetreeparser/tests/gnupg_home/gpg.conf new file mode 100644 index 00000000..f1760823 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/gnupg_home/gpgsm.conf.in b/framework/domain/mimetreeparser/tests/gnupg_home/gpgsm.conf.in new file mode 100644 index 00000000..92b6119d --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/gnupg_home/pinentry-fake.sh b/framework/domain/mimetreeparser/tests/gnupg_home/pinentry-fake.sh new file mode 100755 index 00000000..7135a942 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/gnupg_home/private-keys-v1.d/1AA8BA52430E51AE249AF0DA97D59F869E4101A8.key b/framework/domain/mimetreeparser/tests/gnupg_home/private-keys-v1.d/1AA8BA52430E51AE249AF0DA97D59F869E4101A8.key new file mode 100644 index 00000000..39ac307b --- /dev/null +++ b/framework/domain/mimetreeparser/tests/gnupg_home/private-keys-v1.d/1AA8BA52430E51AE249AF0DA97D59F869E4101A8.key | |||
Binary files differ | |||
diff --git a/framework/domain/mimetreeparser/tests/gnupg_home/pubring.gpg b/framework/domain/mimetreeparser/tests/gnupg_home/pubring.gpg new file mode 100644 index 00000000..2e00fa24 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/gnupg_home/pubring.gpg | |||
Binary files differ | |||
diff --git a/framework/domain/mimetreeparser/tests/gnupg_home/pubring.kbx b/framework/domain/mimetreeparser/tests/gnupg_home/pubring.kbx new file mode 100644 index 00000000..0230f313 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/gnupg_home/pubring.kbx | |||
Binary files differ | |||
diff --git a/framework/domain/mimetreeparser/tests/gnupg_home/scdaemon.conf b/framework/domain/mimetreeparser/tests/gnupg_home/scdaemon.conf new file mode 100644 index 00000000..a17a0354 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/gnupg_home/secring.gpg b/framework/domain/mimetreeparser/tests/gnupg_home/secring.gpg new file mode 100644 index 00000000..cfd3387d --- /dev/null +++ b/framework/domain/mimetreeparser/tests/gnupg_home/secring.gpg | |||
Binary files differ | |||
diff --git a/framework/domain/mimetreeparser/tests/gnupg_home/trustdb.gpg b/framework/domain/mimetreeparser/tests/gnupg_home/trustdb.gpg new file mode 100644 index 00000000..70089c15 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/gnupg_home/trustdb.gpg | |||
Binary files differ | |||
diff --git a/framework/domain/mimetreeparser/tests/gnupg_home/trustlist.txt b/framework/domain/mimetreeparser/tests/gnupg_home/trustlist.txt new file mode 100644 index 00000000..bbb0442d --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/interfacetest.cpp b/framework/domain/mimetreeparser/tests/interfacetest.cpp new file mode 100644 index 00000000..3ae32a4a --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/tests/kdepim_add_gpg_crypto_test.cmake b/framework/domain/mimetreeparser/tests/kdepim_add_gpg_crypto_test.cmake new file mode 100644 index 00000000..17078202 --- /dev/null +++ b/framework/domain/mimetreeparser/tests/kdepim_add_gpg_crypto_test.cmake | |||
@@ -0,0 +1,60 @@ | |||
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( GNUPGHOME ${CMAKE_BINARY_DIR}/framework/domain/mimetreeparser/tests/gnupg_home ) | ||
7 | add_definitions( -DGNUPGHOME="\\"${GNUPGHOME}\\"" ) | ||
8 | |||
9 | macro (ADD_GPG_CRYPTO_TEST _target _testname) | ||
10 | if (UNIX) | ||
11 | if (APPLE) | ||
12 | set(_library_path_variable "DYLD_LIBRARY_PATH") | ||
13 | elseif (CYGWIN) | ||
14 | set(_library_path_variable "PATH") | ||
15 | else (APPLE) | ||
16 | set(_library_path_variable "LD_LIBRARY_PATH") | ||
17 | endif (APPLE) | ||
18 | |||
19 | if (APPLE) | ||
20 | # DYLD_LIBRARY_PATH does not work like LD_LIBRARY_PATH | ||
21 | # OSX already has the RPATH in libraries and executables, putting runtime directories in | ||
22 | # DYLD_LIBRARY_PATH actually breaks things | ||
23 | set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/") | ||
24 | else (APPLE) | ||
25 | set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/:${LIB_INSTALL_DIR}:${QT_LIBRARY_DIR}") | ||
26 | endif (APPLE) | ||
27 | set(_executable "$<TARGET_FILE:${_target}>") | ||
28 | |||
29 | # use add_custom_target() to have the sh-wrapper generated during build time instead of cmake time | ||
30 | add_custom_command(TARGET ${_target} POST_BUILD | ||
31 | COMMAND ${CMAKE_COMMAND} | ||
32 | -D_filename=${_executable}.shell -D_library_path_variable=${_library_path_variable} | ||
33 | -D_ld_library_path="${_ld_library_path}" -D_executable=$<TARGET_FILE:${_target}> | ||
34 | -D_gnupghome="${GNUPGHOME}" | ||
35 | -P ${CMAKE_SOURCE_DIR}/framework/domain/mimetreeparser/tests/kdepim_generate_crypto_test_wrapper.cmake | ||
36 | ) | ||
37 | |||
38 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${_executable}.shell" ) | ||
39 | add_test(NAME ${_testname} COMMAND ${_executable}.shell) | ||
40 | |||
41 | else (UNIX) | ||
42 | # under windows, set the property WRAPPER_SCRIPT just to the name of the executable | ||
43 | # maybe later this will change to a generated batch file (for setting the PATH so that the Qt libs are found) | ||
44 | set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}\;${LIB_INSTALL_DIR}\;${QT_LIBRARY_DIR}") | ||
45 | set(_executable "$<TARGET_FILE:${_target}>") | ||
46 | |||
47 | # use add_custom_target() to have the batch-file-wrapper generated during build time instead of cmake time | ||
48 | add_custom_command(TARGET ${_target} POST_BUILD | ||
49 | COMMAND ${CMAKE_COMMAND} | ||
50 | -D_filename="${_executable}.bat" | ||
51 | -D_ld_library_path="${_ld_library_path}" -D_executable="${_executable}" | ||
52 | -D_gnupghome="${GNUPGHOME}" | ||
53 | -P ${CMAKE_SOURCE_DIR}/framework/domain/mimetreeparser/tests/kdepim_generate_crypto_test_wrapper.cmake | ||
54 | ) | ||
55 | |||
56 | add_test(NAME ${_testname} COMMAND ${_executable}.bat) | ||
57 | |||
58 | endif (UNIX) | ||
59 | endmacro (ADD_GPG_CRYPTO_TEST) | ||
60 | |||
diff --git a/framework/domain/mimetreeparser/tests/kdepim_generate_crypto_test_wrapper.cmake b/framework/domain/mimetreeparser/tests/kdepim_generate_crypto_test_wrapper.cmake new file mode 100644 index 00000000..e1412f37 --- /dev/null +++ b/framework/domain/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/domain/mimetreeparser/thoughts.txt b/framework/domain/mimetreeparser/thoughts.txt new file mode 100644 index 00000000..3340347a --- /dev/null +++ b/framework/domain/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/domain/modeltest.cpp b/framework/domain/modeltest.cpp new file mode 100644 index 00000000..9e1d92fa --- /dev/null +++ b/framework/domain/modeltest.cpp | |||
@@ -0,0 +1,588 @@ | |||
1 | /**************************************************************************** | ||
2 | ** | ||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | ||
4 | ** Contact: https://www.qt.io/licensing/ | ||
5 | ** | ||
6 | ** This file is part of the test suite of the Qt Toolkit. | ||
7 | ** | ||
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | ||
9 | ** Commercial License Usage | ||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
11 | ** accordance with the commercial license agreement provided with the | ||
12 | ** Software or, alternatively, in accordance with the terms contained in | ||
13 | ** a written agreement between you and The Qt Company. For licensing terms | ||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | ||
15 | ** information use the contact form at https://www.qt.io/contact-us. | ||
16 | ** | ||
17 | ** GNU General Public License Usage | ||
18 | ** Alternatively, this file may be used under the terms of the GNU | ||
19 | ** General Public License version 3 as published by the Free Software | ||
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | ||
21 | ** included in the packaging of this file. Please review the following | ||
22 | ** information to ensure the GNU General Public License requirements will | ||
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | ||
24 | ** | ||
25 | ** $QT_END_LICENSE$ | ||
26 | ** | ||
27 | ****************************************************************************/ | ||
28 | |||
29 | #include "modeltest.h" | ||
30 | |||
31 | #include <QtCore/QtCore> | ||
32 | #include <QtTest/QtTest> | ||
33 | |||
34 | #include <QDebug> | ||
35 | /*! | ||
36 | Connect to all of the models signals. Whenever anything happens recheck everything. | ||
37 | */ | ||
38 | ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false ) | ||
39 | { | ||
40 | if (!model) | ||
41 | qFatal("%s: model must not be null", Q_FUNC_INFO); | ||
42 | |||
43 | connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), | ||
44 | this, SLOT(runAllTests()) ); | ||
45 | connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), | ||
46 | this, SLOT(runAllTests()) ); | ||
47 | connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)), | ||
48 | this, SLOT(runAllTests()) ); | ||
49 | connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), | ||
50 | this, SLOT(runAllTests()) ); | ||
51 | connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), | ||
52 | this, SLOT(runAllTests()) ); | ||
53 | connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), | ||
54 | this, SLOT(runAllTests()) ); | ||
55 | connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests()) ); | ||
56 | connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests()) ); | ||
57 | connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests()) ); | ||
58 | connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), | ||
59 | this, SLOT(runAllTests()) ); | ||
60 | connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), | ||
61 | this, SLOT(runAllTests()) ); | ||
62 | connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), | ||
63 | this, SLOT(runAllTests()) ); | ||
64 | connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), | ||
65 | this, SLOT(runAllTests()) ); | ||
66 | |||
67 | // Special checks for changes | ||
68 | connect(model, SIGNAL(layoutAboutToBeChanged()), | ||
69 | this, SLOT(layoutAboutToBeChanged()) ); | ||
70 | connect(model, SIGNAL(layoutChanged()), | ||
71 | this, SLOT(layoutChanged()) ); | ||
72 | |||
73 | connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), | ||
74 | this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)) ); | ||
75 | connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), | ||
76 | this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)) ); | ||
77 | connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), | ||
78 | this, SLOT(rowsInserted(QModelIndex,int,int)) ); | ||
79 | connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), | ||
80 | this, SLOT(rowsRemoved(QModelIndex,int,int)) ); | ||
81 | connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), | ||
82 | this, SLOT(dataChanged(QModelIndex,QModelIndex)) ); | ||
83 | connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), | ||
84 | this, SLOT(headerDataChanged(Qt::Orientation,int,int)) ); | ||
85 | |||
86 | runAllTests(); | ||
87 | } | ||
88 | |||
89 | void ModelTest::runAllTests() | ||
90 | { | ||
91 | if ( fetchingMore ) | ||
92 | return; | ||
93 | nonDestructiveBasicTest(); | ||
94 | rowCount(); | ||
95 | columnCount(); | ||
96 | hasIndex(); | ||
97 | index(); | ||
98 | parent(); | ||
99 | data(); | ||
100 | } | ||
101 | |||
102 | /*! | ||
103 | nonDestructiveBasicTest tries to call a number of the basic functions (not all) | ||
104 | to make sure the model doesn't outright segfault, testing the functions that makes sense. | ||
105 | */ | ||
106 | void ModelTest::nonDestructiveBasicTest() | ||
107 | { | ||
108 | QVERIFY( model->buddy ( QModelIndex() ) == QModelIndex() ); | ||
109 | model->canFetchMore ( QModelIndex() ); | ||
110 | QVERIFY( model->columnCount ( QModelIndex() ) >= 0 ); | ||
111 | QVERIFY( model->data ( QModelIndex() ) == QVariant() ); | ||
112 | fetchingMore = true; | ||
113 | model->fetchMore ( QModelIndex() ); | ||
114 | fetchingMore = false; | ||
115 | Qt::ItemFlags flags = model->flags ( QModelIndex() ); | ||
116 | QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 ); | ||
117 | model->hasChildren ( QModelIndex() ); | ||
118 | model->hasIndex ( 0, 0 ); | ||
119 | model->headerData ( 0, Qt::Horizontal ); | ||
120 | model->index ( 0, 0 ); | ||
121 | model->itemData ( QModelIndex() ); | ||
122 | QVariant cache; | ||
123 | model->match ( QModelIndex(), -1, cache ); | ||
124 | model->mimeTypes(); | ||
125 | QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); | ||
126 | QVERIFY( model->rowCount() >= 0 ); | ||
127 | QVariant variant; | ||
128 | model->setData ( QModelIndex(), variant, -1 ); | ||
129 | model->setHeaderData ( -1, Qt::Horizontal, QVariant() ); | ||
130 | model->setHeaderData ( 999999, Qt::Horizontal, QVariant() ); | ||
131 | QMap<int, QVariant> roles; | ||
132 | model->sibling ( 0, 0, QModelIndex() ); | ||
133 | model->span ( QModelIndex() ); | ||
134 | model->supportedDropActions(); | ||
135 | } | ||
136 | |||
137 | /*! | ||
138 | Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren() | ||
139 | |||
140 | Models that are dynamically populated are not as fully tested here. | ||
141 | */ | ||
142 | void ModelTest::rowCount() | ||
143 | { | ||
144 | // qDebug() << "rc"; | ||
145 | // check top row | ||
146 | QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); | ||
147 | int rows = model->rowCount ( topIndex ); | ||
148 | QVERIFY( rows >= 0 ); | ||
149 | if ( rows > 0 ) | ||
150 | QVERIFY( model->hasChildren ( topIndex ) ); | ||
151 | |||
152 | QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex ); | ||
153 | if ( secondLevelIndex.isValid() ) { // not the top level | ||
154 | // check a row count where parent is valid | ||
155 | rows = model->rowCount ( secondLevelIndex ); | ||
156 | QVERIFY( rows >= 0 ); | ||
157 | if ( rows > 0 ) | ||
158 | QVERIFY( model->hasChildren ( secondLevelIndex ) ); | ||
159 | } | ||
160 | |||
161 | // The models rowCount() is tested more extensively in checkChildren(), | ||
162 | // but this catches the big mistakes | ||
163 | } | ||
164 | |||
165 | /*! | ||
166 | Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren() | ||
167 | */ | ||
168 | void ModelTest::columnCount() | ||
169 | { | ||
170 | // check top row | ||
171 | QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); | ||
172 | QVERIFY( model->columnCount ( topIndex ) >= 0 ); | ||
173 | |||
174 | // check a column count where parent is valid | ||
175 | QModelIndex childIndex = model->index ( 0, 0, topIndex ); | ||
176 | if ( childIndex.isValid() ) | ||
177 | QVERIFY( model->columnCount ( childIndex ) >= 0 ); | ||
178 | |||
179 | // columnCount() is tested more extensively in checkChildren(), | ||
180 | // but this catches the big mistakes | ||
181 | } | ||
182 | |||
183 | /*! | ||
184 | Tests model's implementation of QAbstractItemModel::hasIndex() | ||
185 | */ | ||
186 | void ModelTest::hasIndex() | ||
187 | { | ||
188 | // qDebug() << "hi"; | ||
189 | // Make sure that invalid values returns an invalid index | ||
190 | QVERIFY( !model->hasIndex ( -2, -2 ) ); | ||
191 | QVERIFY( !model->hasIndex ( -2, 0 ) ); | ||
192 | QVERIFY( !model->hasIndex ( 0, -2 ) ); | ||
193 | |||
194 | int rows = model->rowCount(); | ||
195 | int columns = model->columnCount(); | ||
196 | |||
197 | // check out of bounds | ||
198 | QVERIFY( !model->hasIndex ( rows, columns ) ); | ||
199 | QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) ); | ||
200 | |||
201 | if ( rows > 0 ) | ||
202 | QVERIFY( model->hasIndex ( 0, 0 ) ); | ||
203 | |||
204 | // hasIndex() is tested more extensively in checkChildren(), | ||
205 | // but this catches the big mistakes | ||
206 | } | ||
207 | |||
208 | /*! | ||
209 | Tests model's implementation of QAbstractItemModel::index() | ||
210 | */ | ||
211 | void ModelTest::index() | ||
212 | { | ||
213 | // qDebug() << "i"; | ||
214 | // Make sure that invalid values returns an invalid index | ||
215 | QVERIFY( model->index ( -2, -2 ) == QModelIndex() ); | ||
216 | QVERIFY( model->index ( -2, 0 ) == QModelIndex() ); | ||
217 | QVERIFY( model->index ( 0, -2 ) == QModelIndex() ); | ||
218 | |||
219 | int rows = model->rowCount(); | ||
220 | int columns = model->columnCount(); | ||
221 | |||
222 | if ( rows == 0 ) | ||
223 | return; | ||
224 | |||
225 | // Catch off by one errors | ||
226 | QVERIFY( model->index ( rows, columns ) == QModelIndex() ); | ||
227 | QVERIFY( model->index ( 0, 0 ).isValid() ); | ||
228 | |||
229 | // Make sure that the same index is *always* returned | ||
230 | QModelIndex a = model->index ( 0, 0 ); | ||
231 | QModelIndex b = model->index ( 0, 0 ); | ||
232 | QVERIFY( a == b ); | ||
233 | |||
234 | // index() is tested more extensively in checkChildren(), | ||
235 | // but this catches the big mistakes | ||
236 | } | ||
237 | |||
238 | /*! | ||
239 | Tests model's implementation of QAbstractItemModel::parent() | ||
240 | */ | ||
241 | void ModelTest::parent() | ||
242 | { | ||
243 | // qDebug() << "p"; | ||
244 | // Make sure the model won't crash and will return an invalid QModelIndex | ||
245 | // when asked for the parent of an invalid index. | ||
246 | QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); | ||
247 | |||
248 | if ( model->rowCount() == 0 ) | ||
249 | return; | ||
250 | |||
251 | // Column 0 | Column 1 | | ||
252 | // QModelIndex() | | | ||
253 | // \- topIndex | topIndex1 | | ||
254 | // \- childIndex | childIndex1 | | ||
255 | |||
256 | // Common error test #1, make sure that a top level index has a parent | ||
257 | // that is a invalid QModelIndex. | ||
258 | QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); | ||
259 | QVERIFY( model->parent ( topIndex ) == QModelIndex() ); | ||
260 | |||
261 | // Common error test #2, make sure that a second level index has a parent | ||
262 | // that is the first level index. | ||
263 | if ( model->rowCount ( topIndex ) > 0 ) { | ||
264 | QModelIndex childIndex = model->index ( 0, 0, topIndex ); | ||
265 | QVERIFY( model->parent ( childIndex ) == topIndex ); | ||
266 | } | ||
267 | |||
268 | // Common error test #3, the second column should NOT have the same children | ||
269 | // as the first column in a row. | ||
270 | // Usually the second column shouldn't have children. | ||
271 | QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() ); | ||
272 | if ( model->rowCount ( topIndex1 ) > 0 ) { | ||
273 | QModelIndex childIndex = model->index ( 0, 0, topIndex ); | ||
274 | QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 ); | ||
275 | QVERIFY( childIndex != childIndex1 ); | ||
276 | } | ||
277 | |||
278 | // Full test, walk n levels deep through the model making sure that all | ||
279 | // parent's children correctly specify their parent. | ||
280 | checkChildren ( QModelIndex() ); | ||
281 | } | ||
282 | |||
283 | /*! | ||
284 | Called from the parent() test. | ||
285 | |||
286 | A model that returns an index of parent X should also return X when asking | ||
287 | for the parent of the index. | ||
288 | |||
289 | This recursive function does pretty extensive testing on the whole model in an | ||
290 | effort to catch edge cases. | ||
291 | |||
292 | This function assumes that rowCount(), columnCount() and index() already work. | ||
293 | If they have a bug it will point it out, but the above tests should have already | ||
294 | found the basic bugs because it is easier to figure out the problem in | ||
295 | those tests then this one. | ||
296 | */ | ||
297 | void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) | ||
298 | { | ||
299 | // First just try walking back up the tree. | ||
300 | QModelIndex p = parent; | ||
301 | while ( p.isValid() ) | ||
302 | p = p.parent(); | ||
303 | |||
304 | // For models that are dynamically populated | ||
305 | if ( model->canFetchMore ( parent ) ) { | ||
306 | fetchingMore = true; | ||
307 | model->fetchMore ( parent ); | ||
308 | fetchingMore = false; | ||
309 | } | ||
310 | |||
311 | int rows = model->rowCount ( parent ); | ||
312 | int columns = model->columnCount ( parent ); | ||
313 | |||
314 | if ( rows > 0 ) | ||
315 | QVERIFY( model->hasChildren ( parent ) ); | ||
316 | |||
317 | // Some further testing against rows(), columns(), and hasChildren() | ||
318 | QVERIFY( rows >= 0 ); | ||
319 | QVERIFY( columns >= 0 ); | ||
320 | if ( rows > 0 ) | ||
321 | QVERIFY( model->hasChildren ( parent ) ); | ||
322 | |||
323 | qWarning() << "parent:" << model->data(parent).toString() << "rows:" << rows | ||
324 | << "columns:" << columns << "parent column:" << parent.column(); | ||
325 | |||
326 | const QModelIndex topLeftChild = model->index( 0, 0, parent ); | ||
327 | |||
328 | QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) ); | ||
329 | for ( int r = 0; r < rows; ++r ) { | ||
330 | if ( model->canFetchMore ( parent ) ) { | ||
331 | fetchingMore = true; | ||
332 | model->fetchMore ( parent ); | ||
333 | fetchingMore = false; | ||
334 | } | ||
335 | QVERIFY( !model->hasIndex ( r, columns + 1, parent ) ); | ||
336 | for ( int c = 0; c < columns; ++c ) { | ||
337 | QVERIFY( model->hasIndex ( r, c, parent ) ); | ||
338 | QModelIndex index = model->index ( r, c, parent ); | ||
339 | // rowCount() and columnCount() said that it existed... | ||
340 | QVERIFY( index.isValid() ); | ||
341 | |||
342 | qWarning() << "\tchild("<< r <<", " << c << ", " << index.column() << "):" << model->data(index).toString() << index.internalPointer(); | ||
343 | |||
344 | // index() should always return the same index when called twice in a row | ||
345 | QModelIndex modifiedIndex = model->index ( r, c, parent ); | ||
346 | QVERIFY( index == modifiedIndex ); | ||
347 | |||
348 | // Make sure we get the same index if we request it twice in a row | ||
349 | QModelIndex a = model->index ( r, c, parent ); | ||
350 | QModelIndex b = model->index ( r, c, parent ); | ||
351 | QVERIFY( a == b ); | ||
352 | |||
353 | { | ||
354 | const QModelIndex sibling = model->sibling( r, c, topLeftChild ); | ||
355 | QVERIFY( index == sibling ); | ||
356 | } | ||
357 | { | ||
358 | const QModelIndex sibling = topLeftChild.sibling( r, c ); | ||
359 | QVERIFY( index == sibling ); | ||
360 | } | ||
361 | |||
362 | // Some basic checking on the index that is returned | ||
363 | QVERIFY( index.model() == model ); | ||
364 | QCOMPARE( index.row(), r ); | ||
365 | QCOMPARE( index.column(), c ); | ||
366 | // While you can technically return a QVariant usually this is a sign | ||
367 | // of a bug in data(). Disable if this really is ok in your model. | ||
368 | // QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() ); | ||
369 | |||
370 | // If the next test fails here is some somewhat useful debug you play with. | ||
371 | |||
372 | if (model->parent(index) != parent) { | ||
373 | qWarning() << r << c << currentDepth << model->data(index).toString() | ||
374 | << model->data(parent).toString(); | ||
375 | qWarning() << index << parent << model->parent(index); | ||
376 | // And a view that you can even use to show the model. | ||
377 | // QTreeView view; | ||
378 | // view.setModel(model); | ||
379 | // view.show(); | ||
380 | } | ||
381 | |||
382 | // Check that we can get back our real parent. | ||
383 | QCOMPARE( model->parent ( index ), parent ); | ||
384 | |||
385 | // recursively go down the children | ||
386 | if ( model->hasChildren ( index ) && currentDepth < 10 ) { | ||
387 | qWarning() << r << c << "has children" << model->rowCount(index); | ||
388 | checkChildren ( index, ++currentDepth ); | ||
389 | }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/ | ||
390 | |||
391 | // make sure that after testing the children that the index doesn't change. | ||
392 | QModelIndex newerIndex = model->index ( r, c, parent ); | ||
393 | QVERIFY( index == newerIndex ); | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | |||
398 | /*! | ||
399 | Tests model's implementation of QAbstractItemModel::data() | ||
400 | */ | ||
401 | void ModelTest::data() | ||
402 | { | ||
403 | // Invalid index should return an invalid qvariant | ||
404 | QVERIFY( !model->data ( QModelIndex() ).isValid() ); | ||
405 | |||
406 | if ( model->rowCount() == 0 ) | ||
407 | return; | ||
408 | |||
409 | // A valid index should have a valid QVariant data | ||
410 | QVERIFY( model->index ( 0, 0 ).isValid() ); | ||
411 | |||
412 | // shouldn't be able to set data on an invalid index | ||
413 | QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) ); | ||
414 | |||
415 | // General Purpose roles that should return a QString | ||
416 | QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole ); | ||
417 | if ( variant.isValid() ) { | ||
418 | QVERIFY( variant.canConvert<QString>() ); | ||
419 | } | ||
420 | variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole ); | ||
421 | if ( variant.isValid() ) { | ||
422 | QVERIFY( variant.canConvert<QString>() ); | ||
423 | } | ||
424 | variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole ); | ||
425 | if ( variant.isValid() ) { | ||
426 | QVERIFY( variant.canConvert<QString>() ); | ||
427 | } | ||
428 | |||
429 | // General Purpose roles that should return a QSize | ||
430 | variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole ); | ||
431 | if ( variant.isValid() ) { | ||
432 | QVERIFY( variant.canConvert<QSize>() ); | ||
433 | } | ||
434 | |||
435 | // General Purpose roles that should return a QFont | ||
436 | QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole ); | ||
437 | if ( fontVariant.isValid() ) { | ||
438 | QVERIFY( fontVariant.canConvert<QFont>() ); | ||
439 | } | ||
440 | |||
441 | // Check that the alignment is one we know about | ||
442 | QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole ); | ||
443 | if ( textAlignmentVariant.isValid() ) { | ||
444 | int alignment = textAlignmentVariant.toInt(); | ||
445 | QCOMPARE( alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) ); | ||
446 | } | ||
447 | |||
448 | // General Purpose roles that should return a QColor | ||
449 | QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole ); | ||
450 | if ( colorVariant.isValid() ) { | ||
451 | QVERIFY( colorVariant.canConvert<QColor>() ); | ||
452 | } | ||
453 | |||
454 | colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole ); | ||
455 | if ( colorVariant.isValid() ) { | ||
456 | QVERIFY( colorVariant.canConvert<QColor>() ); | ||
457 | } | ||
458 | |||
459 | // Check that the "check state" is one we know about. | ||
460 | QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole ); | ||
461 | if ( checkStateVariant.isValid() ) { | ||
462 | int state = checkStateVariant.toInt(); | ||
463 | QVERIFY( state == Qt::Unchecked || | ||
464 | state == Qt::PartiallyChecked || | ||
465 | state == Qt::Checked ); | ||
466 | } | ||
467 | } | ||
468 | |||
469 | /*! | ||
470 | Store what is about to be inserted to make sure it actually happens | ||
471 | |||
472 | \sa rowsInserted() | ||
473 | */ | ||
474 | void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */) | ||
475 | { | ||
476 | // Q_UNUSED(end); | ||
477 | // qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() | ||
478 | // << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) ); | ||
479 | // qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); | ||
480 | Changing c; | ||
481 | c.parent = parent; | ||
482 | c.oldSize = model->rowCount ( parent ); | ||
483 | c.last = model->data ( model->index ( start - 1, 0, parent ) ); | ||
484 | c.next = model->data ( model->index ( start, 0, parent ) ); | ||
485 | insert.push ( c ); | ||
486 | } | ||
487 | |||
488 | /*! | ||
489 | Confirm that what was said was going to happen actually did | ||
490 | |||
491 | \sa rowsAboutToBeInserted() | ||
492 | */ | ||
493 | void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) | ||
494 | { | ||
495 | Changing c = insert.pop(); | ||
496 | QVERIFY( c.parent == parent ); | ||
497 | // qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize | ||
498 | // << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent ); | ||
499 | |||
500 | // for (int ii=start; ii <= end; ii++) | ||
501 | // { | ||
502 | // qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent )); | ||
503 | // } | ||
504 | // qDebug(); | ||
505 | |||
506 | QVERIFY( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) ); | ||
507 | QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); | ||
508 | |||
509 | if (c.next != model->data(model->index(end + 1, 0, c.parent))) { | ||
510 | qDebug() << start << end; | ||
511 | for (int i=0; i < model->rowCount(); ++i) | ||
512 | qDebug() << model->index(i, 0).data().toString(); | ||
513 | qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent)); | ||
514 | } | ||
515 | |||
516 | QVERIFY( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) ); | ||
517 | } | ||
518 | |||
519 | void ModelTest::layoutAboutToBeChanged() | ||
520 | { | ||
521 | for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i ) | ||
522 | changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) ); | ||
523 | } | ||
524 | |||
525 | void ModelTest::layoutChanged() | ||
526 | { | ||
527 | for ( int i = 0; i < changing.count(); ++i ) { | ||
528 | QPersistentModelIndex p = changing[i]; | ||
529 | QVERIFY( p == model->index ( p.row(), p.column(), p.parent() ) ); | ||
530 | } | ||
531 | changing.clear(); | ||
532 | } | ||
533 | |||
534 | /*! | ||
535 | Store what is about to be inserted to make sure it actually happens | ||
536 | |||
537 | \sa rowsRemoved() | ||
538 | */ | ||
539 | void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end ) | ||
540 | { | ||
541 | qDebug() << "ratbr" << parent << start << end; | ||
542 | Changing c; | ||
543 | c.parent = parent; | ||
544 | c.oldSize = model->rowCount ( parent ); | ||
545 | c.last = model->data ( model->index ( start - 1, 0, parent ) ); | ||
546 | c.next = model->data ( model->index ( end + 1, 0, parent ) ); | ||
547 | remove.push ( c ); | ||
548 | } | ||
549 | |||
550 | /*! | ||
551 | Confirm that what was said was going to happen actually did | ||
552 | |||
553 | \sa rowsAboutToBeRemoved() | ||
554 | */ | ||
555 | void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) | ||
556 | { | ||
557 | qDebug() << "rr" << parent << start << end; | ||
558 | Changing c = remove.pop(); | ||
559 | QVERIFY( c.parent == parent ); | ||
560 | QVERIFY( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) ); | ||
561 | QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); | ||
562 | QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); | ||
563 | } | ||
564 | |||
565 | void ModelTest::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) | ||
566 | { | ||
567 | QVERIFY(topLeft.isValid()); | ||
568 | QVERIFY(bottomRight.isValid()); | ||
569 | QModelIndex commonParent = bottomRight.parent(); | ||
570 | QCOMPARE(topLeft.parent(), commonParent); | ||
571 | QVERIFY(topLeft.row() <= bottomRight.row()); | ||
572 | QVERIFY(topLeft.column() <= bottomRight.column()); | ||
573 | int rowCount = model->rowCount(commonParent); | ||
574 | int columnCount = model->columnCount(commonParent); | ||
575 | QVERIFY(bottomRight.row() < rowCount); | ||
576 | QVERIFY(bottomRight.column() < columnCount); | ||
577 | } | ||
578 | |||
579 | void ModelTest::headerDataChanged(Qt::Orientation orientation, int start, int end) | ||
580 | { | ||
581 | QVERIFY(start >= 0); | ||
582 | QVERIFY(end >= 0); | ||
583 | QVERIFY(start <= end); | ||
584 | int itemCount = orientation == Qt::Vertical ? model->rowCount() : model->columnCount(); | ||
585 | QVERIFY(start < itemCount); | ||
586 | QVERIFY(end < itemCount); | ||
587 | } | ||
588 | |||
diff --git a/framework/domain/modeltest.h b/framework/domain/modeltest.h new file mode 100644 index 00000000..735a4227 --- /dev/null +++ b/framework/domain/modeltest.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /**************************************************************************** | ||
2 | ** | ||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | ||
4 | ** Contact: https://www.qt.io/licensing/ | ||
5 | ** | ||
6 | ** This file is part of the test suite of the Qt Toolkit. | ||
7 | ** | ||
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | ||
9 | ** Commercial License Usage | ||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
11 | ** accordance with the commercial license agreement provided with the | ||
12 | ** Software or, alternatively, in accordance with the terms contained in | ||
13 | ** a written agreement between you and The Qt Company. For licensing terms | ||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | ||
15 | ** information use the contact form at https://www.qt.io/contact-us. | ||
16 | ** | ||
17 | ** GNU General Public License Usage | ||
18 | ** Alternatively, this file may be used under the terms of the GNU | ||
19 | ** General Public License version 3 as published by the Free Software | ||
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | ||
21 | ** included in the packaging of this file. Please review the following | ||
22 | ** information to ensure the GNU General Public License requirements will | ||
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | ||
24 | ** | ||
25 | ** $QT_END_LICENSE$ | ||
26 | ** | ||
27 | ****************************************************************************/ | ||
28 | |||
29 | |||
30 | #ifndef MODELTEST_H | ||
31 | #define MODELTEST_H | ||
32 | |||
33 | #include <QtCore/QObject> | ||
34 | #include <QtCore/QAbstractItemModel> | ||
35 | #include <QtCore/QStack> | ||
36 | |||
37 | class ModelTest : public QObject | ||
38 | { | ||
39 | Q_OBJECT | ||
40 | |||
41 | public: | ||
42 | ModelTest( QAbstractItemModel *model, QObject *parent = 0 ); | ||
43 | |||
44 | private Q_SLOTS: | ||
45 | void nonDestructiveBasicTest(); | ||
46 | void rowCount(); | ||
47 | void columnCount(); | ||
48 | void hasIndex(); | ||
49 | void index(); | ||
50 | void parent(); | ||
51 | void data(); | ||
52 | |||
53 | protected Q_SLOTS: | ||
54 | void runAllTests(); | ||
55 | void layoutAboutToBeChanged(); | ||
56 | void layoutChanged(); | ||
57 | void rowsAboutToBeInserted( const QModelIndex &parent, int start, int end ); | ||
58 | void rowsInserted( const QModelIndex & parent, int start, int end ); | ||
59 | void rowsAboutToBeRemoved( const QModelIndex &parent, int start, int end ); | ||
60 | void rowsRemoved( const QModelIndex & parent, int start, int end ); | ||
61 | void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); | ||
62 | void headerDataChanged(Qt::Orientation orientation, int start, int end); | ||
63 | |||
64 | private: | ||
65 | void checkChildren( const QModelIndex &parent, int currentDepth = 0 ); | ||
66 | |||
67 | QAbstractItemModel *model; | ||
68 | |||
69 | struct Changing { | ||
70 | QModelIndex parent; | ||
71 | int oldSize; | ||
72 | QVariant last; | ||
73 | QVariant next; | ||
74 | }; | ||
75 | QStack<Changing> insert; | ||
76 | QStack<Changing> remove; | ||
77 | |||
78 | bool fetchingMore; | ||
79 | |||
80 | QList<QPersistentModelIndex> changing; | ||
81 | }; | ||
82 | |||
83 | #endif | ||