Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
GNOME
Geary
Commits
18fcf0e1
Commit
18fcf0e1
authored
Jun 15, 2018
by
Oliver Giles
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
TNEF (winmail.dat) parsing support via libytnef
parent
ef8f9762
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1870 additions
and
6 deletions
+1870
-6
.gitlab-ci.yml
.gitlab-ci.yml
+2
-2
INSTALL
INSTALL
+3
-2
bindings/vapi/libytnef.vapi
bindings/vapi/libytnef.vapi
+56
-0
meson.build
meson.build
+1
-0
meson_options.txt
meson_options.txt
+1
-0
org.gnome.Geary.json
org.gnome.Geary.json
+10
-0
src/engine/meson.build
src/engine/meson.build
+8
-0
src/engine/rfc822/rfc822-message.vala
src/engine/rfc822/rfc822-message.vala
+35
-2
test/data/basic-multipart-tnef.eml
test/data/basic-multipart-tnef.eml
+1743
-0
test/data/org.gnome.GearyTest.gresource.xml
test/data/org.gnome.GearyTest.gresource.xml
+1
-0
test/engine/rfc822-message-test.vala
test/engine/rfc822-message-test.vala
+10
-0
No files found.
.gitlab-ci.yml
View file @
18fcf0e1
...
...
@@ -27,7 +27,7 @@ variables:
gtk3-devel iso-codes-devel json-glib-devel itstool
libcanberra-devel libgee-devel libhandy-devel
libnotify-devel libsecret-devel libunwind-devel
libxml2-devel sqlite-devel webkitgtk4-devel
libxml2-devel
libytnef-devel
sqlite-devel webkitgtk4-devel
FEDORA_TEST_DEPS
:
Xvfb tar xz
# Ubuntu packages
...
...
@@ -39,7 +39,7 @@ variables:
libhandy-0.0-dev libjson-glib-dev libmessaging-menu-dev
libnotify-dev libsecret-1-dev libsqlite3-dev
libunity-dev libunwind-dev libwebkit2gtk-4.0-dev
libxml2-dev
libxml2-dev
libytnef0-dev
UBUNTU_TEST_DEPS
:
xauth xvfb
fedora
:
...
...
INSTALL
View file @
18fcf0e1
...
...
@@ -45,7 +45,8 @@ Install them by running this command:
glib2-devel gmime-devel gnome-online-accounts-devel gtk3-devel \
iso-codes-devel json-glib-devel libcanberra-devel \
libgee-devel libhandy-devel libnotify-devel libsecret-devel \
libunwind-devel libxml2-devel sqlite-devel webkitgtk4-devel
libunwind-devel libxml2-devel libytnef-devel sqlite-devel \
webkitgtk4-devel
Installing dependencies on Ubuntu/Debian
----------------------------------------
...
...
@@ -58,7 +59,7 @@ Install them by running this command:
libglib2.0-dev libgmime-2.6-dev libgoa-1.0-dev libgtk-3-dev \
libjson-glib-dev libhandy-dev libnotify-dev libsecret-1-dev \
libsqlite3-dev libunwind-dev libwebkit2gtk-4.0-dev \
libxml2-dev
libxml2-dev
libytnef0-dev
And for Ubuntu Unity integration:
...
...
bindings/vapi/libytnef.vapi
0 → 100644
View file @
18fcf0e1
/*
* Copyright (c) 2018 Oliver Giles <ohw.giles@gmail.com>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
[CCode (cheader_filename = "ytnef.h")]
namespace Ytnef {
[CCode (cname ="variableLength", has_type_id = false)]
public struct VariableLength {
[CCode (array_length_cname = "size")]
uint8[] data;
}
[CCode (cname = "MAPI_UNDEFINED")]
public VariableLength* MAPI_UNDEFINED;
[CCode (cname = "int", cprefix = "PT_", has_type_id = false)]
public enum PropType {
STRING8
}
[CCode (cname = "int", cprefix = "PR_", has_type_id = false)]
public enum PropID {
DISPLAY_NAME,
ATTACH_LONG_FILENAME
}
[CCode (cname = "PROP_TAG")]
public static int PROP_TAG(PropType type, PropID id);
[CCode (cname = "MAPIProps", has_type_id = false)]
public struct MAPIProps {
}
[CCode (cname = "Attachment", has_type_id = false)]
public struct Attachment {
VariableLength Title;
VariableLength FileData;
MAPIProps MAPI;
Attachment? next;
}
[CCode (cname = "TNEFStruct", destroy_function="TNEFFree", has_type_id = false)]
public struct TNEFStruct {
Attachment starting_attach;
}
[CCode (cname = "TNEFParseMemory", has_type_id = false)]
public static int ParseMemory(uint8[] data, out TNEFStruct tnef);
[CCode (cname = "MAPIFindProperty")]
public static unowned VariableLength* MAPIFindProperty(MAPIProps MAPI, uint tag);
}
meson.build
View file @
18fcf0e1
...
...
@@ -78,6 +78,7 @@ libunwind_generic_dep = dependency(
'libunwind-generic'
,
version
:
'>= 1.1'
,
required
:
not
get_option
(
'libunwind_optional'
)
)
libxml
=
dependency
(
'libxml-2.0'
,
version
:
'>= 2.7.8'
)
libytnef
=
dependency
(
'libytnef'
,
version
:
'>= 1.9.3'
,
required
:
get_option
(
'tnef-support'
))
posix
=
valac
.
find_library
(
'posix'
)
webkit2gtk_web_extension
=
dependency
(
'webkit2gtk-web-extension-4.0'
,
version
:
'>='
+
target_webkit
)
...
...
meson_options.txt
View file @
18fcf0e1
...
...
@@ -5,3 +5,4 @@ option('ref_tracking', type: 'boolean', value: false, description: 'Whether to u
option('iso_639_xml', type: 'string', value: '', description: 'Full path to the ISO 639 XML file.')
option('iso_3166_xml', type: 'string', value: '', description: 'Full path to the ISO 3166 XML file.')
option('libunwind_optional', type: 'boolean', value: false, description: 'Determines if libunwind is required.')
option('tnef-support', type: 'boolean', value: true, description: 'Whether to support TNEF attachments (requires libytnef).')
org.gnome.Geary.json
View file @
18fcf0e1
...
...
@@ -205,6 +205,16 @@
}
]
},
{
"name"
:
"libytnef"
,
"sources"
:
[
{
"type"
:
"git"
,
"url"
:
"https://github.com/Yeraze/ytnef.git"
,
"branch"
:
"master"
}
]
},
{
"name"
:
"geary"
,
"buildsystem"
:
"meson"
,
...
...
src/engine/meson.build
View file @
18fcf0e1
...
...
@@ -333,6 +333,7 @@ geary_engine_dependencies = [
gmime
,
javascriptcoregtk
,
libxml
,
libytnef
,
posix
,
sqlite
]
...
...
@@ -358,6 +359,13 @@ if libunwind_dep.found()
]
endif
if
get_option
(
'tnef-support'
)
geary_engine_dependencies
+=
libytnef
geary_engine_vala_options
+=
[
'-D'
,
'WITH_TNEF_SUPPORT'
]
endif
geary_engine_lib
=
static_library
(
'geary-engine'
,
geary_engine_sources
,
dependencies
:
geary_engine_dependencies
,
...
...
src/engine/rfc822/rfc822-message.vala
View file @
18fcf0e1
...
...
@@ -880,17 +880,50 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
Mime
.
ContentType
content_type
=
part
.
get_effective_content_type
();
// Skip text/plain and text/html parts that are INLINE
// or UNSPECIFIED, as they will be included in the body
#if WITH_TNEF_SUPPORT
if
(
content_type
.
is_type
(
"application"
,
"vnd.ms-tnef"
))
{
GMime
.
StreamMem
stream
=
new
GMime
.
StreamMem
();
((
GMime
.
Part
)
root
).
get_content_object
().
write_to_stream
(
stream
);
ByteArray
tnef_data
=
stream
.
get_byte_array
();
Ytnef
.
TNEFStruct
tn
;
if
(
Ytnef
.
ParseMemory
(
tnef_data
.
data
,
out
tn
)
==
0
)
{
for
(
unowned
Ytnef
.
Attachment
?
a
=
tn
.
starting_attach
.
next
;
a
!=
null
;
a
=
a
.
next
)
{
attachments
.
add
(
new
Part
(
tnef_attachment_to_gmime_part
(
a
)));
}
}
}
else
#endif // WITH_TNEF_SUPPORT
if
(
actual_disposition
==
Mime
.
DispositionType
.
ATTACHMENT
||
(!
content_type
.
is_type
(
"text"
,
"plain"
)
&&
!
content_type
.
is_type
(
"text"
,
"html"
)))
{
// Skip text/plain and text/html parts that are INLINE
// or UNSPECIFIED, as they will be included in the body
attachments
.
add
(
part
);
}
}
}
}
#if WITH_TNEF_SUPPORT
private
GMime
.
Part
tnef_attachment_to_gmime_part
(
Ytnef
.
Attachment
a
)
{
Ytnef
.
VariableLength
*
filenameProp
=
Ytnef
.
MAPIFindProperty
(
a
.
MAPI
,
Ytnef
.
PROP_TAG
(
Ytnef
.
PropType
.
STRING8
,
Ytnef
.
PropID
.
ATTACH_LONG_FILENAME
));
if
(
filenameProp
==
Ytnef
.
MAPI_UNDEFINED
)
{
filenameProp
=
Ytnef
.
MAPIFindProperty
(
a
.
MAPI
,
Ytnef
.
PROP_TAG
(
Ytnef
.
PropType
.
STRING8
,
Ytnef
.
PropID
.
DISPLAY_NAME
));
if
(
filenameProp
==
Ytnef
.
MAPI_UNDEFINED
)
{
filenameProp
=
&
a
.
Title
;
}
}
string
filename
=
(
string
)
filenameProp
.
data
;
uint8
[]
data
=
Bytes
.
unref_to_data
(
new
Bytes
(
a
.
FileData
.
data
));
GMime
.
Part
part
=
new
GMime
.
Part
();
part
.
set_filename
(
filename
);
part
.
set_content_type
(
new
GMime
.
ContentType
.
from_string
(
GLib
.
ContentType
.
guess
(
filename
,
data
,
null
)));
part
.
set_content_object
(
new
GMime
.
DataWrapper
.
with_stream
(
new
GMime
.
StreamMem
.
with_buffer
(
data
),
GMime
.
ContentEncoding
.
BINARY
));
return
part
;
}
#endif
public
Gee
.
List
<
Geary
.
RFC822
.
Message
>
get_sub_messages
()
{
Gee
.
List
<
Geary
.
RFC822
.
Message
>
messages
=
new
Gee
.
ArrayList
<
Geary
.
RFC822
.
Message
>();
find_sub_messages
(
messages
,
message
.
get_mime_part
());
...
...
test/data/basic-multipart-tnef.eml
0 → 100644
View file @
18fcf0e1
This diff is collapsed.
Click to expand it.
test/data/org.gnome.GearyTest.gresource.xml
View file @
18fcf0e1
...
...
@@ -4,6 +4,7 @@
<file>
basic-text-plain.eml
</file>
<file>
basic-text-html.eml
</file>
<file>
basic-multipart-alternative.eml
</file>
<file>
basic-multipart-tnef.eml
</file>
<file>
geary-0.6-db.tar.xz
</file>
</gresource>
</gresources>
test/engine/rfc822-message-test.vala
View file @
18fcf0e1
...
...
@@ -12,6 +12,7 @@ class Geary.RFC822.MessageTest : TestCase {
private
const
string
BASIC_TEXT_HTML
=
"basic-text-html.eml"
;
private
const
string
BASIC_MULTIPART_ALTERNATIVE
=
"basic-multipart-alternative.eml"
;
private
const
string
BASIC_MULTIPART_TNEF
=
"basic-multipart-tnef.eml"
;
private
const
string
HTML_CONVERSION_TEMPLATE
=
"<div class=\"plaintext\" style=\"white-space: pre-wrap;\">%s</div>"
;
...
...
@@ -38,6 +39,7 @@ This is the second line.
add_test
(
"text_plain_as_html"
,
text_plain_as_html
);
add_test
(
"text_html_as_html"
,
text_html_as_html
);
add_test
(
"text_html_as_plain"
,
text_html_as_plain
);
add_test
(
"tnef_extract_attachments"
,
tnef_extract_attachments
);
add_test
(
"multipart_alternative_as_plain"
,
multipart_alternative_as_plain
);
add_test
(
"multipart_alternative_as_converted_html"
,
...
...
@@ -124,6 +126,14 @@ This is the second line.
assert_string
(
BASIC_HTML_BODY
,
test
.
get_html_body
(
null
));
}
public
void
tnef_extract_attachments
()
throws
Error
{
Message
test
=
resource_to_message
(
BASIC_MULTIPART_TNEF
);
Gee
.
List
<
Part
>
attachments
=
test
.
get_attachments
();
assert_true
(
attachments
.
size
==
2
);
assert_true
(
attachments
[
0
].
get_clean_filename
()
==
"zappa_av1.jpg"
);
assert_true
(
attachments
[
1
].
get_clean_filename
()
==
"bookmark.htm"
);
}
public
void
multipart_alternative_as_plain
()
throws
Error
{
Message
test
=
resource_to_message
(
BASIC_MULTIPART_ALTERNATIVE
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment