rustify new_data_part() and related sanitizations

This commit is contained in:
holger krekel
2019-09-23 16:19:50 +02:00
parent ba231d2c5f
commit f70897a6d3
3 changed files with 88 additions and 118 deletions

View File

@@ -2,7 +2,6 @@ use std::path::Path;
use std::ptr; use std::ptr;
use chrono::TimeZone; use chrono::TimeZone;
use libc::free;
use mmime::clist::*; use mmime::clist::*;
use mmime::mailimf_types::*; use mmime::mailimf_types::*;
use mmime::mailimf_types_helper::*; use mmime::mailimf_types_helper::*;
@@ -535,7 +534,7 @@ pub unsafe fn dc_mimefactory_render(
meta.type_0 = Viewtype::Image; meta.type_0 = Viewtype::Image;
meta.param.set(Param::File, grpimage); meta.param.set(Param::File, grpimage);
let res = build_body_file(context, &meta, "group-image"); let res = build_body_file(context, &meta, "group-image")?;
meta_part = res.0; meta_part = res.0;
let filename_as_sent = res.1; let filename_as_sent = res.1;
if !meta_part.is_null() { if !meta_part.is_null() {
@@ -610,12 +609,10 @@ pub unsafe fn dc_mimefactory_render(
24 * 1024 * 1024 / 4 * 3 / 1000 / 1000, 24 * 1024 * 1024 / 4 * 3 / 1000 / 1000,
); );
} else { } else {
let (file_part, _) = build_body_file(context, &factory.msg, ""); let (file_part, _) = build_body_file(context, &factory.msg, "")?;
if !file_part.is_null() {
mailmime_smart_add_part(message, file_part); mailmime_smart_add_part(message, file_part);
} }
} }
}
if !meta_part.is_null() { if !meta_part.is_null() {
mailmime_smart_add_part(message, meta_part); mailmime_smart_add_part(message, meta_part);
} }
@@ -699,8 +696,7 @@ pub unsafe fn dc_mimefactory_render(
factory.msg.rfc724_mid factory.msg.rfc724_mid
); );
let content_type_0 = let content_type_0 = wrapmime::new_content_type("message/disposition-notification")?;
wrapmime::new_mailmime_content_type("message/disposition-notification");
let mime_fields_0: *mut mailmime_fields = let mime_fields_0: *mut mailmime_fields =
mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int); mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int);
let mach_mime_part: *mut mailmime = mailmime_new_empty(content_type_0, mime_fields_0); let mach_mime_part: *mut mailmime = mailmime_new_empty(content_type_0, mime_fields_0);
@@ -816,10 +812,14 @@ fn get_subject(
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn build_body_file(context: &Context, msg: &Message, base_name: &str) -> (*mut mailmime, String) { fn build_body_file(
context: &Context,
msg: &Message,
base_name: &str,
) -> Result<(*mut mailmime, String), Error> {
let path_filename = match msg.param.get(Param::File) { let path_filename = match msg.param.get(Param::File) {
None => { None => {
return (ptr::null_mut(), "".to_string()); bail!("msg has no filename");
} }
Some(path) => path, Some(path) => path,
}; };
@@ -913,23 +913,16 @@ fn build_body_file(context: &Context, msg: &Message, base_name: &str) -> (*mut m
} }
} }
} }
let content = wrapmime::new_mailmime_content_type(&mimetype); let content = wrapmime::new_content_type(&mimetype)?;
let filename_encoded = dc_encode_header_words(&filename_to_send).strdup(); let filename_encoded = dc_encode_header_words(&filename_to_send);
clist_insert_after( wrapmime::append_ct_param(content, "name", &filename_encoded)?;
(*content).ct_parameters,
(*(*content).ct_parameters).last,
mailmime_param_new_with_data(
b"name\x00" as *const u8 as *const libc::c_char as *mut libc::c_char,
filename_encoded,
) as *mut libc::c_void,
);
free(filename_encoded as *mut libc::c_void);
let mime_sub = mailmime_new_empty(content, mime_fields); let mime_sub = mailmime_new_empty(content, mime_fields);
let abs_path = dc_get_abs_path(context, path_filename) let abs_path = dc_get_abs_path(context, path_filename)
.to_c_string() .to_c_string()
.unwrap(); .unwrap();
mailmime_set_body_file(mime_sub, dc_strdup(abs_path.as_ptr())); mailmime_set_body_file(mime_sub, dc_strdup(abs_path.as_ptr()));
(mime_sub, filename_to_send) Ok((mime_sub, filename_to_send))
} }
} }

