mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 09:26:29 +03:00
refactor: rustify interface of maimlime_transfer_decode
This commit is contained in:
committed by
holger krekel
parent
7dd3bad8bd
commit
266b205c75
@@ -21,6 +21,7 @@ use crate::dc_simplify::*;
|
|||||||
use crate::dc_strencode::*;
|
use crate::dc_strencode::*;
|
||||||
use crate::dc_tools::*;
|
use crate::dc_tools::*;
|
||||||
use crate::e2ee::*;
|
use crate::e2ee::*;
|
||||||
|
use crate::error::Error;
|
||||||
use crate::location;
|
use crate::location;
|
||||||
use crate::param::*;
|
use crate::param::*;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::StockMessage;
|
||||||
@@ -580,9 +581,11 @@ impl<'a> MimeParser<'a> {
|
|||||||
if mime.is_null() || (*mime).mm_data.mm_single.is_null() {
|
if mime.is_null() || (*mime).mm_data.mm_single.is_null() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let mut raw_mime: *mut libc::c_char = ptr::null_mut();
|
|
||||||
|
let mut raw_mime = ptr::null_mut();
|
||||||
let mut msg_type = Viewtype::Unknown;
|
let mut msg_type = Viewtype::Unknown;
|
||||||
let mime_type = mailmime_get_mime_type(mime, &mut msg_type, &mut raw_mime);
|
let mime_type = mailmime_get_mime_type(mime, &mut msg_type, &mut raw_mime);
|
||||||
|
|
||||||
let mime_data = (*mime).mm_data.mm_single;
|
let mime_data = (*mime).mm_data.mm_single;
|
||||||
if (*mime_data).dt_type != MAILMIME_DATA_TEXT as libc::c_int
|
if (*mime_data).dt_type != MAILMIME_DATA_TEXT as libc::c_int
|
||||||
/* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */
|
/* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */
|
||||||
@@ -592,22 +595,14 @@ impl<'a> MimeParser<'a> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mmap_string_unref()'d if set */
|
let mut decoded_data = match mailmime_transfer_decode(mime) {
|
||||||
let mut transfer_decoding_buffer: *mut libc::c_char = ptr::null_mut();
|
Ok(decoded_data) => decoded_data,
|
||||||
/* must not be free()'d */
|
Err(_) => {
|
||||||
let mut decoded_data: *const libc::c_char = ptr::null();
|
// Note that it's now always an error - might be no data
|
||||||
let mut decoded_data_bytes = 0;
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if !mailmime_transfer_decode(
|
|
||||||
mime,
|
|
||||||
&mut decoded_data,
|
|
||||||
&mut decoded_data_bytes,
|
|
||||||
&mut transfer_decoding_buffer,
|
|
||||||
) {
|
|
||||||
/* mailmime_transfer_decode does not allocate when it returns false.
|
|
||||||
Note that it's now always an error - might be no data */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let old_part_count = self.parts.len();
|
let old_part_count = self.parts.len();
|
||||||
|
|
||||||
/* regard `Content-Transfer-Encoding:` */
|
/* regard `Content-Transfer-Encoding:` */
|
||||||
@@ -628,26 +623,18 @@ impl<'a> MimeParser<'a> {
|
|||||||
if let Some(encoding) =
|
if let Some(encoding) =
|
||||||
Charset::for_label(CStr::from_ptr(charset).to_str().unwrap().as_bytes())
|
Charset::for_label(CStr::from_ptr(charset).to_str().unwrap().as_bytes())
|
||||||
{
|
{
|
||||||
let data = std::slice::from_raw_parts(
|
let (res, _, _) = encoding.decode(&decoded_data);
|
||||||
decoded_data as *const u8,
|
|
||||||
decoded_data_bytes,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (res, _, _) = encoding.decode(data);
|
|
||||||
if res.is_empty() {
|
if res.is_empty() {
|
||||||
/* no error - but nothing to add */
|
/* no error - but nothing to add */
|
||||||
ok_to_continue = false;
|
ok_to_continue = false;
|
||||||
} else {
|
} else {
|
||||||
let b = res.as_bytes();
|
decoded_data = res.as_bytes().to_vec()
|
||||||
decoded_data = b.as_ptr() as *const libc::c_char;
|
|
||||||
decoded_data_bytes = b.len();
|
|
||||||
std::mem::forget(res);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!(
|
warn!(
|
||||||
self.context,
|
self.context,
|
||||||
"Cannot convert {} bytes from \"{}\" to \"utf-8\".",
|
"Cannot convert {} bytes from \"{}\" to \"utf-8\".",
|
||||||
decoded_data_bytes as libc::c_int,
|
decoded_data.len(),
|
||||||
as_str(charset),
|
as_str(charset),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -656,13 +643,11 @@ impl<'a> MimeParser<'a> {
|
|||||||
/* check header directly as is_send_by_messenger is not yet set up */
|
/* check header directly as is_send_by_messenger is not yet set up */
|
||||||
let is_msgrmsg = self.lookup_optional_field("Chat-Version").is_some();
|
let is_msgrmsg = self.lookup_optional_field("Chat-Version").is_some();
|
||||||
|
|
||||||
let simplified_txt = if decoded_data_bytes <= 0 || decoded_data.is_null() {
|
let simplified_txt = if decoded_data.is_empty() {
|
||||||
"".into()
|
"".into()
|
||||||
} else {
|
} else {
|
||||||
let input_c = strndup(decoded_data, decoded_data_bytes as _);
|
let input = std::string::String::from_utf8_lossy(&decoded_data);
|
||||||
let input = to_string_lossy(input_c);
|
|
||||||
let is_html = mime_type == 70;
|
let is_html = mime_type == 70;
|
||||||
free(input_c as *mut _);
|
|
||||||
|
|
||||||
simplifier.unwrap().simplify(&input, is_html, is_msgrmsg)
|
simplifier.unwrap().simplify(&input, is_html, is_msgrmsg)
|
||||||
};
|
};
|
||||||
@@ -671,12 +656,8 @@ impl<'a> MimeParser<'a> {
|
|||||||
part.typ = Viewtype::Text;
|
part.typ = Viewtype::Text;
|
||||||
part.mimetype = mime_type;
|
part.mimetype = mime_type;
|
||||||
part.msg = Some(simplified_txt);
|
part.msg = Some(simplified_txt);
|
||||||
part.msg_raw = {
|
part.msg_raw =
|
||||||
let raw_c = strndup(decoded_data, decoded_data_bytes as libc::c_ulong);
|
Some(std::string::String::from_utf8_lossy(&decoded_data).to_string());
|
||||||
let raw = to_string_lossy(raw_c);
|
|
||||||
free(raw_c.cast());
|
|
||||||
Some(raw)
|
|
||||||
};
|
|
||||||
self.do_add_single_part(part);
|
self.do_add_single_part(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -764,26 +745,23 @@ impl<'a> MimeParser<'a> {
|
|||||||
if desired_filename.starts_with("location")
|
if desired_filename.starts_with("location")
|
||||||
&& desired_filename.ends_with(".kml")
|
&& desired_filename.ends_with(".kml")
|
||||||
{
|
{
|
||||||
if !decoded_data.is_null() && decoded_data_bytes > 0 {
|
if !decoded_data.is_empty() {
|
||||||
let d = dc_null_terminate(decoded_data, decoded_data_bytes as i32);
|
let d = std::string::String::from_utf8_lossy(&decoded_data);
|
||||||
self.location_kml = location::Kml::parse(self.context, as_str(d)).ok();
|
self.location_kml = location::Kml::parse(self.context, &d).ok();
|
||||||
free(d.cast());
|
|
||||||
}
|
}
|
||||||
} else if desired_filename.starts_with("message")
|
} else if desired_filename.starts_with("message")
|
||||||
&& desired_filename.ends_with(".kml")
|
&& desired_filename.ends_with(".kml")
|
||||||
{
|
{
|
||||||
if !decoded_data.is_null() && decoded_data_bytes > 0 {
|
if !decoded_data.is_empty() {
|
||||||
let d = dc_null_terminate(decoded_data, decoded_data_bytes as i32);
|
let d = std::string::String::from_utf8_lossy(&decoded_data);
|
||||||
self.message_kml = location::Kml::parse(self.context, as_str(d)).ok();
|
self.message_kml = location::Kml::parse(self.context, &d).ok();
|
||||||
free(d.cast());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.do_add_single_file_part(
|
self.do_add_single_file_part(
|
||||||
msg_type,
|
msg_type,
|
||||||
mime_type,
|
mime_type,
|
||||||
as_str(raw_mime),
|
as_str(raw_mime),
|
||||||
decoded_data,
|
&decoded_data,
|
||||||
decoded_data_bytes,
|
|
||||||
&desired_filename,
|
&desired_filename,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -792,9 +770,7 @@ impl<'a> MimeParser<'a> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
/* add object? (we do not add all objects, eg. signatures etc. are ignored) */
|
/* add object? (we do not add all objects, eg. signatures etc. are ignored) */
|
||||||
if !transfer_decoding_buffer.is_null() {
|
|
||||||
mmap_string_unref(transfer_decoding_buffer);
|
|
||||||
}
|
|
||||||
free(raw_mime as *mut libc::c_void);
|
free(raw_mime as *mut libc::c_void);
|
||||||
self.parts.len() > old_part_count
|
self.parts.len() > old_part_count
|
||||||
}
|
}
|
||||||
@@ -804,30 +780,24 @@ impl<'a> MimeParser<'a> {
|
|||||||
msg_type: Viewtype,
|
msg_type: Viewtype,
|
||||||
mime_type: libc::c_int,
|
mime_type: libc::c_int,
|
||||||
raw_mime: &str,
|
raw_mime: &str,
|
||||||
decoded_data: *const libc::c_char,
|
decoded_data: &[u8],
|
||||||
decoded_data_bytes: libc::size_t,
|
|
||||||
desired_filename: &str,
|
desired_filename: &str,
|
||||||
) {
|
) {
|
||||||
/* create a free file name to use */
|
/* create a free file name to use */
|
||||||
let path_filename = dc_get_fine_path_filename(self.context, "$BLOBDIR", desired_filename);
|
let path_filename = dc_get_fine_path_filename(self.context, "$BLOBDIR", desired_filename);
|
||||||
let bytes = std::slice::from_raw_parts(decoded_data as *const u8, decoded_data_bytes);
|
|
||||||
|
|
||||||
/* copy data to file */
|
/* copy data to file */
|
||||||
if dc_write_file(self.context, &path_filename, bytes) {
|
if dc_write_file(self.context, &path_filename, decoded_data) {
|
||||||
let mut part = Part::default();
|
let mut part = Part::default();
|
||||||
part.typ = msg_type;
|
part.typ = msg_type;
|
||||||
part.mimetype = mime_type;
|
part.mimetype = mime_type;
|
||||||
part.bytes = decoded_data_bytes as libc::c_int;
|
part.bytes = decoded_data.len() as libc::c_int;
|
||||||
part.param.set(Param::File, path_filename.to_string_lossy());
|
part.param.set(Param::File, path_filename.to_string_lossy());
|
||||||
part.param.set(Param::MimeType, raw_mime);
|
part.param.set(Param::MimeType, raw_mime);
|
||||||
if mime_type == 80 {
|
if mime_type == 80 {
|
||||||
assert!(!decoded_data.is_null(), "invalid image data");
|
assert!(!decoded_data.is_empty(), "invalid image data");
|
||||||
let data = std::slice::from_raw_parts(
|
|
||||||
decoded_data as *const u8,
|
|
||||||
decoded_data_bytes as usize,
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Ok((width, height)) = dc_get_filemeta(data) {
|
if let Ok((width, height)) = dc_get_filemeta(decoded_data) {
|
||||||
part.param.set_int(Param::Width, width as i32);
|
part.param.set_int(Param::Width, width as i32);
|
||||||
part.param.set_int(Param::Height, height as i32);
|
part.param.set_int(Param::Height, height as i32);
|
||||||
}
|
}
|
||||||
@@ -1233,32 +1203,12 @@ pub unsafe fn mailmime_find_ct_parameter(
|
|||||||
ptr::null_mut()
|
ptr::null_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mailmime_transfer_decode(
|
pub unsafe fn mailmime_transfer_decode(mime: *mut mailmime) -> Result<Vec<u8>, Error> {
|
||||||
mime: *mut mailmime,
|
ensure!(!mime.is_null(), "invalid inputs");
|
||||||
ret_decoded_data: *mut *const libc::c_char,
|
|
||||||
ret_decoded_data_bytes: *mut libc::size_t,
|
|
||||||
ret_to_mmap_string_unref: *mut *mut libc::c_char,
|
|
||||||
) -> bool {
|
|
||||||
let mut mime_transfer_encoding = MAILMIME_MECHANISM_BINARY as libc::c_int;
|
let mut mime_transfer_encoding = MAILMIME_MECHANISM_BINARY as libc::c_int;
|
||||||
let mime_data: *mut mailmime_data;
|
|
||||||
|
|
||||||
/* must not be free()'d */
|
let mime_data = (*mime).mm_data.mm_single;
|
||||||
let decoded_data: *const libc::c_char;
|
|
||||||
let mut decoded_data_bytes = 0;
|
|
||||||
|
|
||||||
/* mmap_string_unref()'d if set */
|
|
||||||
let mut transfer_decoding_buffer: *mut libc::c_char = ptr::null_mut();
|
|
||||||
if mime.is_null()
|
|
||||||
|| ret_decoded_data.is_null()
|
|
||||||
|| ret_decoded_data_bytes.is_null()
|
|
||||||
|| ret_to_mmap_string_unref.is_null()
|
|
||||||
|| !(*ret_decoded_data).is_null()
|
|
||||||
|| *ret_decoded_data_bytes != 0
|
|
||||||
|| !(*ret_to_mmap_string_unref).is_null()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mime_data = (*mime).mm_data.mm_single;
|
|
||||||
if !(*mime).mm_mime_fields.is_null() {
|
if !(*mime).mm_mime_fields.is_null() {
|
||||||
for cur in (*(*(*mime).mm_mime_fields).fld_list).into_iter() {
|
for cur in (*(*(*mime).mm_mime_fields).fld_list).into_iter() {
|
||||||
let field = cur as *mut mailmime_field;
|
let field = cur as *mut mailmime_field;
|
||||||
@@ -1277,35 +1227,42 @@ pub unsafe fn mailmime_transfer_decode(
|
|||||||
|| mime_transfer_encoding == MAILMIME_MECHANISM_8BIT as libc::c_int
|
|| mime_transfer_encoding == MAILMIME_MECHANISM_8BIT as libc::c_int
|
||||||
|| mime_transfer_encoding == MAILMIME_MECHANISM_BINARY as libc::c_int
|
|| mime_transfer_encoding == MAILMIME_MECHANISM_BINARY as libc::c_int
|
||||||
{
|
{
|
||||||
decoded_data = (*mime_data).dt_data.dt_text.dt_data;
|
let decoded_data = (*mime_data).dt_data.dt_text.dt_data;
|
||||||
decoded_data_bytes = (*mime_data).dt_data.dt_text.dt_length;
|
let decoded_data_bytes = (*mime_data).dt_data.dt_text.dt_length;
|
||||||
|
|
||||||
if decoded_data.is_null() || decoded_data_bytes <= 0 {
|
if decoded_data.is_null() || decoded_data_bytes <= 0 {
|
||||||
return false;
|
bail!("No data to decode found");
|
||||||
|
} else {
|
||||||
|
let result = std::slice::from_raw_parts(decoded_data as *const u8, decoded_data_bytes);
|
||||||
|
return Ok(result.to_vec());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
let mut current_index = 0;
|
|
||||||
let r = mailmime_part_parse(
|
|
||||||
(*mime_data).dt_data.dt_text.dt_data,
|
|
||||||
(*mime_data).dt_data.dt_text.dt_length,
|
|
||||||
&mut current_index,
|
|
||||||
mime_transfer_encoding,
|
|
||||||
&mut transfer_decoding_buffer,
|
|
||||||
&mut decoded_data_bytes,
|
|
||||||
);
|
|
||||||
if r != MAILIMF_NO_ERROR as libc::c_int
|
|
||||||
|| transfer_decoding_buffer.is_null()
|
|
||||||
|| decoded_data_bytes <= 0
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
decoded_data = transfer_decoding_buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret_decoded_data = decoded_data;
|
let mut current_index = 0;
|
||||||
*ret_decoded_data_bytes = decoded_data_bytes;
|
let mut transfer_decoding_buffer = ptr::null_mut();
|
||||||
*ret_to_mmap_string_unref = transfer_decoding_buffer;
|
let mut decoded_data_bytes = 0;
|
||||||
|
|
||||||
true
|
let r = mailmime_part_parse(
|
||||||
|
(*mime_data).dt_data.dt_text.dt_data,
|
||||||
|
(*mime_data).dt_data.dt_text.dt_length,
|
||||||
|
&mut current_index,
|
||||||
|
mime_transfer_encoding,
|
||||||
|
&mut transfer_decoding_buffer,
|
||||||
|
&mut decoded_data_bytes,
|
||||||
|
);
|
||||||
|
|
||||||
|
if r == MAILIMF_NO_ERROR as libc::c_int
|
||||||
|
&& !transfer_decoding_buffer.is_null()
|
||||||
|
&& decoded_data_bytes > 0
|
||||||
|
{
|
||||||
|
let result =
|
||||||
|
std::slice::from_raw_parts(transfer_decoding_buffer as *const u8, decoded_data_bytes);
|
||||||
|
mmap_string_unref(transfer_decoding_buffer);
|
||||||
|
|
||||||
|
return Ok(result.to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(format_err!("Failed to to decode"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet<String> {
|
pub unsafe fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet<String> {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use mmime::mailimf_types::*;
|
|||||||
use mmime::mailmime::*;
|
use mmime::mailmime::*;
|
||||||
use mmime::mailmime_content::*;
|
use mmime::mailmime_content::*;
|
||||||
use mmime::mailmime_types::*;
|
use mmime::mailmime_types::*;
|
||||||
use mmime::mmapstring::*;
|
|
||||||
use mmime::other::*;
|
use mmime::other::*;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
@@ -800,22 +799,13 @@ unsafe fn handle_reports(
|
|||||||
b"disposition-notification\x00" as *const u8 as *const libc::c_char,
|
b"disposition-notification\x00" as *const u8 as *const libc::c_char,
|
||||||
) == 0
|
) == 0
|
||||||
{
|
{
|
||||||
let mut report_body = std::ptr::null();
|
if let Ok(report_body) = mailmime_transfer_decode(report_data) {
|
||||||
let mut report_body_bytes = 0;
|
|
||||||
let mut to_mmap_string_unref = std::ptr::null_mut();
|
|
||||||
|
|
||||||
if mailmime_transfer_decode(
|
|
||||||
report_data,
|
|
||||||
&mut report_body,
|
|
||||||
&mut report_body_bytes,
|
|
||||||
&mut to_mmap_string_unref,
|
|
||||||
) {
|
|
||||||
let mut report_parsed = std::ptr::null_mut();
|
let mut report_parsed = std::ptr::null_mut();
|
||||||
let mut dummy = 0;
|
let mut dummy = 0;
|
||||||
|
|
||||||
if mailmime_parse(
|
if mailmime_parse(
|
||||||
report_body,
|
report_body.as_ptr() as *const _,
|
||||||
report_body_bytes,
|
report_body.len(),
|
||||||
&mut dummy,
|
&mut dummy,
|
||||||
&mut report_parsed,
|
&mut report_parsed,
|
||||||
) == MAIL_NO_ERROR as libc::c_int
|
) == MAIL_NO_ERROR as libc::c_int
|
||||||
@@ -867,9 +857,6 @@ unsafe fn handle_reports(
|
|||||||
}
|
}
|
||||||
mailmime_free(report_parsed);
|
mailmime_free(report_parsed);
|
||||||
}
|
}
|
||||||
if !to_mmap_string_unref.is_null() {
|
|
||||||
mmap_string_unref(to_mmap_string_unref);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/e2ee.rs
21
src/e2ee.rs
@@ -1093,25 +1093,8 @@ Sent with my Delta Chat Messenger: https://delta.chat";
|
|||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let msg1 = (*decrypted_mime).mm_data.mm_message.mm_msg_mime;
|
let msg1 = (*decrypted_mime).mm_data.mm_message.mm_msg_mime;
|
||||||
let mut decoded_data = ptr::null();
|
let data = mailmime_transfer_decode(msg1).unwrap();
|
||||||
let mut decoded_data_bytes = 0;
|
println!("{:?}", String::from_utf8_lossy(&data));
|
||||||
let mut transfer_decoding_buffer: *mut libc::c_char = ptr::null_mut();
|
|
||||||
|
|
||||||
assert!(mailmime_transfer_decode(
|
|
||||||
msg1,
|
|
||||||
&mut decoded_data,
|
|
||||||
&mut decoded_data_bytes,
|
|
||||||
&mut transfer_decoding_buffer,
|
|
||||||
));
|
|
||||||
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_eq!(res, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user