diff --git a/src/dc_e2ee.rs b/src/dc_e2ee.rs index 2b54eb638..870095241 100644 --- a/src/dc_e2ee.rs +++ b/src/dc_e2ee.rs @@ -293,7 +293,7 @@ pub unsafe fn dc_e2ee_encrypt( ) { let ctext_bytes = ctext_v.len(); let ctext = ctext_v.strdup(); - (*helper).cdata_to_free = ctext as *mut _; + helper.cdata_to_free = ctext as *mut _; /* create MIME-structure that will contain the encrypted text */ let mut encrypted_part: *mut mailmime = new_data_part( @@ -339,7 +339,7 @@ pub unsafe fn dc_e2ee_encrypt( (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; (*encrypted_part).mm_parent = in_out_message; mailmime_free(message_to_encrypt); - (*helper).encryption_successfull = 1i32; + helper.encryption_successfull = 1i32; } } } @@ -933,6 +933,7 @@ unsafe fn decrypt_part( *ret_decrypted_mime = decrypted_mime; sth_decrypted = 1i32 } + std::mem::forget(plain); } } } @@ -1062,3 +1063,69 @@ pub unsafe fn dc_ensure_secret_key_exists(context: &Context) -> libc::c_int { success } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_mailmime_parse() { + let plain = b"Chat-Disposition-Notification-To: holger@deltachat.de +Chat-Group-ID: CovhGgau8M- +Chat-Group-Name: Delta Chat Dev +Subject: =?utf-8?Q?Chat=3A?= Delta Chat =?utf-8?Q?Dev=3A?= sidenote for + =?utf-8?Q?all=3A?= rust core master ... +Content-Type: text/plain; charset=\"utf-8\"; protected-headers=\"v1\" +Content-Transfer-Encoding: quoted-printable + +sidenote for all: rust core master is broken currently ... so dont recomm= +end to try to run with desktop or ios unless you are ready to hunt bugs + +-- =20 +Sent with my Delta Chat Messenger: https://delta.chat"; + let plain_bytes = plain.len(); + let plain_buf = plain.as_ptr() as *const libc::c_char; + + let mut index = 0; + let mut decrypted_mime = std::ptr::null_mut(); + + let res = unsafe { + mailmime_parse( + plain_buf as *const _, + plain_bytes, + &mut index, + &mut decrypted_mime, + ) + }; + unsafe { + let msg1 = (*decrypted_mime).mm_data.mm_message.mm_msg_mime; + let mut decoded_data = 0 as *const libc::c_char; + let mut decoded_data_bytes = 0; + let mut transfer_decoding_buffer: *mut libc::c_char = 0 as *mut libc::c_char; + + assert_eq!( + mailmime_transfer_decode( + msg1, + &mut decoded_data, + &mut decoded_data_bytes, + &mut transfer_decoding_buffer, + ), + 1 + ); + println!( + "{:?}", + String::from_utf8_lossy(std::slice::from_raw_parts( + decoded_data as *const u8, + decoded_data_bytes as usize, + )) + ); + + free(decoded_data as *mut _); + } + + assert_eq!(res, 0); + assert!(!decrypted_mime.is_null()); + + unsafe { free(decrypted_mime as *mut _) }; + } +} diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index 2e3d7e79a..db267a584 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -98,34 +98,34 @@ pub unsafe fn dc_mimeparser_empty(mimeparser: &mut dc_mimeparser_t) { 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() { - mailimf_fields_free((*mimeparser).header_protected); - (*mimeparser).header_protected = 0 as *mut mailimf_fields + mimeparser.header_root = 0 as *mut mailimf_fields; + mimeparser.header.clear(); + if !mimeparser.header_protected.is_null() { + mailimf_fields_free(mimeparser.header_protected); + mimeparser.header_protected = 0 as *mut mailimf_fields } - (*mimeparser).is_send_by_messenger = 0i32; - (*mimeparser).is_system_message = 0i32; - free((*mimeparser).subject as *mut libc::c_void); - (*mimeparser).subject = 0 as *mut libc::c_char; - if !(*mimeparser).mimeroot.is_null() { - mailmime_free((*mimeparser).mimeroot); - (*mimeparser).mimeroot = 0 as *mut mailmime + mimeparser.is_send_by_messenger = 0i32; + mimeparser.is_system_message = 0i32; + free(mimeparser.subject as *mut libc::c_void); + mimeparser.subject = 0 as *mut libc::c_char; + if !mimeparser.mimeroot.is_null() { + mailmime_free(mimeparser.mimeroot); + mimeparser.mimeroot = 0 as *mut mailmime } - (*mimeparser).is_forwarded = 0i32; - (*mimeparser).reports.clear(); - (*mimeparser).decrypting_failed = 0i32; - dc_e2ee_thanks(&mut (*mimeparser).e2ee_helper); + mimeparser.is_forwarded = 0i32; + mimeparser.reports.clear(); + mimeparser.decrypting_failed = 0i32; + dc_e2ee_thanks(&mut mimeparser.e2ee_helper); - if let Some(location_kml) = (*mimeparser).location_kml.as_mut() { + if let Some(location_kml) = mimeparser.location_kml.as_mut() { dc_kml_unref(location_kml); } - (*mimeparser).location_kml = None; + mimeparser.location_kml = None; - if let Some(message_kml) = (*mimeparser).message_kml.as_mut() { + if let Some(message_kml) = mimeparser.message_kml.as_mut() { dc_kml_unref(message_kml); } - (*mimeparser).message_kml = None; + mimeparser.message_kml = None; } unsafe fn dc_mimepart_unref(mut mimepart: dc_mimepart_t) { @@ -148,19 +148,18 @@ pub unsafe fn dc_mimeparser_parse( body_not_terminated, body_bytes, &mut index, - &mut (*mimeparser).mimeroot, + &mut mimeparser.mimeroot, ); - if !(r != MAILIMF_NO_ERROR as libc::c_int || (*mimeparser).mimeroot.is_null()) { + if !(r != MAILIMF_NO_ERROR as libc::c_int || mimeparser.mimeroot.is_null()) { dc_e2ee_decrypt( - (*mimeparser).context, - (*mimeparser).mimeroot, - &mut (*mimeparser).e2ee_helper, + mimeparser.context, + mimeparser.mimeroot, + &mut mimeparser.e2ee_helper, ); - dc_mimeparser_parse_mime_recursive(mimeparser, (*mimeparser).mimeroot); + dc_mimeparser_parse_mime_recursive(mimeparser, mimeparser.mimeroot); let field: *mut mailimf_field = dc_mimeparser_lookup_field(mimeparser, "Subject"); if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { - (*mimeparser).subject = - dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value) + mimeparser.subject = dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value) } if !dc_mimeparser_lookup_optional_field( mimeparser, @@ -168,7 +167,7 @@ pub unsafe fn dc_mimeparser_parse( ) .is_null() { - (*mimeparser).is_send_by_messenger = 1i32 + mimeparser.is_send_by_messenger = 1i32 } if !dc_mimeparser_lookup_field(mimeparser, "Autocrypt-Setup-Message").is_null() { let mut has_setup_file: libc::c_int = 0i32; @@ -212,7 +211,7 @@ pub unsafe fn dc_mimeparser_parse( b"location-streaming-enabled\x00" as *const u8 as *const libc::c_char, ) == 0i32 { - (*mimeparser).is_system_message = 8i32 + mimeparser.is_system_message = 8i32 } } } @@ -229,7 +228,7 @@ pub unsafe fn dc_mimeparser_parse( } } } - if 0 != (*mimeparser).is_send_by_messenger + if 0 != mimeparser.is_send_by_messenger && 0 != S_GENERATE_COMPOUND_MSGS && mimeparser.parts.len() == 2 { @@ -255,15 +254,15 @@ pub unsafe fn dc_mimeparser_parse( dc_mimepart_unref(textpart); } } - if !(*mimeparser).subject.is_null() { + if !mimeparser.subject.is_null() { let mut prepend_subject: libc::c_int = 1i32; - if 0 == (*mimeparser).decrypting_failed { - let p: *mut libc::c_char = strchr((*mimeparser).subject, ':' as i32); - if p.wrapping_offset_from((*mimeparser).subject) == 2 - || p.wrapping_offset_from((*mimeparser).subject) == 3 - || 0 != (*mimeparser).is_send_by_messenger + if 0 == mimeparser.decrypting_failed { + let p: *mut libc::c_char = strchr(mimeparser.subject, ':' as i32); + if p.wrapping_offset_from(mimeparser.subject) == 2 + || p.wrapping_offset_from(mimeparser.subject) == 3 + || 0 != mimeparser.is_send_by_messenger || !strstr( - (*mimeparser).subject, + mimeparser.subject, b"Chat:\x00" as *const u8 as *const libc::c_char, ) .is_null() @@ -272,7 +271,7 @@ pub unsafe fn dc_mimeparser_parse( } } if 0 != prepend_subject { - let subj: *mut libc::c_char = dc_strdup((*mimeparser).subject); + let subj: *mut libc::c_char = dc_strdup(mimeparser.subject); let p_0: *mut libc::c_char = strchr(subj, '[' as i32); if !p_0.is_null() { *p_0 = 0i32 as libc::c_char @@ -295,7 +294,7 @@ pub unsafe fn dc_mimeparser_parse( free(subj as *mut libc::c_void); } } - if 0 != (*mimeparser).is_forwarded { + if 0 != mimeparser.is_forwarded { for part in mimeparser.parts.iter_mut() { part.param.set_int(Param::Forwarded, 1); } @@ -327,7 +326,7 @@ pub unsafe fn dc_mimeparser_parse( } } } - if 0 == (*mimeparser).decrypting_failed { + if 0 == mimeparser.decrypting_failed { let dn_field: *const mailimf_optional_field = dc_mimeparser_lookup_optional_field( mimeparser, b"Chat-Disposition-Notification-To\x00" as *const u8 as *const libc::c_char, @@ -372,11 +371,11 @@ 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_none() && (*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 { - part_5.msg = dc_strdup((*mimeparser).subject) + if !mimeparser.subject.is_null() && 0 == mimeparser.is_send_by_messenger { + part_5.msg = dc_strdup(mimeparser.subject) } else { part_5.msg = dc_strdup(b"\x00" as *const u8 as *const libc::c_char) } @@ -493,32 +492,32 @@ unsafe fn dc_mimeparser_parse_mime_recursive( ) == 0i32 { info!( - (*mimeparser).context, + mimeparser.context, 0, "Protected headers found in text/rfc822-headers attachment: Will be ignored.", ); return 0i32; } - if (*mimeparser).header_protected.is_null() { + if mimeparser.header_protected.is_null() { let mut dummy: size_t = 0i32 as size_t; if mailimf_envelope_and_optional_fields_parse( (*mime).mm_mime_start, (*mime).mm_length, &mut dummy, - &mut (*mimeparser).header_protected, + &mut mimeparser.header_protected, ) != MAILIMF_NO_ERROR as libc::c_int - || (*mimeparser).header_protected.is_null() + || mimeparser.header_protected.is_null() { - warn!((*mimeparser).context, 0, "Protected headers parsing error.",); + warn!(mimeparser.context, 0, "Protected headers parsing error.",); } else { hash_header( - &mut (*mimeparser).header, - (*mimeparser).header_protected, - (*mimeparser).context, + &mut mimeparser.header, + mimeparser.header_protected, + mimeparser.context, ); } } else { info!( - (*mimeparser).context, + mimeparser.context, 0, "Protected headers found in MIME header: Will be ignored as we already found an outer one." ); @@ -622,7 +621,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( let mut part = dc_mimepart_new(); part.type_0 = 10i32; let msg_body = CString::new( - (*mimeparser) + mimeparser .context .stock_str(StockMessage::CantDecryptMsgBody) .as_ref(), @@ -635,7 +634,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( part.msg_raw = dc_strdup(part.msg); mimeparser.parts.push(part); any_part_added = 1i32; - (*mimeparser).decrypting_failed = 1i32 + mimeparser.decrypting_failed = 1i32 } 46 => { cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; @@ -663,7 +662,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( b"disposition-notification\x00" as *const u8 as *const libc::c_char, ) == 0i32 { - (*mimeparser).reports.push(mime); + mimeparser.reports.push(mime); } else { any_part_added = dc_mimeparser_parse_mime_recursive( mimeparser, @@ -713,7 +712,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( } if plain_cnt == 1i32 && html_cnt == 1i32 { warn!( - (*mimeparser).context, + mimeparser.context, 0i32, "HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted." ); @@ -742,12 +741,12 @@ unsafe fn dc_mimeparser_parse_mime_recursive( } } 3 => { - if (*mimeparser).header_root.is_null() { - (*mimeparser).header_root = (*mime).mm_data.mm_message.mm_fields; + if mimeparser.header_root.is_null() { + mimeparser.header_root = (*mime).mm_data.mm_message.mm_fields; hash_header( - &mut (*mimeparser).header, - (*mimeparser).header_root, - (*mimeparser).context, + &mut mimeparser.header, + mimeparser.header_root, + mimeparser.context, ); } if !(*mime).mm_data.mm_message.mm_msg_mime.is_null() { @@ -1220,7 +1219,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known( free(simplified_txt as *mut libc::c_void); } if 0 != simplifier.unwrap().is_forwarded { - (*mimeparser).is_forwarded = 1i32 + mimeparser.is_forwarded = 1i32 } current_block = 10261677128829721533; } @@ -1348,8 +1347,8 @@ unsafe fn dc_mimeparser_add_single_part_if_known( 4, ) == 0i32 { - (*mimeparser).location_kml = Some(dc_kml_parse( - (*mimeparser).context, + mimeparser.location_kml = Some(dc_kml_parse( + mimeparser.context, decoded_data, decoded_data_bytes, )); @@ -1367,8 +1366,8 @@ unsafe fn dc_mimeparser_add_single_part_if_known( 4, ) == 0i32 { - (*mimeparser).message_kml = Some(dc_kml_parse( - (*mimeparser).context, + mimeparser.message_kml = Some(dc_kml_parse( + mimeparser.context, decoded_data, decoded_data_bytes, )); @@ -1590,7 +1589,7 @@ pub unsafe fn dc_mimeparser_sender_equals_recipient(mimeparser: &dc_mimeparser_t let mut fld_from: *const mailimf_from = 0 as *const mailimf_from; let mb: *mut mailimf_mailbox; - if !(*mimeparser).header_root.is_null() { + if !mimeparser.header_root.is_null() { /* get From: and check there is exactly one sender */ fld = mailimf_find_field(mimeparser.header_root, MAILIMF_FIELD_FROM as libc::c_int); if !(fld.is_null() diff --git a/src/dc_simplify.rs b/src/dc_simplify.rs index bca7a7fe5..6cfb25fd0 100644 --- a/src/dc_simplify.rs +++ b/src/dc_simplify.rs @@ -29,6 +29,10 @@ impl dc_simplify_t { is_html: libc::c_int, is_msgrmsg: libc::c_int, ) -> *mut libc::c_char { + if in_bytes <= 0 { + return "".strdup(); + } + /* create a copy of the given buffer */ let mut out: *mut libc::c_char; let mut temp: *mut libc::c_char;