View File

@@ -252,16 +252,16 @@ impl EncryptHelper {
ptr::null_mut(), ptr::null_mut(),
0 as libc::size_t, 0 as libc::size_t,
"multipart/encrypted", "multipart/encrypted",
-1, MAILMIME_MECHANISM_BASE64,
); )?;
let content: *mut mailmime_content = (*encrypted_part).mm_content_type; let content: *mut mailmime_content = (*encrypted_part).mm_content_type;
wrapmime::append_ct_param(content, "protocol", "application/pgp-encrypted")?; wrapmime::append_ct_param(content, "protocol", "application/pgp-encrypted")?;
let version_mime: *mut mailmime = new_data_part( let version_mime: *mut mailmime = new_data_part(
VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void, VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void,
strlen(VERSION_CONTENT.as_mut_ptr()), strlen(VERSION_CONTENT.as_mut_ptr()),
"application/pgp-encrypted", "application/pgp-encrypted",
MAILMIME_MECHANISM_7BIT as i32, MAILMIME_MECHANISM_7BIT,
); )?;
mailmime_smart_add_part(encrypted_part, version_mime); mailmime_smart_add_part(encrypted_part, version_mime);
// we assume that ctext_v is not dropped until the end // we assume that ctext_v is not dropped until the end
@@ -270,8 +270,8 @@ impl EncryptHelper {
ctext_v.as_ptr() as *mut libc::c_void, ctext_v.as_ptr() as *mut libc::c_void,
ctext_v.len(), ctext_v.len(),
"application/octet-stream", "application/octet-stream",
MAILMIME_MECHANISM_7BIT as i32, MAILMIME_MECHANISM_7BIT,
); )?;
mailmime_smart_add_part(encrypted_part, ctext_part); mailmime_smart_add_part(encrypted_part, ctext_part);
(*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part;
(*encrypted_part).mm_parent = in_out_message; (*encrypted_part).mm_parent = in_out_message;
@@ -421,96 +421,39 @@ impl E2eeHelper {
} }
} }
unsafe fn new_data_part( fn new_data_part(
data: *mut libc::c_void, data: *mut libc::c_void,
data_bytes: libc::size_t, data_bytes: libc::size_t,
default_content_type: &str, content_type: &str,
default_encoding: libc::c_int, default_encoding: u32,
) -> *mut mailmime { ) -> Result<*mut mailmime> {
let mut ok_to_continue = true; let content = new_content_type(&content_type)?;
unsafe {
let mut encoding: *mut mailmime_mechanism = ptr::null_mut(); let mut encoding: *mut mailmime_mechanism = ptr::null_mut();
let content: *mut mailmime_content; if wrapmime::content_type_needs_encoding(content) {
let mime: *mut mailmime; encoding = mailmime_mechanism_new(default_encoding as i32, ptr::null_mut());
let mime_fields: *mut mailmime_fields; ensure!(!encoding.is_null(), "failed to create encoding");
let encoding_type: libc::c_int;
let mut do_encoding: libc::c_int;
let content_type = if default_content_type.is_empty() {
"application/octet-stream"
} else {
default_content_type
};
content = new_mailmime_content_type(&content_type);
if content.is_null() {
ok_to_continue = false;
} else {
do_encoding = 1i32;
if (*(*content).ct_type).tp_type == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int {
let composite: *mut mailmime_composite_type;
composite = (*(*content).ct_type).tp_data.tp_composite_type;
match (*composite).ct_type {
1 => {
if strcasecmp(
(*content).ct_subtype,
b"rfc822\x00" as *const u8 as *const libc::c_char,
) == 0i32
{
do_encoding = 0i32
} }
} let mime_fields = mailmime_fields_new_with_data(
2 => do_encoding = 0i32,
_ => {}
}
}
if 0 != do_encoding {
if default_encoding == -1i32 {
encoding_type = MAILMIME_MECHANISM_BASE64 as libc::c_int
} else {
encoding_type = default_encoding
}
encoding = mailmime_mechanism_new(encoding_type, ptr::null_mut());
if encoding.is_null() {
ok_to_continue = false;
}
}
if ok_to_continue {
mime_fields = mailmime_fields_new_with_data(
encoding, encoding,
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
); );
if mime_fields.is_null() { ensure!(!mime_fields.is_null(), "internal mime error");
ok_to_continue = false;
} else { let mime = mailmime_new_empty(content, mime_fields);
mime = mailmime_new_empty(content, mime_fields); ensure!(!mime.is_null(), "internal mime error");
if mime.is_null() {
mailmime_fields_free(mime_fields); if (*mime).mm_type == MAILMIME_SINGLE as libc::c_int {
mailmime_content_free(content); if !data.is_null() && data_bytes > 0 {
} else {
if !data.is_null()
&& data_bytes > 0
&& (*mime).mm_type == MAILMIME_SINGLE as libc::c_int
{
mailmime_set_body_text(mime, data as *mut libc::c_char, data_bytes); mailmime_set_body_text(mime, data as *mut libc::c_char, data_bytes);
} }
return mime;
} }
return Ok(mime);
} }
} }
}
if ok_to_continue == false {
if !encoding.is_null() {
mailmime_mechanism_free(encoding);
}
if !content.is_null() {
mailmime_content_free(content);
}
}
ptr::null_mut()
}
/// Load public key from database or generate a new one. /// Load public key from database or generate a new one.
/// ///

