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

View File

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