diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index 05c1bec43..89522d047 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -44,7 +44,7 @@ pub struct dc_mimepart_t { #[derive(Clone)] #[allow(non_camel_case_types)] pub struct dc_mimeparser_t<'a> { - pub parts: *mut carray, + pub parts: Vec, pub mimeroot: *mut mailmime, pub header: HashMap, pub header_root: *mut mailimf_fields, @@ -71,7 +71,7 @@ static mut S_GENERATE_COMPOUND_MSGS: libc::c_int = 1i32; pub unsafe fn dc_mimeparser_new(context: &Context) -> dc_mimeparser_t { dc_mimeparser_t { - parts: carray_new(16i32 as libc::c_uint), + parts: Vec::new(), mimeroot: std::ptr::null_mut(), header: Default::default(), header_root: std::ptr::null_mut(), @@ -91,25 +91,13 @@ pub unsafe fn dc_mimeparser_new(context: &Context) -> dc_mimeparser_t { pub unsafe fn dc_mimeparser_unref(mimeparser: &mut dc_mimeparser_t) { dc_mimeparser_empty(mimeparser); - if !(*mimeparser).parts.is_null() { - carray_free((*mimeparser).parts); - } } pub unsafe fn dc_mimeparser_empty(mimeparser: &mut dc_mimeparser_t) { - if !(*mimeparser).parts.is_null() { - let mut i: libc::c_int; - let cnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; - i = 0i32; - while i < cnt { - let part = carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; - if !part.is_null() { - dc_mimepart_unref(*Box::from_raw(part)); - } - i += 1 - } - carray_set_size((*mimeparser).parts, 0i32 as libc::c_uint); + for part in mimeparser.parts.drain(..) { + dc_mimepart_unref(part); } + assert!(mimeparser.parts.is_empty()); (*mimeparser).header_root = 0 as *mut mailimf_fields; (*mimeparser).header.clear(); if !(*mimeparser).header_protected.is_null() { @@ -183,29 +171,34 @@ pub unsafe fn dc_mimeparser_parse( (*mimeparser).is_send_by_messenger = 1i32 } if !dc_mimeparser_lookup_field(mimeparser, "Autocrypt-Setup-Message").is_null() { - let mut i: libc::c_int; let mut has_setup_file: libc::c_int = 0i32; - i = 0i32; - while (i as libc::c_uint) < carray_count((*mimeparser).parts) { - let part: *mut dc_mimepart_t = - carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; - if (*part).int_mimetype == 111i32 { + for part in &mimeparser.parts { + if part.int_mimetype == 111i32 { has_setup_file = 1i32 } - i += 1 } if 0 != has_setup_file { - (*mimeparser).is_system_message = 6i32; - i = 0i32; - while (i as libc::c_uint) < carray_count((*mimeparser).parts) { - let part_0 = - carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; - if (*part_0).int_mimetype != 111i32 { - dc_mimepart_unref(*Box::from_raw(part_0)); - carray_delete_slow((*mimeparser).parts, i as libc::c_uint); - i -= 1 + mimeparser.is_system_message = 6i32; + + // TODO: replace the following code with this + // once drain_filter stabilizes. + // + // See https://doc.rust-lang.org/std/vec/struct.Vec.html#method.drain_filter + // and https://github.com/rust-lang/rust/issues/43244 + // + // mimeparser + // .parts + // .drain_filter(|part| part.int_mimetype != 111) + // .for_each(|part| dc_mimepart_unref(part)); + + let mut i = 0; + while i != mimeparser.parts.len() { + if mimeparser.parts[i].int_mimetype != 111 { + let part = mimeparser.parts.remove(i); + dc_mimepart_unref(part); + } else { + i += 1; } - i += 1 } } } else { @@ -224,40 +217,42 @@ pub unsafe fn dc_mimeparser_parse( } } if !dc_mimeparser_lookup_field(mimeparser, "Chat-Group-Image").is_null() - && carray_count((*mimeparser).parts) >= 1i32 as libc::c_uint + && !mimeparser.parts.is_empty() { - let textpart: *mut dc_mimepart_t = - carray_get((*mimeparser).parts, 0i32 as libc::c_uint) as *mut dc_mimepart_t; - if (*textpart).type_0 == 10i32 { - if carray_count((*mimeparser).parts) >= 2i32 as libc::c_uint { - let mut imgpart: *mut dc_mimepart_t = - carray_get((*mimeparser).parts, 1i32 as libc::c_uint) as *mut dc_mimepart_t; - if (*imgpart).type_0 == 20i32 { - (*imgpart).is_meta = 1i32 + let textpart = &mimeparser.parts[0]; + if textpart.type_0 == 10i32 { + if mimeparser.parts.len() >= 2 { + let imgpart = &mut mimeparser.parts[1]; + if imgpart.type_0 == 20i32 { + imgpart.is_meta = 1i32 } } } } if 0 != (*mimeparser).is_send_by_messenger && 0 != S_GENERATE_COMPOUND_MSGS - && carray_count((*mimeparser).parts) == 2i32 as libc::c_uint + && mimeparser.parts.len() == 2 { - let mut textpart_0 = carray_get((*mimeparser).parts, 0) as *mut dc_mimepart_t; - let mut filepart = carray_get((*mimeparser).parts, 1) as *mut dc_mimepart_t; - if (*textpart_0).type_0 == 10i32 - && ((*filepart).type_0 == 20i32 - || (*filepart).type_0 == 21i32 - || (*filepart).type_0 == 40i32 - || (*filepart).type_0 == 41i32 - || (*filepart).type_0 == 50i32 - || (*filepart).type_0 == 60i32) - && 0 == (*filepart).is_meta + let need_drop: bool; { - free((*filepart).msg as *mut libc::c_void); - (*filepart).msg = (*textpart_0).msg; - (*textpart_0).msg = 0 as *mut libc::c_char; - dc_mimepart_unref(*Box::from_raw(textpart_0)); - carray_delete_slow((*mimeparser).parts, 0i32 as libc::c_uint); + let textpart = &mimeparser.parts[0]; + let filepart = &mimeparser.parts[1]; + need_drop = textpart.type_0 == 10i32 + && (filepart.type_0 == 20i32 + || filepart.type_0 == 21i32 + || filepart.type_0 == 40i32 + || filepart.type_0 == 41i32 + || filepart.type_0 == 50i32 + || filepart.type_0 == 60i32) + && 0 == filepart.is_meta; + } + + if need_drop { + free(mimeparser.parts[1].msg as *mut libc::c_void); + let mut textpart = mimeparser.parts.swap_remove(0); + mimeparser.parts[1].msg = textpart.msg; + textpart.msg = 0 as *mut libc::c_char; + dc_mimepart_unref(textpart); } } if !(*mimeparser).subject.is_null() { @@ -284,24 +279,16 @@ pub unsafe fn dc_mimeparser_parse( } dc_trim(subj); if 0 != *subj.offset(0isize) { - let mut i_0: libc::c_int; - let icnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; - i_0 = 0i32; - while i_0 < icnt { - let mut part_1: *mut dc_mimepart_t = - carray_get((*mimeparser).parts, i_0 as libc::c_uint) - as *mut dc_mimepart_t; - if (*part_1).type_0 == 10i32 { + for part in mimeparser.parts.iter_mut() { + if part.type_0 == 10i32 { let new_txt: *mut libc::c_char = dc_mprintf( b"%s \xe2\x80\x93 %s\x00" as *const u8 as *const libc::c_char, subj, - (*part_1).msg, + part.msg, ); - free((*part_1).msg as *mut libc::c_void); - (*part_1).msg = new_txt; + free(part.msg as *mut libc::c_void); + part.msg = new_txt; break; - } else { - i_0 += 1 } } } @@ -309,30 +296,24 @@ pub unsafe fn dc_mimeparser_parse( } } if 0 != (*mimeparser).is_forwarded { - let mut i_1: libc::c_int; - let icnt_0: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; - i_1 = 0i32; - while i_1 < icnt_0 { - let part_2 = - carray_get((*mimeparser).parts, i_1 as libc::c_uint) as *mut dc_mimepart_t; - (*part_2).param.set_int(Param::Forwarded, 1); - i_1 += 1 + for part in mimeparser.parts.iter_mut() { + part.param.set_int(Param::Forwarded, 1); } } - if carray_count((*mimeparser).parts) == 1i32 as libc::c_uint { - let mut part_3: *mut dc_mimepart_t = - carray_get((*mimeparser).parts, 0i32 as libc::c_uint) as *mut dc_mimepart_t; - if (*part_3).type_0 == 40i32 { + if mimeparser.parts.len() == 1 { + if mimeparser.parts[0].type_0 == 40i32 { if !dc_mimeparser_lookup_optional_field( mimeparser, b"Chat-Voice-Message\x00" as *const u8 as *const libc::c_char, ) .is_null() { - (*part_3).type_0 = 41i32 + let part_mut = &mut mimeparser.parts[0]; + part_mut.type_0 = 41i32 } } - if (*part_3).type_0 == 40i32 || (*part_3).type_0 == 41i32 || (*part_3).type_0 == 50i32 { + let part = &mimeparser.parts[0]; + if part.type_0 == 40i32 || part.type_0 == 41i32 || part.type_0 == 50i32 { let field_0 = dc_mimeparser_lookup_optional_field( mimeparser, b"Chat-Duration\x00" as *const u8 as *const libc::c_char, @@ -340,7 +321,8 @@ pub unsafe fn dc_mimeparser_parse( if !field_0.is_null() { let duration_ms: libc::c_int = dc_atoi_null_is_0((*field_0).fld_value); if duration_ms > 0i32 && duration_ms < 24i32 * 60i32 * 60i32 * 1000i32 { - (*part_3).param.set_int(Param::Duration, duration_ms); + let part_mut = &mut mimeparser.parts[0]; + part_mut.param.set_int(Param::Duration, duration_ms); } } } @@ -350,7 +332,7 @@ pub unsafe fn dc_mimeparser_parse( mimeparser, b"Chat-Disposition-Notification-To\x00" as *const u8 as *const libc::c_char, ); - if !dn_field.is_null() && !dc_mimeparser_get_last_nonmeta(mimeparser).is_null() { + if !dn_field.is_null() && dc_mimeparser_get_last_nonmeta(mimeparser).is_some() { let mut mb_list: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list; let mut index_0: size_t = 0i32 as size_t; if mailimf_mailbox_list_parse( @@ -374,10 +356,9 @@ pub unsafe fn dc_mimeparser_parse( ); if !from_addr.is_null() { if strcmp(from_addr, dn_to_addr) == 0i32 { - let part_4: *mut dc_mimepart_t = - dc_mimeparser_get_last_nonmeta(mimeparser); - if !part_4.is_null() { - (*part_4).param.set_int(Param::WantsMdn, 1); + if let Some(part_4) = dc_mimeparser_get_last_nonmeta(mimeparser) + { + part_4.param.set_int(Param::WantsMdn, 1); } } free(from_addr as *mut libc::c_void); @@ -391,7 +372,7 @@ pub unsafe fn dc_mimeparser_parse( } } /* Cleanup - and try to create at least an empty part if there are no parts yet */ - if dc_mimeparser_get_last_nonmeta(mimeparser).is_null() && (*mimeparser).reports.is_empty() { + if dc_mimeparser_get_last_nonmeta(mimeparser).is_none() && (*mimeparser).reports.is_empty() { let mut part_5 = dc_mimepart_new(); part_5.type_0 = 10i32; if !(*mimeparser).subject.is_null() && 0 == (*mimeparser).is_send_by_messenger { @@ -399,11 +380,7 @@ pub unsafe fn dc_mimeparser_parse( } else { part_5.msg = dc_strdup(b"\x00" as *const u8 as *const libc::c_char) } - carray_add( - (*mimeparser).parts, - Box::into_raw(Box::new(part_5)) as *mut libc::c_void, - 0 as *mut libc::c_uint, - ); + mimeparser.parts.push(part_5); }; } @@ -422,22 +399,14 @@ unsafe fn dc_mimepart_new() -> dc_mimepart_t { } } -pub unsafe fn dc_mimeparser_get_last_nonmeta(mimeparser: &dc_mimeparser_t) -> *mut dc_mimepart_t { - if !(*mimeparser).parts.is_null() { - let mut i: libc::c_int; - let icnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; - i = icnt - 1i32; - while i >= 0i32 { - let part: *mut dc_mimepart_t = - carray_get(mimeparser.parts, i as libc::c_uint) as *mut dc_mimepart_t; - if !part.is_null() && 0 == (*part).is_meta { - return part; - } - i -= 1 - } - } - - 0 as *mut dc_mimepart_t +pub fn dc_mimeparser_get_last_nonmeta<'a>( + mimeparser: &'a mut dc_mimeparser_t, +) -> Option<&'a mut dc_mimepart_t> { + mimeparser + .parts + .iter_mut() + .rev() + .find(|part| part.is_meta == 0) } /*the result must be freed*/ @@ -664,11 +633,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( msg_body.as_ptr(), ); part.msg_raw = dc_strdup(part.msg); - carray_add( - (*mimeparser).parts, - Box::into_raw(Box::new(part)) as *mut libc::c_void, - 0 as *mut libc::c_uint, - ); + mimeparser.parts.push(part); any_part_added = 1i32; (*mimeparser).decrypting_failed = 1i32 } @@ -1125,7 +1090,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known( mime: *mut mailmime, ) -> libc::c_int { let mut current_block: u64; - let old_part_count: libc::c_int = carray_count(mimeparser.parts) as libc::c_int; + let old_part_count = mimeparser.parts.len(); let mime_type: libc::c_int; let mime_data: *mut mailmime_data; let file_suffix: *mut libc::c_char = 0 as *mut libc::c_char; @@ -1418,16 +1383,16 @@ unsafe fn dc_mimeparser_add_single_part_if_known( free(file_suffix as *mut libc::c_void); free(desired_filename as *mut libc::c_void); free(raw_mime as *mut libc::c_void); - return if carray_count((*mimeparser).parts) > old_part_count as libc::c_uint { - 1i32 + return if mimeparser.parts.len() > old_part_count { + 1 } else { - 0i32 + 0 }; } #[allow(non_snake_case)] unsafe fn do_add_single_file_part( - parser: &dc_mimeparser_t, + parser: &mut dc_mimeparser_t, msg_type: libc::c_int, mime_type: libc::c_int, raw_mime: *const libc::c_char, @@ -1476,17 +1441,13 @@ unsafe fn do_add_single_file_part( free(pathNfilename as *mut libc::c_void); } -unsafe fn do_add_single_part(parser: &dc_mimeparser_t, mut part: dc_mimepart_t) { +unsafe fn do_add_single_part(parser: &mut dc_mimeparser_t, mut part: dc_mimepart_t) { if 0 != (*parser).e2ee_helper.encrypted && (*parser).e2ee_helper.signatures.len() > 0 { part.param.set_int(Param::GuranteeE2ee, 1); } else if 0 != (*parser).e2ee_helper.encrypted { part.param.set_int(Param::ErroneousE2ee, 0x2); } - carray_add( - (*parser).parts, - Box::into_raw(Box::new(part)) as *mut libc::c_void, - 0 as *mut libc::c_uint, - ); + parser.parts.push(part); } // TODO should return bool /rtn @@ -1773,27 +1734,20 @@ pub unsafe fn mailimf_find_field( } pub unsafe fn dc_mimeparser_repl_msg_by_error( - mimeparser: &dc_mimeparser_t, + mimeparser: &mut dc_mimeparser_t, error_msg: *const libc::c_char, ) { - let mut part: *mut dc_mimepart_t; - let mut i: libc::c_int; - if (*mimeparser).parts.is_null() || carray_count((*mimeparser).parts) <= 0i32 as libc::c_uint { + if mimeparser.parts.is_empty() { return; } - part = carray_get((*mimeparser).parts, 0i32 as libc::c_uint) as *mut dc_mimepart_t; - (*part).type_0 = 10i32; - free((*part).msg as *mut libc::c_void); - (*part).msg = dc_mprintf(b"[%s]\x00" as *const u8 as *const libc::c_char, error_msg); - i = 1i32; - while (i as libc::c_uint) < carray_count((*mimeparser).parts) { - part = carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; - if !part.is_null() { - dc_mimepart_unref(*Box::from_raw(part)); - } - i += 1 + let part = &mut mimeparser.parts[0]; + part.type_0 = 10i32; + free(part.msg as *mut libc::c_void); + part.msg = dc_mprintf(b"[%s]\x00" as *const u8 as *const libc::c_char, error_msg); + for part in mimeparser.parts.drain(1..) { + dc_mimepart_unref(part); } - carray_set_size((*mimeparser).parts, 1i32 as libc::c_uint); + assert_eq!(mimeparser.parts.len(), 1); } /*the result is a pointer to mime, must not be freed*/ diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index cde7c3615..606ab43de 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -138,7 +138,7 @@ pub unsafe fn dc_receive_imf( ); } } - if !dc_mimeparser_get_last_nonmeta(&mime_parser).is_null() { + if dc_mimeparser_get_last_nonmeta(&mut mime_parser).is_some() { field = dc_mimeparser_lookup_field(&mime_parser, "Cc"); if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_CC as libc::c_int { let fld_cc: *mut mailimf_cc = (*field).fld_data.fld_cc; @@ -435,7 +435,7 @@ pub unsafe fn dc_receive_imf( ) } } - let icnt = carray_count(mime_parser.parts) as size_t; + let icnt = mime_parser.parts.len(); context.sql.prepare( "INSERT INTO msgs \ @@ -450,23 +450,23 @@ pub unsafe fn dc_receive_imf( current_block = 2756754640271984560; break; } - let part = carray_get(mime_parser.parts, i as libc::c_uint) as *mut dc_mimepart_t; - if !(0 != (*part).is_meta) { + let part = &mut mime_parser.parts[i]; + if part.is_meta == 0 { if !mime_parser.location_kml.is_none() && icnt == 1 - && !(*part).msg.is_null() + && !part.msg.is_null() && (strcmp( - (*part).msg, + part.msg, b"-location-\x00" as *const u8 as *const libc::c_char, ) == 0 - || *(*part).msg.offset(0isize) as libc::c_int == 0) + || *part.msg.offset(0isize) as libc::c_int == 0) { hidden = 1; if state == 10 { state = 13 } } - if (*part).type_0 == 10 { + if part.type_0 == 10 { txt_raw = dc_mprintf( b"%s\n\n%s\x00" as *const u8 as *const libc::c_char, if !mime_parser.subject.is_null() { @@ -474,12 +474,12 @@ pub unsafe fn dc_receive_imf( } else { b"\x00" as *const u8 as *const libc::c_char }, - (*part).msg_raw, + part.msg_raw, ) } if 0 != mime_parser.is_system_message { - (*part).param.set_int( Param::Cmd, + part.param.set_int( Param::Cmd, mime_parser.is_system_message, ); } @@ -494,11 +494,11 @@ pub unsafe fn dc_receive_imf( sort_timestamp, sent_timestamp, rcvd_timestamp, - (*part).type_0, + part.type_0, state, msgrmsg, - if !(*part).msg.is_null() { - as_str((*part).msg) + if !part.msg.is_null() { + as_str(part.msg) } else { "" }, @@ -508,8 +508,8 @@ pub unsafe fn dc_receive_imf( } else { String::new() }, - (*part).param.to_string(), - (*part).bytes, + part.param.to_string(), + part.bytes, hidden, if 0 != save_mime_headers { let body_string = std::str::from_utf8(std::slice::from_raw_parts(imf_raw_not_terminated as *const u8, imf_raw_bytes)).unwrap(); @@ -1201,20 +1201,15 @@ unsafe fn create_or_lookup_group( { ok = 1 } else { - let mut i_0: libc::c_int = 0; - while (i_0 as libc::c_uint) < carray_count(mime_parser.parts) { - let part: *mut dc_mimepart_t = - carray_get(mime_parser.parts, i_0 as libc::c_uint) - as *mut dc_mimepart_t; - if (*part).type_0 == 20 { - grpimage = (*part) + for part in &mut mime_parser.parts { + if part.type_0 == 20 { + grpimage = part .param .get(Param::File) .map(|s| s.strdup()) .unwrap_or_else(|| std::ptr::null_mut()); ok = 1 } - i_0 += 1 } } if 0 != ok { @@ -1709,14 +1704,13 @@ unsafe fn check_verified_properties( 1 } -unsafe fn set_better_msg>(mime_parser: &dc_mimeparser_t, better_msg: T) { +unsafe fn set_better_msg>(mime_parser: &mut dc_mimeparser_t, better_msg: T) { let msg = better_msg.as_ref(); - if !(msg.len() > 0) && carray_count((*mime_parser).parts) > 0 { - let mut part: *mut dc_mimepart_t = - carray_get(mime_parser.parts, 0 as libc::c_uint) as *mut dc_mimepart_t; + if !(msg.len() > 0) && !mime_parser.parts.is_empty() { + let part = &mut mime_parser.parts[0]; if (*part).type_0 == 10 { - free((*part).msg as *mut libc::c_void); - (*part).msg = msg.strdup(); + free(part.msg as *mut libc::c_void); + part.msg = msg.strdup(); } }; } diff --git a/tests/stress.rs b/tests/stress.rs index 38c0723e3..f0530e093 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -881,7 +881,7 @@ fn test_dc_mimeparser_with_context() { b"Chat-Version\x00" as *const u8 as *const libc::c_char, ); assert_eq!(as_str((*of).fld_value as *const libc::c_char), "1.0",); - assert_eq!(carray_count(mimeparser.parts), 1); + assert_eq!(mimeparser.parts.len(), 1); dc_mimeparser_unref(&mut mimeparser); }