refactor(mimeparser): split and cleanup parse_mime_recursive

This commit is contained in:
dignifiedquire
2019-09-20 20:29:53 +02:00
committed by holger krekel
parent e583c99f94
commit 0bdcc4269f
2 changed files with 173 additions and 196 deletions

View File

@@ -366,27 +366,17 @@ impl<'a> MimeParser<'a> {
if mime.is_null() {
return false;
}
let mut any_part_added = false;
if !mailmime_find_ct_parameter(
mime,
b"protected-headers\x00" as *const u8 as *const libc::c_char,
)
.is_null()
{
if (*mime).mm_type == MAILMIME_SINGLE as libc::c_int
&& (*(*(*mime).mm_content_type).ct_type).tp_type
if !mailmime_find_ct_parameter(mime, "protected-headers").is_null() {
let mime = *mime;
if mime.mm_type == MAILMIME_SINGLE as libc::c_int
&& (*(*mime.mm_content_type).ct_type).tp_type
== MAILMIME_TYPE_DISCRETE_TYPE as libc::c_int
&& (*(*(*(*mime).mm_content_type).ct_type)
.tp_data
.tp_discrete_type)
.dt_type
&& (*(*(*mime.mm_content_type).ct_type).tp_data.tp_discrete_type).dt_type
== MAILMIME_DISCRETE_TYPE_TEXT as libc::c_int
&& !(*(*mime).mm_content_type).ct_subtype.is_null()
&& strcmp(
(*(*mime).mm_content_type).ct_subtype,
b"rfc822-headers\x00" as *const u8 as *const libc::c_char,
) == 0i32
&& !(*mime.mm_content_type).ct_subtype.is_null()
&& &to_string_lossy((*mime.mm_content_type).ct_subtype) == "rfc822-headers"
{
info!(
self.context,
@@ -394,13 +384,14 @@ impl<'a> MimeParser<'a> {
);
return false;
}
if self.header_protected.is_null() {
/* use the most outer protected header - this is typically
created in sync with the normal, unprotected header */
let mut dummy = 0;
if mailimf_envelope_and_optional_fields_parse(
(*mime).mm_mime_start,
(*mime).mm_length,
mime.mm_mime_start,
mime.mm_length,
&mut dummy,
&mut self.header_protected,
) != MAILIMF_NO_ERROR as libc::c_int
@@ -417,9 +408,27 @@ impl<'a> MimeParser<'a> {
);
}
}
match (*mime).mm_type as u32 {
MAILMIME_SINGLE => any_part_added = self.add_single_part_if_known(mime),
MAILMIME_MULTIPLE => {
MAILMIME_SINGLE => self.add_single_part_if_known(mime),
MAILMIME_MULTIPLE => self.handle_multiple(mime),
MAILMIME_MESSAGE => {
if self.header_root.is_null() {
self.header_root = (*mime).mm_data.mm_message.mm_fields;
hash_header(&mut self.header, self.header_root);
}
if (*mime).mm_data.mm_message.mm_msg_mime.is_null() {
return false;
}
self.parse_mime_recursive((*mime).mm_data.mm_message.mm_msg_mime)
}
_ => false,
}
}
unsafe fn handle_multiple(&mut self, mime: *mut mailmime) -> bool {
let mut any_part_added = false;
match mailmime_get_mime_type(mime, ptr::null_mut(), ptr::null_mut()) {
/* Most times, mutlipart/alternative contains true alternatives
as text/plain and text/html. If we find a multipart/mixed
@@ -427,11 +436,8 @@ impl<'a> MimeParser<'a> {
apple mail: "plaintext" as an alternative to "html+PDF attachment") */
DC_MIMETYPE_MP_ALTERNATIVE => {
for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() {
if mailmime_get_mime_type(
cur_data as *mut _,
ptr::null_mut(),
ptr::null_mut(),
) == DC_MIMETYPE_MP_MIXED
if mailmime_get_mime_type(cur_data as *mut _, ptr::null_mut(), ptr::null_mut())
== DC_MIMETYPE_MP_MIXED
{
any_part_added = self.parse_mime_recursive(cur_data as *mut _);
break;
@@ -468,8 +474,7 @@ impl<'a> MimeParser<'a> {
however, most times it seems okay. */
let cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
if !cur.is_null() {
any_part_added =
self.parse_mime_recursive((*cur).data as *mut mailmime);
any_part_added = self.parse_mime_recursive((*cur).data as *mut mailmime);
}
}
DC_MIMETYPE_MP_NOT_DECRYPTABLE => {
@@ -496,37 +501,26 @@ impl<'a> MimeParser<'a> {
for background information why we use encrypted+signed) */
let cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
if !cur.is_null() {
any_part_added =
self.parse_mime_recursive((*cur).data as *mut mailmime);
any_part_added = self.parse_mime_recursive((*cur).data as *mut _);
}
}
DC_MIMETYPE_MP_REPORT => {
/* RFC 6522: the first part is for humans, the second for machines */
if (*(*mime).mm_data.mm_multipart.mm_mp_list).count >= 2i32 {
let report_type = mailmime_find_ct_parameter(
mime,
b"report-type\x00" as *const u8 as *const libc::c_char,
);
if (*(*mime).mm_data.mm_multipart.mm_mp_list).count >= 2 {
let report_type = mailmime_find_ct_parameter(mime, "report-type");
if !report_type.is_null()
&& !(*report_type).pa_value.is_null()
&& strcmp(
(*report_type).pa_value,
b"disposition-notification\x00" as *const u8
as *const libc::c_char,
) == 0i32
&& &to_string_lossy((*report_type).pa_value) == "disposition-notification"
{
self.reports.push(mime);
} else {
/* eg. `report-type=delivery-status`;
maybe we should show them as a little error icon */
if !(*(*mime).mm_data.mm_multipart.mm_mp_list).first.is_null() {
any_part_added = self.parse_mime_recursive(
(if !(*(*mime).mm_data.mm_multipart.mm_mp_list).first.is_null()
{
(*(*(*mime).mm_data.mm_multipart.mm_mp_list).first).data
} else {
ptr::null_mut()
}) as *mut mailmime,
)
(*(*(*mime).mm_data.mm_multipart.mm_mp_list).first).data as *mut _,
);
}
}
}
}
@@ -541,8 +535,9 @@ impl<'a> MimeParser<'a> {
plain+html in multipart/mixed - if so, we should disable the hack. */
let mut skip_part = ptr::null_mut();
let mut html_part = ptr::null_mut();
let mut plain_cnt = 0i32;
let mut html_cnt = 0i32;
let mut plain_cnt = 0;
let mut html_cnt = 0;
for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() {
match mailmime_get_mime_type(
cur_data as *mut _,
@@ -564,8 +559,9 @@ impl<'a> MimeParser<'a> {
self.context,
"HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted."
);
skip_part = html_part
skip_part = html_part;
}
for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() {
if cur_data as *mut _ != skip_part {
if self.parse_mime_recursive(cur_data as *mut _) {
@@ -575,19 +571,7 @@ impl<'a> MimeParser<'a> {
}
}
}
}
MAILMIME_MESSAGE => {
if self.header_root.is_null() {
self.header_root = (*mime).mm_data.mm_message.mm_fields;
hash_header(&mut self.header, self.header_root);
}
if !(*mime).mm_data.mm_message.mm_msg_mime.is_null() {
any_part_added =
self.parse_mime_recursive((*mime).mm_data.mm_message.mm_msg_mime);
}
}
_ => {}
}
any_part_added
}
@@ -763,10 +747,7 @@ impl<'a> MimeParser<'a> {
dc_decode_ext_header(filename_parts.as_bytes()).strdup();
}
if desired_filename.is_null() {
let param = mailmime_find_ct_parameter(
mime,
b"name\x00" as *const u8 as *const libc::c_char,
);
let param = mailmime_find_ct_parameter(mime, "name");
if !param.is_null()
&& !(*param).pa_value.is_null()
&& 0 != *(*param).pa_value.offset(0isize) as libc::c_int
@@ -1274,10 +1255,9 @@ unsafe fn mailmime_is_attachment_disposition(mime: *mut mailmime) -> bool {
/* low-level-tools for working with mailmime structures directly */
pub unsafe fn mailmime_find_ct_parameter(
mime: *mut mailmime,
name: *const libc::c_char,
name: &str,
) -> *mut mailmime_parameter {
if mime.is_null()
|| name.is_null()
|| (*mime).mm_content_type.is_null()
|| (*(*mime).mm_content_type).ct_parameters.is_null()
{
@@ -1287,7 +1267,7 @@ pub unsafe fn mailmime_find_ct_parameter(
for cur in (*(*(*mime).mm_content_type).ct_parameters).into_iter() {
let param = cur as *mut mailmime_parameter;
if !param.is_null() && !(*param).pa_name.is_null() {
if strcmp((*param).pa_name, name) == 0i32 {
if &to_string_lossy((*param).pa_name) == name {
return param;
}
}

View File

@@ -749,10 +749,7 @@ unsafe fn handle_reports(
for report_root in &mime_parser.reports {
let report_root = *report_root;
let mut mdn_consumed = 0;
let report_type = mailmime_find_ct_parameter(
report_root,
b"report-type\x00" as *const u8 as *const libc::c_char,
);
let report_type = mailmime_find_ct_parameter(report_root, "report-type");
if report_root.is_null() || report_type.is_null() || (*report_type).pa_value.is_null() {
continue;