View File

@@ -5,6 +5,7 @@ use crate::error::Error;
use mmime::clist::*; use mmime::clist::*;
use mmime::mailimf_types::*; use mmime::mailimf_types::*;
use mmime::mailimf_types_helper::*; use mmime::mailimf_types_helper::*;
use mmime::mailmime::*;
use mmime::mailmime_disposition::*; use mmime::mailmime_disposition::*;
use mmime::mailmime_types::*; use mmime::mailmime_types::*;
use mmime::mailmime_types_helper::*; use mmime::mailmime_types_helper::*;
@@ -60,7 +61,7 @@ pub fn build_body_text(text: &str) -> Result<*mut mailmime, Error> {
let mime_fields: *mut mailmime_fields; let mime_fields: *mut mailmime_fields;
let message_part: *mut mailmime; let message_part: *mut mailmime;
let content = new_mailmime_content_type("text/plain"); let content = new_content_type("text/plain")?;
append_ct_param(content, "charset", "utf-8")?; append_ct_param(content, "charset", "utf-8")?;
unsafe { unsafe {
@@ -92,18 +93,15 @@ pub fn append_ct_param(
Ok(()) Ok(())
} }
pub fn new_mailmime_content_type(content_type: &str) -> *mut mailmime_content { pub fn new_content_type(content_type: &str) -> Result<*mut mailmime_content, Error> {
let ct = CString::new(content_type).unwrap(); let ct = CString::new(content_type).unwrap();
let content: *mut mailmime_content; let content: *mut mailmime_content;
// mailmime_content_new_with_str only parses but does not retain/own ct // mailmime_content_new_with_str only parses but does not retain/own ct
//
unsafe { unsafe {
content = mailmime_content_new_with_str(ct.as_ptr()); content = mailmime_content_new_with_str(ct.as_ptr());
} }
if content.is_null() { ensure!(!content.is_null(), "mailimf failed to allocate");
panic!("mailimf failed to allocate"); Ok(content)
}
content
} }
pub fn set_body_text(part: *mut mailmime, text: &str) -> Result<(), Error> { pub fn set_body_text(part: *mut mailmime, text: &str) -> Result<(), Error> {
@@ -116,3 +114,39 @@ pub fn set_body_text(part: *mut mailmime, text: &str) -> Result<(), Error> {
} }
Ok(()) Ok(())
} }
pub fn content_type_needs_encoding(content: *const mailmime_content) -> bool {
unsafe {
if (*(*content).ct_type).tp_type == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int {
let composite = (*(*content).ct_type).tp_data.tp_composite_type;
match (*composite).ct_type as u32 {
MAILMIME_COMPOSITE_TYPE_MESSAGE => as_str((*content).ct_subtype) != "rfc822",
MAILMIME_COMPOSITE_TYPE_MULTIPART => false,
_ => false,
}
} else {
true
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_needs_encoding() {
assert!(content_type_needs_encoding(
new_content_type("text/plain").unwrap()
));
assert!(content_type_needs_encoding(
new_content_type("application/octect-stream").unwrap()
));
assert!(!content_type_needs_encoding(
new_content_type("multipart/encrypted").unwrap()
));
assert!(content_type_needs_encoding(
new_content_type("application/pgp-encrypted").unwrap()
));
}
}