From cb6c8ac78bd18a4fafdce1869ca79e7d2e39042b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 18 Aug 2019 21:26:53 +0200 Subject: [PATCH] refactor(msg): use rust based allocations --- deltachat-ffi/deltachat.h | 1 - deltachat-ffi/src/lib.rs | 158 +++++---- examples/repl/cmdline.rs | 53 ++- src/chat.rs | 267 ++++++-------- src/chatlist.rs | 31 +- src/dc_imex.rs | 39 +-- src/dc_location.rs | 16 +- src/dc_mimefactory.rs | 709 +++++++++++++++++++------------------- src/dc_move.rs | 42 ++- src/dc_msg.rs | 650 +++++++++++++--------------------- src/dc_securejoin.rs | 27 +- src/job.rs | 214 +++++------- src/lib.rs | 2 +- 13 files changed, 982 insertions(+), 1227 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index f0e3d2f98..26e17d872 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -505,7 +505,6 @@ int dc_chat_is_sending_locations (const dc_chat_t*); dc_msg_t* dc_msg_new (dc_context_t*, int viewtype); void dc_msg_unref (dc_msg_t*); -void dc_msg_empty (dc_msg_t*); uint32_t dc_msg_get_id (const dc_msg_t*); uint32_t dc_msg_get_from_id (const dc_msg_t*); uint32_t dc_msg_get_chat_id (const dc_msg_t*); diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 5d65e75d7..1c51fdefe 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -354,12 +354,13 @@ pub unsafe extern "C" fn dc_get_chat_id_by_contact_id( pub unsafe extern "C" fn dc_prepare_msg( context: *mut dc_context_t, chat_id: u32, - msg: *mut dc_msg::dc_msg_t, + msg: *mut dc_msg_t, ) -> u32 { assert!(!context.is_null()); assert!(!msg.is_null()); - let context = &*context; + let context = &mut *context; + let msg = &mut *msg; chat::prepare_msg(context, chat_id, msg) .unwrap_or_log_default(context, "Failed to prepare message") } @@ -368,11 +369,12 @@ pub unsafe extern "C" fn dc_prepare_msg( pub unsafe extern "C" fn dc_send_msg( context: *mut dc_context_t, chat_id: u32, - msg: *mut dc_msg::dc_msg_t, + msg: *mut dc_msg_t, ) -> u32 { assert!(!context.is_null()); assert!(!msg.is_null()); - let context = &*context; + let context = &mut *context; + let msg = &mut *msg; chat::send_msg(context, chat_id, msg).unwrap_or_log_default(context, "Failed to send message") } @@ -396,10 +398,11 @@ pub unsafe extern "C" fn dc_send_text_msg( pub unsafe extern "C" fn dc_set_draft( context: *mut dc_context_t, chat_id: u32, - msg: *mut dc_msg::dc_msg_t, + msg: *mut dc_msg_t, ) { assert!(!context.is_null()); let context = &*context; + let msg = if msg.is_null() { None } else { Some(&mut *msg) }; chat::set_draft(context, chat_id, msg) } @@ -408,11 +411,11 @@ pub unsafe extern "C" fn dc_set_draft( pub unsafe extern "C" fn dc_get_draft<'a>( context: *mut dc_context_t, chat_id: u32, -) -> *mut dc_msg::dc_msg_t<'a> { +) -> *mut dc_msg_t<'a> { assert!(!context.is_null()); let context = &*context; - chat::get_draft(context, chat_id) + chat::get_draft(context, chat_id).into_raw() } #[no_mangle] @@ -778,11 +781,11 @@ pub unsafe extern "C" fn dc_star_msgs( pub unsafe extern "C" fn dc_get_msg<'a>( context: *mut dc_context_t, msg_id: u32, -) -> *mut dc_msg::dc_msg_t<'a> { +) -> *mut dc_msg_t<'a> { assert!(!context.is_null()); let context = &*context; - dc_msg::dc_get_msg(context, msg_id) + dc_msg::dc_get_msg(context, msg_id).into_raw() } #[no_mangle] @@ -1398,299 +1401,325 @@ pub unsafe extern "C" fn dc_chat_is_sending_locations(chat: *mut dc_chat_t) -> l // dc_msg_t #[no_mangle] -pub type dc_msg_t<'a> = dc_msg::dc_msg_t<'a>; +pub type dc_msg_t<'a> = dc_msg::Message<'a>; #[no_mangle] pub unsafe extern "C" fn dc_msg_new<'a>( context: *mut dc_context_t, viewtype: libc::c_int, -) -> *mut dc_msg::dc_msg_t<'a> { +) -> *mut dc_msg_t<'a> { assert!(!context.is_null()); let context = &*context; let viewtype = from_prim(viewtype).expect(&format!("invalid viewtype = {}", viewtype)); - dc_msg::dc_msg_new(context, viewtype) + Box::into_raw(Box::new(dc_msg::dc_msg_new(context, viewtype))) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_unref(msg: *mut dc_msg::dc_msg_t) { +pub unsafe extern "C" fn dc_msg_unref(msg: *mut dc_msg_t) { assert!(!msg.is_null()); - dc_msg::dc_msg_unref(msg) + Box::from_raw(msg); } #[no_mangle] -pub unsafe extern "C" fn dc_msg_empty(msg: *mut dc_msg::dc_msg_t) { - assert!(!msg.is_null()); - - dc_msg::dc_msg_empty(msg) -} - -#[no_mangle] -pub unsafe extern "C" fn dc_msg_get_id(msg: *mut dc_msg::dc_msg_t) -> u32 { +pub unsafe extern "C" fn dc_msg_get_id(msg: *mut dc_msg_t) -> u32 { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_id(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_from_id(msg: *mut dc_msg::dc_msg_t) -> u32 { +pub unsafe extern "C" fn dc_msg_get_from_id(msg: *mut dc_msg_t) -> u32 { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_from_id(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_chat_id(msg: *mut dc_msg::dc_msg_t) -> u32 { +pub unsafe extern "C" fn dc_msg_get_chat_id(msg: *mut dc_msg_t) -> u32 { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_chat_id(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_viewtype(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_get_viewtype(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_viewtype(msg) .to_i64() .expect("impossible: Viewtype -> i64 conversion failed") as libc::c_int } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_state(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_get_state(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_state(msg) as libc::c_int } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_timestamp(msg: *mut dc_msg::dc_msg_t) -> i64 { +pub unsafe extern "C" fn dc_msg_get_timestamp(msg: *mut dc_msg_t) -> i64 { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_timestamp(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_received_timestamp(msg: *mut dc_msg::dc_msg_t) -> i64 { +pub unsafe extern "C" fn dc_msg_get_received_timestamp(msg: *mut dc_msg_t) -> i64 { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_received_timestamp(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_sort_timestamp(msg: *mut dc_msg::dc_msg_t) -> i64 { +pub unsafe extern "C" fn dc_msg_get_sort_timestamp(msg: *mut dc_msg_t) -> i64 { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_sort_timestamp(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_text(msg: *mut dc_msg::dc_msg_t) -> *mut libc::c_char { +pub unsafe extern "C" fn dc_msg_get_text(msg: *mut dc_msg_t) -> *mut libc::c_char { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_text(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_file(msg: *mut dc_msg::dc_msg_t) -> *mut libc::c_char { +pub unsafe extern "C" fn dc_msg_get_file(msg: *mut dc_msg_t) -> *mut libc::c_char { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_file(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_filename(msg: *mut dc_msg::dc_msg_t) -> *mut libc::c_char { +pub unsafe extern "C" fn dc_msg_get_filename(msg: *mut dc_msg_t) -> *mut libc::c_char { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_filename(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_filemime(msg: *mut dc_msg::dc_msg_t) -> *mut libc::c_char { +pub unsafe extern "C" fn dc_msg_get_filemime(msg: *mut dc_msg_t) -> *mut libc::c_char { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_filemime(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_filebytes(msg: *mut dc_msg::dc_msg_t) -> u64 { +pub unsafe extern "C" fn dc_msg_get_filebytes(msg: *mut dc_msg_t) -> u64 { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_filebytes(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_width(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_get_width(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_width(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_height(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_get_height(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_height(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_duration(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_get_duration(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_duration(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_showpadlock(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_get_showpadlock(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_showpadlock(msg) } #[no_mangle] pub unsafe extern "C" fn dc_msg_get_summary<'a>( - msg: *mut dc_msg::dc_msg_t<'a>, + msg: *mut dc_msg_t<'a>, chat: *mut dc_chat_t<'a>, ) -> *mut dc_lot_t { assert!(!msg.is_null()); let chat = if chat.is_null() { None } else { Some(&*chat) }; + let msg = &mut *msg; + let lot = dc_msg::dc_msg_get_summary(msg, chat); Box::into_raw(Box::new(lot)) } #[no_mangle] pub unsafe extern "C" fn dc_msg_get_summarytext( - msg: *mut dc_msg::dc_msg_t, + msg: *mut dc_msg_t, approx_characters: libc::c_int, ) -> *mut libc::c_char { assert!(!msg.is_null()); + let msg = &mut *msg; dc_msg::dc_msg_get_summarytext(msg, approx_characters.try_into().unwrap()) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_has_deviating_timestamp(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_has_deviating_timestamp(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_has_deviating_timestamp(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_has_location(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_has_location(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_has_location(msg) as libc::c_int } #[no_mangle] -pub unsafe extern "C" fn dc_msg_is_sent(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_is_sent(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_is_sent(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_is_starred(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_is_starred(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_is_starred(msg).into() } #[no_mangle] -pub unsafe extern "C" fn dc_msg_is_forwarded(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_is_forwarded(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_is_forwarded(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_is_info(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_is_info(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_is_info(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_is_increation(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_is_increation(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_is_increation(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_is_setupmessage(msg: *mut dc_msg::dc_msg_t) -> libc::c_int { +pub unsafe extern "C" fn dc_msg_is_setupmessage(msg: *mut dc_msg_t) -> libc::c_int { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_is_setupmessage(msg) as libc::c_int } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_setupcodebegin( - msg: *mut dc_msg::dc_msg_t, -) -> *mut libc::c_char { +pub unsafe extern "C" fn dc_msg_get_setupcodebegin(msg: *mut dc_msg_t) -> *mut libc::c_char { assert!(!msg.is_null()); + let msg = &*msg; dc_msg::dc_msg_get_setupcodebegin(msg) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_set_text(msg: *mut dc_msg::dc_msg_t, text: *mut libc::c_char) { +pub unsafe extern "C" fn dc_msg_set_text(msg: *mut dc_msg_t, text: *mut libc::c_char) { assert!(!msg.is_null()); + let msg = &mut *msg; // TODO: {text} equal to NULL is treated as "", which is strange. Does anyone rely on it? dc_msg::dc_msg_set_text(msg, text) } #[no_mangle] pub unsafe extern "C" fn dc_msg_set_file( - msg: *mut dc_msg::dc_msg_t, + msg: *mut dc_msg_t, file: *mut libc::c_char, filemime: *mut libc::c_char, ) { assert!(!msg.is_null()); + let msg = &mut *msg; dc_msg::dc_msg_set_file(msg, file, filemime) } #[no_mangle] pub unsafe extern "C" fn dc_msg_set_dimension( - msg: *mut dc_msg::dc_msg_t, + msg: *mut dc_msg_t, width: libc::c_int, height: libc::c_int, ) { assert!(!msg.is_null()); + let msg = &mut *msg; dc_msg::dc_msg_set_dimension(msg, width, height) } #[no_mangle] -pub unsafe extern "C" fn dc_msg_set_duration(msg: *mut dc_msg::dc_msg_t, duration: libc::c_int) { +pub unsafe extern "C" fn dc_msg_set_duration(msg: *mut dc_msg_t, duration: libc::c_int) { assert!(!msg.is_null()); + let msg = &mut *msg; dc_msg::dc_msg_set_duration(msg, duration) } #[no_mangle] pub unsafe extern "C" fn dc_msg_set_location( - msg: *mut dc_msg::dc_msg_t, + msg: *mut dc_msg_t, latitude: libc::c_double, longitude: libc::c_double, ) { assert!(!msg.is_null()); + let msg = &mut *msg; dc_msg::dc_msg_set_location(msg, latitude, longitude) } #[no_mangle] pub unsafe extern "C" fn dc_msg_latefiling_mediasize( - msg: *mut dc_msg::dc_msg_t, + msg: *mut dc_msg_t, width: libc::c_int, height: libc::c_int, duration: libc::c_int, ) { assert!(!msg.is_null()); + let msg = &mut *msg; dc_msg::dc_msg_latefiling_mediasize(msg, width, height, duration) } @@ -1869,7 +1898,7 @@ fn as_opt_str<'a>(s: *const libc::c_char) -> Option<&'a str> { Some(dc_tools::as_str(s)) } -pub trait ResultExt { +pub trait ResultExt { fn unwrap_or_log_default(self, context: &context::Context, message: &str) -> T; fn log_err(&self, context: &context::Context, message: &str); } @@ -1898,3 +1927,16 @@ unsafe fn strdup_opt(s: Option>) -> *mut libc::c_char { None => ptr::null_mut(), } } + +pub trait ResultNullableExt { + fn into_raw(self) -> *mut T; +} + +impl ResultNullableExt for Result { + fn into_raw(self) -> *mut T { + match self { + Ok(t) => Box::into_raw(Box::new(t)), + Err(_) => ptr::null_mut(), + } + } +} diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index d1454e0e3..31656dede 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -13,6 +13,7 @@ use deltachat::dc_location::*; use deltachat::dc_msg::*; use deltachat::dc_receive_imf::*; use deltachat::dc_tools::*; +use deltachat::error::Error; use deltachat::job::*; use deltachat::lot::LotState; use deltachat::peerstate::*; @@ -210,7 +211,7 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int success } -unsafe fn log_msg(context: &Context, prefix: impl AsRef, msg: *mut dc_msg_t) { +unsafe fn log_msg(context: &Context, prefix: impl AsRef, msg: &Message) { let contact = Contact::get_by_id(context, dc_msg_get_from_id(msg)).expect("invalid contact"); let contact_name = contact.get_name(); let contact_id = contact.get_id(); @@ -260,7 +261,7 @@ unsafe fn log_msg(context: &Context, prefix: impl AsRef, msg: *mut dc_msg_t free(msgtext as *mut libc::c_void); } -unsafe fn log_msglist(context: &Context, msglist: &Vec) { +unsafe fn log_msglist(context: &Context, msglist: &Vec) -> Result<(), Error> { let mut lines_out = 0; for &msg_id in msglist { if msg_id == 9 as libc::c_uint { @@ -279,9 +280,8 @@ unsafe fn log_msglist(context: &Context, msglist: &Vec) { ); lines_out += 1 } - let msg = dc_get_msg(context, msg_id); - log_msg(context, "Msg", msg); - dc_msg_unref(msg); + let msg = dc_get_msg(context, msg_id)?; + log_msg(context, "Msg", &msg); } } if lines_out > 0 { @@ -290,6 +290,7 @@ unsafe fn log_msglist(context: &Context, msglist: &Vec) { 0, "--------------------------------------------------------------------------------" ); } + Ok(()) } unsafe fn log_contactlist(context: &Context, contacts: &Vec) { @@ -496,9 +497,9 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E "get-setupcodebegin" => { ensure!(!arg1.is_empty(), "Argument missing."); let msg_id: u32 = arg1.parse()?; - let msg: *mut dc_msg_t = dc_get_msg(context, msg_id); - if dc_msg_is_setupmessage(msg) { - let setupcodebegin = dc_msg_get_setupcodebegin(msg); + let msg = dc_get_msg(context, msg_id)?; + if dc_msg_is_setupmessage(&msg) { + let setupcodebegin = dc_msg_get_setupcodebegin(&msg); println!( "The setup code for setup message Msg#{} starts with: {}", msg_id, @@ -508,7 +509,6 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E } else { bail!("Msg#{} is no setup message.", msg_id,); } - dc_msg_unref(msg); } "continue-key-transfer" => { ensure!( @@ -688,12 +688,11 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E "" }, ); - log_msglist(context, &msglist); - let draft = chat::get_draft(context, sel_chat.get_id()); - if !draft.is_null() { - log_msg(context, "Draft", draft); - dc_msg_unref(draft); + log_msglist(context, &msglist)?; + if let Ok(draft) = chat::get_draft(context, sel_chat.get_id()) { + log_msg(context, "Draft", &draft); } + println!( "{} messages.", chat::get_msg_cnt(context, sel_chat.get_id()) @@ -861,7 +860,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E ensure!(sel_chat.is_some(), "No chat selected."); ensure!(!arg1.is_empty() && !arg2.is_empty(), "No file given."); - let msg_0 = dc_msg_new( + let mut msg = dc_msg_new( context, if arg0 == "sendimage" { Viewtype::Image @@ -869,10 +868,9 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E Viewtype::File }, ); - dc_msg_set_file(msg_0, arg1_c, 0 as *const libc::c_char); - dc_msg_set_text(msg_0, arg2_c); - chat::send_msg(context, sel_chat.as_ref().unwrap().get_id(), msg_0)?; - dc_msg_unref(msg_0); + dc_msg_set_file(&mut msg, arg1_c, 0 as *const libc::c_char); + dc_msg_set_text(&mut msg, arg2_c); + chat::send_msg(context, sel_chat.as_ref().unwrap().get_id(), &mut msg)?; } "listmsgs" => { ensure!(!arg1.is_empty(), "Argument missing."); @@ -885,24 +883,23 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E let msglist = dc_search_msgs(context, chat, arg1_c); - log_msglist(context, &msglist); + log_msglist(context, &msglist)?; println!("{} messages.", msglist.len()); } "draft" => { ensure!(sel_chat.is_some(), "No chat selected."); if !arg1.is_empty() { - let draft_0 = dc_msg_new(context, Viewtype::Text); - dc_msg_set_text(draft_0, arg1_c); - chat::set_draft(context, sel_chat.as_ref().unwrap().get_id(), draft_0); - dc_msg_unref(draft_0); - println!("Draft saved."); - } else { + let mut draft = dc_msg_new(context, Viewtype::Text); + dc_msg_set_text(&mut draft, arg1_c); chat::set_draft( context, sel_chat.as_ref().unwrap().get_id(), - 0 as *mut dc_msg_t, + Some(&mut draft), ); + println!("Draft saved."); + } else { + chat::set_draft(context, sel_chat.as_ref().unwrap().get_id(), None); println!("Draft deleted."); } } @@ -949,7 +946,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E "listfresh" => { let msglist = dc_get_fresh_msgs(context); - log_msglist(context, &msglist); + log_msglist(context, &msglist)?; print!("{} fresh messages.", msglist.len()); } "forward" => { diff --git a/src/chat.rs b/src/chat.rs index a86d988cd..add8245d6 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -272,7 +272,7 @@ impl<'a> Chat<'a> { unsafe fn prepare_msg_raw( &mut self, context: &Context, - msg: *mut dc_msg_t, + msg: &mut Message, timestamp: i64, ) -> Result { let mut do_guarantee_e2ee: libc::c_int; @@ -351,11 +351,7 @@ impl<'a> Chat<'a> { .get_config_int(context, "e2ee_enabled") .unwrap_or_else(|| 1); if 0 != e2ee_enabled - && (*msg) - .param - .get_int(Param::ForcePlaintext) - .unwrap_or_default() - == 0 + && msg.param.get_int(Param::ForcePlaintext).unwrap_or_default() == 0 { let mut can_encrypt = 1; let mut all_mutual = 1; @@ -409,9 +405,9 @@ impl<'a> Chat<'a> { } } if 0 != do_guarantee_e2ee { - (*msg).param.set_int(Param::GuranteeE2ee, 1); + msg.param.set_int(Param::GuranteeE2ee, 1); } - (*msg).param.remove(Param::ErroneousE2ee); + msg.param.remove(Param::ErroneousE2ee); if !self.is_self_talk() && self .get_parent_mime_headers( @@ -466,7 +462,7 @@ impl<'a> Chat<'a> { // add independent location to database - if (*msg).param.exists(Param::SetLatitude) { + if msg.param.exists(Param::SetLatitude) { if sql::execute( context, &context.sql, @@ -477,14 +473,8 @@ impl<'a> Chat<'a> { timestamp, DC_CONTACT_ID_SELF as i32, self.id as i32, - (*msg) - .param - .get_float(Param::SetLatitude) - .unwrap_or_default(), - (*msg) - .param - .get_float(Param::SetLongitude) - .unwrap_or_default(), + msg.param.get_float(Param::SetLatitude).unwrap_or_default(), + msg.param.get_float(Param::SetLongitude).unwrap_or_default(), ], ) .is_ok() @@ -513,11 +503,11 @@ impl<'a> Chat<'a> { 1i32, to_id as i32, timestamp, - (*msg).type_0, - (*msg).state, - (*msg).text, - (*msg).param.to_string(), - (*msg).hidden, + msg.type_0, + msg.state, + msg.text, + msg.param.to_string(), + msg.hidden, to_string(new_in_reply_to), to_string(new_references), location_id as i32, @@ -574,27 +564,20 @@ impl<'a> Chat<'a> { pub fn create_by_msg_id(context: &Context, msg_id: u32) -> Result { let mut chat_id = 0; let mut send_event = false; - let msg = unsafe { dc_msg_new_untyped(context) }; - if dc_msg_load_from_db(msg, context, msg_id) { - if let Ok(chat) = Chat::load_from_db(context, unsafe { (*msg).chat_id }) { + if let Ok(msg) = dc_msg_load_from_db(context, msg_id) { + if let Ok(chat) = Chat::load_from_db(context, msg.chat_id) { if chat.id > DC_CHAT_ID_LAST_SPECIAL as u32 { chat_id = chat.id; if chat.blocked != Blocked::Not { unblock(context, chat.id); send_event = true; } - Contact::scaleup_origin_by_id( - context, - unsafe { (*msg).from_id }, - Origin::CreateChat, - ); + Contact::scaleup_origin_by_id(context, msg.from_id, Origin::CreateChat); } } } - unsafe { dc_msg_unref(msg) }; - if send_event { context.call_cb(Event::MSGS_CHANGED, 0, 0); } @@ -721,20 +704,19 @@ pub fn get_by_contact_id(context: &Context, contact_id: u32) -> Result( context: &'a Context, chat_id: u32, - mut msg: *mut dc_msg_t<'a>, + msg: &mut Message<'a>, ) -> Result { - ensure!(!msg.is_null(), "No message provided"); ensure!( chat_id > DC_CHAT_ID_LAST_SPECIAL as u32, "Cannot prepare message for special chat" ); - unsafe { (*msg).state = MessageState::OutPreparing }; + msg.state = MessageState::OutPreparing; let msg_id = prepare_msg_common(context, chat_id, msg)?; context.call_cb( Event::MSGS_CHANGED, - unsafe { (*msg).chat_id as uintptr_t }, - unsafe { (*msg).id as uintptr_t }, + msg.chat_id as uintptr_t, + msg.id as uintptr_t, ); Ok(msg_id) @@ -755,12 +737,8 @@ pub fn msgtype_has_file(msgtype: Viewtype) -> bool { fn prepare_msg_common<'a>( context: &'a Context, chat_id: u32, - msg: *mut dc_msg_t<'a>, + msg: &mut Message<'a>, ) -> Result { - ensure!(!msg.is_null(), "No message provided"); - - let msg = unsafe { &mut *msg }; - msg.id = 0; msg.context = context; @@ -881,39 +859,37 @@ pub fn unarchive(context: &Context, chat_id: u32) -> Result<(), Error> { pub unsafe fn send_msg<'a>( context: &'a Context, chat_id: u32, - msg: *mut dc_msg_t<'a>, + msg: &mut Message<'a>, ) -> Result { - ensure!(!msg.is_null(), "Invalid message"); - - if (*msg).state != MessageState::OutPreparing { + if msg.state != MessageState::OutPreparing { // automatically prepare normal messages prepare_msg_common(context, chat_id, msg)?; } else { // update message state of separately prepared messages ensure!( - chat_id == 0 || chat_id == (*msg).chat_id, + chat_id == 0 || chat_id == msg.chat_id, "Inconsistent chat ID" ); - dc_update_msg_state(context, (*msg).id, MessageState::OutPending); + dc_update_msg_state(context, msg.id, MessageState::OutPending); } ensure!( - job_send_msg(context, (*msg).id) != 0, + job_send_msg(context, msg.id) != 0, "Failed to initiate send job" ); context.call_cb( Event::MSGS_CHANGED, - (*msg).chat_id as uintptr_t, - (*msg).id as uintptr_t, + msg.chat_id as uintptr_t, + msg.id as uintptr_t, ); - if (*msg).param.exists(Param::SetLatitude) { + if msg.param.exists(Param::SetLatitude) { context.call_cb(Event::LOCATION_CHANGED, DC_CONTACT_ID_SELF, 0); } if 0 == chat_id { - let forwards = (*msg).param.get(Param::PrepForwards); + let forwards = msg.param.get(Param::PrepForwards); if let Some(forwards) = forwards { for forward in forwards.split(' ') { let id: i32 = forward.parse().unwrap_or_default(); @@ -921,20 +897,18 @@ pub unsafe fn send_msg<'a>( // avoid hanging if user tampers with db break; } else { - let copy = dc_get_msg(context, id as u32); - if !copy.is_null() { + if let Ok(mut copy) = dc_get_msg(context, id as u32) { // TODO: handle cleanup and return early instead - send_msg(context, 0, copy).unwrap(); + send_msg(context, 0, &mut copy).unwrap(); } - dc_msg_unref(copy); } } - (*msg).param.remove(Param::PrepForwards); + msg.param.remove(Param::PrepForwards); dc_msg_save_param_to_disk(msg); } } - Ok((*msg).id) + Ok(msg.id) } pub unsafe fn send_text_msg( @@ -949,11 +923,12 @@ pub unsafe fn send_text_msg( ); let mut msg = dc_msg_new(context, Viewtype::Text); - (*msg).text = Some(text_to_send); - send_msg(context, chat_id, msg) + msg.text = Some(text_to_send); + send_msg(context, chat_id, &mut msg) } -pub unsafe fn set_draft(context: &Context, chat_id: u32, msg: *mut dc_msg_t) { +// passing `None` as message jsut deletes the draft +pub unsafe fn set_draft(context: &Context, chat_id: u32, msg: Option<&mut Message>) { if chat_id <= DC_CHAT_ID_LAST_SPECIAL as u32 { return; } @@ -962,31 +937,32 @@ pub unsafe fn set_draft(context: &Context, chat_id: u32, msg: *mut dc_msg_t) { }; } +// similar to as dc_set_draft() but does not emit an event #[allow(non_snake_case)] -unsafe fn set_draft_raw(context: &Context, chat_id: u32, msg: *mut dc_msg_t) -> bool { +unsafe fn set_draft_raw(context: &Context, chat_id: u32, mut msg: Option<&mut Message>) -> bool { let mut OK_TO_CONTINUE = true; - // similar to as dc_set_draft() but does not emit an event - let prev_draft_msg_id: u32; + let mut sth_changed = false; - prev_draft_msg_id = get_draft_msg_id(context, chat_id); + let prev_draft_msg_id = get_draft_msg_id(context, chat_id); if 0 != prev_draft_msg_id { dc_delete_msg_from_db(context, prev_draft_msg_id); sth_changed = true; } - // save new draft - if !msg.is_null() { - if (*msg).type_0 == Viewtype::Text { - OK_TO_CONTINUE = (*msg).text.as_ref().map_or(false, |s| !s.is_empty()); - } else if msgtype_has_file((*msg).type_0) { - if let Some(path_filename) = (*msg).param.get(Param::File) { + + if let Some(ref mut msg) = msg { + // save new draft + if msg.type_0 == Viewtype::Text { + OK_TO_CONTINUE = msg.text.as_ref().map_or(false, |s| !s.is_empty()); + } else if msgtype_has_file(msg.type_0) { + if let Some(path_filename) = msg.param.get(Param::File) { let mut path_filename = path_filename.to_string(); if 0 != dc_msg_is_increation(msg) && !dc_is_blobdir_path(context, &path_filename) { OK_TO_CONTINUE = false; } else if !dc_make_rel_and_copy(context, &mut path_filename) { OK_TO_CONTINUE = false; } else { - (*msg).param.set(Param::File, path_filename); + msg.param.set(Param::File, path_filename); } } } else { @@ -1002,10 +978,10 @@ unsafe fn set_draft_raw(context: &Context, chat_id: u32, msg: *mut dc_msg_t) -> chat_id as i32, 1, time(), - (*msg).type_0, + msg.type_0, MessageState::OutDraft, - (*msg).text.as_ref().map(String::as_str).unwrap_or(""), - (*msg).param.to_string(), + msg.text.as_ref().map(String::as_str).unwrap_or(""), + msg.param.to_string(), 1, ], ) @@ -1015,7 +991,6 @@ unsafe fn set_draft_raw(context: &Context, chat_id: u32, msg: *mut dc_msg_t) -> } } } - sth_changed } @@ -1031,21 +1006,12 @@ fn get_draft_msg_id(context: &Context, chat_id: u32) -> u32 { .unwrap_or_default() as u32 } -pub unsafe fn get_draft(context: &Context, chat_id: u32) -> *mut dc_msg_t { - if chat_id <= DC_CHAT_ID_LAST_SPECIAL as u32 { - return ptr::null_mut(); - } +pub unsafe fn get_draft(context: &Context, chat_id: u32) -> Result { + ensure!(chat_id > DC_CHAT_ID_LAST_SPECIAL as u32, "Invalid chat ID"); let draft_msg_id = get_draft_msg_id(context, chat_id); - if draft_msg_id == 0 { - return ptr::null_mut(); - } - let draft_msg = dc_msg_new_untyped(context); - if !dc_msg_load_from_db(draft_msg, context, draft_msg_id) { - dc_msg_unref(draft_msg); - return ptr::null_mut(); - } + ensure!(draft_msg_id != 0, "Invalid draft message ID"); - draft_msg + dc_msg_load_from_db(context, draft_msg_id) } pub fn get_chat_msgs(context: &Context, chat_id: u32, flags: u32, marker1before: u32) -> Vec { @@ -1235,15 +1201,15 @@ pub unsafe fn get_next_media( msg_type3: Viewtype, ) -> u32 { let mut ret = 0; - let msg: *mut dc_msg_t = dc_msg_new_untyped(context); - if dc_msg_load_from_db(msg, context, curr_msg_id) { + + if let Ok(msg) = dc_msg_load_from_db(context, curr_msg_id) { let list = get_chat_media( context, - (*msg).chat_id, + msg.chat_id, if msg_type != Viewtype::Unknown { msg_type } else { - (*msg).type_0 + msg.type_0 }, msg_type2, msg_type3, @@ -1263,8 +1229,6 @@ pub unsafe fn get_next_media( } } } - dc_msg_unref(msg); - ret } @@ -1400,10 +1364,9 @@ pub unsafe fn create_group_chat( if chat_id != 0 { if 0 != add_to_chat_contacts_table(context, chat_id, 1) { - let draft_msg = dc_msg_new(context, Viewtype::Text); - dc_msg_set_text(draft_msg, draft_txt.as_ptr()); - set_draft_raw(context, chat_id, draft_msg); - dc_msg_unref(draft_msg); + let mut draft_msg = dc_msg_new(context, Viewtype::Text); + dc_msg_set_text(&mut draft_msg, draft_txt.as_ptr()); + set_draft_raw(context, chat_id, Some(&mut draft_msg)); } context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t); @@ -1506,21 +1469,21 @@ pub unsafe fn add_contact_to_chat_ex( } if OK_TO_CONTINUE { if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 { - (*msg).type_0 = Viewtype::Text; - (*msg).text = Some(context.stock_system_msg( + msg.type_0 = Viewtype::Text; + msg.text = Some(context.stock_system_msg( StockMessage::MsgAddMember, contact.get_addr(), "", DC_CONTACT_ID_SELF as u32, )); - (*msg).param.set_int(Param::Cmd, 4); - (*msg).param.set(Param::Arg, contact.get_addr()); - (*msg).param.set_int(Param::Arg2, flags); - (*msg).id = send_msg(context, chat_id, msg).unwrap_or_default(); + msg.param.set_int(Param::Cmd, 4); + msg.param.set(Param::Arg, contact.get_addr()); + msg.param.set_int(Param::Arg2, flags); + msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default(); context.call_cb( Event::MSGS_CHANGED, chat_id as uintptr_t, - (*msg).id as uintptr_t, + msg.id as uintptr_t, ); } context.call_cb(Event::MSGS_CHANGED, chat_id as uintptr_t, 0 as uintptr_t); @@ -1530,8 +1493,6 @@ pub unsafe fn add_contact_to_chat_ex( } } - dc_msg_unref(msg); - success } @@ -1619,30 +1580,30 @@ pub unsafe fn remove_contact_from_chat( /* we should respect this - whatever we send to the group, it gets discarded anyway! */ if let Ok(contact) = Contact::get_by_id(context, contact_id) { if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 { - (*msg).type_0 = Viewtype::Text; + msg.type_0 = Viewtype::Text; if contact.id == DC_CONTACT_ID_SELF as u32 { set_group_explicitly_left(context, chat.grpid).unwrap(); - (*msg).text = Some(context.stock_system_msg( + msg.text = Some(context.stock_system_msg( StockMessage::MsgGroupLeft, "", "", DC_CONTACT_ID_SELF as u32, )); } else { - (*msg).text = Some(context.stock_system_msg( + msg.text = Some(context.stock_system_msg( StockMessage::MsgDelMember, contact.get_addr(), "", DC_CONTACT_ID_SELF as u32, )); } - (*msg).param.set_int(Param::Cmd, 5); - (*msg).param.set(Param::Arg, contact.get_addr()); - (*msg).id = send_msg(context, chat_id, msg).unwrap_or_default(); + msg.param.set_int(Param::Cmd, 5); + msg.param.set(Param::Arg, contact.get_addr()); + msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default(); context.call_cb( Event::MSGS_CHANGED, chat_id as uintptr_t, - (*msg).id as uintptr_t, + msg.id as uintptr_t, ); } } @@ -1660,8 +1621,6 @@ pub unsafe fn remove_contact_from_chat( } } - dc_msg_unref(msg); - if !success { bail!("Failed to remove contact"); } @@ -1728,22 +1687,22 @@ pub unsafe fn set_chat_name( .is_ok() { if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 { - (*msg).type_0 = Viewtype::Text; - (*msg).text = Some(context.stock_system_msg( + msg.type_0 = Viewtype::Text; + msg.text = Some(context.stock_system_msg( StockMessage::MsgGrpName, &chat.name, new_name.as_ref(), DC_CONTACT_ID_SELF as u32, )); - (*msg).param.set_int(Param::Cmd, 2); + msg.param.set_int(Param::Cmd, 2); if !chat.name.is_empty() { - (*msg).param.set(Param::Arg, &chat.name); + msg.param.set(Param::Arg, &chat.name); } - (*msg).id = send_msg(context, chat_id, msg).unwrap_or_default(); + msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default(); context.call_cb( Event::MSGS_CHANGED, chat_id as uintptr_t, - (*msg).id as uintptr_t, + msg.id as uintptr_t, ); } context.call_cb( @@ -1756,8 +1715,6 @@ pub unsafe fn set_chat_name( } } - dc_msg_unref(msg); - if !success { bail!("Failed to set name"); } @@ -1806,12 +1763,12 @@ pub unsafe fn set_chat_profile_image( } if chat.update_param().is_ok() { if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 { - (*msg).param.set_int(Param::Cmd, 3); + msg.param.set_int(Param::Cmd, 3); if let Some(ref new_image_rel) = new_image_rel { - (*msg).param.set(Param::Arg, new_image_rel); + msg.param.set(Param::Arg, new_image_rel); } - (*msg).type_0 = Viewtype::Text; - (*msg).text = Some(context.stock_system_msg( + msg.type_0 = Viewtype::Text; + msg.text = Some(context.stock_system_msg( if new_image_rel.is_some() { StockMessage::MsgGrpImgChanged } else { @@ -1821,11 +1778,11 @@ pub unsafe fn set_chat_profile_image( "", DC_CONTACT_ID_SELF as u32, )); - (*msg).id = send_msg(context, chat_id, msg).unwrap_or_default(); + msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default(); context.call_cb( Event::MSGS_CHANGED, chat_id as uintptr_t, - (*msg).id as uintptr_t, + msg.id as uintptr_t, ); } context.call_cb( @@ -1838,8 +1795,6 @@ pub unsafe fn set_chat_profile_image( } } - dc_msg_unref(msg); - if !success { bail!("Failed to set profile image"); } @@ -1857,7 +1812,6 @@ pub unsafe fn forward_msgs( return; } - let msg = dc_msg_new_untyped(context); let mut created_db_entries = Vec::new(); let mut curr_timestamp: i64; @@ -1887,45 +1841,45 @@ pub unsafe fn forward_msgs( for id in ids { let src_msg_id = id; - if !dc_msg_load_from_db(msg, context, src_msg_id as u32) { + let msg = dc_msg_load_from_db(context, src_msg_id as u32); + if msg.is_err() { break; } - let original_param = (*msg).param.clone(); - if (*msg).from_id != DC_CONTACT_ID_SELF as u32 { - (*msg).param.set_int(Param::Forwarded, 1); + let mut msg = msg.unwrap(); + let original_param = msg.param.clone(); + if msg.from_id != DC_CONTACT_ID_SELF as u32 { + msg.param.set_int(Param::Forwarded, 1); } - (*msg).param.remove(Param::GuranteeE2ee); - (*msg).param.remove(Param::ForcePlaintext); - (*msg).param.remove(Param::Cmd); + msg.param.remove(Param::GuranteeE2ee); + msg.param.remove(Param::ForcePlaintext); + msg.param.remove(Param::Cmd); let new_msg_id: u32; - if (*msg).state == MessageState::OutPreparing { + if msg.state == MessageState::OutPreparing { let fresh9 = curr_timestamp; curr_timestamp = curr_timestamp + 1; new_msg_id = chat - .prepare_msg_raw(context, msg, fresh9) + .prepare_msg_raw(context, &mut msg, fresh9) .unwrap_or_default(); - let save_param = (*msg).param.clone(); - (*msg).param = original_param; - (*msg).id = src_msg_id as u32; + let save_param = msg.param.clone(); + msg.param = original_param; + msg.id = src_msg_id as u32; - if let Some(old_fwd) = (*msg).param.get(Param::PrepForwards) { + if let Some(old_fwd) = msg.param.get(Param::PrepForwards) { let new_fwd = format!("{} {}", old_fwd, new_msg_id); - (*msg).param.set(Param::PrepForwards, new_fwd); + msg.param.set(Param::PrepForwards, new_fwd); } else { - (*msg) - .param - .set(Param::PrepForwards, new_msg_id.to_string()); + msg.param.set(Param::PrepForwards, new_msg_id.to_string()); } - dc_msg_save_param_to_disk(msg); - (*msg).param = save_param; + dc_msg_save_param_to_disk(&mut msg); + msg.param = save_param; } else { - (*msg).state = MessageState::OutPending; + msg.state = MessageState::OutPending; let fresh10 = curr_timestamp; curr_timestamp = curr_timestamp + 1; new_msg_id = chat - .prepare_msg_raw(context, msg, fresh10) + .prepare_msg_raw(context, &mut msg, fresh10) .unwrap_or_default(); job_send_msg(context, new_msg_id); } @@ -1941,7 +1895,6 @@ pub unsafe fn forward_msgs( created_db_entries[i + 1] as uintptr_t, ); } - dc_msg_unref(msg); } pub fn get_chat_contact_cnt(context: &Context, chat_id: u32) -> libc::c_int { diff --git a/src/chatlist.rs b/src/chatlist.rs index 79848fa81..21aed4890 100644 --- a/src/chatlist.rs +++ b/src/chatlist.rs @@ -275,29 +275,36 @@ impl<'a> Chatlist<'a> { let mut lastcontact = None; let lastmsg = if 0 != lastmsg_id { - let lastmsg = dc_msg_new_untyped(self.context); - dc_msg_load_from_db(lastmsg, self.context, lastmsg_id); + if let Ok(lastmsg) = dc_msg_load_from_db(self.context, lastmsg_id) { + if lastmsg.from_id != 1 as libc::c_uint + && (chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup) + { + lastcontact = Contact::load_from_db(self.context, lastmsg.from_id).ok(); + } - if (*lastmsg).from_id != 1 as libc::c_uint - && (chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup) - { - lastcontact = Contact::load_from_db(self.context, (*lastmsg).from_id).ok(); + Some(lastmsg) + } else { + None } - lastmsg } else { - std::ptr::null_mut() + None }; if chat.id == DC_CHAT_ID_ARCHIVED_LINK as u32 { ret.text2 = None; - } else if lastmsg.is_null() || (*lastmsg).from_id == DC_CONTACT_ID_UNDEFINED as u32 { + } else if lastmsg.is_none() + || lastmsg.as_ref().unwrap().from_id == DC_CONTACT_ID_UNDEFINED as u32 + { ret.text2 = Some(self.context.stock_str(StockMessage::NoMessages).to_string()); } else { - ret.fill(lastmsg, chat, lastcontact.as_ref(), self.context); + ret.fill( + &mut lastmsg.unwrap(), + chat, + lastcontact.as_ref(), + self.context, + ); } - dc_msg_unref(lastmsg); - ret } } diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 55858e759..c76b333af 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -102,7 +102,7 @@ pub unsafe fn dc_imex_has_backup( pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char { let mut setup_file_name: *mut libc::c_char = ptr::null_mut(); - let mut msg: *mut dc_msg_t = ptr::null_mut(); + let mut msg: Message; if dc_alloc_ongoing(context) == 0 { return std::ptr::null_mut(); } @@ -140,14 +140,13 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char { { if let Ok(chat_id) = chat::create_by_contact_id(context, 1) { msg = dc_msg_new_untyped(context); - (*msg).type_0 = Viewtype::File; - (*msg).param.set(Param::File, as_str(setup_file_name)); + msg.type_0 = Viewtype::File; + msg.param.set(Param::File, as_str(setup_file_name)); - (*msg) - .param + msg.param .set(Param::MimeType, "application/autocrypt-setup"); - (*msg).param.set_int(Param::Cmd, 6); - (*msg).param.set_int(Param::ForcePlaintext, 2); + msg.param.set_int(Param::Cmd, 6); + msg.param.set_int(Param::ForcePlaintext, 2); if !context .running_state @@ -156,9 +155,7 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char { .unwrap() .shall_stop_ongoing { - if let Ok(msg_id) = chat::send_msg(context, chat_id, msg) { - dc_msg_unref(msg); - msg = ptr::null_mut(); + if let Ok(msg_id) = chat::send_msg(context, chat_id, &mut msg) { info!(context, 0, "Wait for setup message being sent ...",); loop { if context @@ -171,13 +168,12 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char { break; } std::thread::sleep(std::time::Duration::from_secs(1)); - msg = dc_get_msg(context, msg_id); - if 0 != dc_msg_is_sent(msg) { - info!(context, 0, "... setup message sent.",); - break; + if let Ok(msg) = dc_get_msg(context, msg_id) { + if 0 != dc_msg_is_sent(&msg) { + info!(context, 0, "... setup message sent.",); + break; + } } - dc_msg_unref(msg); - msg = 0 as *mut dc_msg_t } } } @@ -187,7 +183,6 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char { } } free(setup_file_name as *mut libc::c_void); - dc_msg_unref(msg); dc_free_ongoing(context); setup_code.strdup() @@ -284,18 +279,17 @@ pub unsafe fn dc_continue_key_transfer( setup_code: *const libc::c_char, ) -> libc::c_int { let mut success: libc::c_int = 0i32; - let mut msg: *mut dc_msg_t = ptr::null_mut(); let mut filename: *mut libc::c_char = ptr::null_mut(); let mut filecontent: *mut libc::c_char = ptr::null_mut(); let mut filebytes: size_t = 0i32 as size_t; let mut armored_key: *mut libc::c_char = ptr::null_mut(); let mut norm_sc: *mut libc::c_char = ptr::null_mut(); if !(msg_id <= 9i32 as libc::c_uint || setup_code.is_null()) { - msg = dc_get_msg(context, msg_id); - if msg.is_null() - || !dc_msg_is_setupmessage(msg) + let msg = dc_get_msg(context, msg_id); + if msg.is_err() + || !dc_msg_is_setupmessage(msg.as_ref().unwrap()) || { - filename = dc_msg_get_file(msg); + filename = dc_msg_get_file(msg.as_ref().unwrap()); filename.is_null() } || *filename.offset(0isize) as libc::c_int == 0i32 @@ -331,7 +325,6 @@ pub unsafe fn dc_continue_key_transfer( free(armored_key as *mut libc::c_void); free(filecontent as *mut libc::c_void); free(filename as *mut libc::c_void); - dc_msg_unref(msg); free(norm_sc as *mut libc::c_void); success diff --git a/src/dc_location.rs b/src/dc_location.rs index eb3744762..7dc265ff6 100644 --- a/src/dc_location.rs +++ b/src/dc_location.rs @@ -70,7 +70,7 @@ impl dc_kml_t { // location streaming pub unsafe fn dc_send_locations_to_chat(context: &Context, chat_id: uint32_t, seconds: i64) { let now = time(); - let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t; + let mut msg: Message; let is_sending_locations_before: bool; if !(seconds < 0 || chat_id <= 9i32 as libc::c_uint) { is_sending_locations_before = dc_is_sending_locations_to_chat(context, chat_id); @@ -91,10 +91,10 @@ pub unsafe fn dc_send_locations_to_chat(context: &Context, chat_id: uint32_t, se { if 0 != seconds && !is_sending_locations_before { msg = dc_msg_new(context, Viewtype::Text); - (*msg).text = + msg.text = Some(context.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", 0)); - (*msg).param.set_int(Param::Cmd, 8); - chat::send_msg(context, chat_id, msg).unwrap(); + msg.param.set_int(Param::Cmd, 8); + chat::send_msg(context, chat_id, &mut msg).unwrap(); } else if 0 == seconds && is_sending_locations_before { let stock_str = context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0); @@ -117,7 +117,6 @@ pub unsafe fn dc_send_locations_to_chat(context: &Context, chat_id: uint32_t, se } } } - dc_msg_unref(msg); } /******************************************************************************* @@ -680,11 +679,10 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context: &Context, _job: &Jo // (might not be 100%, however, as positions are sent combined later // and dc_set_location() is typically called periodically, this is ok) let mut msg = dc_msg_new(context, Viewtype::Text); - (*msg).hidden = 1; - (*msg).param.set_int(Param::Cmd, 9); + msg.hidden = true; + msg.param.set_int(Param::Cmd, 9); // TODO: handle cleanup on error - chat::send_msg(context, chat_id as u32, msg).unwrap(); - dc_msg_unref(msg); + chat::send_msg(context, chat_id as u32, &mut msg).unwrap(); } Ok(()) }, diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs index fe8dc2b0c..af9689156 100644 --- a/src/dc_mimefactory.rs +++ b/src/dc_mimefactory.rs @@ -1,4 +1,5 @@ use std::ffi::CString; +use std::ptr; use chrono::TimeZone; use mmime::mailimf_types::*; @@ -19,6 +20,7 @@ use crate::dc_location::*; use crate::dc_msg::*; use crate::dc_strencode::*; use crate::dc_tools::*; +use crate::error::Error; use crate::param::*; use crate::stock::StockMessage; use crate::types::*; @@ -35,7 +37,7 @@ pub struct dc_mimefactory_t<'a> { pub timestamp: i64, pub rfc724_mid: *mut libc::c_char, pub loaded: dc_mimefactory_loaded_t, - pub msg: *mut dc_msg_t<'a>, + pub msg: Message<'a>, pub chat: Option>, pub increation: libc::c_int, pub in_reply_to: *mut libc::c_char, @@ -49,295 +51,291 @@ pub struct dc_mimefactory_t<'a> { pub context: &'a Context, } +impl<'a> Drop for dc_mimefactory_t<'a> { + fn drop(&mut self) { + unsafe { + free(self.from_addr as *mut libc::c_void); + free(self.from_displayname as *mut libc::c_void); + free(self.selfstatus as *mut libc::c_void); + free(self.rfc724_mid as *mut libc::c_void); + if !self.recipients_names.is_null() { + clist_free_content(self.recipients_names); + clist_free(self.recipients_names); + } + if !self.recipients_addr.is_null() { + clist_free_content(self.recipients_addr); + clist_free(self.recipients_addr); + } + + free(self.in_reply_to as *mut libc::c_void); + free(self.references as *mut libc::c_void); + if !self.out.is_null() { + mmap_string_free(self.out); + } + free(self.error as *mut libc::c_void); + } + } +} + #[allow(non_camel_case_types)] type dc_mimefactory_loaded_t = libc::c_uint; const DC_MF_MDN_LOADED: dc_mimefactory_loaded_t = 2; pub const DC_MF_MSG_LOADED: dc_mimefactory_loaded_t = 1; pub const DC_MF_NOTHING_LOADED: dc_mimefactory_loaded_t = 0; -pub unsafe fn dc_mimefactory_empty(mut factory: *mut dc_mimefactory_t) { - if factory.is_null() { - return; - } - free((*factory).from_addr as *mut libc::c_void); - (*factory).from_addr = 0 as *mut libc::c_char; - free((*factory).from_displayname as *mut libc::c_void); - (*factory).from_displayname = 0 as *mut libc::c_char; - free((*factory).selfstatus as *mut libc::c_void); - (*factory).selfstatus = 0 as *mut libc::c_char; - free((*factory).rfc724_mid as *mut libc::c_void); - (*factory).rfc724_mid = 0 as *mut libc::c_char; - if !(*factory).recipients_names.is_null() { - clist_free_content((*factory).recipients_names); - clist_free((*factory).recipients_names); - (*factory).recipients_names = 0 as *mut clist - } - if !(*factory).recipients_addr.is_null() { - clist_free_content((*factory).recipients_addr); - clist_free((*factory).recipients_addr); - (*factory).recipients_addr = 0 as *mut clist - } - dc_msg_unref((*factory).msg); - (*factory).msg = 0 as *mut dc_msg_t; - (*factory).chat = None; - free((*factory).in_reply_to as *mut libc::c_void); - (*factory).in_reply_to = 0 as *mut libc::c_char; - free((*factory).references as *mut libc::c_void); - (*factory).references = 0 as *mut libc::c_char; - if !(*factory).out.is_null() { - mmap_string_free((*factory).out); - (*factory).out = 0 as *mut MMAPString - } - (*factory).out_encrypted = 0; - (*factory).loaded = DC_MF_NOTHING_LOADED; - free((*factory).error as *mut libc::c_void); - (*factory).error = 0 as *mut libc::c_char; - (*factory).timestamp = 0; -} - pub unsafe fn dc_mimefactory_load_msg( - mut factory: *mut dc_mimefactory_t, - msg_id: uint32_t, -) -> libc::c_int { - if factory.is_null() || msg_id <= 9 || !(*factory).msg.is_null() { - return 0; - } + context: &Context, + msg_id: u32, +) -> Result { + ensure!(msg_id > DC_CHAT_ID_LAST_SPECIAL as u32, "Invalid chat id"); - let mut success = 0; + let msg = dc_msg_load_from_db(context, msg_id)?; + let chat = Chat::load_from_db(context, msg.chat_id)?; + let mut factory = dc_mimefactory_t { + from_addr: ptr::null_mut(), + from_displayname: ptr::null_mut(), + selfstatus: ptr::null_mut(), + recipients_names: clist_new(), + recipients_addr: clist_new(), + timestamp: 0, + rfc724_mid: ptr::null_mut(), + loaded: DC_MF_NOTHING_LOADED, + msg, + chat: Some(chat), + increation: 0, + in_reply_to: ptr::null_mut(), + references: ptr::null_mut(), + req_mdn: 0, + out: ptr::null_mut(), + out_encrypted: 0, + out_gossiped: 0, + out_last_added_location_id: 0, + error: ptr::null_mut(), + context, + }; - /*call empty() before */ - let context = (*factory).context; - (*factory).recipients_names = clist_new(); - (*factory).recipients_addr = clist_new(); - (*factory).msg = dc_msg_new_untyped(context); + load_from(&mut factory); - if dc_msg_load_from_db((*factory).msg, context, msg_id) { - if let Ok(chat) = Chat::load_from_db(context, (*(*factory).msg).chat_id) { - (*factory).chat = Some(chat); + // just set the chat above + let chat = factory.chat.as_ref().unwrap(); - let chat = (*factory).chat.as_ref().unwrap(); - - load_from(factory); - (*factory).req_mdn = 0; - if chat.is_self_talk() { - clist_insert_after( - (*factory).recipients_names, - (*(*factory).recipients_names).last, - dc_strdup_keep_null((*factory).from_displayname) as *mut libc::c_void, - ); - clist_insert_after( - (*factory).recipients_addr, - (*(*factory).recipients_addr).last, - dc_strdup((*factory).from_addr) as *mut libc::c_void, - ); - } else { - context - .sql - .query_map( - "SELECT c.authname, c.addr \ - FROM chats_contacts cc \ - LEFT JOIN contacts c ON cc.contact_id=c.id \ - WHERE cc.chat_id=? AND cc.contact_id>9;", - params![(*(*factory).msg).chat_id as i32], - |row| { - let authname: String = row.get(0)?; - let addr: String = row.get(1)?; - Ok((authname, addr)) - }, - |rows| { - for row in rows { - let (authname, addr) = row?; - let addr_c = addr.strdup(); - if clist_search_string_nocase((*factory).recipients_addr, addr_c) - == 0 - { - clist_insert_after( - (*factory).recipients_names, - (*(*factory).recipients_names).last, - if !authname.is_empty() { - authname.strdup() - } else { - std::ptr::null_mut() - } - as *mut libc::c_void, - ); - clist_insert_after( - (*factory).recipients_addr, - (*(*factory).recipients_addr).last, - addr_c as *mut libc::c_void, - ); - } - } - Ok(()) - }, - ) - .unwrap(); - - let command = (*(*factory).msg) - .param - .get_int(Param::Cmd) - .unwrap_or_default(); - - if command == 5 { - let email_to_remove = - (*(*factory).msg).param.get(Param::Arg).unwrap_or_default(); - let email_to_remove_c = email_to_remove.strdup(); - - let self_addr = context - .sql - .get_config(context, "configured_addr") - .unwrap_or_default(); - - if !email_to_remove.is_empty() && email_to_remove != self_addr { - if clist_search_string_nocase((*factory).recipients_addr, email_to_remove_c) - == 0 - { + if chat.is_self_talk() { + clist_insert_after( + factory.recipients_names, + (*factory.recipients_names).last, + dc_strdup_keep_null(factory.from_displayname) as *mut libc::c_void, + ); + clist_insert_after( + factory.recipients_addr, + (*factory.recipients_addr).last, + dc_strdup(factory.from_addr) as *mut libc::c_void, + ); + } else { + context + .sql + .query_map( + "SELECT c.authname, c.addr \ + FROM chats_contacts cc \ + LEFT JOIN contacts c ON cc.contact_id=c.id \ + WHERE cc.chat_id=? AND cc.contact_id>9;", + params![factory.msg.chat_id as i32], + |row| { + let authname: String = row.get(0)?; + let addr: String = row.get(1)?; + Ok((authname, addr)) + }, + |rows| { + for row in rows { + let (authname, addr) = row?; + let addr_c = addr.strdup(); + if clist_search_string_nocase(factory.recipients_addr, addr_c) == 0 { clist_insert_after( - (*factory).recipients_names, - (*(*factory).recipients_names).last, - 0 as *mut libc::c_void, + factory.recipients_names, + (*factory.recipients_names).last, + if !authname.is_empty() { + authname.strdup() + } else { + std::ptr::null_mut() + } as *mut libc::c_void, ); clist_insert_after( - (*factory).recipients_addr, - (*(*factory).recipients_addr).last, - email_to_remove_c as *mut libc::c_void, + factory.recipients_addr, + (*factory.recipients_addr).last, + addr_c as *mut libc::c_void, ); } } - } - if command != 6 - && command != 7 - && 0 != context - .sql - .get_config_int(context, "mdns_enabled") - .unwrap_or_else(|| 1) - { - (*factory).req_mdn = 1 - } - } - let row = context.sql.query_row( - "SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?", - params![(*(*factory).msg).id as i32], - |row| { - let in_reply_to: String = row.get(0)?; - let references: String = row.get(1)?; - - Ok((in_reply_to, references)) + Ok(()) }, - ); - match row { - Ok((in_reply_to, references)) => { - (*factory).in_reply_to = in_reply_to.strdup(); - (*factory).references = references.strdup(); - } - Err(err) => { - error!( - context, - 0, "mimefactory: failed to load mime_in_reply_to: {:?}", err + ) + .unwrap(); + + let command = factory.msg.param.get_int(Param::Cmd).unwrap_or_default(); + let msg = &factory.msg; + + if command == 5 { + let email_to_remove = msg.param.get(Param::Arg).unwrap_or_default(); + let email_to_remove_c = email_to_remove.strdup(); + + let self_addr = context + .sql + .get_config(context, "configured_addr") + .unwrap_or_default(); + + if !email_to_remove.is_empty() && email_to_remove != self_addr { + if clist_search_string_nocase(factory.recipients_addr, email_to_remove_c) == 0 { + clist_insert_after( + factory.recipients_names, + (*factory.recipients_names).last, + 0 as *mut libc::c_void, + ); + clist_insert_after( + factory.recipients_addr, + (*factory.recipients_addr).last, + email_to_remove_c as *mut libc::c_void, ); } } - - success = 1; - (*factory).loaded = DC_MF_MSG_LOADED; - (*factory).timestamp = (*(*factory).msg).timestamp_sort; - (*factory).rfc724_mid = dc_strdup((*(*factory).msg).rfc724_mid) + } + if command != 6 + && command != 7 + && 0 != context + .sql + .get_config_int(context, "mdns_enabled") + .unwrap_or_else(|| 1) + { + factory.req_mdn = 1; } } - if 0 != success { - (*factory).increation = dc_msg_is_increation((*factory).msg) + let row = context.sql.query_row( + "SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?", + params![factory.msg.id as i32], + |row| { + let in_reply_to: String = row.get(0)?; + let references: String = row.get(1)?; + + Ok((in_reply_to, references)) + }, + ); + match row { + Ok((in_reply_to, references)) => { + factory.in_reply_to = in_reply_to.strdup(); + factory.references = references.strdup(); + } + Err(err) => { + error!( + context, + 0, "mimefactory: failed to load mime_in_reply_to: {:?}", err + ); + } } - success + factory.loaded = DC_MF_MSG_LOADED; + factory.timestamp = factory.msg.timestamp_sort; + factory.rfc724_mid = dc_strdup(factory.msg.rfc724_mid); + factory.increation = dc_msg_is_increation(&factory.msg); + + Ok(factory) } -unsafe fn load_from(mut factory: *mut dc_mimefactory_t) { - let context = (*factory).context; - (*factory).from_addr = context +unsafe fn load_from(factory: &mut dc_mimefactory_t) { + let context = factory.context; + factory.from_addr = context .sql .get_config(context, "configured_addr") .unwrap_or_default() .strdup(); - (*factory).from_displayname = context + factory.from_displayname = context .sql .get_config(context, "displayname") .unwrap_or_default() .strdup(); - (*factory).selfstatus = context + factory.selfstatus = context .sql .get_config(context, "selfstatus") .unwrap_or_default() .strdup(); - if (*factory).selfstatus.is_null() { - (*factory).selfstatus = (*factory) - .context - .stock_str(StockMessage::StatusLine) - .strdup(); + if factory.selfstatus.is_null() { + factory.selfstatus = factory.context.stock_str(StockMessage::StatusLine).strdup(); }; } -pub unsafe fn dc_mimefactory_load_mdn( - mut factory: *mut dc_mimefactory_t, +pub unsafe fn dc_mimefactory_load_mdn<'a>( + context: &'a Context, msg_id: uint32_t, -) -> libc::c_int { - if factory.is_null() { - return 0; - } - - let mut success = 0; - - (*factory).recipients_names = clist_new(); - (*factory).recipients_addr = clist_new(); - (*factory).msg = dc_msg_new_untyped((*factory).context); - if 0 != (*factory) - .context +) -> Result { + if 0 == context .sql - .get_config_int((*factory).context, "mdns_enabled") + .get_config_int(context, "mdns_enabled") .unwrap_or_else(|| 1) { - // MDNs not enabled - check this is late, in the job. the use may have changed its choice while offline ... - if !dc_msg_load_from_db((*factory).msg, (*factory).context, msg_id) { - return success; - } + // MDNs not enabled - check this is late, in the job. the use may have changed its + // choice while offline ... - if let Ok(contact) = Contact::load_from_db((*factory).context, (*(*factory).msg).from_id) { - if !(contact.is_blocked() || (*(*factory).msg).chat_id <= 9 as libc::c_uint) { - // Do not send MDNs trash etc.; chats.blocked is already checked by the caller in dc_markseen_msgs() - if !((*(*factory).msg).from_id <= 9 as libc::c_uint) { - clist_insert_after( - (*factory).recipients_names, - (*(*factory).recipients_names).last, - (if !contact.get_authname().is_empty() { - contact.get_authname().strdup() - } else { - 0 as *mut libc::c_char - }) as *mut libc::c_void, - ); - clist_insert_after( - (*factory).recipients_addr, - (*(*factory).recipients_addr).last, - contact.get_addr().strdup() as *mut libc::c_void, - ); - load_from(factory); - (*factory).timestamp = dc_create_smeared_timestamp((*factory).context); - (*factory).rfc724_mid = dc_create_outgoing_rfc724_mid( - 0 as *const libc::c_char, - (*factory).from_addr, - ); - success = 1; - (*factory).loaded = DC_MF_MDN_LOADED - } - } - } + bail!("MDNs disabled ") } - success + let msg = dc_msg_load_from_db(context, msg_id)?; + + let mut factory = dc_mimefactory_t { + from_addr: ptr::null_mut(), + from_displayname: ptr::null_mut(), + selfstatus: ptr::null_mut(), + recipients_names: clist_new(), + recipients_addr: clist_new(), + timestamp: 0, + rfc724_mid: ptr::null_mut(), + loaded: DC_MF_NOTHING_LOADED, + msg, + chat: None, + increation: 0, + in_reply_to: ptr::null_mut(), + references: ptr::null_mut(), + req_mdn: 0, + out: ptr::null_mut(), + out_encrypted: 0, + out_gossiped: 0, + out_last_added_location_id: 0, + error: ptr::null_mut(), + context, + }; + + let contact = Contact::load_from_db(factory.context, factory.msg.from_id)?; + + // Do not send MDNs trash etc.; chats.blocked is already checked by the caller + // in dc_markseen_msgs() + ensure!(!contact.is_blocked(), "Contact blocked"); + ensure!( + factory.msg.chat_id > DC_CHAT_ID_LAST_SPECIAL as u32, + "Invalid chat id" + ); + + clist_insert_after( + factory.recipients_names, + (*factory.recipients_names).last, + (if !contact.get_authname().is_empty() { + contact.get_authname().strdup() + } else { + 0 as *mut libc::c_char + }) as *mut libc::c_void, + ); + clist_insert_after( + factory.recipients_addr, + (*factory.recipients_addr).last, + contact.get_addr().strdup() as *mut libc::c_void, + ); + load_from(&mut factory); + factory.timestamp = dc_create_smeared_timestamp(factory.context); + factory.rfc724_mid = dc_create_outgoing_rfc724_mid(0 as *const libc::c_char, factory.from_addr); + factory.loaded = DC_MF_MDN_LOADED; + + Ok(factory) } // TODO should return bool /rtn -pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc::c_int { +pub unsafe fn dc_mimefactory_render(factory: &mut dc_mimefactory_t) -> libc::c_int { let subject: *mut mailimf_subject; let mut ok_to_continue = true; let imf_fields: *mut mailimf_fields; @@ -363,9 +361,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: gossipped_addr: Default::default(), }; - if factory.is_null() - || (*factory).loaded as libc::c_uint == DC_MF_NOTHING_LOADED as libc::c_int as libc::c_uint - || !(*factory).out.is_null() + if factory.loaded as libc::c_uint == DC_MF_NOTHING_LOADED as libc::c_int as libc::c_uint + || !factory.out.is_null() { /*call empty() before*/ set_error( @@ -377,24 +374,24 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: mailimf_mailbox_list_add( from, mailimf_mailbox_new( - if !(*factory).from_displayname.is_null() { - dc_encode_header_words((*factory).from_displayname) + if !factory.from_displayname.is_null() { + dc_encode_header_words(factory.from_displayname) } else { 0 as *mut libc::c_char }, - dc_strdup((*factory).from_addr), + dc_strdup(factory.from_addr), ), ); let mut to: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - if !(*factory).recipients_names.is_null() - && !(*factory).recipients_addr.is_null() - && (*(*factory).recipients_addr).count > 0 + if !factory.recipients_names.is_null() + && !factory.recipients_addr.is_null() + && (*factory.recipients_addr).count > 0 { let mut iter1: *mut clistiter; let mut iter2: *mut clistiter; to = mailimf_address_list_new_empty(); - iter1 = (*(*factory).recipients_names).first; - iter2 = (*(*factory).recipients_addr).first; + iter1 = (*factory.recipients_names).first; + iter2 = (*factory.recipients_addr).first; while !iter1.is_null() && !iter2.is_null() { let name: *const libc::c_char = (if !iter1.is_null() { (*iter1).data @@ -434,38 +431,35 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: } } let mut references_list: *mut clist = 0 as *mut clist; - if !(*factory).references.is_null() - && 0 != *(*factory).references.offset(0isize) as libc::c_int - { + if !factory.references.is_null() && 0 != *factory.references.offset(0isize) as libc::c_int { references_list = dc_str_to_clist( - (*factory).references, + factory.references, b" \x00" as *const u8 as *const libc::c_char, ) } let mut in_reply_to_list: *mut clist = 0 as *mut clist; - if !(*factory).in_reply_to.is_null() - && 0 != *(*factory).in_reply_to.offset(0isize) as libc::c_int + if !factory.in_reply_to.is_null() && 0 != *factory.in_reply_to.offset(0isize) as libc::c_int { in_reply_to_list = dc_str_to_clist( - (*factory).in_reply_to, + factory.in_reply_to, b" \x00" as *const u8 as *const libc::c_char, ) } imf_fields = mailimf_fields_new_with_data_all( - mailimf_get_date((*factory).timestamp as i64), + mailimf_get_date(factory.timestamp as i64), from, 0 as *mut mailimf_mailbox, 0 as *mut mailimf_address_list, to, 0 as *mut mailimf_address_list, 0 as *mut mailimf_address_list, - dc_strdup((*factory).rfc724_mid), + dc_strdup(factory.rfc724_mid), in_reply_to_list, references_list, 0 as *mut libc::c_char, ); - let os_name = &(*factory).context.os_name; + let os_name = &factory.context.os_name; let os_part = os_name .as_ref() .map(|s| format!("/{}", s)) @@ -492,24 +486,23 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: strdup(b"1.0\x00" as *const u8 as *const libc::c_char), ), ); - if 0 != (*factory).req_mdn { + if 0 != factory.req_mdn { mailimf_fields_add( imf_fields, mailimf_field_new_custom( strdup( b"Chat-Disposition-Notification-To\x00" as *const u8 as *const libc::c_char, ), - strdup((*factory).from_addr), + strdup(factory.from_addr), ), ); } message = mailmime_new_message_data(0 as *mut mailmime); mailmime_set_imf_fields(message, imf_fields); - if (*factory).loaded as libc::c_uint == DC_MF_MSG_LOADED as libc::c_int as libc::c_uint { + if factory.loaded as libc::c_uint == DC_MF_MSG_LOADED as libc::c_int as libc::c_uint { /* Render a normal message *********************************************************************/ - let chat = (*factory).chat.as_ref().unwrap(); - let msg = (*factory).msg; + let chat = factory.chat.as_ref().unwrap(); let mut meta_part: *mut mailmime = 0 as *mut mailmime; let mut placeholdertext: *mut libc::c_char = 0 as *mut libc::c_char; if chat.typ == Chattype::VerifiedGroup { @@ -524,12 +517,14 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: e2ee_guaranteed = 1; min_verified = 2 } else { - force_plaintext = (*(*factory).msg) + force_plaintext = factory + .msg .param .get_int(Param::ForcePlaintext) .unwrap_or_default(); if force_plaintext == 0 { - e2ee_guaranteed = (*(*factory).msg) + e2ee_guaranteed = factory + .msg .param .get_int(Param::GuranteeE2ee) .unwrap_or_default() @@ -542,7 +537,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: } /* build header etc. */ - let command = (*msg).param.get_int(Param::Cmd).unwrap_or_default(); + let command = factory.msg.param.get_int(Param::Cmd).unwrap_or_default(); if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { mailimf_fields_add( imf_fields, @@ -560,7 +555,12 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); if command == 5 { - let email_to_remove = (*msg).param.get(Param::Arg).unwrap_or_default().strdup(); + let email_to_remove = factory + .msg + .param + .get(Param::Arg) + .unwrap_or_default() + .strdup(); if strlen(email_to_remove) > 0 { mailimf_fields_add( imf_fields, @@ -574,8 +574,9 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); } } else if command == 4 { + let msg = &factory.msg; do_gossip = 1; - let email_to_add = (*msg).param.get(Param::Arg).unwrap_or_default().strdup(); + let email_to_add = msg.param.get(Param::Arg).unwrap_or_default().strdup(); if strlen(email_to_add) > 0 { mailimf_fields_add( imf_fields, @@ -589,9 +590,9 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); grpimage = chat.param.get(Param::ProfileImage); } - if 0 != (*msg).param.get_int(Param::Arg2).unwrap_or_default() & 0x1 { + if 0 != msg.param.get_int(Param::Arg2).unwrap_or_default() & 0x1 { info!( - (*msg).context, + msg.context, 0, "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", "vg-member-added", @@ -605,7 +606,9 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); } } else if command == 2 { - let value_to_add = (*msg).param.get(Param::Arg).unwrap_or_default().strdup(); + let msg = &factory.msg; + + let value_to_add = msg.param.get(Param::Arg).unwrap_or_default().strdup(); mailimf_fields_add( imf_fields, mailimf_field_new_custom( @@ -616,7 +619,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); } else if command == 3 { - grpimage = (*msg).param.get(Param::Arg); + let msg = &factory.msg; + grpimage = msg.param.get(Param::Arg); if grpimage.is_none() { mailimf_fields_add( imf_fields, @@ -647,16 +651,17 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: strdup(b"v1\x00" as *const u8 as *const libc::c_char), ), ); - placeholdertext = (*factory) + placeholdertext = factory .context .stock_str(StockMessage::AcSetupMsgBody) .strdup(); } if command == 7 { - let step = (*msg).param.get(Param::Arg).unwrap_or_default().strdup(); + let msg = &factory.msg; + let step = msg.param.get(Param::Arg).unwrap_or_default().strdup(); if strlen(step) > 0 { info!( - (*msg).context, + msg.context, 0, "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", as_str(step), @@ -668,7 +673,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: step, ), ); - let param2 = (*msg).param.get(Param::Arg2).unwrap_or_default().strdup(); + let param2 = msg.param.get(Param::Arg2).unwrap_or_default().strdup(); if strlen(param2) > 0 { mailimf_fields_add( imf_fields, @@ -696,7 +701,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); } - let fingerprint = (*msg).param.get(Param::Arg3).unwrap_or_default().strdup(); + let fingerprint = msg.param.get(Param::Arg3).unwrap_or_default().strdup(); if strlen(fingerprint) > 0 { mailimf_fields_add( imf_fields, @@ -709,7 +714,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); } - let grpid = match (*msg).param.get(Param::Arg4) { + let grpid = match msg.param.get(Param::Arg4) { Some(id) => id.strdup(), None => std::ptr::null_mut(), }; @@ -727,13 +732,13 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: } } if let Some(grpimage) = grpimage { - let mut meta = dc_msg_new_untyped((*factory).context); - (*meta).type_0 = Viewtype::Image; - (*meta).param.set(Param::File, grpimage); + let mut meta = dc_msg_new_untyped(factory.context); + meta.type_0 = Viewtype::Image; + meta.param.set(Param::File, grpimage); let mut filename_as_sent = 0 as *mut libc::c_char; meta_part = build_body_file( - meta, + &meta, b"group-image\x00" as *const u8 as *const libc::c_char, &mut filename_as_sent, ); @@ -746,14 +751,13 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); } - dc_msg_unref(meta); } - if (*msg).type_0 == Viewtype::Voice - || (*msg).type_0 == Viewtype::Audio - || (*msg).type_0 == Viewtype::Video + if factory.msg.type_0 == Viewtype::Voice + || factory.msg.type_0 == Viewtype::Audio + || factory.msg.type_0 == Viewtype::Video { - if (*msg).type_0 == Viewtype::Voice { + if factory.msg.type_0 == Viewtype::Voice { mailimf_fields_add( imf_fields, mailimf_field_new_custom( @@ -762,7 +766,11 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); } - let duration_ms = (*msg).param.get_int(Param::Duration).unwrap_or_default(); + let duration_ms = factory + .msg + .param + .get_int(Param::Duration) + .unwrap_or_default(); if duration_ms > 0 { mailimf_fields_add( imf_fields, @@ -776,7 +784,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); } } - afwd_email = (*msg).param.exists(Param::Forwarded) as libc::c_int; + afwd_email = factory.msg.param.exists(Param::Forwarded) as libc::c_int; let mut fwdhint = 0 as *mut libc::c_char; if 0 != afwd_email { fwdhint = dc_strdup( @@ -788,7 +796,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: let final_text = { if !placeholdertext.is_null() { to_string(placeholdertext) - } else if let Some(ref text) = (*msg).text { + } else if let Some(ref text) = factory.msg.text { text.clone() } else { "".into() @@ -796,7 +804,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: }; let final_text = CString::yolo(final_text); - let footer: *mut libc::c_char = (*factory).selfstatus; + let footer: *mut libc::c_char = factory.selfstatus; message_text = dc_mprintf( b"%s%s%s%s%s\x00" as *const u8 as *const libc::c_char, if !fwdhint.is_null() { @@ -831,8 +839,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: free(placeholdertext as *mut libc::c_void); /* add attachment part */ - if chat::msgtype_has_file((*msg).type_0) { - if !is_file_size_okay(msg) { + if chat::msgtype_has_file(factory.msg.type_0) { + if !is_file_size_okay(&factory.msg) { let error: *mut libc::c_char = dc_mprintf( b"Message exceeds the recommended %i MB.\x00" as *const u8 as *const libc::c_char, @@ -842,8 +850,11 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: free(error as *mut libc::c_void); ok_to_continue = false; } else { - let file_part: *mut mailmime = - build_body_file(msg, 0 as *const libc::c_char, 0 as *mut *mut libc::c_char); + let file_part: *mut mailmime = build_body_file( + &factory.msg, + 0 as *const libc::c_char, + 0 as *mut *mut libc::c_char, + ); if !file_part.is_null() { mailmime_smart_add_part(message, file_part); parts += 1 @@ -861,17 +872,19 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: if !meta_part.is_null() { mailmime_smart_add_part(message, meta_part); } - if (*msg).param.exists(Param::SetLatitude) { - let latitude = (*msg) + if factory.msg.param.exists(Param::SetLatitude) { + let latitude = factory + .msg .param .get_float(Param::SetLatitude) .unwrap_or_default(); - let longitude = (*msg) + let longitude = factory + .msg .param .get_float(Param::SetLongitude) .unwrap_or_default(); let kml_file = - dc_get_message_kml((*msg).timestamp_sort, latitude, longitude); + dc_get_message_kml(factory.msg.timestamp_sort, latitude, longitude); if !kml_file.is_null() { let content_type = mailmime_content_new_with_str( b"application/vnd.google-earth.kml+xml\x00" as *const u8 @@ -889,11 +902,11 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: } } - if dc_is_sending_locations_to_chat((*msg).context, (*msg).chat_id) { + if dc_is_sending_locations_to_chat(factory.msg.context, factory.msg.chat_id) { let mut last_added_location_id: uint32_t = 0 as uint32_t; let kml_file: *mut libc::c_char = dc_get_location_kml( - (*msg).context, - (*msg).chat_id, + factory.msg.context, + factory.msg.chat_id, &mut last_added_location_id, ); if !kml_file.is_null() { @@ -910,16 +923,15 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: mailmime_new_empty(content_type, mime_fields); mailmime_set_body_text(kml_mime_part, kml_file, strlen(kml_file)); mailmime_smart_add_part(message, kml_mime_part); - if !(*msg).param.exists(Param::SetLatitude) { + if !factory.msg.param.exists(Param::SetLatitude) { // otherwise, the independent location is already filed - (*factory).out_last_added_location_id = last_added_location_id; + factory.out_last_added_location_id = last_added_location_id; } } } } } - } else if (*factory).loaded as libc::c_uint - == DC_MF_MDN_LOADED as libc::c_int as libc::c_uint + } else if factory.loaded as libc::c_uint == DC_MF_MDN_LOADED as libc::c_int as libc::c_uint { let multipart: *mut mailmime = mailmime_multiple_new(b"multipart/report\x00" as *const u8 as *const libc::c_char); @@ -935,19 +947,20 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); mailmime_add_part(message, multipart); let p1 = if 0 - != (*(*factory).msg) + != factory + .msg .param .get_int(Param::GuranteeE2ee) .unwrap_or_default() { - (*factory) + factory .context .stock_str(StockMessage::EncryptedMsg) .into_owned() } else { - to_string(dc_msg_get_summarytext((*factory).msg, 32)) + to_string(dc_msg_get_summarytext(&mut factory.msg, 32)) }; - let p2 = (*factory) + let p2 = factory .context .stock_string_repl_str(StockMessage::ReadRcptMailBody, p1); message_text = format!("{}\r\n", p2).strdup(); @@ -955,11 +968,13 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: mailmime_add_part(multipart, human_mime_part); let version = dc_get_version_str(); message_text2 = - dc_mprintf(b"Reporting-UA: Delta Chat %s\r\nOriginal-Recipient: rfc822;%s\r\nFinal-Recipient: rfc822;%s\r\nOriginal-Message-ID: <%s>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n\x00" - as *const u8 as *const libc::c_char, - version, - (*factory).from_addr, (*factory).from_addr, - (*(*factory).msg).rfc724_mid); + dc_mprintf( + b"Reporting-UA: Delta Chat %s\r\nOriginal-Recipient: rfc822;%s\r\nFinal-Recipient: rfc822;%s\r\nOriginal-Message-ID: <%s>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n\x00" + as *const u8 as *const libc::c_char, + version, + factory.from_addr, factory.from_addr, + factory.msg.rfc724_mid + ); free(version.cast()); let content_type_0: *mut mailmime_content = mailmime_content_new_with_str( b"message/disposition-notification\x00" as *const u8 as *const libc::c_char, @@ -979,21 +994,15 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: } if ok_to_continue { - if (*factory).loaded as libc::c_uint == DC_MF_MDN_LOADED as libc::c_int as libc::c_uint - { - let e = CString::new( - (*factory) - .context - .stock_str(StockMessage::ReadRcpt) - .as_ref(), - ) - .unwrap(); + if factory.loaded as libc::c_uint == DC_MF_MDN_LOADED as libc::c_int as libc::c_uint { + let e = CString::new(factory.context.stock_str(StockMessage::ReadRcpt).as_ref()) + .unwrap(); subject_str = dc_mprintf( b"Chat: %s\x00" as *const u8 as *const libc::c_char, e.as_ptr(), ); } else { - subject_str = get_subject((*factory).chat.as_ref(), (*factory).msg, afwd_email) + subject_str = get_subject(factory.chat.as_ref(), &mut factory.msg, afwd_email) } subject = mailimf_subject_new(dc_encode_header_words(subject_str)); mailimf_fields_add( @@ -1026,8 +1035,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); if force_plaintext != 2 { dc_e2ee_encrypt( - (*factory).context, - (*factory).recipients_addr, + factory.context, + factory.recipients_addr, force_plaintext, e2ee_guaranteed, min_verified, @@ -1037,13 +1046,13 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); } if 0 != e2ee_helper.encryption_successfull { - (*factory).out_encrypted = 1; + factory.out_encrypted = 1; if 0 != do_gossip { - (*factory).out_gossiped = 1 + factory.out_gossiped = 1 } } - (*factory).out = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - mailmime_write_mem((*factory).out, &mut col, message); + factory.out = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); + mailmime_write_mem(factory.out, &mut col, message); success = 1 } } @@ -1061,7 +1070,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: unsafe fn get_subject( chat: Option<&Chat>, - msg: *mut dc_msg_t, + msg: &mut Message, afwd_email: libc::c_int, ) -> *mut libc::c_char { if chat.is_none() { @@ -1073,14 +1082,8 @@ unsafe fn get_subject( let ret: *mut libc::c_char; let raw_subject = { - dc_msg_get_summarytext_by_raw( - (*msg).type_0, - (*msg).text.as_ref(), - &mut (*msg).param, - 32, - context, - ) - .strdup() + dc_msg_get_summarytext_by_raw(msg.type_0, msg.text.as_ref(), &mut msg.param, 32, context) + .strdup() }; let fwd = if 0 != afwd_email { @@ -1088,7 +1091,7 @@ unsafe fn get_subject( } else { b"\x00" as *const u8 as *const libc::c_char }; - if (*msg).param.get_int(Param::Cmd).unwrap_or_default() == 6 { + if msg.param.get_int(Param::Cmd).unwrap_or_default() == 6 { ret = context.stock_str(StockMessage::AcSetupMsgSubject).strdup() } else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { ret = format!( @@ -1110,7 +1113,7 @@ unsafe fn get_subject( ret } -unsafe fn set_error(mut factory: *mut dc_mimefactory_t, text: *const libc::c_char) { +unsafe fn set_error(factory: *mut dc_mimefactory_t, text: *const libc::c_char) { if factory.is_null() { return; } @@ -1140,7 +1143,7 @@ unsafe fn build_body_text(text: *mut libc::c_char) -> *mut mailmime { #[allow(non_snake_case)] unsafe fn build_body_file( - msg: *const dc_msg_t, + msg: &Message, mut base_name: *const libc::c_char, ret_file_name_as_sent: *mut *mut libc::c_char, ) -> *mut mailmime { @@ -1148,9 +1151,9 @@ unsafe fn build_body_file( let mime_fields: *mut mailmime_fields; let mut mime_sub: *mut mailmime = 0 as *mut mailmime; let content: *mut mailmime_content; - let path_filename = (*msg).param.get(Param::File); + let path_filename = msg.param.get(Param::File); - let mut mimetype = (*msg) + let mut mimetype = msg .param .get(Param::MimeType) .map(|s| s.strdup()) @@ -1162,8 +1165,8 @@ unsafe fn build_body_file( if let Some(ref path_filename) = path_filename { let suffix = dc_get_filesuffix_lc(path_filename); - if (*msg).type_0 == Viewtype::Voice { - let ts = chrono::Utc.timestamp((*msg).timestamp_sort as i64, 0); + if msg.type_0 == Viewtype::Voice { + let ts = chrono::Utc.timestamp(msg.timestamp_sort as i64, 0); let suffix = if !suffix.is_null() { to_string(suffix) @@ -1174,9 +1177,9 @@ unsafe fn build_body_file( .format(&format!("voice-message_%Y-%m-%d_%H-%M-%S.{}", suffix)) .to_string(); filename_to_send = res.strdup(); - } else if (*msg).type_0 == Viewtype::Audio { + } else if msg.type_0 == Viewtype::Audio { filename_to_send = dc_get_filename(path_filename) - } else if (*msg).type_0 == Viewtype::Image || (*msg).type_0 == Viewtype::Gif { + } else if msg.type_0 == Viewtype::Image || msg.type_0 == Viewtype::Gif { if base_name.is_null() { base_name = b"image\x00" as *const u8 as *const libc::c_char } @@ -1189,7 +1192,7 @@ unsafe fn build_body_file( b"dat\x00" as *const u8 as *const libc::c_char }, ) - } else if (*msg).type_0 == Viewtype::Video { + } else if msg.type_0 == Viewtype::Video { filename_to_send = dc_mprintf( b"video.%s\x00" as *const u8 as *const libc::c_char, if !suffix.is_null() { @@ -1292,7 +1295,7 @@ unsafe fn build_body_file( ) as *mut libc::c_void, ); mime_sub = mailmime_new_empty(content, mime_fields); - mailmime_set_body_file(mime_sub, dc_get_abs_path((*msg).context, path_filename)); + mailmime_set_body_file(mime_sub, dc_get_abs_path(msg.context, path_filename)); if !ret_file_name_as_sent.is_null() { *ret_file_name_as_sent = dc_strdup(filename_to_send) } @@ -1309,10 +1312,10 @@ unsafe fn build_body_file( /******************************************************************************* * Render ******************************************************************************/ -unsafe fn is_file_size_okay(msg: *const dc_msg_t) -> bool { +unsafe fn is_file_size_okay(msg: &Message) -> bool { let mut file_size_okay = true; - let path = (*msg).param.get(Param::File).unwrap_or_default(); - let bytes = dc_get_filebytes((*msg).context, &path); + let path = msg.param.get(Param::File).unwrap_or_default(); + let bytes = dc_get_filebytes(msg.context, &path); if bytes > (49 * 1024 * 1024 / 4 * 3) { file_size_okay = false; diff --git a/src/dc_move.rs b/src/dc_move.rs index 3767db86a..5eb5b5174 100644 --- a/src/dc_move.rs +++ b/src/dc_move.rs @@ -18,29 +18,27 @@ pub unsafe fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u3 return; } - let msg = dc_msg_new_load(context, msg_id); - if dc_msg_is_setupmessage(msg) { - // do not move setup messages; - // there may be a non-delta device that wants to handle it - dc_msg_unref(msg); - return; - } + if let Ok(msg) = dc_msg_new_load(context, msg_id) { + if dc_msg_is_setupmessage(&msg) { + // do not move setup messages; + // there may be a non-delta device that wants to handle it + return; + } - if dc_is_mvbox(context, folder) { - dc_update_msg_move_state(context, (*msg).rfc724_mid, MoveState::Stay); - } + if dc_is_mvbox(context, folder) { + dc_update_msg_move_state(context, msg.rfc724_mid, MoveState::Stay); + } - // 1 = dc message, 2 = reply to dc message - if 0 != (*msg).is_dc_message { - job_add( - context, - Action::MoveMsg, - (*msg).id as libc::c_int, - Params::new(), - 0, - ); - dc_update_msg_move_state(context, (*msg).rfc724_mid, MoveState::Moving); + // 1 = dc message, 2 = reply to dc message + if 0 != msg.is_dc_message { + job_add( + context, + Action::MoveMsg, + msg.id as libc::c_int, + Params::new(), + 0, + ); + dc_update_msg_move_state(context, msg.rfc724_mid, MoveState::Moving); + } } - - dc_msg_unref(msg); } diff --git a/src/dc_msg.rs b/src/dc_msg.rs index 5bd739497..2bc9558c7 100644 --- a/src/dc_msg.rs +++ b/src/dc_msg.rs @@ -10,6 +10,7 @@ use crate::constants::*; use crate::contact::*; use crate::context::*; use crate::dc_tools::*; +use crate::error::Error; use crate::job::*; use crate::lot::{Lot, LotState, Meaning}; use crate::param::*; @@ -71,22 +72,16 @@ impl Lot { /* in practice, the user additionally cuts the string himself pixel-accurate */ pub fn fill( &mut self, - msg: *mut dc_msg_t, + msg: &mut Message, chat: &Chat, contact: Option<&Contact>, context: &Context, ) { - if msg.is_null() { - return; - } - - let msg = unsafe { &mut *msg }; - if msg.state == MessageState::OutDraft { self.text1 = Some(context.stock_str(StockMessage::Draft).to_owned().into()); self.text1_meaning = Meaning::Text1Draft; } else if msg.from_id == DC_CONTACT_ID_SELF as u32 { - if 0 != unsafe { dc_msg_is_info(msg) } || chat.is_self_talk() { + if 0 != dc_msg_is_info(msg) || chat.is_self_talk() { self.text1 = None; self.text1_meaning = Meaning::None; } else { @@ -94,7 +89,7 @@ impl Lot { self.text1_meaning = Meaning::Text1Self; } } else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { - if 0 != unsafe { dc_msg_is_info(msg) } || contact.is_none() { + if 0 != dc_msg_is_info(msg) || contact.is_none() { self.text1 = None; self.text1_meaning = Meaning::None; } else { @@ -123,23 +118,28 @@ impl Lot { context, )); - self.timestamp = unsafe { dc_msg_get_timestamp(msg) }; + self.timestamp = dc_msg_get_timestamp(msg); self.state = msg.state.into(); } } -/* * the structure behind dc_msg_t */ +/// An object representing a single message in memory. +/// The message object is not updated. +/// If you want an update, you have to recreate the object. +/// +/// to check if a mail was sent, use dc_msg_is_sent() +/// approx. max. length returned by dc_msg_get_text() +/// approx. max. length returned by dc_get_msg_info() #[derive(Clone)] -#[repr(C)] -pub struct dc_msg_t<'a> { - pub id: uint32_t, - pub from_id: uint32_t, - pub to_id: uint32_t, - pub chat_id: uint32_t, +pub struct Message<'a> { + pub id: u32, + pub from_id: u32, + pub to_id: u32, + pub chat_id: u32, pub move_state: MoveState, pub type_0: Viewtype, pub state: MessageState, - pub hidden: libc::c_int, + pub hidden: bool, pub timestamp_sort: i64, pub timestamp_sent: i64, pub timestamp_rcvd: i64, @@ -148,21 +148,26 @@ pub struct dc_msg_t<'a> { pub rfc724_mid: *mut libc::c_char, pub in_reply_to: *mut libc::c_char, pub server_folder: Option, - pub server_uid: uint32_t, - pub is_dc_message: libc::c_int, - pub starred: libc::c_int, - pub chat_blocked: libc::c_int, - pub location_id: uint32_t, + pub server_uid: u32, + // TODO: enum + pub is_dc_message: u32, + pub starred: bool, + pub chat_blocked: Blocked, + pub location_id: u32, pub param: Params, } // handle messages pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_char { - let msg = dc_msg_new_untyped(context); let mut p: *mut libc::c_char; let mut ret = String::new(); - dc_msg_load_from_db(msg, context, msg_id); + let msg = dc_msg_load_from_db(context, msg_id); + if msg.is_err() { + return ptr::null_mut(); + } + + let msg = msg.unwrap(); let rawtxt: Option = context.sql.query_row_col( context, @@ -173,35 +178,33 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch if rawtxt.is_none() { ret += &format!("Cannot load message #{}.", msg_id as usize); - dc_msg_unref(msg); return ret.strdup(); } let rawtxt = rawtxt.unwrap(); let rawtxt = dc_truncate(rawtxt.trim(), 100000, false); - let fts = dc_timestamp_to_str(dc_msg_get_timestamp(msg)); + let fts = dc_timestamp_to_str(dc_msg_get_timestamp(&msg)); ret += &format!("Sent: {}", fts); - let name = Contact::load_from_db(context, (*msg).from_id) + let name = Contact::load_from_db(context, msg.from_id) .map(|contact| contact.get_name_n_addr()) .unwrap_or_default(); ret += &format!(" by {}", name); ret += "\n"; - if (*msg).from_id != DC_CONTACT_ID_SELF as libc::c_uint { - let s = dc_timestamp_to_str(if 0 != (*msg).timestamp_rcvd { - (*msg).timestamp_rcvd + if msg.from_id != DC_CONTACT_ID_SELF as libc::c_uint { + let s = dc_timestamp_to_str(if 0 != msg.timestamp_rcvd { + msg.timestamp_rcvd } else { - (*msg).timestamp_sort + msg.timestamp_sort }); ret += &format!("Received: {}", &s); ret += "\n"; } - if (*msg).from_id == 2 || (*msg).to_id == 2 { + if msg.from_id == 2 || msg.to_id == 2 { // device-internal message, no further details needed - dc_msg_unref(msg); return ret.strdup(); } @@ -235,7 +238,7 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch ret += "State: "; use MessageState::*; - match (*msg).state { + match msg.state { InFresh => ret += "Fresh", InNoticed => ret += "Noticed", InSeen => ret += "Seen", @@ -244,38 +247,30 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch OutMdnRcvd => ret += "Read", OutPending => ret += "Pending", OutPreparing => ret += "Preparing", - _ => ret += &format!("{}", (*msg).state), + _ => ret += &format!("{}", msg.state), } - if dc_msg_has_location(msg) { + if dc_msg_has_location(&msg) { ret += ", Location sent"; } - let e2ee_errors = (*msg) - .param - .get_int(Param::ErroneousE2ee) - .unwrap_or_default(); + let e2ee_errors = msg.param.get_int(Param::ErroneousE2ee).unwrap_or_default(); if 0 != e2ee_errors { if 0 != e2ee_errors & 0x2 { ret += ", Encrypted, no valid signature"; } - } else if 0 - != (*msg) - .param - .get_int(Param::GuranteeE2ee) - .unwrap_or_default() - { + } else if 0 != msg.param.get_int(Param::GuranteeE2ee).unwrap_or_default() { ret += ", Encrypted"; } ret += "\n"; - match (*msg).param.get(Param::Error) { + match msg.param.get(Param::Error) { Some(err) => ret += &format!("Error: {}", err), _ => {} } - p = dc_msg_get_file(msg); + p = dc_msg_get_file(&msg); if !p.is_null() && 0 != *p.offset(0isize) as libc::c_int { ret += &format!( "\nFile: {}, {}, bytes\n", @@ -285,55 +280,44 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch } free(p as *mut libc::c_void); - if (*msg).type_0 != Viewtype::Text { + if msg.type_0 != Viewtype::Text { ret += "Type: "; - ret += &format!("{}", (*msg).type_0); + ret += &format!("{}", msg.type_0); ret += "\n"; - p = dc_msg_get_filemime(msg); + p = dc_msg_get_filemime(&msg); ret += &format!("Mimetype: {}\n", as_str(p)); free(p as *mut libc::c_void); } - let w = (*msg).param.get_int(Param::Width).unwrap_or_default(); - let h = (*msg).param.get_int(Param::Height).unwrap_or_default(); + let w = msg.param.get_int(Param::Width).unwrap_or_default(); + let h = msg.param.get_int(Param::Height).unwrap_or_default(); if w != 0 || h != 0 { ret += &format!("Dimension: {} x {}\n", w, h,); } - let duration = (*msg).param.get_int(Param::Duration).unwrap_or_default(); + let duration = msg.param.get_int(Param::Duration).unwrap_or_default(); if duration != 0 { ret += &format!("Duration: {} ms\n", duration,); } if !rawtxt.is_empty() { ret += &format!("\n{}\n", rawtxt); } - if !(*msg).rfc724_mid.is_null() && 0 != *(*msg).rfc724_mid.offset(0) as libc::c_int { - ret += &format!("\nMessage-ID: {}", as_str((*msg).rfc724_mid)); + if !msg.rfc724_mid.is_null() && 0 != *msg.rfc724_mid.offset(0) as libc::c_int { + ret += &format!("\nMessage-ID: {}", as_str(msg.rfc724_mid)); } - if let Some(ref server_folder) = (*msg).server_folder { + if let Some(ref server_folder) = msg.server_folder { if server_folder != "" { - ret += &format!("\nLast seen as: {}/{}", server_folder, (*msg).server_uid); + ret += &format!("\nLast seen as: {}/{}", server_folder, msg.server_uid); } } - dc_msg_unref(msg); ret.strdup() } -pub unsafe fn dc_msg_new_untyped<'a>(context: &'a Context) -> *mut dc_msg_t<'a> { +pub unsafe fn dc_msg_new_untyped<'a>(context: &'a Context) -> Message<'a> { dc_msg_new(context, Viewtype::Unknown) } -/* * - * @class dc_msg_t - * - * An object representing a single message in memory. - * The message object is not updated. - * If you want an update, you have to recreate the object. - */ -// to check if a mail was sent, use dc_msg_is_sent() -// approx. max. length returned by dc_msg_get_text() -// approx. max. length returned by dc_get_msg_info() -pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut dc_msg_t<'a> { - let msg = dc_msg_t { +pub fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> Message<'a> { + Message { id: 0, from_id: 0, to_id: 0, @@ -341,7 +325,7 @@ pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut d move_state: MoveState::Undefined, type_0: viewtype, state: MessageState::Undefined, - hidden: 0, + hidden: false, timestamp_sort: 0, timestamp_sent: 0, timestamp_rcvd: 0, @@ -352,43 +336,26 @@ pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut d server_folder: None, server_uid: 0, is_dc_message: 0, - starred: 0, - chat_blocked: 0, + starred: false, + chat_blocked: Blocked::Not, location_id: 0, param: Params::new(), - }; - - Box::into_raw(Box::new(msg)) + } } -pub unsafe fn dc_msg_unref(msg: *mut dc_msg_t) { - if msg.is_null() { - return; +impl<'a> Drop for Message<'a> { + fn drop(&mut self) { + unsafe { + free(self.rfc724_mid.cast()); + free(self.in_reply_to.cast()); + } } - dc_msg_empty(msg); - Box::from_raw(msg); } -pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) { - if msg.is_null() { - return; - } - free((*msg).rfc724_mid as *mut libc::c_void); - (*msg).rfc724_mid = 0 as *mut libc::c_char; - free((*msg).in_reply_to as *mut libc::c_void); - (*msg).in_reply_to = 0 as *mut libc::c_char; - (*msg).param = Params::new(); - (*msg).hidden = 0i32; -} - -pub unsafe fn dc_msg_get_filemime(msg: *const dc_msg_t) -> *mut libc::c_char { - if msg.is_null() { - return dc_strdup(0 as *const libc::c_char); - } - - if let Some(m) = (*msg).param.get(Param::MimeType) { +pub unsafe fn dc_msg_get_filemime(msg: &Message) -> *mut libc::c_char { + if let Some(m) = msg.param.get(Param::MimeType) { return m.strdup(); - } else if let Some(file) = (*msg).param.get(Param::File) { + } else if let Some(file) = msg.param.get(Param::File) { if let Some((_, mime)) = dc_msg_guess_msgtype_from_suffix(Path::new(file)) { return mime.strdup(); } @@ -415,13 +382,11 @@ pub fn dc_msg_guess_msgtype_from_suffix(path: &Path) -> Option<(Viewtype, &str)> KNOWN.get(extension).map(|x| *x) } -pub unsafe fn dc_msg_get_file(msg: *const dc_msg_t) -> *mut libc::c_char { +pub unsafe fn dc_msg_get_file(msg: &Message) -> *mut libc::c_char { let mut file_abs = 0 as *mut libc::c_char; - if !msg.is_null() { - if let Some(file_rel) = (*msg).param.get(Param::File) { - file_abs = dc_get_abs_path((*msg).context, file_rel); - } + if let Some(file_rel) = msg.param.get(Param::File) { + file_abs = dc_get_abs_path(msg.context, file_rel); } if !file_abs.is_null() { file_abs @@ -435,16 +400,12 @@ pub unsafe fn dc_msg_get_file(msg: *const dc_msg_t) -> *mut libc::c_char { * These messages are also returned by dc_get_locations() * and the UI may decide to display a special icon beside such messages, * - * @memberof dc_msg_t + * @memberof Message * @param msg The message object. * @return 1=Message has location bound to it, 0=No location bound to message. */ -pub unsafe fn dc_msg_has_location(msg: *const dc_msg_t) -> bool { - if msg.is_null() { - return false; - } - - ((*msg).location_id != 0i32 as libc::c_uint) +pub fn dc_msg_has_location(msg: &Message) -> bool { + msg.location_id != 0 } /** @@ -458,42 +419,31 @@ pub unsafe fn dc_msg_has_location(msg: *const dc_msg_t) -> bool { * Typically results in the event #DC_EVENT_LOCATION_CHANGED with * contact_id set to DC_CONTACT_ID_SELF. * - * @memberof dc_msg_t + * @memberof Message * @param msg The message object. * @param latitude North-south position of the location. * @param longitude East-west position of the location. * @return None. */ -pub unsafe fn dc_msg_set_location( - msg: *mut dc_msg_t, - latitude: libc::c_double, - longitude: libc::c_double, -) { - if msg.is_null() || (latitude == 0.0 && longitude == 0.0) { +pub fn dc_msg_set_location(msg: &mut Message, latitude: libc::c_double, longitude: libc::c_double) { + if latitude == 0.0 && longitude == 0.0 { return; } - (*msg).param.set_float(Param::SetLatitude, latitude); - (*msg).param.set_float(Param::SetLongitude, longitude); + msg.param.set_float(Param::SetLatitude, latitude); + msg.param.set_float(Param::SetLongitude, longitude); } -pub unsafe fn dc_msg_get_timestamp(msg: *const dc_msg_t) -> i64 { - if msg.is_null() { - return 0; - } - if 0 != (*msg).timestamp_sent { - (*msg).timestamp_sent +pub fn dc_msg_get_timestamp(msg: &Message) -> i64 { + if 0 != msg.timestamp_sent { + msg.timestamp_sent } else { - (*msg).timestamp_sort + msg.timestamp_sort } } -pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id: u32) -> bool { - if msg.is_null() { - return false; - } - - let res = context.sql.query_row( +pub fn dc_msg_load_from_db<'a>(context: &'a Context, id: u32) -> Result, Error> { + context.sql.query_row( "SELECT \ m.id,rfc724_mid,m.mime_in_reply_to,m.server_folder,m.server_uid,m.move_state,m.chat_id, \ m.from_id,m.to_id,m.timestamp,m.timestamp_sent,m.timestamp_rcvd, m.type,m.state,m.msgrmsg,m.txt, \ @@ -503,27 +453,26 @@ pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id: params![id as i32], |row| { unsafe { - (*msg).context = context; - dc_msg_empty(msg); - - (*msg).id = row.get::<_, i32>(0)? as u32; - (*msg).rfc724_mid = row.get::<_, String>(1)?.strdup(); - (*msg).in_reply_to = match row.get::<_, Option>(2)? { + let mut msg = dc_msg_new_untyped(context); + msg.context = context; + msg.id = row.get::<_, i32>(0)? as u32; + msg.rfc724_mid = row.get::<_, String>(1)?.strdup(); + msg.in_reply_to = match row.get::<_, Option>(2)? { Some(s) => s.strdup(), None => std::ptr::null_mut(), }; - (*msg).server_folder = row.get::<_, Option>(3)?; - (*msg).server_uid = row.get(4)?; - (*msg).move_state = row.get(5)?; - (*msg).chat_id = row.get(6)?; - (*msg).from_id = row.get(7)?; - (*msg).to_id = row.get(8)?; - (*msg).timestamp_sort = row.get(9)?; - (*msg).timestamp_sent = row.get(10)?; - (*msg).timestamp_rcvd = row.get(11)?; - (*msg).type_0 = row.get(12)?; - (*msg).state = row.get(13)?; - (*msg).is_dc_message = row.get(14)?; + msg.server_folder = row.get::<_, Option>(3)?; + msg.server_uid = row.get(4)?; + msg.move_state = row.get(5)?; + msg.chat_id = row.get(6)?; + msg.from_id = row.get(7)?; + msg.to_id = row.get(8)?; + msg.timestamp_sort = row.get(9)?; + msg.timestamp_sent = row.get(10)?; + msg.timestamp_rcvd = row.get(11)?; + msg.type_0 = row.get(12)?; + msg.state = row.get(13)?; + msg.is_dc_message = row.get(14)?; let text; if let rusqlite::types::ValueRef::Text(buf) = row.get_raw(15) { @@ -537,38 +486,29 @@ pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id: warn!(context, 0, "dc_msg_load_from_db: could not get text column for id {}", id); text = "[ Could not read from db ]".to_string(); } - (*msg).text = Some(text); + msg.text = Some(text); - (*msg).param = row.get::<_, String>(16)?.parse().unwrap_or_default(); - (*msg).starred = row.get(17)?; - (*msg).hidden = row.get(18)?; - (*msg).location_id = row.get(19)?; - (*msg).chat_blocked = row.get::<_, Option>(20)?.unwrap_or_default(); - if (*msg).chat_blocked == 2 { - if let Some(ref text) = (*msg).text { + msg.param = row.get::<_, String>(16)?.parse().unwrap_or_default(); + msg.starred = row.get(17)?; + msg.hidden = row.get(18)?; + msg.location_id = row.get(19)?; + msg.chat_blocked = row.get::<_, Option>(20)?.unwrap_or_default(); + if msg.chat_blocked == Blocked::Deaddrop { + if let Some(ref text) = msg.text { let ptr = text.strdup(); dc_truncate_n_unwrap_str(ptr, 256, 0); - (*msg).text = Some(to_string(ptr)); + msg.text = Some(to_string(ptr)); free(ptr.cast()); } }; - Ok(()) + Ok(msg) } - }); - - if let Err(e) = res { - warn!( - context, - 0, "Error in msg_load_from_db for id {} because of {}", id, e - ); - return false; - } - true + }) } -pub unsafe fn dc_get_mime_headers(context: &Context, msg_id: uint32_t) -> *mut libc::c_char { +pub unsafe fn dc_get_mime_headers(context: &Context, msg_id: u32) -> *mut libc::c_char { let headers: Option = context.sql.query_row_col( context, "SELECT mime_headers FROM msgs WHERE id=?;", @@ -584,13 +524,13 @@ pub unsafe fn dc_get_mime_headers(context: &Context, msg_id: uint32_t) -> *mut l } } -pub unsafe fn dc_delete_msgs(context: &Context, msg_ids: *const uint32_t, msg_cnt: libc::c_int) { +pub unsafe fn dc_delete_msgs(context: &Context, msg_ids: *const u32, msg_cnt: libc::c_int) { if msg_ids.is_null() || msg_cnt <= 0i32 { return; } let mut i: libc::c_int = 0i32; while i < msg_cnt { - dc_update_msg_chat_id(context, *msg_ids.offset(i as isize), 3i32 as uint32_t); + dc_update_msg_chat_id(context, *msg_ids.offset(i as isize), 3i32 as u32); job_add( context, Action::DeleteMsgOnImap, @@ -676,7 +616,7 @@ pub fn dc_markseen_msgs(context: &Context, msg_ids: *const u32, msg_cnt: usize) true } -pub fn dc_update_msg_state(context: &Context, msg_id: uint32_t, state: MessageState) -> bool { +pub fn dc_update_msg_state(context: &Context, msg_id: u32, state: MessageState) -> bool { sql::execute( context, &context.sql, @@ -706,85 +646,44 @@ pub fn dc_star_msgs( .is_ok() } -pub unsafe fn dc_get_msg<'a>(context: &'a Context, msg_id: uint32_t) -> *mut dc_msg_t<'a> { - let mut success = false; - let obj: *mut dc_msg_t = dc_msg_new_untyped(context); - if dc_msg_load_from_db(obj, context, msg_id) { - success = true - } +pub fn dc_get_msg<'a>(context: &'a Context, msg_id: u32) -> Result, Error> { + dc_msg_load_from_db(context, msg_id) +} - if success { - obj +pub fn dc_msg_get_id(msg: &Message) -> u32 { + msg.id +} + +pub fn dc_msg_get_from_id(msg: &Message) -> u32 { + msg.from_id +} + +pub fn dc_msg_get_chat_id(msg: &Message) -> u32 { + if msg.chat_blocked != Blocked::Not { + 1 } else { - dc_msg_unref(obj); - 0 as *mut dc_msg_t + msg.chat_id } } -pub unsafe fn dc_msg_get_id(msg: *const dc_msg_t) -> uint32_t { - if msg.is_null() { - return 0i32 as uint32_t; - } - - (*msg).id +pub fn dc_msg_get_viewtype(msg: &Message) -> Viewtype { + msg.type_0 } -pub unsafe fn dc_msg_get_from_id(msg: *const dc_msg_t) -> uint32_t { - if msg.is_null() { - return 0i32 as uint32_t; - } - - (*msg).from_id +pub fn dc_msg_get_state(msg: &Message) -> MessageState { + msg.state } -pub unsafe fn dc_msg_get_chat_id(msg: *const dc_msg_t) -> uint32_t { - if msg.is_null() { - return 0i32 as uint32_t; - } - return if 0 != (*msg).chat_blocked { - 1i32 as libc::c_uint - } else { - (*msg).chat_id - }; +pub fn dc_msg_get_received_timestamp(msg: &Message) -> i64 { + msg.timestamp_rcvd } -pub unsafe fn dc_msg_get_viewtype(msg: *const dc_msg_t) -> Viewtype { - if msg.is_null() { - return Viewtype::Unknown; - } - - (*msg).type_0 +pub fn dc_msg_get_sort_timestamp(msg: &Message) -> i64 { + msg.timestamp_sort } -pub unsafe fn dc_msg_get_state(msg: *const dc_msg_t) -> MessageState { - if msg.is_null() { - return MessageState::Undefined; - } - - (*msg).state -} - -pub unsafe fn dc_msg_get_received_timestamp(msg: *const dc_msg_t) -> i64 { - if msg.is_null() { - return 0; - } - - (*msg).timestamp_rcvd -} - -pub unsafe fn dc_msg_get_sort_timestamp(msg: *const dc_msg_t) -> i64 { - if msg.is_null() { - return 0; - } - - (*msg).timestamp_sort -} - -pub unsafe fn dc_msg_get_text(msg: *const dc_msg_t) -> *mut libc::c_char { - if msg.is_null() { - return dc_strdup(0 as *const libc::c_char); - } - if let Some(ref text) = (*msg).text { +pub unsafe fn dc_msg_get_text(msg: &Message) -> *mut libc::c_char { + if let Some(ref text) = msg.text { dc_truncate(text, 30000, false).strdup() } else { ptr::null_mut() @@ -792,13 +691,11 @@ pub unsafe fn dc_msg_get_text(msg: *const dc_msg_t) -> *mut libc::c_char { } #[allow(non_snake_case)] -pub unsafe fn dc_msg_get_filename(msg: *const dc_msg_t) -> *mut libc::c_char { +pub unsafe fn dc_msg_get_filename(msg: &Message) -> *mut libc::c_char { let mut ret = 0 as *mut libc::c_char; - if !msg.is_null() { - if let Some(file) = (*msg).param.get(Param::File) { - ret = dc_get_filename(file); - } + if let Some(file) = msg.param.get(Param::File) { + ret = dc_get_filename(file); } if !ret.is_null() { ret @@ -807,69 +704,43 @@ pub unsafe fn dc_msg_get_filename(msg: *const dc_msg_t) -> *mut libc::c_char { } } -pub unsafe fn dc_msg_get_filebytes(msg: *const dc_msg_t) -> uint64_t { - if !msg.is_null() { - if let Some(file) = (*msg).param.get(Param::File) { - return dc_get_filebytes((*msg).context, &file); - } +pub unsafe fn dc_msg_get_filebytes(msg: &Message) -> uint64_t { + if let Some(file) = msg.param.get(Param::File) { + return dc_get_filebytes(msg.context, &file); } 0 } -pub unsafe fn dc_msg_get_width(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() { - return 0; - } - - (*msg).param.get_int(Param::Width).unwrap_or_default() +pub fn dc_msg_get_width(msg: &Message) -> libc::c_int { + msg.param.get_int(Param::Width).unwrap_or_default() } -pub unsafe fn dc_msg_get_height(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() { - return 0; - } - - (*msg).param.get_int(Param::Height).unwrap_or_default() +pub fn dc_msg_get_height(msg: &Message) -> libc::c_int { + msg.param.get_int(Param::Height).unwrap_or_default() } -pub unsafe fn dc_msg_get_duration(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() { - return 0; - } - - (*msg).param.get_int(Param::Duration).unwrap_or_default() +pub fn dc_msg_get_duration(msg: &Message) -> libc::c_int { + msg.param.get_int(Param::Duration).unwrap_or_default() } // TODO should return bool /rtn -pub unsafe fn dc_msg_get_showpadlock(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() { - return 0; - } - if (*msg) - .param - .get_int(Param::GuranteeE2ee) - .unwrap_or_default() - != 0 - { +pub fn dc_msg_get_showpadlock(msg: &Message) -> libc::c_int { + if msg.param.get_int(Param::GuranteeE2ee).unwrap_or_default() != 0 { return 1; } 0 } -pub unsafe fn dc_msg_get_summary<'a>(msg: *mut dc_msg_t<'a>, chat: Option<&Chat<'a>>) -> Lot { +pub unsafe fn dc_msg_get_summary<'a>(msg: &mut Message<'a>, chat: Option<&Chat<'a>>) -> Lot { let mut ret = Lot::new(); - if msg.is_null() { - return ret; - } - let chat_loaded: Chat; let chat = if let Some(chat) = chat { chat } else { - if let Ok(chat) = Chat::load_from_db((*msg).context, (*msg).chat_id) { + if let Ok(chat) = Chat::load_from_db(msg.context, msg.chat_id) { chat_loaded = chat; &chat_loaded } else { @@ -877,33 +748,29 @@ pub unsafe fn dc_msg_get_summary<'a>(msg: *mut dc_msg_t<'a>, chat: Option<&Chat< } }; - let contact = if (*msg).from_id != DC_CONTACT_ID_SELF as libc::c_uint + let contact = if msg.from_id != DC_CONTACT_ID_SELF as libc::c_uint && ((*chat).typ == Chattype::Group || (*chat).typ == Chattype::VerifiedGroup) { - Contact::get_by_id((*chat).context, (*msg).from_id).ok() + Contact::get_by_id((*chat).context, msg.from_id).ok() } else { None }; - ret.fill(msg, chat, contact.as_ref(), (*msg).context); + ret.fill(msg, chat, contact.as_ref(), msg.context); ret } pub unsafe fn dc_msg_get_summarytext( - msg: *mut dc_msg_t, + msg: &mut Message, approx_characters: usize, ) -> *mut libc::c_char { - if msg.is_null() { - return dc_strdup(0 as *const libc::c_char); - } - dc_msg_get_summarytext_by_raw( - (*msg).type_0, - (*msg).text.as_ref(), - &mut (*msg).param, + msg.type_0, + msg.text.as_ref(), + &mut msg.param, approx_characters, - (*msg).context, + msg.context, ) .strdup() } @@ -972,7 +839,7 @@ pub fn dc_msg_get_summarytext_by_raw( ret } -pub unsafe fn dc_msg_has_deviating_timestamp(msg: *const dc_msg_t) -> libc::c_int { +pub unsafe fn dc_msg_has_deviating_timestamp(msg: &Message) -> libc::c_int { let cnv_to_local = dc_gm2local_offset(); let sort_timestamp = dc_msg_get_sort_timestamp(msg) as i64 + cnv_to_local; let send_timestamp = dc_msg_get_timestamp(msg) as i64 + cnv_to_local; @@ -981,30 +848,21 @@ pub unsafe fn dc_msg_has_deviating_timestamp(msg: *const dc_msg_t) -> libc::c_in } // TODO should return bool /rtn -pub unsafe fn dc_msg_is_sent(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() { - return 0; - } - if (*msg).state as i32 >= MessageState::OutDelivered as i32 { +pub fn dc_msg_is_sent(msg: &Message) -> libc::c_int { + if msg.state as i32 >= MessageState::OutDelivered as i32 { 1 } else { 0 } } -pub unsafe fn dc_msg_is_starred(msg: *const dc_msg_t) -> bool { - if msg.is_null() { - return false; - } - 0 != (*msg).starred +pub fn dc_msg_is_starred(msg: &Message) -> bool { + msg.starred } // TODO should return bool /rtn -pub unsafe fn dc_msg_is_forwarded(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() { - return 0; - } - if 0 != (*msg).param.get_int(Param::Forwarded).unwrap_or_default() { +pub fn dc_msg_is_forwarded(msg: &Message) -> libc::c_int { + if 0 != msg.param.get_int(Param::Forwarded).unwrap_or_default() { 1 } else { 0 @@ -1012,13 +870,10 @@ pub unsafe fn dc_msg_is_forwarded(msg: *const dc_msg_t) -> libc::c_int { } // TODO should return bool /rtn -pub unsafe fn dc_msg_is_info(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() { - return 0; - } - let cmd = (*msg).param.get_int(Param::Cmd).unwrap_or_default(); - if (*msg).from_id == 2i32 as libc::c_uint - || (*msg).to_id == 2i32 as libc::c_uint +pub fn dc_msg_is_info(msg: &Message) -> libc::c_int { + let cmd = msg.param.get_int(Param::Cmd).unwrap_or_default(); + if msg.from_id == 2i32 as libc::c_uint + || msg.to_id == 2i32 as libc::c_uint || 0 != cmd && cmd != 6i32 { return 1; @@ -1028,27 +883,23 @@ pub unsafe fn dc_msg_is_info(msg: *const dc_msg_t) -> libc::c_int { } // TODO should return bool /rtn -pub unsafe fn dc_msg_is_increation(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() { - return 0; - } - - if chat::msgtype_has_file((*msg).type_0) && (*msg).state == MessageState::OutPreparing { +pub fn dc_msg_is_increation(msg: &Message) -> libc::c_int { + if chat::msgtype_has_file(msg.type_0) && msg.state == MessageState::OutPreparing { 1 } else { 0 } } -pub unsafe fn dc_msg_is_setupmessage(msg: *const dc_msg_t) -> bool { - if msg.is_null() || (*msg).type_0 != Viewtype::File { +pub fn dc_msg_is_setupmessage(msg: &Message) -> bool { + if msg.type_0 != Viewtype::File { return false; } - (*msg).param.get_int(Param::Cmd) == Some(6) + msg.param.get_int(Param::Cmd) == Some(6) } -pub unsafe fn dc_msg_get_setupcodebegin(msg: *const dc_msg_t) -> *mut libc::c_char { +pub unsafe fn dc_msg_get_setupcodebegin(msg: &Message) -> *mut libc::c_char { let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; let mut buf: *mut libc::c_char = 0 as *mut libc::c_char; let mut buf_bytes: size_t = 0i32 as size_t; @@ -1062,7 +913,7 @@ pub unsafe fn dc_msg_get_setupcodebegin(msg: *const dc_msg_t) -> *mut libc::c_ch if !(filename.is_null() || *filename.offset(0isize) as libc::c_int == 0i32) { if !(0 == dc_read_file( - (*msg).context, + msg.context, filename, &mut buf as *mut *mut libc::c_char as *mut *mut libc::c_void, &mut buf_bytes, @@ -1096,72 +947,53 @@ pub unsafe fn dc_msg_get_setupcodebegin(msg: *const dc_msg_t) -> *mut libc::c_ch } } -pub unsafe fn dc_msg_set_text(mut msg: *mut dc_msg_t, text: *const libc::c_char) { - if msg.is_null() { - return; - } - (*msg).text = if text.is_null() { +pub fn dc_msg_set_text(msg: &mut Message, text: *const libc::c_char) { + msg.text = if text.is_null() { None } else { Some(to_string(text)) }; } -pub unsafe fn dc_msg_set_file( - msg: *mut dc_msg_t, +pub fn dc_msg_set_file( + msg: &mut Message, file: *const libc::c_char, filemime: *const libc::c_char, ) { - if msg.is_null() { - return; - } if !file.is_null() { - (*msg).param.set(Param::File, as_str(file)); + msg.param.set(Param::File, as_str(file)); } if !filemime.is_null() { - (*msg).param.set(Param::MimeType, as_str(filemime)); + msg.param.set(Param::MimeType, as_str(filemime)); } } -pub unsafe fn dc_msg_set_dimension(msg: *mut dc_msg_t, width: libc::c_int, height: libc::c_int) { - if msg.is_null() { - return; - } - (*msg).param.set_int(Param::Width, width); - (*msg).param.set_int(Param::Height, height); +pub fn dc_msg_set_dimension(msg: &mut Message, width: libc::c_int, height: libc::c_int) { + msg.param.set_int(Param::Width, width); + msg.param.set_int(Param::Height, height); } -pub unsafe fn dc_msg_set_duration(msg: *mut dc_msg_t, duration: libc::c_int) { - if msg.is_null() { - return; - } - (*msg).param.set_int(Param::Duration, duration); +pub fn dc_msg_set_duration(msg: &mut Message, duration: libc::c_int) { + msg.param.set_int(Param::Duration, duration); } -pub unsafe fn dc_msg_latefiling_mediasize( - msg: *mut dc_msg_t, +pub fn dc_msg_latefiling_mediasize( + msg: &mut Message, width: libc::c_int, height: libc::c_int, duration: libc::c_int, ) { - if !msg.is_null() { - if width > 0 && height > 0 { - (*msg).param.set_int(Param::Width, width); - (*msg).param.set_int(Param::Height, height); - } - if duration > 0 { - (*msg).param.set_int(Param::Duration, duration); - } - dc_msg_save_param_to_disk(msg); - }; + if width > 0 && height > 0 { + msg.param.set_int(Param::Width, width); + msg.param.set_int(Param::Height, height); + } + if duration > 0 { + msg.param.set_int(Param::Duration, duration); + } + dc_msg_save_param_to_disk(msg); } -pub fn dc_msg_save_param_to_disk(msg: *mut dc_msg_t) -> bool { - if msg.is_null() { - return false; - } - - let msg = unsafe { &*msg }; +pub fn dc_msg_save_param_to_disk(msg: &mut Message) -> bool { sql::execute( msg.context, &msg.context.sql, @@ -1171,31 +1003,27 @@ pub fn dc_msg_save_param_to_disk(msg: *mut dc_msg_t) -> bool { .is_ok() } -pub unsafe fn dc_msg_new_load<'a>(context: &'a Context, msg_id: uint32_t) -> *mut dc_msg_t<'a> { - let msg = dc_msg_new_untyped(context); - dc_msg_load_from_db(msg, context, msg_id); - msg +pub fn dc_msg_new_load<'a>(context: &'a Context, msg_id: u32) -> Result, Error> { + dc_msg_load_from_db(context, msg_id) } -pub unsafe fn dc_delete_msg_from_db(context: &Context, msg_id: uint32_t) { - let msg: *mut dc_msg_t = dc_msg_new_untyped(context); - if dc_msg_load_from_db(msg, context, msg_id) { +pub fn dc_delete_msg_from_db(context: &Context, msg_id: u32) { + if let Ok(msg) = dc_msg_load_from_db(context, msg_id) { sql::execute( context, &context.sql, "DELETE FROM msgs WHERE id=?;", - params![(*msg).id as i32], + params![msg.id as i32], ) .ok(); sql::execute( context, &context.sql, "DELETE FROM msgs_mdns WHERE msg_id=?;", - params![(*msg).id as i32], + params![msg.id as i32], ) .ok(); } - dc_msg_unref(msg); } /* as we do not cut inside words, this results in about 32-42 characters. @@ -1205,7 +1033,7 @@ The value is also used for CC:-summaries */ // Context functions to work with messages -pub unsafe fn dc_msg_exists(context: &Context, msg_id: uint32_t) -> libc::c_int { +pub unsafe fn dc_msg_exists(context: &Context, msg_id: u32) -> libc::c_int { if msg_id <= 9 { return 0; } @@ -1242,15 +1070,13 @@ pub fn dc_update_msg_move_state( .is_ok() } -pub unsafe fn dc_set_msg_failed(context: &Context, msg_id: u32, error: Option>) { - let mut msg = dc_msg_new_untyped(context); - - if dc_msg_load_from_db(msg, context, msg_id) { - if (*msg).state.can_fail() { - (*msg).state = MessageState::OutFailed; +pub fn dc_set_msg_failed(context: &Context, msg_id: u32, error: Option>) { + if let Ok(mut msg) = dc_msg_load_from_db(context, msg_id) { + if msg.state.can_fail() { + msg.state = MessageState::OutFailed; } if let Some(error) = error { - (*msg).param.set(Param::Error, error.as_ref()); + msg.param.set(Param::Error, error.as_ref()); error!(context, 0, "{}", error.as_ref()); } @@ -1258,19 +1084,17 @@ pub unsafe fn dc_set_msg_failed(context: &Context, msg_id: u32, error: Option uint32_t { + ret_server_uid: *mut u32, +) -> u32 { if rfc724_mid.is_null() || unsafe { *rfc724_mid.offset(0) as libc::c_int } == 0 { return 0; } @@ -1459,7 +1283,7 @@ pub fn dc_update_server_uid( context: &Context, rfc724_mid: *const libc::c_char, server_folder: impl AsRef, - server_uid: uint32_t, + server_uid: u32, ) { match context.sql.execute( "UPDATE msgs SET server_folder=?, server_uid=? WHERE rfc724_mid=?;", @@ -1489,25 +1313,21 @@ mod tests { pub fn test_prepare_message_and_send() { use crate::config::Config; - unsafe { - let d = test::dummy_context(); - let ctx = &d.ctx; + let d = test::dummy_context(); + let ctx = &d.ctx; - let contact = - Contact::create(ctx, "", "dest@example.com").expect("failed to create contact"); + let contact = + Contact::create(ctx, "", "dest@example.com").expect("failed to create contact"); - let res = ctx.set_config(Config::ConfiguredAddr, Some("self@example.com")); - assert!(res.is_ok()); + let res = ctx.set_config(Config::ConfiguredAddr, Some("self@example.com")); + assert!(res.is_ok()); - let chat = chat::create_by_contact_id(ctx, contact).unwrap(); + let chat = chat::create_by_contact_id(ctx, contact).unwrap(); - let msg = dc_msg_new(ctx, Viewtype::Text); - assert!(!msg.is_null()); + let mut msg = dc_msg_new(ctx, Viewtype::Text); - let msg_id = chat::prepare_msg(ctx, chat, msg).unwrap(); + let msg_id = chat::prepare_msg(ctx, chat, &mut msg).unwrap(); - let msg2 = dc_get_msg(ctx, msg_id); - assert!(!msg2.is_null()); - } + let _msg2 = dc_get_msg(ctx, msg_id).unwrap(); } } diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs index 1910411c8..b4ff73cc1 100644 --- a/src/dc_securejoin.rs +++ b/src/dc_securejoin.rs @@ -293,38 +293,37 @@ unsafe fn send_handshake_msg( fingerprint: *const libc::c_char, grpid: impl AsRef, ) { - let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); - (*msg).type_0 = Viewtype::Text; - (*msg).text = Some(format!("Secure-Join: {}", to_string(step))); - (*msg).hidden = 1; - (*msg).param.set_int(Param::Cmd, 7); + let mut msg = dc_msg_new_untyped(context); + msg.type_0 = Viewtype::Text; + msg.text = Some(format!("Secure-Join: {}", to_string(step))); + msg.hidden = true; + msg.param.set_int(Param::Cmd, 7); if step.is_null() { - (*msg).param.remove(Param::Arg); + msg.param.remove(Param::Arg); } else { - (*msg).param.set(Param::Arg, as_str(step)); + msg.param.set(Param::Arg, as_str(step)); } if !param2.as_ref().is_empty() { - (*msg).param.set(Param::Arg2, param2); + msg.param.set(Param::Arg2, param2); } if !fingerprint.is_null() { - (*msg).param.set(Param::Arg3, as_str(fingerprint)); + msg.param.set(Param::Arg3, as_str(fingerprint)); } if !grpid.as_ref().is_empty() { - (*msg).param.set(Param::Arg4, grpid.as_ref()); + msg.param.set(Param::Arg4, grpid.as_ref()); } if strcmp(step, b"vg-request\x00" as *const u8 as *const libc::c_char) == 0i32 || strcmp(step, b"vc-request\x00" as *const u8 as *const libc::c_char) == 0i32 { - (*msg).param.set_int( + msg.param.set_int( Param::ForcePlaintext, ForcePlaintext::AddAutocryptHeader as i32, ); } else { - (*msg).param.set_int(Param::GuranteeE2ee, 1); + msg.param.set_int(Param::GuranteeE2ee, 1); } // TODO. handle cleanup on error - chat::send_msg(context, contact_chat_id, msg).unwrap(); - dc_msg_unref(msg); + chat::send_msg(context, contact_chat_id, &mut msg).unwrap(); } unsafe fn chat_id_2_contact_id(context: &Context, contact_chat_id: uint32_t) -> uint32_t { diff --git a/src/job.rs b/src/job.rs index ea7faa5a7..a147a944f 100644 --- a/src/job.rs +++ b/src/job.rs @@ -226,7 +226,6 @@ impl Job { #[allow(non_snake_case)] fn do_DC_JOB_MOVE_MSG(&mut self, context: &Context) { let ok_to_continue; - let msg = unsafe { dc_msg_new_untyped(context) }; let mut dest_uid = 0; let inbox = context.inbox.read().unwrap(); @@ -243,7 +242,7 @@ impl Job { ok_to_continue = true; } if ok_to_continue { - if dc_msg_load_from_db(msg, context, self.foreign_id) { + if let Ok(msg) = dc_msg_load_from_db(context, self.foreign_id) { if context .sql .get_config_int(context, "folders_configured") @@ -254,8 +253,6 @@ impl Job { } let dest_folder = context.sql.get_config(context, "configured_mvbox_folder"); - let msg = unsafe { &mut *msg }; - if let Some(dest_folder) = dest_folder { let server_folder = msg.server_folder.as_ref().unwrap(); @@ -278,71 +275,65 @@ impl Job { } } } - - unsafe { dc_msg_unref(msg) }; } #[allow(non_snake_case)] fn do_DC_JOB_DELETE_MSG_ON_IMAP(&mut self, context: &Context) { let mut delete_from_server = 1; - let msg = unsafe { dc_msg_new_untyped(context) }; let inbox = context.inbox.read().unwrap(); - if !(!dc_msg_load_from_db(msg, context, self.foreign_id) - || unsafe { (*msg).rfc724_mid.is_null() } - || unsafe { *(*msg).rfc724_mid.offset(0isize) as libc::c_int == 0 }) - { - let ok_to_continue1; - /* eg. device messages have no Message-ID */ - if dc_rfc724_mid_cnt(context, unsafe { (*msg).rfc724_mid }) != 1 { - info!( - context, - 0, "The message is deleted from the server when all parts are deleted.", - ); - delete_from_server = 0i32 - } - /* if this is the last existing part of the message, we delete the message from the server */ - if 0 != delete_from_server { - let ok_to_continue; - if !inbox.is_connected() { - connect_to_inbox(context, &inbox); + if let Ok(mut msg) = dc_msg_load_from_db(context, self.foreign_id) { + if !(msg.rfc724_mid.is_null() + || unsafe { *msg.rfc724_mid.offset(0isize) as libc::c_int == 0 }) + { + let ok_to_continue1; + /* eg. device messages have no Message-ID */ + if dc_rfc724_mid_cnt(context, msg.rfc724_mid) != 1 { + info!( + context, + 0, "The message is deleted from the server when all parts are deleted.", + ); + delete_from_server = 0i32 + } + /* if this is the last existing part of the message, we delete the message from the server */ + if 0 != delete_from_server { + let ok_to_continue; if !inbox.is_connected() { - self.try_again_later(3i32, None); - ok_to_continue = false; + connect_to_inbox(context, &inbox); + if !inbox.is_connected() { + self.try_again_later(3i32, None); + ok_to_continue = false; + } else { + ok_to_continue = true; + } } else { ok_to_continue = true; } - } else { - ok_to_continue = true; - } - if ok_to_continue { - let mid = unsafe { CStr::from_ptr((*msg).rfc724_mid).to_str().unwrap() }; - let server_folder = unsafe { (*msg).server_folder.as_ref().unwrap() }; - if 0 == inbox.delete_msg(context, mid, server_folder, unsafe { - &mut (*msg).server_uid - }) { - self.try_again_later(-1i32, None); - ok_to_continue1 = false; + if ok_to_continue { + let mid = unsafe { CStr::from_ptr(msg.rfc724_mid).to_str().unwrap() }; + let server_folder = msg.server_folder.as_ref().unwrap(); + if 0 == inbox.delete_msg(context, mid, server_folder, &mut msg.server_uid) { + self.try_again_later(-1i32, None); + ok_to_continue1 = false; + } else { + ok_to_continue1 = true; + } } else { - ok_to_continue1 = true; + ok_to_continue1 = false; } } else { - ok_to_continue1 = false; + ok_to_continue1 = true; + } + if ok_to_continue1 { + dc_delete_msg_from_db(context, msg.id); } - } else { - ok_to_continue1 = true; - } - if ok_to_continue1 { - unsafe { dc_delete_msg_from_db(context, (*msg).id) }; } } - unsafe { dc_msg_unref(msg) } } #[allow(non_snake_case)] fn do_DC_JOB_MARKSEEN_MSG_ON_IMAP(&mut self, context: &Context) { let ok_to_continue; - let msg = unsafe { dc_msg_new_untyped(context) }; let inbox = context.inbox.read().unwrap(); if !inbox.is_connected() { @@ -357,32 +348,29 @@ impl Job { ok_to_continue = true; } if ok_to_continue { - if dc_msg_load_from_db(msg, context, self.foreign_id) { - let server_folder = unsafe { (*msg).server_folder.as_ref().unwrap() }; - match inbox.set_seen(context, server_folder, unsafe { (*msg).server_uid }) - as libc::c_uint - { + if let Ok(msg) = dc_msg_load_from_db(context, self.foreign_id) { + let server_folder = msg.server_folder.as_ref().unwrap(); + match inbox.set_seen(context, server_folder, msg.server_uid) as libc::c_uint { 0 => {} 1 => { self.try_again_later(3i32, None); } _ => { - if 0 != unsafe { (*msg).param.get_int(Param::WantsMdn).unwrap_or_default() } + if 0 != msg.param.get_int(Param::WantsMdn).unwrap_or_default() && 0 != context .sql .get_config_int(context, "mdns_enabled") .unwrap_or_else(|| 1) { - let folder = unsafe { (*msg).server_folder.as_ref().unwrap() }; + let folder = msg.server_folder.as_ref().unwrap(); - match inbox.set_mdnsent(context, folder, unsafe { (*msg).server_uid }) - as libc::c_uint + match inbox.set_mdnsent(context, folder, msg.server_uid) as libc::c_uint { 1 => { self.try_again_later(3i32, None); } 3 => { - send_mdn(context, unsafe { (*msg).id }); + send_mdn(context, msg.id); } 0 | 2 | _ => {} } @@ -391,7 +379,6 @@ impl Job { } } } - unsafe { dc_msg_unref(msg) }; } #[allow(non_snake_case)] @@ -674,55 +661,38 @@ pub fn job_action_exists(context: &Context, action: Action) -> bool { #[allow(non_snake_case)] pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int { let mut success = 0; - let mut mimefactory = dc_mimefactory_t { - from_addr: ptr::null_mut(), - from_displayname: ptr::null_mut(), - selfstatus: ptr::null_mut(), - recipients_names: ptr::null_mut(), - recipients_addr: ptr::null_mut(), - timestamp: 0, - rfc724_mid: ptr::null_mut(), - loaded: DC_MF_NOTHING_LOADED, - msg: ptr::null_mut(), - chat: None, - increation: 0, - in_reply_to: ptr::null_mut(), - references: ptr::null_mut(), - req_mdn: 0, - out: ptr::null_mut(), - out_encrypted: 0, - out_gossiped: 0, - out_last_added_location_id: 0, - error: ptr::null_mut(), - context, - }; /* load message data */ - if 0 == dc_mimefactory_load_msg(&mut mimefactory, msg_id) || mimefactory.from_addr.is_null() { + let mimefactory = dc_mimefactory_load_msg(context, msg_id); + if mimefactory.is_err() || mimefactory.as_ref().unwrap().from_addr.is_null() { warn!( context, 0, "Cannot load data to send, maybe the message is deleted in between.", ); } else { + let mut mimefactory = mimefactory.unwrap(); // no redo, no IMAP. moreover, as the data does not exist, there is no need in calling dc_set_msg_failed() - if chat::msgtype_has_file((*mimefactory.msg).type_0) { - if let Some(pathNfilename) = (*mimefactory.msg).param.get(Param::File) { - if ((*mimefactory.msg).type_0 == Viewtype::Image - || (*mimefactory.msg).type_0 == Viewtype::Gif) - && !(*mimefactory.msg).param.exists(Param::Width) + if chat::msgtype_has_file(mimefactory.msg.type_0) { + let file_param = mimefactory + .msg + .param + .get(Param::File) + .map(|s| s.to_string()); + if let Some(pathNfilename) = file_param { + if (mimefactory.msg.type_0 == Viewtype::Image + || mimefactory.msg.type_0 == Viewtype::Gif) + && !mimefactory.msg.param.exists(Param::Width) { - (*mimefactory.msg).param.set_int(Param::Width, 0); - (*mimefactory.msg).param.set_int(Param::Height, 0); + mimefactory.msg.param.set_int(Param::Width, 0); + mimefactory.msg.param.set_int(Param::Height, 0); if let Some(buf) = dc_read_file_safe(context, pathNfilename) { if let Ok((width, height)) = dc_get_filemeta(&buf) { - (*mimefactory.msg).param.set_int(Param::Width, width as i32); - (*mimefactory.msg) - .param - .set_int(Param::Height, height as i32); + mimefactory.msg.param.set_int(Param::Width, width as i32); + mimefactory.msg.param.set_int(Param::Height, height as i32); } } - dc_msg_save_param_to_disk(mimefactory.msg); + dc_msg_save_param_to_disk(&mut mimefactory.msg); } } } @@ -730,7 +700,8 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int { if 0 == dc_mimefactory_render(&mut mimefactory) { dc_set_msg_failed(context, msg_id, as_opt_str(mimefactory.error)); } else if 0 - != (*mimefactory.msg) + != mimefactory + .msg .param .get_int(Param::GuranteeE2ee) .unwrap_or_default() @@ -741,7 +712,7 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int { 0, "e2e encryption unavailable {} - {:?}", msg_id, - (*mimefactory.msg).param.get_int(Param::GuranteeE2ee), + mimefactory.msg.param.get_int(Param::GuranteeE2ee), ); dc_set_msg_failed( context, @@ -765,32 +736,32 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int { ); } if 0 != mimefactory.out_gossiped { - chat::set_gossiped_timestamp(context, (*mimefactory.msg).chat_id, time()); + chat::set_gossiped_timestamp(context, mimefactory.msg.chat_id, time()); } if 0 != mimefactory.out_last_added_location_id { - dc_set_kml_sent_timestamp(context, (*mimefactory.msg).chat_id, time()); - if 0 == (*mimefactory.msg).hidden { + dc_set_kml_sent_timestamp(context, mimefactory.msg.chat_id, time()); + if !mimefactory.msg.hidden { dc_set_msg_location_id( context, - (*mimefactory.msg).id, + mimefactory.msg.id, mimefactory.out_last_added_location_id, ); } } if 0 != mimefactory.out_encrypted - && (*mimefactory.msg) + && mimefactory + .msg .param .get_int(Param::GuranteeE2ee) .unwrap_or_default() == 0 { - (*mimefactory.msg).param.set_int(Param::GuranteeE2ee, 1); - dc_msg_save_param_to_disk(mimefactory.msg); + mimefactory.msg.param.set_int(Param::GuranteeE2ee, 1); + dc_msg_save_param_to_disk(&mut mimefactory.msg); } success = add_smtp_job(context, Action::SendMsgToSmtp, &mut mimefactory); } } - dc_mimefactory_empty(&mut mimefactory); success } @@ -979,9 +950,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) { } } else { if job.action == Action::SendMsgToSmtp { - unsafe { - dc_set_msg_failed(context, job.foreign_id, job.pending_error.as_ref()) - }; + dc_set_msg_failed(context, job.foreign_id, job.pending_error.as_ref()); } job.delete(context); } @@ -1034,33 +1003,10 @@ fn connect_to_inbox(context: &Context, inbox: &Imap) -> libc::c_int { } fn send_mdn(context: &Context, msg_id: uint32_t) { - let mut mimefactory = dc_mimefactory_t { - from_addr: ptr::null_mut(), - from_displayname: ptr::null_mut(), - selfstatus: ptr::null_mut(), - recipients_names: ptr::null_mut(), - recipients_addr: ptr::null_mut(), - timestamp: 0, - rfc724_mid: ptr::null_mut(), - loaded: DC_MF_NOTHING_LOADED, - msg: ptr::null_mut(), - chat: None, - increation: 0, - in_reply_to: ptr::null_mut(), - references: ptr::null_mut(), - req_mdn: 0, - out: ptr::null_mut(), - out_encrypted: 0, - out_gossiped: 0, - out_last_added_location_id: 0, - error: ptr::null_mut(), - context, - }; - - if !(0 == unsafe { dc_mimefactory_load_mdn(&mut mimefactory, msg_id) } - || 0 == unsafe { dc_mimefactory_render(&mut mimefactory) }) - { - add_smtp_job(context, Action::SendMdn, &mut mimefactory); + if let Ok(mut mimefactory) = unsafe { dc_mimefactory_load_mdn(context, msg_id) } { + if 0 != unsafe { dc_mimefactory_render(&mut mimefactory) } { + add_smtp_job(context, Action::SendMdn, &mut mimefactory); + } } } @@ -1116,7 +1062,7 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_ (if mimefactory.loaded as libc::c_uint == DC_MF_MSG_LOADED as libc::c_int as libc::c_uint { - unsafe { (*mimefactory.msg).id } + mimefactory.msg.id } else { 0 }) as libc::c_int, diff --git a/src/lib.rs b/src/lib.rs index bdebfb851..37ba888c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ extern crate strum_macros; #[macro_use] mod log; #[macro_use] -mod error; +pub mod error; mod aheader; pub mod chat;