Merge branch 'letorbi/gmime-3' into 'mainline'
Upgrade to GMime 3.2.4 Closes #622 See merge request GNOME/geary!382
This commit is contained in:
commit
ba3b91f037
30 changed files with 277 additions and 1855 deletions
|
|
@ -27,7 +27,7 @@ variables:
|
|||
# Fedora packages
|
||||
FEDORA_DEPS:
|
||||
meson vala desktop-file-utils enchant2-devel folks-devel gcr-devel
|
||||
glib2-devel gmime-devel gnome-online-accounts-devel gspell-devel
|
||||
glib2-devel gmime30-devel gnome-online-accounts-devel gspell-devel
|
||||
gtk3-devel iso-codes-devel json-glib-devel itstool
|
||||
libappstream-glib-devel libgee-devel libhandy-devel libpeas-devel
|
||||
libsecret-devel libunwind-devel libxml2-devel libytnef-devel
|
||||
|
|
@ -38,7 +38,7 @@ variables:
|
|||
UBUNTU_DEPS:
|
||||
meson build-essential valac desktop-file-utils gettext iso-codes
|
||||
itstool libappstream-glib-dev libenchant-dev libfolks-dev
|
||||
libgcr-3-dev libgee-0.8-dev libglib2.0-dev libgmime-2.6-dev
|
||||
libgcr-3-dev libgee-0.8-dev libglib2.0-dev libgmime-3.0-dev
|
||||
libgoa-1.0-dev libgspell-1-dev libgtk-3-dev libhandy-0.0-dev
|
||||
libjson-glib-dev libmessaging-menu-dev libpeas-dev libsecret-1-dev
|
||||
libsqlite3-dev libunwind-dev libwebkit2gtk-4.0-dev libxml2-dev
|
||||
|
|
|
|||
4
INSTALL
4
INSTALL
|
|
@ -40,7 +40,7 @@ Installing dependencies on Fedora
|
|||
Install them by running this command:
|
||||
|
||||
sudo dnf install meson vala desktop-file-utils enchant2-devel \
|
||||
folks-devel gcr-devel glib2-devel gmime-devel \
|
||||
folks-devel gcr-devel glib2-devel gmime30-devel \
|
||||
gnome-online-accounts-devel gspell-devel gtk3-devel \
|
||||
iso-codes-devel json-glib-devel libappstream-glib-devel \
|
||||
libgee-devel libhandy-devel libpeas-devel libsecret-devel \
|
||||
|
|
@ -55,7 +55,7 @@ Install them by running this command:
|
|||
sudo apt-get install meson build-essential valac \
|
||||
desktop-file-utils iso-codes gettext itstool \
|
||||
libappstream-glib-dev libenchant-dev libfolks-dev libgcr-3-dev \
|
||||
libgee-0.8-dev libglib2.0-dev libgmime-2.6-dev libgoa-1.0-dev \
|
||||
libgee-0.8-dev libglib2.0-dev libgmime3.0-dev libgoa-1.0-dev \
|
||||
libgspell-1-dev libgtk-3-dev libjson-glib-dev libhandy-0.0-dev \
|
||||
libpeas-dev libsecret-1-dev libsqlite3-dev libunwind-dev \
|
||||
libwebkit2gtk-4.0-dev libxml2-dev libytnef0-dev
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
# NOTE: The dependencies in this file require vapigen and vala-gen-introspect to be installed,
|
||||
# which are not default in a standard Vala installation.
|
||||
|
||||
GMIME_FILES := \
|
||||
gmime-2.6/gmime-2.6.defines \
|
||||
gmime-2.6/gmime-2.6.files \
|
||||
gmime-2.6/gmime-2.6.metadata \
|
||||
gmime-2.6/gmime-2.6.namespace \
|
||||
gmime-2.6/gmime-2.6-custom.vala
|
||||
|
||||
all: gmime-2.6.vapi
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm gmime-2.6.vapi gmime-2.6/gmime-2.6.gi
|
||||
|
||||
gmime-2.6/gmime-2.6.gi: $(GMIME_FILES)
|
||||
vala-gen-introspect gmime-2.6 gmime-2.6
|
||||
|
||||
gmime-2.6.vapi: gmime-2.6/gmime-2.6.gi
|
||||
vapigen --pkg=glib-2.0 --pkg=gio-2.0 --library gmime-2.6 gmime-2.6/gmime-2.6.gi gmime-2.6/gmime-2.6-custom.vala
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,72 +0,0 @@
|
|||
/* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
[CCode (cname="InternetAddress", cheader_filename="gmime/gmime.h", type_id="INTERNET_ADDRESS_TYPE", type_check_function="IS_INTERNET_ADDRESS")]
|
||||
public class InternetAddress : GLib.Object {
|
||||
[CCode (cname="internet_address_get_name")]
|
||||
public unowned string? get_name();
|
||||
[CCode (cname="internet_address_set_name")]
|
||||
public void set_name(string? name);
|
||||
[CCode (cname="internet_address_to_string")]
|
||||
public virtual string to_string(bool encoded);
|
||||
}
|
||||
|
||||
[CCode (cname="InternetAddressGroup", cheader_filename="gmime/gmime.h", type_id="INTERNET_ADDRESS_TYPE_GROUP", type_check_function="INTERNET_ADDRESS_IS_GROUP")]
|
||||
public class InternetAddressGroup : InternetAddress {
|
||||
[CCode (cname="internet_address_group_new")]
|
||||
public InternetAddressGroup(string name);
|
||||
[CCode (cname="internet_address_group_get_members")]
|
||||
public unowned InternetAddressList get_members();
|
||||
[CCode (cname="internet_address_group_set_members")]
|
||||
public void set_members(InternetAddressList members);
|
||||
[CCode (cname="internet_address_group_add_member")]
|
||||
public int add_member(InternetAddress member);
|
||||
}
|
||||
|
||||
[CCode (cname="InternetAddressMailbox", cheader_filename="gmime/gmime.h", type_id="INTERNET_ADDRESS_TYPE_MAILBOX", type_check_function="INTERNET_ADDRESS_IS_MAILBOX")]
|
||||
public class InternetAddressMailbox : InternetAddress {
|
||||
[CCode (cname="internet_address_mailbox_new")]
|
||||
public InternetAddressMailbox(string? name, string addr);
|
||||
[CCode (cname="internet_address_mailbox_get_addr")]
|
||||
public unowned string get_addr();
|
||||
[CCode (cname="internet_address_mailbox_set_addr")]
|
||||
public void set_addr(string addr);
|
||||
}
|
||||
|
||||
[CCode (cname="InternetAddressList", cheader_filename="gmime/gmime.h", type_id="INTERNET_ADDRESS_LIST_TYPE", type_check_function="IS_INTERNET_ADDRESS_LIST")]
|
||||
public class InternetAddressList : GLib.Object {
|
||||
[CCode (cname="internet_address_list_new")]
|
||||
public InternetAddressList();
|
||||
[CCode (cname="internet_address_list_length")]
|
||||
public int length();
|
||||
[CCode (cname="internet_address_list_clear")]
|
||||
public void clear();
|
||||
[CCode (cname="internet_address_list_add")]
|
||||
public int add(InternetAddress addr);
|
||||
[CCode (cname="internet_address_list_insert")]
|
||||
public void insert(int index, InternetAddress addr);
|
||||
[CCode (cname="internet_address_list_remove")]
|
||||
public bool remove(InternetAddress addr);
|
||||
[CCode (cname="internet_address_list_remove_at")]
|
||||
public bool remove_at(int index);
|
||||
[CCode (cname="internet_address_list_contains")]
|
||||
public bool contains(InternetAddress addr);
|
||||
[CCode (cname="internet_address_list_index_of")]
|
||||
public int index_of(InternetAddress addr);
|
||||
[CCode (cname="internet_address_list_get_address")]
|
||||
public unowned InternetAddress get_address(int index);
|
||||
[CCode (cname="internet_address_list_set_address")]
|
||||
public void set_address(int index, InternetAddress addr);
|
||||
[CCode (cname="internet_address_list_prepend")]
|
||||
public void prepend(InternetAddressList prepend);
|
||||
[CCode (cname="internet_address_list_append")]
|
||||
public void append(InternetAddressList append);
|
||||
[CCode (cname="internet_address_list_to_string")]
|
||||
public string? to_string(bool encode);
|
||||
[CCode (cname="internet_address_list_parse_string")]
|
||||
public static InternetAddressList? parse_string(string str);
|
||||
}
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
include/gmime-2.6/
|
||||
lib/x86_64-linux-gnu/libgmime-2.6.so
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
GMime lower_case_cprefix="gmime_" cheader_filename="gmime/gmime.h"
|
||||
|
||||
GMimeObject abstract="1"
|
||||
GMimeStream abstract="1"
|
||||
|
||||
g_mime_content_type_to_string transfer_ownership="1"
|
||||
g_mime_header_list_get_iter.iter is_out="1"
|
||||
g_mime_message_get_date.date is_out="1"
|
||||
g_mime_message_get_date.tz_offset is_out="1"
|
||||
g_mime_message_get_date_as_string transfer_ownership="1"
|
||||
g_mime_message_get_mime_part is_nullable="1"
|
||||
g_mime_multipart_remove_at is_nullable="1" transfer_ownership="1"
|
||||
g_mime_multipart_replace is_nullable="1" transfer_ownership="1"
|
||||
g_mime_object_get_content_disposition nullable="1"
|
||||
g_mime_object_get_content_type nullable="1"
|
||||
g_mime_object_get_content_type_parameter nullable="1"
|
||||
g_mime_object_get_headers transfer_ownership="1"
|
||||
g_mime_object_to_string transfer_ownership="1"
|
||||
g_mime_param_next name="get_next"
|
||||
g_mime_parser_construct_message nullable="1" transfer_ownership="1"
|
||||
g_mime_parser_construct_part nullable="1" transfer_ownership="1"
|
||||
g_mime_part_get_content_description nullable="1"
|
||||
g_mime_part_get_content_location nullable="1"
|
||||
g_mime_part_get_content_id nullable="1"
|
||||
g_mime_part_get_content_md5 nullable="1"
|
||||
g_mime_part_get_content_object nullable="1"
|
||||
g_mime_part_get_content_part nullable="1"
|
||||
g_mime_part_get_filename nullable="1"
|
||||
g_mime_signer_next name="get_next"
|
||||
g_mime_stream_mem_new_with_buffer.buffer is_array="1" array_length_pos="1.0" type_name="uint8[]"
|
||||
g_mime_stream_mem_new_with_buffer.len hidden="1"
|
||||
g_mime_stream_read.buf is_array="1" type_name="uint8[]"
|
||||
g_mime_stream_read.len hidden="1"
|
||||
g_mime_utils_decode_8bit transfer_ownership="1"
|
||||
g_mime_utils_decode_message_id transfer_ownership="1"
|
||||
g_mime_utils_generate_message_id transfer_ownership="1"
|
||||
g_mime_utils_header_decode_date type_name="time_t"
|
||||
g_mime_utils_header_decode_date.tz_offset is_out="1"
|
||||
g_mime_utils_header_decode_phrase transfer_ownership="1"
|
||||
g_mime_utils_header_decode_text transfer_ownership="1"
|
||||
g_mime_utils_header_encode_phrase transfer_ownership="1"
|
||||
g_mime_utils_header_encode_text transfer_ownership="1"
|
||||
g_mime_utils_header_fold transfer_ownership="1"
|
||||
g_mime_utils_header_format_date transfer_ownership="1"
|
||||
g_mime_utils_header_printf transfer_ownership="1"
|
||||
g_mime_utils_quote_string transfer_ownership="1"
|
||||
g_mime_utils_structured_header_fold transfer_ownership="1"
|
||||
g_mime_utils_unstructured_header_fold transfer_ownership="1"
|
||||
|
||||
# FIXME: there is no keyword "is_protected"
|
||||
GMimeFilter.backbuf type_name="char*" is_protected="1"
|
||||
GMimeFilter.backlen is_protected="1"
|
||||
GMimeFilter.backsize is_protected="1"
|
||||
GMimeFilter.outbuf is_array="1" type_name="char[]" array_length_cname="outsize" array_length_type="size_t" is_protected="1"
|
||||
GMimeFilter.outpre is_protected="1"
|
||||
GMimeFilter.outptr type_name="char*" is_protected="1"
|
||||
GMimeFilter.outreal type_name="char*" is_protected="1"
|
||||
GMimeFilter.outsize hidden="1" is_protected="1"
|
||||
GMimeFilterBest.charset hidden="1"
|
||||
|
||||
g_mime_filter_backup.data is_array="1" array_length_pos="1.1" array_length_type="size_t" type_name="char[]"
|
||||
g_mime_filter_backup.length hidden="1"
|
||||
g_mime_filter_complete.inbuf is_array="1" array_length_pos="1.1" array_length_type="size_t" type_name="char[]"
|
||||
g_mime_filter_complete.inlen hidden="1"
|
||||
g_mime_filter_complete.outbuf is_array="1" array_length_pos="3.1" array_length_type="size_t" type_name="char[]" is_out="1" transfer_ownership="0"
|
||||
g_mime_filter_complete.outlen hidden="1"
|
||||
g_mime_filter_complete.outprespace is_out="1"
|
||||
g_mime_filter_filter.inbuf is_array="1" array_length_pos="1.1" array_length_type="size_t" type_name="char[]"
|
||||
g_mime_filter_filter.inlen hidden="1"
|
||||
g_mime_filter_filter.outbuf is_array="1" array_length_pos="3.1" array_length_type="size_t" type_name="char[]" is_out="1" transfer_ownership="0"
|
||||
g_mime_filter_filter.outlen hidden="1"
|
||||
g_mime_filter_filter.outprespace is_out="1"
|
||||
g_mime_filter_copy transfer_ownership="1"
|
||||
|
||||
InternetAddress hidden="1"
|
||||
internet_address_* hidden="1"
|
||||
InternetAddress.name hidden="1"
|
||||
|
||||
InternetAddressGroup hidden="1"
|
||||
internet_address_group_* hidden="1"
|
||||
InternetAddressGroup.members hidden="1"
|
||||
|
||||
InternetAddressList hidden="1"
|
||||
internet_address_list_* hidden="1"
|
||||
InternetAddressList.array hidden="1"
|
||||
|
||||
InternetAddressMailbox hidden="1"
|
||||
internet_address_mailbox_* hidden="1"
|
||||
InternetAddressMailbox.addr hidden="1"
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
GMime
|
||||
|
|
@ -57,7 +57,7 @@ target_webkit = '2.24'
|
|||
|
||||
# Primary deps
|
||||
glib = dependency('glib-2.0', version: '>=' + target_glib)
|
||||
gmime = dependency('gmime-2.6', version: '>= 2.6.17')
|
||||
gmime = dependency('gmime-3.0', version: '>= 3.2.4')
|
||||
gtk = dependency('gtk+-3.0', version: '>=' + target_gtk)
|
||||
sqlite = dependency('sqlite3', version: '>= 3.24')
|
||||
webkit2gtk = dependency('webkit2gtk-4.0', version: '>=' + target_webkit)
|
||||
|
|
|
|||
|
|
@ -167,8 +167,7 @@
|
|||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/jstedfast/gmime.git",
|
||||
"branch": "gmime-2-6"
|
||||
"url": "https://github.com/jstedfast/gmime.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -175,7 +175,6 @@ modules:
|
|||
sources:
|
||||
- type: git
|
||||
url: https://github.com/jstedfast/gmime.git
|
||||
branch: gmime-2-6
|
||||
|
||||
# Geary dependency
|
||||
- name: libhandy
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ private class Geary.ImapDB.Attachment : Geary.Attachment {
|
|||
target_stream
|
||||
);
|
||||
stream = new GMime.StreamBuffer(
|
||||
stream, GMime.StreamBufferMode.BLOCK_WRITE
|
||||
stream, GMime.StreamBufferMode.WRITE
|
||||
);
|
||||
|
||||
part.write_to_stream(stream, RFC822.Part.EncodingConversion.NONE);
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ public class Geary.Mime.ContentDisposition : Geary.BaseObject {
|
|||
out is_unknown);
|
||||
is_unknown_disposition_type = is_unknown;
|
||||
original_disposition_type_string = content_disposition.get_disposition();
|
||||
params = new ContentParameters.from_gmime(content_disposition.get_params());
|
||||
params = new ContentParameters.from_gmime(content_disposition.get_parameters());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,11 +51,13 @@ public class Geary.Mime.ContentParameters : BaseObject {
|
|||
}
|
||||
}
|
||||
|
||||
internal ContentParameters.from_gmime(GMime.Param? gmime_param) {
|
||||
internal ContentParameters.from_gmime(GMime.ParamList? gmime_params) {
|
||||
Gee.Map<string,string> params = new Gee.HashMap<string,string>();
|
||||
while (gmime_param != null) {
|
||||
params.set(gmime_param.get_name(), gmime_param.get_value());
|
||||
gmime_param = gmime_param.get_next();
|
||||
if (gmime_params != null) {
|
||||
for (int i = 0; i < gmime_params.length(); i++) {
|
||||
GMime.Param gmime_param = gmime_params.get_parameter_at(i);
|
||||
params.set(gmime_param.get_name(), gmime_param.get_value());
|
||||
}
|
||||
}
|
||||
this(params);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,10 @@ public class Geary.Mime.ContentType : Geary.BaseObject {
|
|||
if (!str.contains("/"))
|
||||
throw new MimeError.PARSE("Invalid MIME Content-Type: %s", str);
|
||||
|
||||
return new ContentType.from_gmime(new GMime.ContentType.from_string(str));
|
||||
return new ContentType.from_gmime(GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
str
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -158,7 +161,7 @@ public class Geary.Mime.ContentType : Geary.BaseObject {
|
|||
internal ContentType.from_gmime(GMime.ContentType content_type) {
|
||||
media_type = content_type.get_media_type().strip();
|
||||
media_subtype = content_type.get_media_subtype().strip();
|
||||
params = new ContentParameters.from_gmime(content_type.get_params());
|
||||
params = new ContentParameters.from_gmime(content_type.get_parameters());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ private class Geary.RFC822.FilterBlockquotes : GMime.Filter {
|
|||
return new_filter;
|
||||
}
|
||||
|
||||
private void do_filter(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
private void do_filter(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace, bool flush) {
|
||||
|
||||
// This may not be strictly necessary.
|
||||
|
|
@ -64,7 +64,7 @@ private class Geary.RFC822.FilterBlockquotes : GMime.Filter {
|
|||
}
|
||||
|
||||
for (uint i = 0; i < inbuf.length; i++) {
|
||||
char c = inbuf[i];
|
||||
uint8 c = inbuf[i];
|
||||
|
||||
if (in_prefix && !in_tag) {
|
||||
if (c == Geary.RFC822.Utils.QUOTE_MARKER) {
|
||||
|
|
@ -122,12 +122,12 @@ private class Geary.RFC822.FilterBlockquotes : GMime.Filter {
|
|||
outprespace = this.outpre;
|
||||
}
|
||||
|
||||
public override void filter(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void filter(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
do_filter(inbuf, prespace, out processed_buffer, out outprespace, false);
|
||||
}
|
||||
|
||||
public override void complete(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void complete(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
do_filter(inbuf, prespace, out processed_buffer, out outprespace, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ private class Geary.RFC822.FilterFlowed : GMime.Filter {
|
|||
return new_filter;
|
||||
}
|
||||
|
||||
public override void filter(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void filter(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
|
||||
// Worst-case scenario: We are about to leave the prefix,
|
||||
|
|
@ -67,7 +67,7 @@ private class Geary.RFC822.FilterFlowed : GMime.Filter {
|
|||
|
||||
uint out_index = 0;
|
||||
for (uint i = 0; i < inbuf.length; i++) {
|
||||
char c = inbuf[i];
|
||||
uint8 c = inbuf[i];
|
||||
|
||||
if (this.in_prefix) {
|
||||
if (c == '>') {
|
||||
|
|
@ -147,7 +147,7 @@ private class Geary.RFC822.FilterFlowed : GMime.Filter {
|
|||
outprespace = this.outpre;
|
||||
}
|
||||
|
||||
public override void complete(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void complete(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
filter(inbuf, prespace, out processed_buffer, out outprespace);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ private class Geary.RFC822.FilterPlain : GMime.Filter {
|
|||
return new_filter;
|
||||
}
|
||||
|
||||
public override void filter(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void filter(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
|
||||
// This may not be strictly necessary.
|
||||
|
|
@ -34,7 +34,7 @@ private class Geary.RFC822.FilterPlain : GMime.Filter {
|
|||
|
||||
uint out_index = 0;
|
||||
for (uint i = 0; i < inbuf.length; i++) {
|
||||
char c = inbuf[i];
|
||||
uint8 c = inbuf[i];
|
||||
|
||||
if (in_prefix) {
|
||||
if (c == '>') {
|
||||
|
|
@ -56,7 +56,7 @@ private class Geary.RFC822.FilterPlain : GMime.Filter {
|
|||
outprespace = this.outpre;
|
||||
}
|
||||
|
||||
public override void complete(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void complete(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
filter(inbuf, prespace, out processed_buffer, out outprespace);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,17 @@ public class Geary.RFC822.MailboxAddress :
|
|||
}
|
||||
|
||||
private static string decode_name(string name) {
|
||||
return GMime.utils_header_decode_phrase(prepare_header_text_part(name));
|
||||
return GMime.utils_header_decode_phrase(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
prepare_header_text_part(name)
|
||||
);
|
||||
}
|
||||
|
||||
private static string decode_address_part(string mailbox) {
|
||||
return GMime.utils_header_decode_text(prepare_header_text_part(mailbox));
|
||||
return GMime.utils_header_decode_text(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
prepare_header_text_part(mailbox)
|
||||
);
|
||||
}
|
||||
|
||||
private static bool display_name_needs_quoting(string name) {
|
||||
|
|
@ -118,8 +124,9 @@ public class Geary.RFC822.MailboxAddress :
|
|||
// _internet_address_decode_name() function.
|
||||
|
||||
// see if a broken mailer has sent raw 8-bit information
|
||||
string text = GMime.utils_text_is_8bit(part, part.length)
|
||||
? part : GMime.utils_decode_8bit(part, part.length);
|
||||
string text = GMime.utils_text_is_8bit(part.data)
|
||||
? part : GMime.utils_decode_8bit(Geary.RFC822.get_parser_options(),
|
||||
part.data);
|
||||
|
||||
// unquote the string then decode the text
|
||||
GMime.utils_unquote_string(text);
|
||||
|
|
@ -222,16 +229,19 @@ public class Geary.RFC822.MailboxAddress :
|
|||
}
|
||||
|
||||
public MailboxAddress.from_rfc822_string(string rfc822) throws RFC822Error {
|
||||
InternetAddressList addrlist = InternetAddressList.parse_string(rfc822);
|
||||
GMime.InternetAddressList addrlist = GMime.InternetAddressList.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
rfc822
|
||||
);
|
||||
if (addrlist == null)
|
||||
return;
|
||||
|
||||
int length = addrlist.length();
|
||||
for (int ctr = 0; ctr < length; ctr++) {
|
||||
InternetAddress? addr = addrlist.get_address(ctr);
|
||||
GMime.InternetAddress? addr = addrlist.get_address(ctr);
|
||||
|
||||
// TODO: Handle group lists
|
||||
InternetAddressMailbox? mbox_addr = addr as InternetAddressMailbox;
|
||||
GMime.InternetAddressMailbox? mbox_addr = addr as GMime.InternetAddressMailbox;
|
||||
if (mbox_addr != null) {
|
||||
this.gmime(mbox_addr);
|
||||
return;
|
||||
|
|
@ -240,11 +250,11 @@ public class Geary.RFC822.MailboxAddress :
|
|||
throw new RFC822Error.INVALID("Could not parse RFC822 address: %s", rfc822);
|
||||
}
|
||||
|
||||
public MailboxAddress.gmime(InternetAddressMailbox mailbox) {
|
||||
public MailboxAddress.gmime(GMime.InternetAddressMailbox mailbox) {
|
||||
// GMime strips source route for us, so the address part
|
||||
// should only ever contain a single '@'
|
||||
string? name = mailbox.get_name();
|
||||
if (name != null) {
|
||||
if (name != "") {
|
||||
this.name = decode_name(name);
|
||||
}
|
||||
|
||||
|
|
@ -456,7 +466,11 @@ public class Geary.RFC822.MailboxAddress :
|
|||
public string to_rfc822_string() {
|
||||
return has_distinct_name()
|
||||
? "%s <%s>".printf(
|
||||
GMime.utils_header_encode_phrase(this.name),
|
||||
GMime.utils_header_encode_phrase(
|
||||
Geary.RFC822.get_format_options(),
|
||||
this.name,
|
||||
"iso-8859-1"
|
||||
),
|
||||
to_rfc822_address()
|
||||
)
|
||||
: to_rfc822_address();
|
||||
|
|
|
|||
|
|
@ -74,27 +74,30 @@ public class Geary.RFC822.MailboxAddresses :
|
|||
}
|
||||
|
||||
public MailboxAddresses.from_rfc822_string(string rfc822) {
|
||||
InternetAddressList addrlist = InternetAddressList.parse_string(rfc822);
|
||||
GMime.InternetAddressList addrlist = GMime.InternetAddressList.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
rfc822
|
||||
);
|
||||
if (addrlist == null)
|
||||
return;
|
||||
|
||||
int length = addrlist.length();
|
||||
for (int ctr = 0; ctr < length; ctr++) {
|
||||
InternetAddress? addr = addrlist.get_address(ctr);
|
||||
GMime.InternetAddress? addr = addrlist.get_address(ctr);
|
||||
|
||||
InternetAddressMailbox? mbox_addr = addr as InternetAddressMailbox;
|
||||
GMime.InternetAddressMailbox? mbox_addr = addr as GMime.InternetAddressMailbox;
|
||||
if (mbox_addr != null) {
|
||||
this.addrs.add(new MailboxAddress.gmime(mbox_addr));
|
||||
} else {
|
||||
// XXX this is pretty bad - we just flatten the
|
||||
// group's addresses into this list, merging lists and
|
||||
// losing the group names.
|
||||
InternetAddressGroup? mbox_group = addr as InternetAddressGroup;
|
||||
GMime.InternetAddressGroup? mbox_group = addr as GMime.InternetAddressGroup;
|
||||
if (mbox_group != null) {
|
||||
InternetAddressList group_list = mbox_group.get_members();
|
||||
GMime.InternetAddressList group_list = mbox_group.get_members();
|
||||
for (int i = 0; i < group_list.length(); i++) {
|
||||
InternetAddressMailbox? group_addr =
|
||||
addrlist.get_address(i) as InternetAddressMailbox;
|
||||
GMime.InternetAddressMailbox? group_addr =
|
||||
addrlist.get_address(i) as GMime.InternetAddressMailbox;
|
||||
if (group_addr != null) {
|
||||
this.addrs.add(new MailboxAddress.gmime(group_addr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,27 +173,13 @@ public class Geary.RFC822.Date : Geary.RFC822.MessageData, Geary.MessageData.Abs
|
|||
public DateTime value { get; private set; }
|
||||
|
||||
public Date(string rfc822) throws ImapError {
|
||||
int offset = 0;
|
||||
int64 time_t_utc = GMime.utils_header_decode_date(rfc822, out offset);
|
||||
if (time_t_utc == 0)
|
||||
throw new ImapError.PARSE_ERROR(
|
||||
"Unable to parse \"%s\": Not ISO-8601 date", rfc822
|
||||
);
|
||||
|
||||
DateTime? value = new DateTime.from_unix_utc(time_t_utc);
|
||||
DateTime? value = GMime.utils_header_decode_date(rfc822);
|
||||
if (value == null) {
|
||||
throw new ImapError.PARSE_ERROR(
|
||||
"Unable to parse \"%s\": Outside supported range", rfc822
|
||||
);
|
||||
}
|
||||
this.value = value;
|
||||
|
||||
if (offset != 0) {
|
||||
this.value = value.to_timezone(
|
||||
new GLib.TimeZone("%+05d".printf(offset))
|
||||
);
|
||||
}
|
||||
|
||||
this.original = rfc822;
|
||||
}
|
||||
|
||||
|
|
@ -206,18 +192,7 @@ public class Geary.RFC822.Date : Geary.RFC822.MessageData, Geary.MessageData.Abs
|
|||
* Returns the {@link Date} in RFC 822 format.
|
||||
*/
|
||||
public string to_rfc822_string() {
|
||||
// Although GMime documents its conversion methods as
|
||||
// requiring the tz offset in hours, it appears the number is
|
||||
// handed directly to the string (i.e. an offset of -7:30 becomes
|
||||
// "-0007", whereas we want "-0730").
|
||||
int hours = (int) GLib.Math.floor(value.get_utc_offset() / TimeSpan.HOUR);
|
||||
int minutes = (int) (
|
||||
(value.get_utc_offset() % TimeSpan.HOUR) / (double) TimeSpan.HOUR * 60
|
||||
);
|
||||
return GMime.utils_header_format_date(
|
||||
(time_t) this.value.to_utc().to_unix(),
|
||||
(hours * 100) + minutes
|
||||
);
|
||||
return GMime.utils_header_format_date(this.value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -261,7 +236,7 @@ public class Geary.RFC822.Subject : Geary.MessageData.StringMessageData,
|
|||
}
|
||||
|
||||
public Subject.decode(string value) {
|
||||
base (GMime.utils_header_decode_text(value));
|
||||
base (GMime.utils_header_decode_text(Geary.RFC822.get_parser_options(), value));
|
||||
original = value;
|
||||
}
|
||||
|
||||
|
|
@ -337,9 +312,8 @@ public class Geary.RFC822.Header : Geary.MessageData.BlockMessageData, Geary.RFC
|
|||
|
||||
GMime.Parser parser = new GMime.Parser.with_stream(Utils.create_stream_mem(buffer));
|
||||
parser.set_respect_content_length(false);
|
||||
parser.set_scan_from(false);
|
||||
|
||||
message = parser.construct_message();
|
||||
message = parser.construct_message(Geary.RFC822.get_parser_options());
|
||||
if (message == null)
|
||||
throw new RFC822Error.INVALID("Unable to parse RFC 822 headers");
|
||||
|
||||
|
|
@ -347,17 +321,22 @@ public class Geary.RFC822.Header : Geary.MessageData.BlockMessageData, Geary.RFC
|
|||
}
|
||||
|
||||
public string? get_header(string name) throws RFC822Error {
|
||||
return get_headers().get(name);
|
||||
GMime.Header header = get_headers().get_header(name);
|
||||
if (header != null)
|
||||
// We should not parse the raw-value here, but use GMime's parsing
|
||||
// functionality instead.
|
||||
// See: https://gitlab.gnome.org/GNOME/geary/merge_requests/382#note_669699
|
||||
return GMime.utils_header_unfold(header.get_raw_value());
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public string[] get_header_names() throws RFC822Error {
|
||||
if (this.names == null) {
|
||||
this.names = new string[0];
|
||||
GMime.HeaderIter iter = new GMime.HeaderIter();
|
||||
if (get_headers().get_iter(iter) && iter.first()) {
|
||||
do {
|
||||
names += iter.get_name();
|
||||
} while (iter.next());
|
||||
GMime.HeaderList headers = get_headers();
|
||||
for (int i = 0; i < headers.get_count(); i++) {
|
||||
names += headers.get_header_at(i).get_name();
|
||||
}
|
||||
}
|
||||
return this.names;
|
||||
|
|
@ -388,7 +367,7 @@ public class Geary.RFC822.PreviewText : Geary.RFC822.Text {
|
|||
// Parse the header.
|
||||
GMime.Stream header_stream = Utils.create_stream_mem(preview_header);
|
||||
GMime.Parser parser = new GMime.Parser.with_stream(header_stream);
|
||||
GMime.Part? gpart = parser.construct_part() as GMime.Part;
|
||||
GMime.Part? gpart = parser.construct_part(Geary.RFC822.get_parser_options()) as GMime.Part;
|
||||
if (gpart != null) {
|
||||
Part part = new Part(gpart);
|
||||
|
||||
|
|
@ -402,7 +381,7 @@ public class Geary.RFC822.PreviewText : Geary.RFC822.Text {
|
|||
new GMime.StreamMem.with_buffer(preview.get_uint8_array()),
|
||||
gpart.get_content_encoding()
|
||||
);
|
||||
gpart.set_content_object(body);
|
||||
gpart.set_content(body);
|
||||
|
||||
try {
|
||||
Memory.Buffer preview_buffer = part.write_to_buffer(
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
*/
|
||||
public delegate string? InlinePartReplacer(Part part);
|
||||
|
||||
private const string HEADER_SENDER = "Sender";
|
||||
private const string HEADER_IN_REPLY_TO = "In-Reply-To";
|
||||
private const string HEADER_REFERENCES = "References";
|
||||
private const string HEADER_MAILER = "X-Mailer";
|
||||
|
|
@ -89,7 +88,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
public Message(Full full) throws RFC822Error {
|
||||
GMime.Parser parser = new GMime.Parser.with_stream(Utils.create_stream_mem(full.buffer));
|
||||
|
||||
message = parser.construct_message();
|
||||
message = parser.construct_message(Geary.RFC822.get_parser_options());
|
||||
if (message == null)
|
||||
throw new RFC822Error.INVALID("Unable to parse RFC 822 message");
|
||||
|
||||
|
|
@ -115,7 +114,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
stream_cat.add_source(new GMime.StreamMem.with_buffer(body.buffer.get_bytes().get_data()));
|
||||
|
||||
GMime.Parser parser = new GMime.Parser.with_stream(stream_cat);
|
||||
message = parser.construct_message();
|
||||
message = parser.construct_message(Geary.RFC822.get_parser_options());
|
||||
if (message == null)
|
||||
throw new RFC822Error.INVALID("Unable to parse RFC 822 message");
|
||||
|
||||
|
|
@ -136,67 +135,71 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
this.from = email.from;
|
||||
this.date = email.date;
|
||||
|
||||
// GMimeMessage.set_sender actually sets the From header - and
|
||||
// although the API docs make it sound otherwise, it also
|
||||
// supports a list of addresses
|
||||
message.set_sender(this.from.to_rfc822_string());
|
||||
message.set_date_as_string(this.date.serialize());
|
||||
if (message_id != null) {
|
||||
this.message_id = new MessageID(message_id);
|
||||
message.set_message_id(message_id);
|
||||
this.message.set_date(this.date.value);
|
||||
|
||||
if (email.from != null) {
|
||||
foreach (RFC822.MailboxAddress mailbox in email.from)
|
||||
this.message.add_mailbox(FROM, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
// Optional headers
|
||||
if (email.to != null) {
|
||||
this.to = email.to;
|
||||
foreach (RFC822.MailboxAddress mailbox in email.to)
|
||||
this.message.add_recipient(GMime.RecipientType.TO, mailbox.name, mailbox.address);
|
||||
this.message.add_mailbox(TO, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
if (email.cc != null) {
|
||||
this.cc = email.cc;
|
||||
foreach (RFC822.MailboxAddress mailbox in email.cc)
|
||||
this.message.add_recipient(GMime.RecipientType.CC, mailbox.name, mailbox.address);
|
||||
this.message.add_mailbox(CC, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
if (email.bcc != null) {
|
||||
this.bcc = email.bcc;
|
||||
foreach (RFC822.MailboxAddress mailbox in email.bcc)
|
||||
this.message.add_recipient(GMime.RecipientType.BCC, mailbox.name, mailbox.address);
|
||||
this.message.add_mailbox(BCC, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
if (email.sender != null) {
|
||||
this.sender = email.sender;
|
||||
this.message.set_header(HEADER_SENDER,
|
||||
email.sender.to_rfc822_string());
|
||||
this.message.add_mailbox(SENDER, this.sender.name, this.sender.address);
|
||||
}
|
||||
|
||||
if (email.reply_to != null) {
|
||||
this.reply_to = email.reply_to;
|
||||
this.message.set_reply_to(email.reply_to.to_rfc822_string());
|
||||
foreach (RFC822.MailboxAddress mailbox in email.reply_to)
|
||||
this.message.add_mailbox(REPLY_TO, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
if (email.in_reply_to != null) {
|
||||
this.in_reply_to = email.in_reply_to;
|
||||
// We could use `this.message.add_mailbox()` in a similar way like
|
||||
// we did for the other headers, but this would require to change
|
||||
// the type of `email.in_reply_to` and `this.in_reply_to` from
|
||||
// `RFC822.MessageIDList` to `RFC822.MailboxAddresses`.
|
||||
this.message.set_header(HEADER_IN_REPLY_TO,
|
||||
email.in_reply_to.to_rfc822_string());
|
||||
email.in_reply_to.to_rfc822_string(),
|
||||
Geary.RFC822.get_charset());
|
||||
}
|
||||
|
||||
if (email.references != null) {
|
||||
this.references = email.references;
|
||||
this.message.set_header(HEADER_REFERENCES,
|
||||
email.references.to_rfc822_string());
|
||||
email.references.to_rfc822_string(),
|
||||
Geary.RFC822.get_charset());
|
||||
}
|
||||
|
||||
if (email.subject != null) {
|
||||
this.subject = email.subject;
|
||||
this.message.set_subject(email.subject.value);
|
||||
this.message.set_subject(email.subject.value,
|
||||
Geary.RFC822.get_charset());
|
||||
}
|
||||
|
||||
// User-Agent
|
||||
if (!Geary.String.is_empty(email.mailer)) {
|
||||
this.mailer = email.mailer;
|
||||
this.message.set_header(HEADER_MAILER, email.mailer);
|
||||
this.message.set_header(HEADER_MAILER, email.mailer,
|
||||
Geary.RFC822.get_charset());
|
||||
}
|
||||
|
||||
// Build the message's body mime parts
|
||||
|
|
@ -406,7 +409,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
string type) {
|
||||
GMime.Object? part = coalesce_parts(parts, "related");
|
||||
if (parts.size > 1) {
|
||||
part.set_header("Type", type);
|
||||
part.set_header("Type", type, Geary.RFC822.get_charset());
|
||||
}
|
||||
return part;
|
||||
}
|
||||
|
|
@ -433,11 +436,12 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
FileQueryInfoFlags.NONE
|
||||
);
|
||||
|
||||
GMime.Part part = new GMime.Part();
|
||||
GMime.Part part = new GMime.Part.with_type("text", "plain");
|
||||
part.set_disposition(disposition.serialize());
|
||||
part.set_filename(file.get_basename());
|
||||
|
||||
GMime.ContentType content_type = new GMime.ContentType.from_string(
|
||||
GMime.ContentType content_type = GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
file_info.get_content_type()
|
||||
);
|
||||
part.set_content_type(content_type);
|
||||
|
|
@ -468,7 +472,10 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
);
|
||||
}
|
||||
|
||||
GMime.ContentType? content_type = new GMime.ContentType.from_string(mime_type.get_mime_type());
|
||||
GMime.ContentType? content_type = GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
mime_type.get_mime_type()
|
||||
);
|
||||
|
||||
if (content_type == null) {
|
||||
throw new RFC822Error.INVALID(
|
||||
|
|
@ -476,7 +483,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
);
|
||||
}
|
||||
|
||||
GMime.Part part = new GMime.Part();
|
||||
GMime.Part part = new GMime.Part.with_type("text", "plain");
|
||||
part.set_disposition(disposition.serialize());
|
||||
part.set_filename(basename);
|
||||
part.set_content_type(content_type);
|
||||
|
|
@ -515,7 +522,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
}
|
||||
|
||||
part.set_content_encoding(encoding);
|
||||
part.set_content_object(
|
||||
part.set_content(
|
||||
new GMime.DataWrapper.with_stream(
|
||||
stream, GMime.ContentEncoding.BINARY
|
||||
)
|
||||
|
|
@ -536,7 +543,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
Geary.Email email = new Geary.Email(id);
|
||||
|
||||
email.set_message_header(new Geary.RFC822.Header(new Geary.Memory.StringBuffer(
|
||||
message.get_headers())));
|
||||
message.get_headers(Geary.RFC822.get_format_options()))));
|
||||
email.set_send_date(date);
|
||||
email.set_originators(from, sender, reply_to);
|
||||
email.set_receivers(to, cc, bcc);
|
||||
|
|
@ -884,68 +891,76 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
}
|
||||
|
||||
private void stock_from_gmime() {
|
||||
this.message.get_header_list().foreach((name, value) => {
|
||||
switch (name.down()) {
|
||||
case "from":
|
||||
this.from = append_address(this.from, value);
|
||||
break;
|
||||
GMime.HeaderList headers = this.message.get_header_list();
|
||||
for (int i = 0; i < headers.get_count(); i++) {
|
||||
GMime.Header header = headers.get_header_at(i);
|
||||
string name = header.get_name();
|
||||
// We should not parse the raw-value here, but use GMime's parsing
|
||||
// functionality instead.
|
||||
// See: https://gitlab.gnome.org/GNOME/geary/merge_requests/382#note_669699
|
||||
string value = GMime.utils_header_unfold(header.get_raw_value());
|
||||
switch (name.down()) {
|
||||
case "from":
|
||||
this.from = append_address(this.from, value);
|
||||
break;
|
||||
|
||||
case "sender":
|
||||
try {
|
||||
this.sender = new RFC822.MailboxAddress.from_rfc822_string(value);
|
||||
} catch (Error err) {
|
||||
debug("Could parse subject: %s", err.message);
|
||||
}
|
||||
break;
|
||||
case "sender":
|
||||
try {
|
||||
this.sender = new RFC822.MailboxAddress.from_rfc822_string(value);
|
||||
} catch (Error err) {
|
||||
debug("Could parse subject: %s", err.message);
|
||||
}
|
||||
break;
|
||||
|
||||
case "reply-to":
|
||||
this.reply_to = append_address(this.reply_to, value);
|
||||
break;
|
||||
case "reply-to":
|
||||
this.reply_to = append_address(this.reply_to, value);
|
||||
break;
|
||||
|
||||
case "to":
|
||||
this.to = append_address(this.to, value);
|
||||
break;
|
||||
case "to":
|
||||
this.to = append_address(this.to, value);
|
||||
break;
|
||||
|
||||
case "cc":
|
||||
this.cc = append_address(this.cc, value);
|
||||
break;
|
||||
case "cc":
|
||||
this.cc = append_address(this.cc, value);
|
||||
break;
|
||||
|
||||
case "bcc":
|
||||
this.bcc = append_address(this.bcc, value);
|
||||
break;
|
||||
case "bcc":
|
||||
this.bcc = append_address(this.bcc, value);
|
||||
break;
|
||||
|
||||
case "subject":
|
||||
this.subject = new RFC822.Subject.decode(value);
|
||||
break;
|
||||
case "subject":
|
||||
this.subject = new RFC822.Subject.decode(value);
|
||||
break;
|
||||
|
||||
case "date":
|
||||
try {
|
||||
this.date = new Geary.RFC822.Date(value);
|
||||
} catch (Error err) {
|
||||
debug("Could not parse date: %s", err.message);
|
||||
}
|
||||
break;
|
||||
case "date":
|
||||
try {
|
||||
this.date = new Geary.RFC822.Date(value);
|
||||
} catch (Error err) {
|
||||
debug("Could not parse date: %s", err.message);
|
||||
}
|
||||
break;
|
||||
|
||||
case "message-id":
|
||||
this.message_id = new MessageID(value);
|
||||
break;
|
||||
case "message-id":
|
||||
this.message_id = new MessageID(value);
|
||||
break;
|
||||
|
||||
case "in-reply-to":
|
||||
this.in_reply_to = append_message_id(this.in_reply_to, value);
|
||||
break;
|
||||
case "in-reply-to":
|
||||
this.in_reply_to = append_message_id(this.in_reply_to, value);
|
||||
break;
|
||||
|
||||
case "references":
|
||||
this.references = append_message_id(this.references, value);
|
||||
break;
|
||||
case "references":
|
||||
this.references = append_message_id(this.references, value);
|
||||
break;
|
||||
|
||||
case "x-mailer":
|
||||
this.mailer = GMime.utils_header_decode_text(value);
|
||||
break;
|
||||
case "x-mailer":
|
||||
this.mailer = GMime.utils_header_decode_text(Geary.RFC822.get_parser_options(), value);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private MailboxAddresses append_address(MailboxAddresses? existing,
|
||||
|
|
@ -990,11 +1005,11 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
|
||||
if (requested_disposition == Mime.DispositionType.UNSPECIFIED || disposition == requested_disposition) {
|
||||
GMime.Stream stream = new GMime.StreamMem();
|
||||
message.write_to_stream(stream);
|
||||
message.write_to_stream(Geary.RFC822.get_format_options(), stream);
|
||||
GMime.DataWrapper data = new GMime.DataWrapper.with_stream(stream,
|
||||
GMime.ContentEncoding.BINARY); // Equivalent to no encoding
|
||||
GMime.Part part = new GMime.Part.with_type("message", "rfc822");
|
||||
part.set_content_object(data);
|
||||
part.set_content(data);
|
||||
part.set_filename((message.get_subject() ?? _("(no subject)")) + ".eml");
|
||||
attachments.add(new Part(part));
|
||||
}
|
||||
|
|
@ -1017,7 +1032,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
#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);
|
||||
((GMime.Part) root).get_content().write_to_stream(stream);
|
||||
ByteArray tnef_data = stream.get_byte_array();
|
||||
Ytnef.TNEFStruct tn;
|
||||
if (Ytnef.ParseMemory(tnef_data.data, out tn) == 0) {
|
||||
|
|
@ -1050,10 +1065,10 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
string filename = (string) filenameProp.data;
|
||||
uint8[] data = Bytes.unref_to_data(new Bytes(a.FileData.data));
|
||||
|
||||
GMime.Part part = new GMime.Part();
|
||||
GMime.Part part = new GMime.Part.with_type("text", "plain");
|
||||
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));
|
||||
part.set_content_type(GMime.ContentType.parse(Geary.RFC822.get_parser_options(), GLib.ContentType.guess(filename, data, null)));
|
||||
part.set_content(new GMime.DataWrapper.with_stream(new GMime.StreamMem.with_buffer(data), GMime.ContentEncoding.BINARY));
|
||||
return part;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1092,19 +1107,29 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
stream.set_owner(false);
|
||||
|
||||
GMime.StreamFilter stream_filter = new GMime.StreamFilter(stream);
|
||||
stream_filter.add(new GMime.FilterCRLF(encoded, dotstuffed));
|
||||
if (encoded) {
|
||||
stream_filter.add(new GMime.FilterUnix2Dos(false));
|
||||
} else {
|
||||
stream_filter.add(new GMime.FilterDos2Unix(false));
|
||||
}
|
||||
if (dotstuffed) {
|
||||
stream_filter.add(new GMime.FilterSmtpData());
|
||||
}
|
||||
|
||||
if (message.write_to_stream(stream_filter) < 0)
|
||||
throw new RFC822Error.FAILED("Unable to write RFC822 message to memory buffer");
|
||||
if (message.write_to_stream(Geary.RFC822.get_format_options(), stream_filter) < 0)
|
||||
throw new RFC822Error.FAILED("Unable to write RFC822 message to filter stream");
|
||||
|
||||
if (stream_filter.flush() != 0)
|
||||
throw new RFC822Error.FAILED("Unable to flush RFC822 message to memory stream");
|
||||
|
||||
if (stream.flush() != 0)
|
||||
throw new RFC822Error.FAILED("Unable to flush RFC822 message to memory buffer");
|
||||
|
||||
return new Memory.ByteBuffer.from_byte_array(byte_array);
|
||||
}
|
||||
|
||||
public string to_string() {
|
||||
return message.to_string();
|
||||
return message.to_string(Geary.RFC822.get_format_options());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1152,11 +1177,13 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
// Base64-encoded text needs to have CR's added after LF's
|
||||
// before encoding, otherwise it breaks format=flowed. See
|
||||
// Bug 753528.
|
||||
filter_stream.add(new GMime.FilterCRLF(true, false));
|
||||
filter_stream.add(new GMime.FilterUnix2Dos(false));
|
||||
}
|
||||
|
||||
GMime.ContentType complete_type =
|
||||
new GMime.ContentType.from_string(content_type);
|
||||
GMime.ContentType complete_type = GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
content_type
|
||||
);
|
||||
complete_type.set_parameter("charset", charset);
|
||||
if (is_flowed) {
|
||||
complete_type.set_parameter("format", "flowed");
|
||||
|
|
@ -1166,9 +1193,9 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
filter_stream, GMime.ContentEncoding.DEFAULT
|
||||
);
|
||||
|
||||
GMime.Part body_part = new GMime.Part();
|
||||
GMime.Part body_part = new GMime.Part.with_type("text", "plain");
|
||||
body_part.set_content_type(complete_type);
|
||||
body_part.set_content_object(body);
|
||||
body_part.set_content(body);
|
||||
body_part.set_content_encoding(encoding);
|
||||
return body_part;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ public class Geary.RFC822.Part : Object {
|
|||
BodyFormatting format = BodyFormatting.NONE)
|
||||
throws RFC822Error {
|
||||
GMime.DataWrapper? wrapper = (this.source_part != null)
|
||||
? this.source_part.get_content_object() : null;
|
||||
? this.source_part.get_content() : null;
|
||||
if (wrapper == null) {
|
||||
throw new RFC822Error.INVALID(
|
||||
"Could not get the content wrapper for content-type %s",
|
||||
|
|
@ -201,7 +201,7 @@ public class Geary.RFC822.Part : Object {
|
|||
if ((this.source_part == null ||
|
||||
this.source_part.encoding != BASE64) &&
|
||||
!(content_type.media_subtype in CR_PRESERVING_TEXT_TYPES)) {
|
||||
filter.add(new GMime.FilterCRLF(false, false));
|
||||
filter.add(new GMime.FilterDos2Unix(false));
|
||||
}
|
||||
|
||||
if (flowed) {
|
||||
|
|
@ -226,12 +226,18 @@ public class Geary.RFC822.Part : Object {
|
|||
filter.add(new Geary.RFC822.FilterBlockquotes());
|
||||
}
|
||||
|
||||
wrapper.write_to_stream(filter);
|
||||
filter.flush();
|
||||
if (wrapper.write_to_stream(filter) < 0)
|
||||
throw new RFC822Error.FAILED("Unable to write textual RFC822 part to filter stream");
|
||||
if (filter.flush() != 0)
|
||||
throw new RFC822Error.FAILED("Unable to flush textual RFC822 part to destination stream");
|
||||
if (destination.flush() != 0)
|
||||
throw new RFC822Error.FAILED("Unable to flush textual RFC822 part to destination");
|
||||
} else {
|
||||
// Keep as binary
|
||||
wrapper.write_to_stream(destination);
|
||||
destination.flush();
|
||||
if (wrapper.write_to_stream(destination) < 0)
|
||||
throw new RFC822Error.FAILED("Unable to write binary RFC822 part to destination stream");
|
||||
if (destination.flush() != 0)
|
||||
throw new RFC822Error.FAILED("Unable to flush binary RFC822 part to destination");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ public string email_addresses_for_reply(Geary.RFC822.MailboxAddresses? addresses
|
|||
}
|
||||
|
||||
|
||||
public bool comp_char_arr_slice(char[] array, uint start, string comp) {
|
||||
public bool comp_char_arr_slice(uint8[] array, uint start, string comp) {
|
||||
for (int i = 0; i < comp.length; i++) {
|
||||
if (array[start + i] != comp[i])
|
||||
return false;
|
||||
|
|
@ -277,7 +277,7 @@ public async string get_best_charset(GMime.Stream in_stream,
|
|||
},
|
||||
cancellable
|
||||
);
|
||||
return filter.charset();
|
||||
return filter.get_charset();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -19,11 +19,6 @@ public enum TextFormat {
|
|||
*/
|
||||
public const string UTF8_CHARSET = "UTF-8";
|
||||
|
||||
/**
|
||||
* Official IANA charset encoding name for the ASCII character set.
|
||||
*/
|
||||
public const string ASCII_CHARSET = "US-ASCII";
|
||||
|
||||
private int init_count = 0;
|
||||
|
||||
internal Regex? invalid_filename_character_re = null;
|
||||
|
|
@ -32,18 +27,8 @@ public void init() {
|
|||
if (init_count++ != 0)
|
||||
return;
|
||||
|
||||
GMime.init(GMime.ENABLE_RFC2047_WORKAROUNDS);
|
||||
|
||||
// This has the effect of ensuring all non US-ASCII and non-ISO-8859-1
|
||||
// headers are always encoded as UTF-8. This should be fine because
|
||||
// message bodies are also always sent as UTF-8.
|
||||
const string?[] USER_CHARSETS = {
|
||||
UTF8_CHARSET,
|
||||
// GMime.set_user_charsets calls g_strdupv under the hood, so
|
||||
// the array needs to be null-terminated
|
||||
null
|
||||
};
|
||||
GMime.set_user_charsets(USER_CHARSETS);
|
||||
GMime.init();
|
||||
GMime.ParserOptions.get_default().set_allow_addresses_without_domain(true);
|
||||
|
||||
try {
|
||||
invalid_filename_character_re = new Regex("[/\\0]");
|
||||
|
|
@ -52,6 +37,17 @@ public void init() {
|
|||
}
|
||||
}
|
||||
|
||||
public GMime.FormatOptions get_format_options() {
|
||||
return GMime.FormatOptions.get_default().clone();
|
||||
}
|
||||
|
||||
public GMime.ParserOptions get_parser_options() {
|
||||
return GMime.ParserOptions.get_default().clone();
|
||||
}
|
||||
|
||||
public string? get_charset() {
|
||||
return UTF8_CHARSET;
|
||||
}
|
||||
|
||||
internal bool is_utf_8(string charset) {
|
||||
string up = charset.up();
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ if enable_valadoc
|
|||
'--pkg', 'gio-2.0',
|
||||
'--pkg', 'gee-0.8',
|
||||
'--pkg', 'sqlite3',
|
||||
'--pkg', 'gmime-2.6',
|
||||
'--pkg', 'gmime-3.0',
|
||||
'--pkg', 'javascriptcoregtk-4.0',
|
||||
'--pkg', 'libxml-2.0',
|
||||
'--pkg', 'libunwind',
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class Geary.ImapDB.AttachmentTest : TestCase {
|
|||
|
||||
public void new_from_minimal_mime_part() throws Error {
|
||||
GMime.Part part = new_part(null, ATTACHMENT_BODY.data);
|
||||
part.set_header("Content-Type", "");
|
||||
part.set_header("Content-Type", "", Geary.RFC822.get_charset());
|
||||
|
||||
Attachment test = new Attachment.from_part(
|
||||
1, new Geary.RFC822.Part(part)
|
||||
|
|
@ -51,7 +51,8 @@ class Geary.ImapDB.AttachmentTest : TestCase {
|
|||
part.set_content_id(ID);
|
||||
part.set_content_description(DESC);
|
||||
part.set_content_disposition(
|
||||
new GMime.ContentDisposition.from_string(
|
||||
GMime.ContentDisposition.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
"attachment; filename=%s".printf(NAME)
|
||||
)
|
||||
);
|
||||
|
|
@ -74,7 +75,10 @@ class Geary.ImapDB.AttachmentTest : TestCase {
|
|||
public void new_from_inline_mime_part() throws Error {
|
||||
GMime.Part part = new_part(null, ATTACHMENT_BODY.data);
|
||||
part.set_content_disposition(
|
||||
new GMime.ContentDisposition.from_string("inline")
|
||||
GMime.ContentDisposition.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
"inline"
|
||||
)
|
||||
);
|
||||
|
||||
Attachment test = new Attachment.from_part(
|
||||
|
|
@ -205,7 +209,8 @@ CREATE TABLE MessageAttachmentTable (
|
|||
part.set_content_id(ID);
|
||||
part.set_content_description(DESCRIPTION);
|
||||
part.set_content_disposition(
|
||||
new GMime.ContentDisposition.from_string(
|
||||
GMime.ContentDisposition.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
"inline; filename=%s;".printf(FILENAME)
|
||||
));
|
||||
|
||||
|
|
@ -350,14 +355,17 @@ VALUES (2, 'text/plain');
|
|||
private GMime.Part new_part(string? mime_type,
|
||||
uint8[] body,
|
||||
GMime.ContentEncoding encoding = GMime.ContentEncoding.DEFAULT) {
|
||||
GMime.Part part = new GMime.Part();
|
||||
GMime.Part part = new GMime.Part.with_type("text", "plain");
|
||||
if (mime_type != null) {
|
||||
part.set_content_type(new GMime.ContentType.from_string(mime_type));
|
||||
part.set_content_type(GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
mime_type
|
||||
));
|
||||
}
|
||||
GMime.DataWrapper body_wrapper = new GMime.DataWrapper.with_stream(
|
||||
new GMime.StreamMem.with_buffer(body),
|
||||
encoding
|
||||
);
|
||||
part.set_content_object(body_wrapper);
|
||||
part.set_content(body_wrapper);
|
||||
return part;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
|
|||
add_test("is_valid_address", is_valid_address);
|
||||
add_test("unescaped_constructor", unescaped_constructor);
|
||||
add_test("from_rfc822_string_encoded", from_rfc822_string_encoded);
|
||||
add_test("prepare_header_text_part", prepare_header_text_part);
|
||||
// latter depends on the former, so test that first
|
||||
add_test("has_distinct_name", has_distinct_name);
|
||||
add_test("is_spoofed", is_spoofed);
|
||||
|
|
@ -140,18 +141,36 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
|
|||
|
||||
// Courtesy Mailsploit https://www.mailsploit.com
|
||||
addr = new MailboxAddress.from_rfc822_string("\"=?utf-8?b?dGVzdCIgPHBvdHVzQHdoaXRlaG91c2UuZ292Pg==?==?utf-8?Q?=00=0A?=\" <demo@mailsploit.com>");
|
||||
assert(addr.name == "test <potus@whitehouse.gov>?\n");
|
||||
assert(addr.name == "test <potus@whitehouse.gov>?");
|
||||
assert(addr.address == "demo@mailsploit.com");
|
||||
|
||||
// Courtesy Mailsploit https://www.mailsploit.com
|
||||
addr = new MailboxAddress.from_rfc822_string("\"=?utf-8?Q?=42=45=47=49=4E=20=2F=20=28=7C=29=7C=3C=7C=3E=7C=40=7C=2C=7C=3B=7C=3A=7C=5C=7C=22=7C=2F=7C=5B=7C=5D=7C=3F=7C=2E=7C=3D=20=2F=20=00=20=50=41=53=53=45=44=20=4E=55=4C=4C=20=42=59=54=45=20=2F=20=0D=0A=20=50=41=53=53=45=44=20=43=52=4C=46=20=2F=20?==?utf-8?b?RU5E=?=\"");
|
||||
assert(addr.name == null);
|
||||
assert(addr.address == "BEGIN / (|)|<|>|@|,|;|:|\\|\"|/|[|]|?|.|= / ? PASSED NULL BYTE / \r\n PASSED CRLF / END");
|
||||
} catch (Error err) {
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("=?UTF-8?Q?=22Firstname_=22=C2=AF\\=5F=28=E3=83=84=29=5F/=C2=AF=22_Lastname_via?==?UTF-8?Q?_Vendor=22_<system@vendor.com>?=");
|
||||
public void prepare_header_text_part() throws Error {
|
||||
try {
|
||||
// Test if prepare_header_text_part() can handle crappy input without grilling the CPU
|
||||
MailboxAddress addr = new MailboxAddress.imap(
|
||||
"=?UTF-8?Q?=22Firstname_=22=C2=AF\\=5F=28=E3=83=84=29=5F/=C2=AF=22_Lastname_via?==?UTF-8?Q?_Vendor=22_<system@vendor.com>?=",
|
||||
null,
|
||||
"=?UTF-8?Q?=22Firstname_=22=C2=AF\\=5F=28=E3=83=84=29=5F/=C2=AF=22_Lastname_via?==?UTF-8?Q?_Vendor=22_<system@vendor.com>?=",
|
||||
"vendor.com");
|
||||
assert(addr.name == "\"Firstname \"¯_(ツ)_/¯\" Lastname via Vendor\" <system@vendor.com>");
|
||||
assert(addr.mailbox == "\"Firstname \"¯_(ツ)_/¯\" Lastname via Vendor\" <system@vendor.com>");
|
||||
|
||||
// A second test with the input that have been passed to prepare_header_text_part() by the pre-GMime3 tests
|
||||
addr = new MailboxAddress.imap(
|
||||
"\"Firstname \"¯_(ツ)_/¯\" Lastname via=?UTF-8?Q?_Vendor=22_",
|
||||
null,
|
||||
"system",
|
||||
"vendor.com");
|
||||
assert(addr.name == "Firstname ¯_(ツ)_/¯ Lastname via=?UTF-8?Q?_Vendor=22_");
|
||||
assert(addr.mailbox == "system");
|
||||
assert(addr.domain == "vendor.com");
|
||||
} catch (Error err) {
|
||||
assert_not_reached();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,10 @@ class Geary.RFC822.PartTest : TestCase {
|
|||
part.set_content_id(ID);
|
||||
part.set_content_description(DESC);
|
||||
part.set_content_disposition(
|
||||
new GMime.ContentDisposition.from_string("inline")
|
||||
GMime.ContentDisposition.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
"inline"
|
||||
)
|
||||
);
|
||||
|
||||
Part test = new Part(part);
|
||||
|
|
@ -91,15 +94,18 @@ class Geary.RFC822.PartTest : TestCase {
|
|||
|
||||
private GMime.Part new_part(string? mime_type,
|
||||
uint8[] body) {
|
||||
GMime.Part part = new GMime.Part();
|
||||
GMime.Part part = new GMime.Part.with_type("text", "plain");
|
||||
if (mime_type != null) {
|
||||
part.set_content_type(new GMime.ContentType.from_string(mime_type));
|
||||
part.set_content_type(GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
mime_type
|
||||
));
|
||||
}
|
||||
GMime.DataWrapper body_wrapper = new GMime.DataWrapper.with_stream(
|
||||
new GMime.StreamMem.with_buffer(body),
|
||||
GMime.ContentEncoding.BINARY
|
||||
);
|
||||
part.set_content_object(body_wrapper);
|
||||
part.set_content(body_wrapper);
|
||||
part.encode(GMime.EncodingConstraint.7BIT);
|
||||
return part;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue