diff --git a/Cargo.lock b/Cargo.lock index 384b1c560..93f5cbdb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -477,7 +477,7 @@ dependencies = [ "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "pgp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1424,6 +1424,11 @@ name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "percent-encoding" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pgp" version = "0.2.1" @@ -2815,6 +2820,7 @@ dependencies = [ "checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" "checksum parking_lot_core 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a7bbaa05312363e0480e1efee133fff1a09ef4a6406b65e226b9a793c223a32" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba4f28a6faf4ffea762ba8f4baef48c61a6db348647c73095034041fc79dd954" "checksum pgp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb80b37b7debf9a98dc0caca3ed40ddf1d383691208763d0458df0b91521020f" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" diff --git a/Cargo.toml b/Cargo.toml index 2865fe893..2d42e6798 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ imap = "1.0.1" mmime = "0.1.0" base64 = "0.10" charset = "0.1" -percent-encoding = "1.0" +percent-encoding = "2.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" chrono = "0.4.6" diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 7a5e77ba5..1b584d892 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -1322,9 +1322,9 @@ pub unsafe extern "C" fn dc_msg_get_showpadlock(msg: *mut dc_msg::dc_msg_t) -> l } #[no_mangle] -pub unsafe extern "C" fn dc_msg_get_summary( - msg: *mut dc_msg::dc_msg_t, - chat: *mut dc_chat_t, +pub unsafe extern "C" fn dc_msg_get_summary<'a>( + msg: *mut dc_msg::dc_msg_t<'a>, + chat: *mut dc_chat_t<'a>, ) -> *mut dc_lot::dc_lot_t { dc_msg::dc_msg_get_summary(msg, chat) } diff --git a/src/context.rs b/src/context.rs index 2d68b5f00..58d585292 100644 --- a/src/context.rs +++ b/src/context.rs @@ -14,6 +14,7 @@ use crate::dc_receive_imf::*; use crate::dc_tools::*; use crate::imap::*; use crate::key::*; +use crate::param::Params; use crate::smtp::*; use crate::sql::Sql; use crate::types::*; @@ -225,13 +226,7 @@ unsafe fn cb_precheck_imf( } dc_do_heuristics_moves(context, server_folder, msg_id); if 0 != mark_seen { - dc_job_add( - context, - 130i32, - msg_id as libc::c_int, - 0 as *const libc::c_char, - 0i32, - ); + dc_job_add(context, 130, msg_id as libc::c_int, Params::new(), 0); } } free(old_server_folder as *mut libc::c_void); diff --git a/src/dc_chat.rs b/src/dc_chat.rs index ef1ccc973..18d0d6922 100644 --- a/src/dc_chat.rs +++ b/src/dc_chat.rs @@ -7,8 +7,8 @@ use crate::dc_array::*; use crate::dc_contact::*; use crate::dc_job::*; use crate::dc_msg::*; -use crate::dc_param::*; use crate::dc_tools::*; +use crate::param::*; use crate::sql::{self, Sql}; use crate::stock::StockMessage; use crate::types::*; @@ -22,7 +22,7 @@ use crate::x::*; * and are not updated on database changes; * if you want an update, you have to recreate the object. */ -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct Chat<'a> { magic: uint32_t, pub id: uint32_t, @@ -32,7 +32,7 @@ pub struct Chat<'a> { pub context: &'a Context, pub grpid: *mut libc::c_char, blocked: libc::c_int, - pub param: *mut dc_param_t, + pub param: Params, pub gossiped_timestamp: i64, is_sending_locations: libc::c_int, } @@ -64,13 +64,21 @@ pub unsafe fn dc_create_chat_by_msg_id(context: &Context, msg_id: uint32_t) -> u } pub unsafe fn dc_chat_new<'a>(context: &'a Context) -> *mut Chat<'a> { - let mut chat: *mut Chat; - chat = calloc(1, ::std::mem::size_of::()) as *mut Chat; - (*chat).magic = 0xc4a7c4a7u32; - (*chat).context = context; - (*chat).type_0 = 0i32; - (*chat).param = dc_param_new(); - chat + let chat = Chat { + magic: 0xc4a7c4a7, + id: 0, + type_0: 0, + name: std::ptr::null_mut(), + archived: 0, + context, + grpid: std::ptr::null_mut(), + blocked: 0, + param: Params::new(), + gossiped_timestamp: 0, + is_sending_locations: 0, + }; + + Box::into_raw(Box::new(chat)) } pub unsafe fn dc_chat_unref(mut chat: *mut Chat) { @@ -78,9 +86,8 @@ pub unsafe fn dc_chat_unref(mut chat: *mut Chat) { return; } dc_chat_empty(chat); - dc_param_unref((*chat).param); - (*chat).magic = 0i32 as uint32_t; - free(chat as *mut libc::c_void); + (*chat).magic = 0; + Box::from_raw(chat); } pub unsafe fn dc_chat_empty(mut chat: *mut Chat) { @@ -95,7 +102,7 @@ pub unsafe fn dc_chat_empty(mut chat: *mut Chat) { (*chat).grpid = 0 as *mut libc::c_char; (*chat).blocked = 0i32; (*chat).gossiped_timestamp = 0; - dc_param_set_packed((*chat).param, 0 as *const libc::c_char); + (*chat).param = Params::new(); } pub unsafe fn dc_unblock_chat(context: &Context, chat_id: uint32_t) { @@ -139,16 +146,12 @@ pub fn dc_chat_load_from_db(chat: *mut Chat, chat_id: u32) -> bool { unsafe { to_cstring(raw) } }; - let packed: String = row.get(4)?; - unsafe { - let p = to_cstring(&packed); - dc_param_set_packed((*chat).param, p); - free(p as *mut _); - }; + c.param = row.get::<_, String>(4)?.parse().unwrap_or_default(); c.archived = row.get(5)?; c.blocked = row.get::<_, Option>(6)?.unwrap_or_default(); c.gossiped_timestamp = row.get(7)?; c.is_sending_locations = row.get(8)?; + Ok(()) }, ); @@ -182,7 +185,7 @@ pub fn dc_chat_load_from_db(chat: *mut Chat, chat_id: u32) -> bool { (*chat).name = to_cstring((*chat).context.stock_str(StockMessage::StarredMsgs)); }, _ => { - if 0 != unsafe { dc_param_exists((*chat).param, DC_PARAM_SELFTALK as i32) } { + if unsafe { &(*chat).param }.exists(Param::Selftalk) { unsafe { free((*chat).name as *mut libc::c_void); (*chat).name = @@ -387,13 +390,16 @@ unsafe fn prepare_msg_common<'a>( mut msg: *mut dc_msg_t<'a>, ) -> uint32_t { let mut OK_TO_CONTINUE = true; - let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; (*msg).id = 0i32 as uint32_t; (*msg).context = context; if (*msg).type_0 == DC_MSG_TEXT { /* the caller should check if the message text is empty */ } else if msgtype_has_file((*msg).type_0) { - pathNfilename = dc_param_get((*msg).param, DC_PARAM_FILE as i32, 0 as *const libc::c_char); + let mut pathNfilename = (*msg) + .param + .get(Param::File) + .map(|s| to_cstring(s)) + .unwrap_or_else(|| std::ptr::null_mut()); if pathNfilename.is_null() { error!( context, @@ -410,29 +416,34 @@ unsafe fn prepare_msg_common<'a>( } else if !dc_make_rel_and_copy(context, &mut pathNfilename) { OK_TO_CONTINUE = false; } else { - dc_param_set((*msg).param, DC_PARAM_FILE as i32, pathNfilename); + (*msg).param.set(Param::File, as_str(pathNfilename)); if (*msg).type_0 == DC_MSG_FILE || (*msg).type_0 == DC_MSG_IMAGE { /* Correct the type, take care not to correct already very special formats as GIF or VOICE. Typical conversions: - from FILE to AUDIO/VIDEO/IMAGE - from FILE/IMAGE to GIF */ - let mut better_type: libc::c_int = 0i32; - let mut better_mime: *mut libc::c_char = 0 as *mut libc::c_char; + let mut better_type = 0; + let mut better_mime = std::ptr::null_mut(); + dc_msg_guess_msgtype_from_suffix(pathNfilename, &mut better_type, &mut better_mime); - if 0 != better_type { + if 0 != better_type && !better_mime.is_null() { (*msg).type_0 = better_type; - dc_param_set((*msg).param, DC_PARAM_MIMETYPE as i32, better_mime); + (*msg).param.set(Param::MimeType, as_str(better_mime)); } free(better_mime as *mut libc::c_void); - } else if 0 == dc_param_exists((*msg).param, DC_PARAM_MIMETYPE as i32) { - let mut better_mime_0: *mut libc::c_char = 0 as *mut libc::c_char; + } else if !(*msg).param.exists(Param::MimeType) { + let mut better_mime = std::ptr::null_mut(); + dc_msg_guess_msgtype_from_suffix( pathNfilename, 0 as *mut libc::c_int, - &mut better_mime_0, + &mut better_mime, ); - dc_param_set((*msg).param, DC_PARAM_MIMETYPE as i32, better_mime_0); - free(better_mime_0 as *mut libc::c_void); + + if !better_mime.is_null() { + (*msg).param.set(Param::MimeType, as_str(better_mime)); + } + free(better_mime as *mut _); } info!( context, @@ -441,6 +452,8 @@ unsafe fn prepare_msg_common<'a>( as_str(pathNfilename), (*msg).type_0 ); + + free(pathNfilename as *mut _); } } else { error!( @@ -463,8 +476,6 @@ unsafe fn prepare_msg_common<'a>( } dc_chat_unref(chat); } - /* potential error already logged */ - free(pathNfilename as *mut libc::c_void); (*msg).id } @@ -473,7 +484,7 @@ unsafe fn prepare_msg_common<'a>( unsafe fn prepare_msg_raw( context: &Context, chat: *mut Chat, - msg: *const dc_msg_t, + msg: *mut dc_msg_t, timestamp: i64, ) -> uint32_t { let mut do_guarantee_e2ee: libc::c_int; @@ -537,12 +548,8 @@ unsafe fn prepare_msg_raw( if (*chat).type_0 == DC_CHAT_TYPE_GROUP || (*chat).type_0 == DC_CHAT_TYPE_VERIFIED_GROUP { - if dc_param_get_int((*chat).param, DC_PARAM_UNPROMOTED as i32, 0) == 1 { - dc_param_set( - (*chat).param, - DC_PARAM_UNPROMOTED as i32, - 0 as *const libc::c_char, - ); + if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 1 { + (*chat).param.remove(Param::Unpromoted); dc_chat_update_param(chat); } } @@ -558,7 +565,11 @@ unsafe fn prepare_msg_raw( .get_config_int(context, "e2ee_enabled") .unwrap_or_else(|| 1); if 0 != e2ee_enabled - && dc_param_get_int((*msg).param, DC_PARAM_FORCE_PLAINTEXT as i32, 0) == 0 + && (*msg) + .param + .get_int(Param::ForcePlaintext) + .unwrap_or_default() + == 0 { let mut can_encrypt = 1; let mut all_mutual = 1; @@ -613,13 +624,9 @@ unsafe fn prepare_msg_raw( } } if 0 != do_guarantee_e2ee { - dc_param_set_int((*msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 1); + (*msg).param.set_int(Param::GuranteeE2ee, 1); } - dc_param_set( - (*msg).param, - DC_PARAM_ERRONEOUS_E2EE as i32, - 0 as *const libc::c_char, - ); + (*msg).param.remove(Param::ErroneousE2ee); if 0 == dc_chat_is_self_talk(chat) && 0 != get_parent_mime_headers( chat, @@ -673,7 +680,7 @@ unsafe fn prepare_msg_raw( // add independent location to database - if 0 != dc_param_exists((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int) { + if (*msg).param.exists(Param::SetLatitude) { if sql::execute( context, &context.sql, @@ -684,16 +691,14 @@ unsafe fn prepare_msg_raw( timestamp, DC_CONTACT_ID_SELF as i32, (*chat).id as i32, - dc_param_get_float( - (*msg).param, - DC_PARAM_SET_LATITUDE as libc::c_int, - 0.0, - ), - dc_param_get_float( - (*msg).param, - DC_PARAM_SET_LONGITUDE as libc::c_int, - 0.0, - ), + (*msg) + .param + .get_float(Param::SetLatitude) + .unwrap_or_default(), + (*msg) + .param + .get_float(Param::SetLongitude) + .unwrap_or_default(), ], ) .is_ok() @@ -725,7 +730,7 @@ unsafe fn prepare_msg_raw( (*msg).type_0, (*msg).state, if !(*msg).text.is_null() { Some(as_str((*msg).text)) } else { None }, - if (*(*msg).param).packed.is_null() { None } else { Some(as_str((*(*msg).param).packed)) }, + (*msg).param.to_string(), (*msg).hidden, to_string(new_in_reply_to), to_string(new_references), @@ -816,9 +821,9 @@ unsafe fn get_parent_mime_headers( pub unsafe fn dc_chat_is_self_talk(chat: *const Chat) -> libc::c_int { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { - return 0i32; + return 0; } - dc_param_exists((*chat).param, DC_PARAM_SELFTALK as i32) + (*chat).param.exists(Param::Selftalk) as libc::c_int } /******************************************************************************* @@ -830,7 +835,6 @@ unsafe fn last_msg_in_chat_encrypted( sql: &Sql, chat_id: uint32_t, ) -> libc::c_int { - let mut last_is_encrypted: libc::c_int = 0i32; let packed: Option = sql.query_row_col( context, "SELECT param \ @@ -840,19 +844,17 @@ unsafe fn last_msg_in_chat_encrypted( 0, ); - if let Some(packed) = packed { - let msg_param = dc_param_new(); - let packed_c = to_cstring(packed); - dc_param_set_packed(msg_param, packed_c); - free(packed_c as *mut _); - - if 0 != dc_param_exists(msg_param, DC_PARAM_GUARANTEE_E2EE as i32) { - last_is_encrypted = 1; + if let Some(ref packed) = packed { + match packed.parse::() { + Ok(param) => param.exists(Param::GuranteeE2ee) as libc::c_int, + Err(err) => { + error!(context, 0, "invalid params stored: '{}', {:?}", packed, err); + 0 + } } - dc_param_unref(msg_param); + } else { + 0 } - - last_is_encrypted } // TODO should return bool /rtn @@ -861,7 +863,7 @@ pub unsafe fn dc_chat_update_param(chat: *mut Chat) -> libc::c_int { (*chat).context, &(*chat).context.sql, "UPDATE chats SET param=? WHERE id=?", - params![to_string((*(*chat).param).packed), (*chat).id as i32], + params![(*chat).param.to_string(), (*chat).id as i32], ) .is_ok() as libc::c_int } @@ -921,39 +923,29 @@ pub unsafe fn dc_send_msg<'a>( (*msg).id as uintptr_t, ); - if 0 != dc_param_exists((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int) { + if (*msg).param.exists(Param::SetLatitude) { context.call_cb(Event::LOCATION_CHANGED, DC_CONTACT_ID_SELF, 0); } if 0 == chat_id { - let forwards = dc_param_get( - (*msg).param, - DC_PARAM_PREP_FORWARDS as i32, - 0 as *const libc::c_char, - ); - if !forwards.is_null() { - let mut p = forwards; - while 0 != *p { - let id = strtol(p, &mut p, 10) as int32_t; + 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(); if 0 == id { // avoid hanging if user tampers with db break; } else { - let copy = dc_get_msg(context, id as uint32_t); + let copy = dc_get_msg(context, id as u32); if !copy.is_null() { - dc_send_msg(context, 0 as uint32_t, copy); + dc_send_msg(context, 0, copy); } dc_msg_unref(copy); } } - dc_param_set( - (*msg).param, - DC_PARAM_PREP_FORWARDS as i32, - 0 as *const libc::c_char, - ); + (*msg).param.remove(Param::PrepForwards); dc_msg_save_param_to_disk(msg); } - free(forwards as *mut libc::c_void); } (*msg).id @@ -1003,7 +995,6 @@ pub unsafe fn dc_set_draft(context: &Context, chat_id: uint32_t, msg: *mut dc_ms unsafe fn set_draft_raw(context: &Context, chat_id: uint32_t, msg: *mut dc_msg_t) -> libc::c_int { let mut OK_TO_CONTINUE = true; // similar to as dc_set_draft() but does not emit an event - let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; let prev_draft_msg_id: uint32_t; let mut sth_changed: libc::c_int = 0i32; prev_draft_msg_id = get_draft_msg_id(context, chat_id); @@ -1018,8 +1009,11 @@ unsafe fn set_draft_raw(context: &Context, chat_id: uint32_t, msg: *mut dc_msg_t OK_TO_CONTINUE = false; } } else if msgtype_has_file((*msg).type_0) { - pathNfilename = - dc_param_get((*msg).param, DC_PARAM_FILE as i32, 0 as *const libc::c_char); + let mut pathNfilename = (*msg) + .param + .get(Param::File) + .map(|s| to_cstring(s)) + .unwrap_or_else(|| std::ptr::null_mut()); if pathNfilename.is_null() { OK_TO_CONTINUE = false; } else if 0 != dc_msg_is_increation(msg) && !dc_is_blobdir_path(context, pathNfilename) @@ -1028,8 +1022,9 @@ unsafe fn set_draft_raw(context: &Context, chat_id: uint32_t, msg: *mut dc_msg_t } else if !dc_make_rel_and_copy(context, &mut pathNfilename) { OK_TO_CONTINUE = false; } else { - dc_param_set((*msg).param, DC_PARAM_FILE as i32, pathNfilename); + (*msg).param.set(Param::File, as_str(pathNfilename)); } + free(pathNfilename as *mut _); } else { OK_TO_CONTINUE = false; } @@ -1050,7 +1045,7 @@ unsafe fn set_draft_raw(context: &Context, chat_id: uint32_t, msg: *mut dc_msg_t } else { "" }, - to_string((*(*msg).param).packed), + (*msg).param.to_string(), 1, ], ) @@ -1060,7 +1055,7 @@ unsafe fn set_draft_raw(context: &Context, chat_id: uint32_t, msg: *mut dc_msg_t } } } - free(pathNfilename as *mut libc::c_void); + sth_changed } @@ -1432,7 +1427,7 @@ pub fn dc_delete_chat(context: &Context, chat_id: u32) -> bool { context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t); dc_job_kill_action(context, 105); - unsafe { dc_job_add(context, 105, 0, 0 as *const libc::c_char, 10) }; + unsafe { dc_job_add(context, 105, 0, Params::new(), 10) }; true } @@ -1587,13 +1582,9 @@ pub unsafe fn dc_add_contact_to_chat_ex( } else { /* we should respect this - whatever we send to the group, it gets discarded anyway! */ if 0 != flags & 0x1 - && dc_param_get_int((*chat).param, DC_PARAM_UNPROMOTED as i32, 0) == 1 + && (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 1 { - dc_param_set( - (*chat).param, - DC_PARAM_UNPROMOTED as i32, - 0 as *const libc::c_char, - ); + (*chat).param.remove(Param::Unpromoted); dc_chat_update_param(chat); } let self_addr = context @@ -1627,7 +1618,7 @@ pub unsafe fn dc_add_contact_to_chat_ex( } } if OK_TO_CONTINUE { - if dc_param_get_int((*chat).param, DC_PARAM_UNPROMOTED as i32, 0) == 0 { + if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 { (*msg).type_0 = DC_MSG_TEXT; (*msg).text = to_cstring(context.stock_system_msg( StockMessage::MsgAddMember, @@ -1635,9 +1626,11 @@ pub unsafe fn dc_add_contact_to_chat_ex( "", DC_CONTACT_ID_SELF as uint32_t, )); - dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 4); - dc_param_set((*msg).param, DC_PARAM_CMD_ARG as i32, (*contact).addr); - dc_param_set_int((*msg).param, DC_PARAM_CMD_ARG2 as i32, flags); + (*msg).param.set_int(Param::Cmd, 4); + if !(*contact).addr.is_null() { + (*msg).param.set(Param::Arg, as_str((*contact).addr)); + } + (*msg).param.set_int(Param::Arg2, flags); (*msg).id = dc_send_msg(context, chat_id, msg); context.call_cb( Event::MSGS_CHANGED, @@ -1736,7 +1729,7 @@ pub unsafe fn dc_remove_contact_from_chat( } else { /* we should respect this - whatever we send to the group, it gets discarded anyway! */ if !contact.is_null() { - if dc_param_get_int((*chat).param, DC_PARAM_UNPROMOTED as i32, 0) == 0 { + if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 { (*msg).type_0 = DC_MSG_TEXT; if (*contact).id == 1 as libc::c_uint { dc_set_group_explicitly_left(context, (*chat).grpid); @@ -1754,8 +1747,10 @@ pub unsafe fn dc_remove_contact_from_chat( DC_CONTACT_ID_SELF as u32, )); } - dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 5); - dc_param_set((*msg).param, DC_PARAM_CMD_ARG as i32, (*contact).addr); + (*msg).param.set_int(Param::Cmd, 5); + if !(*contact).addr.is_null() { + (*msg).param.set(Param::Arg, as_str((*contact).addr)); + } (*msg).id = dc_send_msg(context, chat_id, msg); context.call_cb( Event::MSGS_CHANGED, @@ -1849,7 +1844,7 @@ pub unsafe fn dc_set_chat_name( ) .is_ok() { - if dc_param_get_int((*chat).param, DC_PARAM_UNPROMOTED as i32, 0i32) == 0i32 { + if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 { (*msg).type_0 = DC_MSG_TEXT; (*msg).text = to_cstring(context.stock_system_msg( StockMessage::MsgGrpName, @@ -1857,8 +1852,10 @@ pub unsafe fn dc_set_chat_name( as_str(new_name), DC_CONTACT_ID_SELF as u32, )); - dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 2); - dc_param_set((*msg).param, DC_PARAM_CMD_ARG as i32, (*chat).name); + (*msg).param.set_int(Param::Cmd, 2); + if !(*chat).name.is_null() { + (*msg).param.set(Param::Arg, as_str((*chat).name)); + } (*msg).id = dc_send_msg(context, chat_id, msg); context.call_cb( Event::MSGS_CHANGED, @@ -1913,12 +1910,13 @@ pub unsafe fn dc_set_chat_profile_image( } } if OK_TO_CONTINUE { - dc_param_set((*chat).param, DC_PARAM_PROFILE_IMAGE as i32, new_image_rel); + (*chat) + .param + .set(Param::ProfileImage, as_str(new_image_rel)); if !(0 == dc_chat_update_param(chat)) { - if dc_param_get_int((*chat).param, DC_PARAM_UNPROMOTED as i32, 0i32) == 0i32 - { - dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 3i32); - dc_param_set((*msg).param, DC_PARAM_CMD_ARG as i32, new_image_rel); + if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 { + (*msg).param.set_int(Param::Cmd, 3); + (*msg).param.set(Param::Arg, as_str(new_image_rel)); (*msg).type_0 = DC_MSG_TEXT; (*msg).text = to_cstring(context.stock_system_msg( if !new_image_rel.is_null() { @@ -1972,7 +1970,6 @@ pub unsafe fn dc_forward_msgs( let created_db_entries = carray_new(16); let mut curr_timestamp: i64; - let original_param: *mut dc_param_t = dc_param_new(); dc_unarchive_chat(context, chat_id); if dc_chat_load_from_db(chat, chat_id) { curr_timestamp = dc_create_smeared_timestamps(context, msg_cnt); @@ -2002,44 +1999,34 @@ pub unsafe fn dc_forward_msgs( if !dc_msg_load_from_db(msg, context, src_msg_id as u32) { break; } - dc_param_set_packed(original_param, (*(*msg).param).packed); - if (*msg).from_id != 1i32 as libc::c_uint { - dc_param_set_int((*msg).param, DC_PARAM_FORWARDED as i32, 1i32); + let original_param = (*msg).param.clone(); + if (*msg).from_id != 1 { + (*msg).param.set_int(Param::Forwarded, 1); } - dc_param_set( - (*msg).param, - DC_PARAM_GUARANTEE_E2EE as i32, - 0 as *const libc::c_char, - ); - dc_param_set( - (*msg).param, - DC_PARAM_FORCE_PLAINTEXT as i32, - 0 as *const libc::c_char, - ); - dc_param_set((*msg).param, DC_PARAM_CMD as i32, 0 as *const libc::c_char); + (*msg).param.remove(Param::GuranteeE2ee); + (*msg).param.remove(Param::ForcePlaintext); + (*msg).param.remove(Param::Cmd); + let new_msg_id: uint32_t; if (*msg).state == DC_STATE_OUT_PREPARING { let fresh9 = curr_timestamp; curr_timestamp = curr_timestamp + 1; new_msg_id = prepare_msg_raw(context, chat, msg, fresh9); - let save_param: *mut dc_param_t = (*msg).param; + let save_param = (*msg).param.clone(); (*msg).param = original_param; (*msg).id = src_msg_id as uint32_t; - let old_fwd: *mut libc::c_char = dc_param_get( - (*msg).param, - DC_PARAM_PREP_FORWARDS as i32, - b"\x00" as *const u8 as *const libc::c_char, - ); - let new_fwd: *mut libc::c_char = dc_mprintf( - b"%s %d\x00" as *const u8 as *const libc::c_char, - old_fwd, - new_msg_id, - ); - dc_param_set((*msg).param, DC_PARAM_PREP_FORWARDS as i32, new_fwd); + + 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); + } else { + (*msg) + .param + .set(Param::PrepForwards, new_msg_id.to_string()); + } + dc_msg_save_param_to_disk(msg); - free(new_fwd as *mut libc::c_void); - free(old_fwd as *mut libc::c_void); - (*msg).param = save_param + (*msg).param = save_param; } else { (*msg).state = DC_STATE_OUT_PENDING; let fresh10 = curr_timestamp; @@ -2076,7 +2063,6 @@ pub unsafe fn dc_forward_msgs( dc_contact_unref(contact); dc_msg_unref(msg); dc_chat_unref(chat); - dc_param_unref(original_param); } pub unsafe fn dc_chat_get_id(chat: *const Chat) -> uint32_t { @@ -2107,7 +2093,7 @@ pub unsafe fn dc_chat_get_subtitle(chat: *const Chat) -> *mut libc::c_char { } let mut ret: *mut libc::c_char = std::ptr::null_mut(); - if (*chat).type_0 == 100 && 0 != dc_param_exists((*chat).param, DC_PARAM_SELFTALK as i32) { + if (*chat).type_0 == 100 && (*chat).param.exists(Param::Selftalk) { ret = to_cstring((*chat).context.stock_str(StockMessage::SelfTalkSubTitle)); } else if (*chat).type_0 == 100 { let ret_raw: String = (*chat) @@ -2160,11 +2146,7 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t; let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t; if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) { - image_rel = dc_param_get( - (*chat).param, - DC_PARAM_PROFILE_IMAGE as i32, - 0 as *const libc::c_char, - ); + image_rel = to_cstring((*chat).param.get(Param::ProfileImage).unwrap_or_default()); if !image_rel.is_null() && 0 != *image_rel.offset(0isize) as libc::c_int { image_abs = dc_get_abs_path((*chat).context, image_rel) } else if (*chat).type_0 == 100i32 { @@ -2216,9 +2198,9 @@ pub unsafe fn dc_chat_get_archived(chat: *const Chat) -> libc::c_int { // TODO should return bool /rtn pub unsafe fn dc_chat_is_unpromoted(chat: *const Chat) -> libc::c_int { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { - return 0i32; + return 0; } - dc_param_get_int((*chat).param, DC_PARAM_UNPROMOTED as i32, 0i32) + (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() as libc::c_int } // TODO should return bool /rtn diff --git a/src/dc_configure.rs b/src/dc_configure.rs index 9b0996e70..a1397742a 100644 --- a/src/dc_configure.rs +++ b/src/dc_configure.rs @@ -1,4 +1,4 @@ -use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET}; +use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use crate::constants::Event; use crate::context::Context; @@ -9,6 +9,7 @@ use crate::dc_saxparser::*; use crate::dc_tools::*; use crate::imap::*; use crate::oauth2::*; +use crate::param::Params; use crate::types::*; use crate::x::*; @@ -60,9 +61,10 @@ pub unsafe fn dc_configure(context: &Context) { ); return; } - dc_job_kill_action(context, 900i32); - dc_job_add(context, 900i32, 0i32, 0 as *const libc::c_char, 0i32); + dc_job_kill_action(context, 900); + dc_job_add(context, 900, 0, Params::new(), 0); } + pub unsafe fn dc_has_ongoing(context: &Context) -> libc::c_int { let s_a = context.running_state.clone(); let s = s_a.read().unwrap(); @@ -208,8 +210,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j let parsed = parsed.unwrap(); let param_domain = parsed.host(); let param_addr_urlencoded = - utf8_percent_encode(¶m.addr, DEFAULT_ENCODE_SET) - .to_string(); + utf8_percent_encode(¶m.addr, NON_ALPHANUMERIC).to_string(); if !s.shall_stop_ongoing { context.call_cb( diff --git a/src/dc_imex.rs b/src/dc_imex.rs index eeb38617c..c414fdbf1 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -12,9 +12,9 @@ use crate::dc_configure::*; use crate::dc_e2ee::*; use crate::dc_job::*; use crate::dc_msg::*; -use crate::dc_param::*; use crate::dc_tools::*; use crate::key::*; +use crate::param::*; use crate::pgp::*; use crate::sql::{self, Sql}; use crate::stock::StockMessage; @@ -32,13 +32,17 @@ pub unsafe fn dc_imex( param1: *const libc::c_char, param2: *const libc::c_char, ) { - let param: *mut dc_param_t = dc_param_new(); - dc_param_set_int(param, DC_PARAM_CMD as i32, what); - dc_param_set(param, DC_PARAM_CMD_ARG as i32, param1); - dc_param_set(param, DC_PARAM_CMD_ARG2 as i32, param2); - dc_job_kill_action(context, 910i32); - dc_job_add(context, 910i32, 0i32, (*param).packed, 0i32); - dc_param_unref(param); + let mut param = Params::new(); + param.set_int(Param::Cmd, what as i32); + if !param1.is_null() { + param.set(Param::Arg, as_str(param1)); + } + if !param2.is_null() { + param.set(Param::Arg2, as_str(param2)); + } + + dc_job_kill_action(context, 910); + dc_job_add(context, 910, 0, param, 0); } /// Returns the filename of the backup if found, nullptr otherwise. @@ -142,15 +146,14 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char { if !(chat_id == 0i32 as libc::c_uint) { msg = dc_msg_new_untyped(context); (*msg).type_0 = DC_MSG_FILE; - dc_param_set((*msg).param, DC_PARAM_FILE as i32, setup_file_name); - dc_param_set( - (*msg).param, - DC_PARAM_MIMETYPE as i32, - b"application/autocrypt-setup\x00" as *const u8 - as *const libc::c_char, - ); - dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 6); - dc_param_set_int((*msg).param, DC_PARAM_FORCE_PLAINTEXT as i32, 2); + (*msg).param.set(Param::File, as_str(setup_file_name)); + + (*msg) + .param + .set(Param::MimeType, "application/autocrypt-setup"); + (*msg).param.set_int(Param::Cmd, 6); + (*msg).param.set_int(Param::ForcePlaintext, 2); + if !context .running_state .clone() @@ -539,33 +542,27 @@ pub unsafe fn dc_normalize_setup_code( #[allow(non_snake_case)] pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t) { let mut current_block: u64; - let mut success: libc::c_int = 0i32; - let mut ongoing_allocated_here: libc::c_int = 0i32; + let mut success: libc::c_int = 0; + let mut ongoing_allocated_here: libc::c_int = 0; let what: libc::c_int; - let mut param1: *mut libc::c_char = 0 as *mut libc::c_char; - let mut param2: *mut libc::c_char = 0 as *mut libc::c_char; + let mut param1 = 0 as *mut libc::c_char; + let mut param2 = 0 as *mut libc::c_char; + if !(0 == dc_alloc_ongoing(context)) { - ongoing_allocated_here = 1i32; - what = dc_param_get_int((*job).param, DC_PARAM_CMD as i32, 0); - param1 = dc_param_get( - (*job).param, - DC_PARAM_CMD_ARG as i32, - 0 as *const libc::c_char, - ); - param2 = dc_param_get( - (*job).param, - DC_PARAM_CMD_ARG2 as i32, - 0 as *const libc::c_char, - ); - if param1.is_null() { + ongoing_allocated_here = 1; + what = (*job).param.get_int(Param::Cmd).unwrap_or_default(); + param1 = to_cstring((*job).param.get(Param::Arg).unwrap_or_default()); + param2 = to_cstring((*job).param.get(Param::Arg2).unwrap_or_default()); + + if strlen(param1) == 0 { error!(context, 0, "No Import/export dir/file given.",); } else { info!(context, 0, "Import/export process started.",); - context.call_cb(Event::IMEX_PROGRESS, 10i32 as uintptr_t, 0i32 as uintptr_t); + context.call_cb(Event::IMEX_PROGRESS, 10 as uintptr_t, 0 as uintptr_t); if !context.sql.is_open() { error!(context, 0, "Import/export: Database not opened.",); } else { - if what == 1i32 || what == 11i32 { + if what == 1 || what == 11 { /* before we export anything, make sure the private key exists */ if 0 == dc_ensure_secret_key_exists(context) { error!( @@ -620,7 +617,7 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t) 3568988166330621280 => {} _ => { info!(context, 0, "Import/export completed.",); - success = 1i32 + success = 1 } } } @@ -660,7 +657,7 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t) 3568988166330621280 => {} _ => { info!(context, 0, "Import/export completed.",); - success = 1i32 + success = 1 } } } @@ -700,7 +697,7 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t) 3568988166330621280 => {} _ => { info!(context, 0, "Import/export completed.",); - success = 1i32 + success = 1 } } } @@ -740,7 +737,7 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t) 3568988166330621280 => {} _ => { info!(context, 0, "Import/export completed.",); - success = 1i32 + success = 1 } } } @@ -758,8 +755,8 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t) } context.call_cb( Event::IMEX_PROGRESS, - (if 0 != success { 1000i32 } else { 0i32 }) as uintptr_t, - 0i32 as uintptr_t, + (if 0 != success { 1000 } else { 0 }) as uintptr_t, + 0 as uintptr_t, ); } diff --git a/src/dc_job.rs b/src/dc_job.rs index 3be8a95d9..e5501bc77 100644 --- a/src/dc_job.rs +++ b/src/dc_job.rs @@ -15,10 +15,10 @@ use crate::dc_location::*; use crate::dc_loginparam::*; use crate::dc_mimefactory::*; use crate::dc_msg::*; -use crate::dc_param::*; use crate::dc_tools::*; use crate::imap::*; use crate::keyhistory::*; +use crate::param::*; use crate::sql; use crate::types::*; use crate::x::*; @@ -33,7 +33,7 @@ use crate::x::*; // timeouts until actions are aborted. // this may also affects IDLE to return, so a re-connect may take this time. // mailcore2 uses 30 seconds, k-9 uses 10 seconds -#[derive(Copy, Clone)] +#[derive(Clone)] #[repr(C)] pub struct dc_job_t { pub job_id: uint32_t, @@ -42,7 +42,7 @@ pub struct dc_job_t { pub desired_timestamp: i64, pub added_timestamp: i64, pub tries: libc::c_int, - pub param: *mut dc_param_t, + pub param: Params, pub try_again: libc::c_int, pub pending_error: *mut libc::c_char, } @@ -91,15 +91,11 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network: desired_timestamp: row.get(5)?, added_timestamp: row.get(4)?, tries: row.get(6)?, - param: dc_param_new(), + param: row.get::<_, String>(3)?.parse().unwrap_or_default(), try_again: 0, pending_error: 0 as *mut libc::c_char, }; - let packed: String = row.get(3)?; - let packed_c = to_cstring(packed); - dc_param_set_packed(job.param, packed_c); - free(packed_c as *mut _); Ok(job) }, |jobs| { @@ -225,7 +221,6 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network: } else { dc_job_delete(context, &mut job); } - dc_param_unref(job.param); free(job.pending_error as *mut libc::c_void); } } @@ -262,7 +257,7 @@ fn dc_job_update(context: &Context, job: &dc_job_t) -> bool { params![ job.desired_timestamp, job.tries as i64, - as_str(unsafe { (*job.param).packed }), + job.param.to_string(), job.job_id as i32, ], ) @@ -287,7 +282,6 @@ unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) { let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; let mut buf: *mut libc::c_void = 0 as *mut libc::c_void; let mut buf_bytes: size_t = 0i32 as size_t; - let mut recipients: *mut libc::c_char = 0 as *mut libc::c_char; /* connect to SMTP server, if not yet done */ if !context.smtp.lock().unwrap().is_connected() { @@ -305,20 +299,15 @@ unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) { } match current_block { 13109137661213826276 => { - filename = dc_param_get(job.param, DC_PARAM_FILE as i32, 0 as *const libc::c_char); - if filename.is_null() { + filename = to_cstring(job.param.get(Param::File).unwrap_or_default()); + if strlen(filename) == 0 { warn!(context, 0, "Missing file name for job {}", job.job_id,); } else if !(0 == dc_read_file(context, filename, &mut buf, &mut buf_bytes)) { - recipients = dc_param_get( - job.param, - DC_PARAM_RECIPIENTS as i32, - 0 as *const libc::c_char, - ); - if recipients.is_null() { + let recipients = job.param.get(Param::Recipients); + if recipients.is_none() { warn!(context, 0, "Missing recipients for job {}", job.job_id,); } else { - let recipients_list = std::ffi::CStr::from_ptr(recipients) - .to_str() + let recipients_list = recipients .unwrap() .split("\x1e") .filter_map(|addr| match lettre::EmailAddress::new(addr.to_string()) { @@ -396,7 +385,6 @@ unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) { } _ => {} } - free(recipients as *mut libc::c_void); free(buf); free(filename as *mut libc::c_void); } @@ -512,19 +500,19 @@ fn connect_to_inbox(context: &Context, inbox: &Imap) -> libc::c_int { #[allow(non_snake_case)] unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context: &Context, job: &mut dc_job_t) { let current_block: u64; - let folder: *mut libc::c_char = dc_param_get( - job.param, - DC_PARAM_SERVER_FOLDER as i32, - 0 as *const libc::c_char, - ); - let uid: uint32_t = dc_param_get_int(job.param, DC_PARAM_SERVER_UID as i32, 0) as uint32_t; - let mut dest_uid: uint32_t = 0i32 as uint32_t; + let folder = job + .param + .get(Param::ServerFolder) + .unwrap_or_default() + .to_string(); + let uid = job.param.get_int(Param::ServerUid).unwrap_or_default() as u32; + let mut dest_uid = 0; let inbox = context.inbox.read().unwrap(); if !inbox.is_connected() { connect_to_inbox(context, &inbox); if !inbox.is_connected() { - dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + dc_job_try_again_later(job, 3, 0 as *const libc::c_char); current_block = 2670689566614003383; } else { current_block = 11006700562992250127; @@ -534,11 +522,10 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context: &Context, job: &mut dc_ } match current_block { 11006700562992250127 => { - let folder = CStr::from_ptr(folder).to_str().unwrap(); - if inbox.set_seen(context, folder, uid) as libc::c_uint == 0i32 as libc::c_uint { + if inbox.set_seen(context, &folder, uid) == 0 { dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); } - if 0 != dc_param_get_int(job.param, DC_PARAM_ALSO_MOVE as i32, 0i32) { + if 0 != job.param.get_int(Param::AlsoMove).unwrap_or_default() { if context .sql .get_config_int(context, "folders_configured") @@ -559,7 +546,6 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context: &Context, job: &mut dc_ } _ => {} } - free(folder as *mut libc::c_void); } #[allow(non_snake_case)] @@ -592,12 +578,8 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &Context, job: &mut dc_ dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); } _ => { - if 0 != dc_param_get_int( - (*msg).param, - DC_PARAM_WANTS_MDN as i32, - 0i32, - ) && 0 - != context + if 0 != (*msg).param.get_int(Param::WantsMdn).unwrap_or_default() + && 0 != context .sql .get_config_int(context, "mdns_enabled") .unwrap_or_else(|| 1) @@ -650,7 +632,7 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &Context, job: &mut dc_ dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); } _ => { - if 0 != dc_param_get_int((*msg).param, DC_PARAM_WANTS_MDN as i32, 0) + if 0 != (*msg).param.get_int(Param::WantsMdn).unwrap_or_default() && 0 != context .sql .get_config_int(context, "mdns_enabled") @@ -756,7 +738,7 @@ unsafe fn dc_add_smtp_job( let pathNfilename: *mut libc::c_char; let mut success: libc::c_int = 0i32; let mut recipients: *mut libc::c_char = 0 as *mut libc::c_char; - let param: *mut dc_param_t = dc_param_new(); + let mut param = Params::new(); pathNfilename = dc_get_fine_pathNfilename( context, b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, @@ -789,8 +771,8 @@ unsafe fn dc_add_smtp_job( (*mimefactory).recipients_addr, b"\x1e\x00" as *const u8 as *const libc::c_char, ); - dc_param_set(param, DC_PARAM_FILE as i32, pathNfilename); - dc_param_set(param, DC_PARAM_RECIPIENTS as i32, recipients); + param.set(Param::File, as_str(pathNfilename)); + param.set(Param::File, as_str(recipients)); dc_job_add( context, action, @@ -799,23 +781,23 @@ unsafe fn dc_add_smtp_job( { (*(*mimefactory).msg).id } else { - 0i32 as libc::c_uint + 0 }) as libc::c_int, - (*param).packed, - 0i32, + param, + 0, ); success = 1i32 } - dc_param_unref(param); free(recipients as *mut libc::c_void); free(pathNfilename as *mut libc::c_void); return success; } + pub unsafe fn dc_job_add( context: &Context, action: libc::c_int, foreign_id: libc::c_int, - param: *const libc::c_char, + param: Params, delay_seconds: libc::c_int, ) { let timestamp = time(); @@ -836,11 +818,7 @@ pub unsafe fn dc_job_add( thread, action, foreign_id, - if !param.is_null() { - as_str(param) - } else { - "" - }, + param.to_string(), (timestamp + delay_seconds as i64) ] ).ok(); @@ -1184,22 +1162,23 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in } else { // no redo, no IMAP. moreover, as the data does not exist, there is no need in calling dc_set_msg_failed() if msgtype_has_file((*mimefactory.msg).type_0) { - let pathNfilename = dc_param_get( - (*mimefactory.msg).param, - DC_PARAM_FILE as i32, - 0 as *const libc::c_char, + let pathNfilename = to_cstring( + (*mimefactory.msg) + .param + .get(Param::File) + .unwrap_or_default(), ); - if !pathNfilename.is_null() { + if strlen(pathNfilename) > 0 { if ((*mimefactory.msg).type_0 == DC_MSG_IMAGE || (*mimefactory.msg).type_0 == DC_MSG_GIF) - && 0 == dc_param_exists((*mimefactory.msg).param, DC_PARAM_WIDTH as i32) + && !(*mimefactory.msg).param.exists(Param::Width) { - let mut buf: *mut libc::c_uchar = 0 as *mut libc::c_uchar; + let mut buf = 0 as *mut libc::c_uchar; let mut buf_bytes: size_t = 0; - let mut w: uint32_t = 0; - let mut h: uint32_t = 0; - dc_param_set_int((*mimefactory.msg).param, DC_PARAM_WIDTH as i32, 0); - dc_param_set_int((*mimefactory.msg).param, DC_PARAM_HEIGHT as i32, 0); + let mut w = 0; + let mut h = 0; + (*mimefactory.msg).param.set_int(Param::Width, 0); + (*mimefactory.msg).param.set_int(Param::Height, 0); if 0 != dc_read_file( context, pathNfilename, @@ -1212,16 +1191,8 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in &mut w, &mut h, ) { - dc_param_set_int( - (*mimefactory.msg).param, - DC_PARAM_WIDTH as i32, - w as int32_t, - ); - dc_param_set_int( - (*mimefactory.msg).param, - DC_PARAM_HEIGHT as i32, - h as int32_t, - ); + (*mimefactory.msg).param.set_int(Param::Width, w as i32); + (*mimefactory.msg).param.set_int(Param::Height, h as i32); } } free(buf as *mut libc::c_void); @@ -1233,15 +1204,19 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in /* create message */ if 0 == dc_mimefactory_render(&mut mimefactory) { dc_set_msg_failed(context, msg_id, mimefactory.error); - } else if 0 != dc_param_get_int((*mimefactory.msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 0) + } else if 0 + != (*mimefactory.msg) + .param + .get_int(Param::GuranteeE2ee) + .unwrap_or_default() && 0 == mimefactory.out_encrypted { warn!( context, 0, - "e2e encryption unavailable {} - {}", + "e2e encryption unavailable {} - {:?}", msg_id, - dc_param_get_int((*mimefactory.msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 0), + (*mimefactory.msg).param.get_int(Param::GuranteeE2ee), ); dc_set_msg_failed( context, @@ -1279,10 +1254,13 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in } } if 0 != mimefactory.out_encrypted - && dc_param_get_int((*mimefactory.msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 0) + && (*mimefactory.msg) + .param + .get_int(Param::GuranteeE2ee) + .unwrap_or_default() == 0 { - dc_param_set_int((*mimefactory.msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 1); + (*mimefactory.msg).param.set_int(Param::GuranteeE2ee, 1); dc_msg_save_param_to_disk(mimefactory.msg); } dc_add_to_keyhistory( diff --git a/src/dc_location.rs b/src/dc_location.rs index 23995e8fb..bdef8671e 100644 --- a/src/dc_location.rs +++ b/src/dc_location.rs @@ -6,9 +6,9 @@ use crate::dc_array::*; use crate::dc_chat::*; use crate::dc_job::*; use crate::dc_msg::*; -use crate::dc_param::*; use crate::dc_saxparser::*; use crate::dc_tools::*; +use crate::param::*; use crate::sql; use crate::stock::StockMessage; use crate::types::*; @@ -105,7 +105,7 @@ pub unsafe fn dc_send_locations_to_chat( "", 0, )); - dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 8); + (*msg).param.set_int(Param::Cmd, 8); dc_send_msg(context, chat_id, msg); } else if 0 == seconds && is_sending_locations_before { let stock_str = CString::new(context.stock_system_msg( @@ -128,7 +128,7 @@ pub unsafe fn dc_send_locations_to_chat( context, 5007i32, chat_id as libc::c_int, - 0 as *const libc::c_char, + Params::new(), seconds + 1i32, ); } @@ -143,7 +143,7 @@ pub unsafe fn dc_send_locations_to_chat( #[allow(non_snake_case)] unsafe fn schedule_MAYBE_SEND_LOCATIONS(context: &Context, flags: libc::c_int) { if 0 != flags & 0x1 || !dc_job_action_exists(context, 5005) { - dc_job_add(context, 5005, 0, 0 as *const libc::c_char, 60); + dc_job_add(context, 5005, 0, Params::new(), 60); }; } @@ -709,7 +709,7 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context: &Context, _job: *mu // and dc_set_location() is typically called periodically, this is ok) let mut msg = dc_msg_new(context, 10); (*msg).hidden = 1; - dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 9); + (*msg).param.set_int(Param::Cmd, 9); dc_send_msg(context, chat_id as u32, msg); dc_msg_unref(msg); } diff --git a/src/dc_lot.rs b/src/dc_lot.rs index a7889f0ac..429859636 100644 --- a/src/dc_lot.rs +++ b/src/dc_lot.rs @@ -125,7 +125,7 @@ pub unsafe fn dc_lot_get_timestamp(lot: *const dc_lot_t) -> i64 { /* in practice, the user additionally cuts the string himself pixel-accurate */ pub unsafe fn dc_lot_fill( mut lot: *mut dc_lot_t, - msg: *const dc_msg_t, + msg: *mut dc_msg_t, chat: *const Chat, contact: *const dc_contact_t, context: &Context, @@ -161,7 +161,7 @@ pub unsafe fn dc_lot_fill( } } (*lot).text2 = - dc_msg_get_summarytext_by_raw((*msg).type_0, (*msg).text, (*msg).param, 160i32, context); + dc_msg_get_summarytext_by_raw((*msg).type_0, (*msg).text, &mut (*msg).param, 160, context); (*lot).timestamp = dc_msg_get_timestamp(msg); (*lot).state = (*msg).state; } diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs index 2617c5dc3..8dc83f8d6 100644 --- a/src/dc_mimefactory.rs +++ b/src/dc_mimefactory.rs @@ -17,9 +17,9 @@ use crate::dc_contact::*; use crate::dc_e2ee::*; use crate::dc_location::*; use crate::dc_msg::*; -use crate::dc_param::*; use crate::dc_strencode::*; use crate::dc_tools::*; +use crate::param::*; use crate::stock::StockMessage; use crate::types::*; use crate::x::*; @@ -114,7 +114,6 @@ pub unsafe fn dc_mimefactory_load_msg( msg_id: uint32_t, ) -> libc::c_int { if factory.is_null() || msg_id <= 9 || !(*factory).msg.is_null() { - info!((*factory).context, 0, "mimefactory: null"); return 0; } @@ -129,12 +128,9 @@ pub unsafe fn dc_mimefactory_load_msg( if dc_msg_load_from_db((*factory).msg, context, msg_id) && dc_chat_load_from_db((*factory).chat, (*(*factory).msg).chat_id) { - info!(context, 0, "mimefactory: loaded msg and chat",); load_from(factory); (*factory).req_mdn = 0; if 0 != dc_chat_is_self_talk((*factory).chat) { - info!(context, 0, "mimefactory: selftalk"); - clist_insert_after( (*factory).recipients_names, (*(*factory).recipients_names).last, @@ -146,7 +142,6 @@ pub unsafe fn dc_mimefactory_load_msg( dc_strdup((*factory).from_addr) as *mut libc::c_void, ); } else { - info!(context, 0, "mimefactory: query map"); context .sql .query_map( @@ -161,7 +156,6 @@ pub unsafe fn dc_mimefactory_load_msg( Ok((authname, addr)) }, |rows| { - info!(context, 0, "mimefactory: processing rows"); for row in rows { let (authname, addr) = row?; let addr_c = to_cstring(addr); @@ -187,14 +181,15 @@ pub unsafe fn dc_mimefactory_load_msg( ) .unwrap(); - let command = dc_param_get_int((*(*factory).msg).param, DC_PARAM_CMD as i32, 0); + let command = (*(*factory).msg) + .param + .get_int(Param::Cmd) + .unwrap_or_default(); + if command == 5 { - let email_to_remove_c = dc_param_get( - (*(*factory).msg).param, - DC_PARAM_CMD_ARG as i32, - 0 as *const libc::c_char, - ); - let email_to_remove = to_string(email_to_remove_c); + let email_to_remove = (*(*factory).msg).param.get(Param::Arg).unwrap_or_default(); + let email_to_remove_c = to_cstring(email_to_remove); + let self_addr = context .sql .get_config(context, "configured_addr") @@ -227,8 +222,6 @@ pub unsafe fn dc_mimefactory_load_msg( (*factory).req_mdn = 1 } } - info!(context, 0, "mimefactory: loading in reply to"); - let row = context.sql.query_row( "SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?", params![(*(*factory).msg).id as i32], @@ -374,7 +367,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: // 1=add Autocrypt-header (needed eg. for handshaking), 2=no Autocrypte-header (used for MDN) let mut force_plaintext: libc::c_int = 0; let mut do_gossip: libc::c_int = 0; - let mut grpimage: *mut libc::c_char = 0 as *mut libc::c_char; + let mut grpimage = None; let mut e2ee_helper = dc_e2ee_helper_t { encryption_successfull: 0, cdata_to_free: 0 as *mut libc::c_void, @@ -543,11 +536,15 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: e2ee_guaranteed = 1; min_verified = 2 } else { - force_plaintext = - dc_param_get_int((*(*factory).msg).param, DC_PARAM_FORCE_PLAINTEXT as i32, 0); + force_plaintext = (*(*factory).msg) + .param + .get_int(Param::ForcePlaintext) + .unwrap_or_default(); if force_plaintext == 0 { - e2ee_guaranteed = - dc_param_get_int((*(*factory).msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 0) + e2ee_guaranteed = (*(*factory).msg) + .param + .get_int(Param::GuranteeE2ee) + .unwrap_or_default() } } if (*chat).gossiped_timestamp == 0 @@ -555,8 +552,9 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: { do_gossip = 1 } + /* build header etc. */ - let command: libc::c_int = dc_param_get_int((*msg).param, DC_PARAM_CMD as i32, 0); + let command = (*msg).param.get_int(Param::Cmd).unwrap_or_default(); if (*chat).type_0 == DC_CHAT_TYPE_GROUP as libc::c_int || (*chat).type_0 == DC_CHAT_TYPE_VERIFIED_GROUP as libc::c_int { @@ -575,12 +573,9 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); if command == 5 { - let email_to_remove: *mut libc::c_char = dc_param_get( - (*msg).param, - DC_PARAM_CMD_ARG as i32, - 0 as *const libc::c_char, - ); - if !email_to_remove.is_null() { + let email_to_remove = + to_cstring((*msg).param.get(Param::Arg).unwrap_or_default()); + if strlen(email_to_remove) > 0 { mailimf_fields_add( imf_fields, mailimf_field_new_custom( @@ -594,12 +589,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: } } else if command == 4 { do_gossip = 1; - let email_to_add: *mut libc::c_char = dc_param_get( - (*msg).param, - DC_PARAM_CMD_ARG as i32, - 0 as *const libc::c_char, - ); - if !email_to_add.is_null() { + let email_to_add = to_cstring((*msg).param.get(Param::Arg).unwrap_or_default()); + if strlen(email_to_add) > 0 { mailimf_fields_add( imf_fields, mailimf_field_new_custom( @@ -610,13 +601,9 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: email_to_add, ), ); - grpimage = dc_param_get( - (*chat).param, - DC_PARAM_PROFILE_IMAGE as i32, - 0 as *const libc::c_char, - ) + grpimage = (*chat).param.get(Param::ProfileImage); } - if 0 != dc_param_get_int((*msg).param, DC_PARAM_CMD_ARG2 as i32, 0) & 0x1 { + if 0 != (*msg).param.get_int(Param::Arg2).unwrap_or_default() & 0x1 { info!( (*msg).context, 0, @@ -632,26 +619,19 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); } } else if command == 2 { + let value_to_add = to_cstring((*msg).param.get(Param::Arg).unwrap_or_default()); mailimf_fields_add( imf_fields, mailimf_field_new_custom( strdup( b"Chat-Group-Name-Changed\x00" as *const u8 as *const libc::c_char, ), - dc_param_get( - (*msg).param, - DC_PARAM_CMD_ARG as i32, - b"\x00" as *const u8 as *const libc::c_char, - ), + value_to_add, ), ); } else if command == 3 { - grpimage = dc_param_get( - (*msg).param, - DC_PARAM_CMD_ARG as i32, - 0 as *const libc::c_char, - ); - if grpimage.is_null() { + grpimage = (*msg).param.get(Param::Arg); + if grpimage.is_none() { mailimf_fields_add( imf_fields, mailimf_field_new_custom( @@ -685,12 +665,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: to_cstring((*factory).context.stock_str(StockMessage::AcSetupMsgBody)); } if command == 7 { - let step: *mut libc::c_char = dc_param_get( - (*msg).param, - DC_PARAM_CMD_ARG as i32, - 0 as *const libc::c_char, - ); - if !step.is_null() { + let step = to_cstring((*msg).param.get(Param::Arg).unwrap_or_default()); + if strlen(step) > 0 { info!( (*msg).context, 0, @@ -704,12 +680,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: step, ), ); - let param2: *mut libc::c_char = dc_param_get( - (*msg).param, - DC_PARAM_CMD_ARG2 as i32, - 0 as *const libc::c_char, - ); - if !param2.is_null() { + let param2 = to_cstring((*msg).param.get(Param::Arg2).unwrap_or_default()); + if strlen(param2) > 0 { mailimf_fields_add( imf_fields, mailimf_field_new_custom( @@ -736,12 +708,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); } - let fingerprint: *mut libc::c_char = dc_param_get( - (*msg).param, - DC_PARAM_CMD_ARG3 as i32, - 0 as *const libc::c_char, - ); - if !fingerprint.is_null() { + let fingerprint = to_cstring((*msg).param.get(Param::Arg3).unwrap_or_default()); + if strlen(fingerprint) > 0 { mailimf_fields_add( imf_fields, mailimf_field_new_custom( @@ -753,11 +721,10 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); } - let grpid: *mut libc::c_char = dc_param_get( - (*msg).param, - DC_PARAM_CMD_ARG4 as i32, - 0 as *const libc::c_char, - ); + let grpid = match (*msg).param.get(Param::Arg4) { + Some(id) => to_cstring(id), + None => std::ptr::null_mut(), + }; if !grpid.is_null() { mailimf_fields_add( imf_fields, @@ -771,11 +738,13 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: } } } - if !grpimage.is_null() { - let mut meta: *mut dc_msg_t = dc_msg_new_untyped((*factory).context); + + if let Some(grpimage) = grpimage { + let mut meta = dc_msg_new_untyped((*factory).context); (*meta).type_0 = DC_MSG_IMAGE as libc::c_int; - dc_param_set((*meta).param, DC_PARAM_FILE as i32, grpimage); - let mut filename_as_sent: *mut libc::c_char = 0 as *mut libc::c_char; + (*meta).param.set(Param::File, grpimage); + + let mut filename_as_sent = 0 as *mut libc::c_char; meta_part = build_body_file( meta, b"group-image\x00" as *const u8 as *const libc::c_char, @@ -792,6 +761,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: } dc_msg_unref(meta); } + if (*msg).type_0 == DC_MSG_VOICE || (*msg).type_0 == DC_MSG_AUDIO || (*msg).type_0 == DC_MSG_VIDEO @@ -805,8 +775,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ), ); } - let duration_ms: libc::c_int = - dc_param_get_int((*msg).param, DC_PARAM_DURATION as i32, 0); + let duration_ms = (*msg).param.get_int(Param::Duration).unwrap_or_default(); if duration_ms > 0 { mailimf_fields_add( imf_fields, @@ -820,14 +789,15 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); } } - afwd_email = dc_param_exists((*msg).param, DC_PARAM_FORWARDED as i32); - let mut fwdhint: *mut libc::c_char = 0 as *mut libc::c_char; + afwd_email = (*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( b"---------- Forwarded message ----------\r\nFrom: Delta Chat\r\n\r\n\x00" as *const u8 as *const libc::c_char, ) } + let mut final_text: *const libc::c_char = 0 as *const libc::c_char; if !placeholdertext.is_null() { final_text = placeholdertext @@ -871,6 +841,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: parts += 1; free(fwdhint as *mut libc::c_void); free(placeholdertext as *mut libc::c_void); + /* add attachment part */ if msgtype_has_file((*msg).type_0) { if 0 == is_file_size_okay(msg) { @@ -907,18 +878,15 @@ 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 0 != dc_param_exists((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int) - { - let latitude = dc_param_get_float( - (*msg).param, - DC_PARAM_SET_LATITUDE as libc::c_int, - 0.0, - ); - let longitude = dc_param_get_float( - (*msg).param, - DC_PARAM_SET_LONGITUDE as libc::c_int, - 0.0, - ); + if (*msg).param.exists(Param::SetLatitude) { + let latitude = (*msg) + .param + .get_float(Param::SetLatitude) + .unwrap_or_default(); + let longitude = (*msg) + .param + .get_float(Param::SetLongitude) + .unwrap_or_default(); let kml_file = dc_get_message_kml((*msg).timestamp_sort, latitude, longitude); if !kml_file.is_null() { @@ -965,10 +933,7 @@ 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 0 == dc_param_exists( - (*msg).param, - DC_PARAM_SET_LATITUDE as libc::c_int, - ) { + if !(*msg).param.exists(Param::SetLatitude) { // otherwise, the independent location is already filed (*factory).out_last_added_location_id = last_added_location_id; } @@ -996,7 +961,11 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: mailmime_add_part(message, multipart); let p1: *mut libc::c_char; let p2: *mut libc::c_char; - if 0 != dc_param_get_int((*(*factory).msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 0) { + if 0 != (*(*factory).msg) + .param + .get_int(Param::GuranteeE2ee) + .unwrap_or_default() + { p1 = to_cstring((*factory).context.stock_str(StockMessage::EncryptedMsg)); } else { p1 = dc_msg_get_summarytext((*factory).msg, 32) @@ -1034,6 +1003,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ); current_block = 11328123142868406523; } + match current_block { 11328123142868406523 => {} _ => { @@ -1114,26 +1084,25 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: free(message_text as *mut libc::c_void); free(message_text2 as *mut libc::c_void); free(subject_str as *mut libc::c_void); - free(grpimage as *mut libc::c_void); success } unsafe fn get_subject( chat: *const Chat, - msg: *const dc_msg_t, + msg: *mut dc_msg_t, afwd_email: libc::c_int, ) -> *mut libc::c_char { let context = (*chat).context; let ret: *mut libc::c_char; - let raw_subject: *mut libc::c_char = - dc_msg_get_summarytext_by_raw((*msg).type_0, (*msg).text, (*msg).param, 32, context); - let fwd: *const libc::c_char = if 0 != afwd_email { + let raw_subject = + dc_msg_get_summarytext_by_raw((*msg).type_0, (*msg).text, &mut (*msg).param, 32, context); + let fwd = if 0 != afwd_email { b"Fwd: \x00" as *const u8 as *const libc::c_char } else { b"\x00" as *const u8 as *const libc::c_char }; - if dc_param_get_int((*msg).param, DC_PARAM_CMD as i32, 0) == 6 { + if (*msg).param.get_int(Param::Cmd).unwrap_or_default() == 6 { ret = to_cstring(context.stock_str(StockMessage::AcSetupMsgSubject)) } else if (*chat).type_0 == DC_CHAT_TYPE_GROUP as libc::c_int || (*chat).type_0 == DC_CHAT_TYPE_VERIFIED_GROUP as libc::c_int @@ -1194,16 +1163,21 @@ 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 pathNfilename: *mut libc::c_char = - dc_param_get((*msg).param, DC_PARAM_FILE as i32, 0 as *const libc::c_char); - let mut mimetype: *mut libc::c_char = dc_param_get( - (*msg).param, - DC_PARAM_MIMETYPE as i32, - 0 as *const libc::c_char, - ); - let suffix: *mut libc::c_char = dc_get_filesuffix_lc(pathNfilename); - let mut filename_to_send: *mut libc::c_char = 0 as *mut libc::c_char; - let mut filename_encoded: *mut libc::c_char = 0 as *mut libc::c_char; + let pathNfilename = (*msg) + .param + .get(Param::File) + .map(|s| to_cstring(s)) + .unwrap_or_else(|| std::ptr::null_mut()); + let mut mimetype = (*msg) + .param + .get(Param::MimeType) + .map(|s| to_cstring(s)) + .unwrap_or_else(|| std::ptr::null_mut()); + + let suffix = dc_get_filesuffix_lc(pathNfilename); + let mut filename_to_send = 0 as *mut libc::c_char; + let mut filename_encoded = 0 as *mut libc::c_char; + if !pathNfilename.is_null() { if (*msg).type_0 == DC_MSG_VOICE { let ts = chrono::Utc.timestamp((*msg).timestamp_sort as i64, 0); @@ -1355,14 +1329,14 @@ unsafe fn build_body_file( ******************************************************************************/ #[allow(non_snake_case)] unsafe fn is_file_size_okay(msg: *const dc_msg_t) -> libc::c_int { - let mut file_size_okay: libc::c_int = 1; - let pathNfilename: *mut libc::c_char = - dc_param_get((*msg).param, DC_PARAM_FILE as i32, 0 as *const libc::c_char); - let bytes: uint64_t = dc_get_filebytes((*msg).context, pathNfilename); - if bytes > (49 * 1024 * 1024 / 4 * 3) as libc::c_ulonglong { + let mut file_size_okay = 1; + let pathNfilename = to_cstring((*msg).param.get(Param::File).unwrap_or_default()); + let bytes = dc_get_filebytes((*msg).context, pathNfilename); + + if bytes > (49 * 1024 * 1024 / 4 * 3) { file_size_okay = 0; } - free(pathNfilename as *mut libc::c_void); + free(pathNfilename as *mut _); file_size_okay } diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index 570b63a3c..f5bc4cc64 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -15,10 +15,10 @@ use crate::context::Context; use crate::dc_contact::*; use crate::dc_e2ee::*; use crate::dc_location::*; -use crate::dc_param::*; use crate::dc_simplify::*; use crate::dc_strencode::*; use crate::dc_tools::*; +use crate::param::*; use crate::stock::StockMessage; use crate::types::*; use crate::x::*; @@ -26,7 +26,7 @@ use crate::x::*; /* Parse MIME body; this is the text part of an IMF, see https://tools.ietf.org/html/rfc5322 dc_mimeparser_t has no deep dependencies to Context or to the database (Context is used for logging only). */ -#[derive(Copy, Clone)] +#[derive(Clone)] #[repr(C)] pub struct dc_mimepart_t { pub type_0: libc::c_int, @@ -35,7 +35,7 @@ pub struct dc_mimepart_t { pub msg: *mut libc::c_char, pub msg_raw: *mut libc::c_char, pub bytes: libc::c_int, - pub param: *mut dc_param_t, + pub param: Params, } /* * @@ -105,10 +105,9 @@ pub unsafe fn dc_mimeparser_empty(mimeparser: &mut dc_mimeparser_t) { let cnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; i = 0i32; while i < cnt { - let part: *mut dc_mimepart_t = - carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; + let part = carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; if !part.is_null() { - dc_mimepart_unref(part); + dc_mimepart_unref(*Box::from_raw(part)); } i += 1 } @@ -146,16 +145,11 @@ pub unsafe fn dc_mimeparser_empty(mimeparser: &mut dc_mimeparser_t) { (*mimeparser).message_kml = None; } -unsafe fn dc_mimepart_unref(mut mimepart: *mut dc_mimepart_t) { - if mimepart.is_null() { - return; - } - free((*mimepart).msg as *mut libc::c_void); - (*mimepart).msg = 0 as *mut libc::c_char; - free((*mimepart).msg_raw as *mut libc::c_void); - (*mimepart).msg_raw = 0 as *mut libc::c_char; - dc_param_unref((*mimepart).param); - free(mimepart as *mut libc::c_void); +unsafe fn dc_mimepart_unref(mut mimepart: dc_mimepart_t) { + free(mimepart.msg as *mut libc::c_void); + mimepart.msg = 0 as *mut libc::c_char; + free(mimepart.msg_raw as *mut libc::c_void); + mimepart.msg_raw = 0 as *mut libc::c_char; } pub unsafe fn dc_mimeparser_parse( @@ -209,10 +203,10 @@ pub unsafe fn dc_mimeparser_parse( (*mimeparser).is_system_message = 6i32; i = 0i32; while (i as libc::c_uint) < carray_count((*mimeparser).parts) { - let part_0: *mut dc_mimepart_t = + let part_0 = carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; if (*part_0).int_mimetype != 111i32 { - dc_mimepart_unref(part_0); + dc_mimepart_unref(*Box::from_raw(part_0)); carray_delete_slow((*mimeparser).parts, i as libc::c_uint); i -= 1 } @@ -253,10 +247,8 @@ pub unsafe fn dc_mimeparser_parse( && 0 != S_GENERATE_COMPOUND_MSGS && carray_count((*mimeparser).parts) == 2i32 as libc::c_uint { - let mut textpart_0: *mut dc_mimepart_t = - carray_get((*mimeparser).parts, 0i32 as libc::c_uint) as *mut dc_mimepart_t; - let mut filepart: *mut dc_mimepart_t = - carray_get((*mimeparser).parts, 1i32 as libc::c_uint) as *mut dc_mimepart_t; + let mut textpart_0 = carray_get((*mimeparser).parts, 0) as *mut dc_mimepart_t; + let mut filepart = carray_get((*mimeparser).parts, 1) as *mut dc_mimepart_t; if (*textpart_0).type_0 == 10i32 && ((*filepart).type_0 == 20i32 || (*filepart).type_0 == 21i32 @@ -269,7 +261,7 @@ pub unsafe fn dc_mimeparser_parse( free((*filepart).msg as *mut libc::c_void); (*filepart).msg = (*textpart_0).msg; (*textpart_0).msg = 0 as *mut libc::c_char; - dc_mimepart_unref(textpart_0); + dc_mimepart_unref(*Box::from_raw(textpart_0)); carray_delete_slow((*mimeparser).parts, 0i32 as libc::c_uint); } } @@ -326,9 +318,9 @@ pub unsafe fn dc_mimeparser_parse( let icnt_0: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; i_1 = 0i32; while i_1 < icnt_0 { - let part_2: *mut dc_mimepart_t = + let part_2 = carray_get((*mimeparser).parts, i_1 as libc::c_uint) as *mut dc_mimepart_t; - dc_param_set_int((*part_2).param, DC_PARAM_FORWARDED as i32, 1); + (*part_2).param.set_int(Param::Forwarded, 1); i_1 += 1 } } @@ -346,14 +338,14 @@ pub unsafe fn dc_mimeparser_parse( } } if (*part_3).type_0 == 40i32 || (*part_3).type_0 == 41i32 || (*part_3).type_0 == 50i32 { - let field_0: *const mailimf_optional_field = dc_mimeparser_lookup_optional_field( + let field_0 = dc_mimeparser_lookup_optional_field( mimeparser, b"Chat-Duration\x00" as *const u8 as *const libc::c_char, ); if !field_0.is_null() { let duration_ms: libc::c_int = dc_atoi_null_is_0((*field_0).fld_value); if duration_ms > 0i32 && duration_ms < 24i32 * 60i32 * 60i32 * 1000i32 { - dc_param_set_int((*part_3).param, DC_PARAM_DURATION as i32, duration_ms); + (*part_3).param.set_int(Param::Duration, duration_ms); } } } @@ -390,11 +382,7 @@ pub unsafe fn dc_mimeparser_parse( let part_4: *mut dc_mimepart_t = dc_mimeparser_get_last_nonmeta(mimeparser); if !part_4.is_null() { - dc_param_set_int( - (*part_4).param, - DC_PARAM_WANTS_MDN as i32, - 1, - ); + (*part_4).param.set_int(Param::WantsMdn, 1); } } free(from_addr as *mut libc::c_void); @@ -411,16 +399,16 @@ pub unsafe fn dc_mimeparser_parse( if dc_mimeparser_get_last_nonmeta(mimeparser).is_null() && carray_count((*mimeparser).reports) == 0i32 as libc::c_uint { - let mut part_5: *mut dc_mimepart_t = dc_mimepart_new(); - (*part_5).type_0 = 10i32; + let mut part_5 = dc_mimepart_new(); + part_5.type_0 = 10i32; if !(*mimeparser).subject.is_null() && 0 == (*mimeparser).is_send_by_messenger { - (*part_5).msg = dc_strdup((*mimeparser).subject) + part_5.msg = dc_strdup((*mimeparser).subject) } else { - (*part_5).msg = dc_strdup(b"\x00" as *const u8 as *const libc::c_char) + part_5.msg = dc_strdup(b"\x00" as *const u8 as *const libc::c_char) } carray_add( (*mimeparser).parts, - part_5 as *mut libc::c_void, + Box::into_raw(Box::new(part_5)) as *mut libc::c_void, 0 as *mut libc::c_uint, ); }; @@ -429,13 +417,16 @@ pub unsafe fn dc_mimeparser_parse( /******************************************************************************* * a MIME part ******************************************************************************/ -unsafe fn dc_mimepart_new() -> *mut dc_mimepart_t { - let mut mimepart: *mut dc_mimepart_t; - mimepart = calloc(1, ::std::mem::size_of::()) as *mut dc_mimepart_t; - assert!(!mimepart.is_null()); - (*mimepart).type_0 = 0i32; - (*mimepart).param = dc_param_new(); - mimepart +unsafe fn dc_mimepart_new() -> dc_mimepart_t { + dc_mimepart_t { + type_0: 0, + is_meta: 0, + int_mimetype: 0, + msg: std::ptr::null_mut(), + msg_raw: std::ptr::null_mut(), + bytes: 0, + param: Params::new(), + } } pub unsafe fn dc_mimeparser_get_last_nonmeta(mimeparser: &dc_mimeparser_t) -> *mut dc_mimepart_t { @@ -666,8 +657,8 @@ unsafe fn dc_mimeparser_parse_mime_recursive( } } 40 => { - let mut part: *mut dc_mimepart_t = dc_mimepart_new(); - (*part).type_0 = 10i32; + let mut part = dc_mimepart_new(); + part.type_0 = 10i32; let msg_body = CString::new( (*mimeparser) .context @@ -675,14 +666,14 @@ unsafe fn dc_mimeparser_parse_mime_recursive( .as_ref(), ) .unwrap(); - (*part).msg = dc_mprintf( + part.msg = dc_mprintf( b"[%s]\x00" as *const u8 as *const libc::c_char, msg_body.as_ptr(), ); - (*part).msg_raw = dc_strdup((*part).msg); + part.msg_raw = dc_strdup(part.msg); carray_add( (*mimeparser).parts, - part as *mut libc::c_void, + Box::into_raw(Box::new(part)) as *mut libc::c_void, 0 as *mut libc::c_uint, ); any_part_added = 1i32; @@ -1145,7 +1136,6 @@ unsafe fn dc_mimeparser_add_single_part_if_known( mime: *mut mailmime, ) -> libc::c_int { let mut current_block: u64; - let mut part: *mut dc_mimepart_t = 0 as *mut dc_mimepart_t; let old_part_count: libc::c_int = carray_count(mimeparser.parts) as libc::c_int; let mime_type: libc::c_int; let mime_data: *mut mailmime_data; @@ -1241,14 +1231,13 @@ unsafe fn dc_mimeparser_add_single_part_if_known( if !simplified_txt.is_null() && 0 != *simplified_txt.offset(0isize) as libc::c_int { - part = dc_mimepart_new(); - (*part).type_0 = 10i32; - (*part).int_mimetype = mime_type; - (*part).msg = simplified_txt; - (*part).msg_raw = + let mut part = dc_mimepart_new(); + part.type_0 = 10i32; + part.int_mimetype = mime_type; + part.msg = simplified_txt; + part.msg_raw = strndup(decoded_data, decoded_data_bytes as libc::c_ulong); do_add_single_part(mimeparser, part); - part = 0 as *mut dc_mimepart_t } else { free(simplified_txt as *mut libc::c_void); } @@ -1440,7 +1429,6 @@ unsafe fn dc_mimeparser_add_single_part_if_known( } free(file_suffix as *mut libc::c_void); free(desired_filename as *mut libc::c_void); - dc_mimepart_unref(part); free(raw_mime as *mut libc::c_void); return if carray_count((*mimeparser).parts) > old_part_count as libc::c_uint { 1i32 @@ -1459,7 +1447,6 @@ unsafe fn do_add_single_file_part( decoded_data_bytes: size_t, desired_filename: *const libc::c_char, ) { - let mut part: *mut dc_mimepart_t = 0 as *mut dc_mimepart_t; let pathNfilename: *mut libc::c_char; /* create a free file name to use */ pathNfilename = dc_get_fine_pathNfilename( @@ -1476,42 +1463,40 @@ unsafe fn do_add_single_file_part( decoded_data_bytes, ) == 0i32) { - part = dc_mimepart_new(); - (*part).type_0 = msg_type; - (*part).int_mimetype = mime_type; - (*part).bytes = decoded_data_bytes as libc::c_int; - dc_param_set((*part).param, DC_PARAM_FILE as i32, pathNfilename); - dc_param_set((*part).param, DC_PARAM_MIMETYPE as i32, raw_mime); - if mime_type == 80i32 { - let mut w: uint32_t = 0i32 as uint32_t; - let mut h: uint32_t = 0i32 as uint32_t; + let mut part = dc_mimepart_new(); + part.type_0 = msg_type; + part.int_mimetype = mime_type; + part.bytes = decoded_data_bytes as libc::c_int; + part.param.set(Param::File, as_str(pathNfilename)); + part.param.set(Param::MimeType, as_str(raw_mime)); + if mime_type == 80 { + let mut w = 0; + let mut h = 0; if 0 != dc_get_filemeta( decoded_data as *const libc::c_void, decoded_data_bytes, &mut w, &mut h, ) { - dc_param_set_int((*part).param, DC_PARAM_WIDTH as i32, w as int32_t); - dc_param_set_int((*part).param, DC_PARAM_HEIGHT as i32, h as int32_t); + part.param.set_int(Param::Width, w as i32); + part.param.set_int(Param::Height, h as i32); } } do_add_single_part(parser, part); - part = 0 as *mut dc_mimepart_t } } free(pathNfilename as *mut libc::c_void); - dc_mimepart_unref(part); } -unsafe fn do_add_single_part(parser: &dc_mimeparser_t, part: *mut dc_mimepart_t) { +unsafe fn do_add_single_part(parser: &dc_mimeparser_t, mut part: dc_mimepart_t) { if 0 != (*parser).e2ee_helper.encrypted && (*parser).e2ee_helper.signatures.len() > 0 { - dc_param_set_int((*part).param, DC_PARAM_GUARANTEE_E2EE as i32, 1); + part.param.set_int(Param::GuranteeE2ee, 1); } else if 0 != (*parser).e2ee_helper.encrypted { - dc_param_set_int((*part).param, DC_PARAM_ERRONEOUS_E2EE as i32, 0x2); + part.param.set_int(Param::ErroneousE2ee, 0x2); } carray_add( (*parser).parts, - part as *mut libc::c_void, + Box::into_raw(Box::new(part)) as *mut libc::c_void, 0 as *mut libc::c_uint, ); } @@ -1816,7 +1801,7 @@ pub unsafe fn dc_mimeparser_repl_msg_by_error( while (i as libc::c_uint) < carray_count((*mimeparser).parts) { part = carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; if !part.is_null() { - dc_mimepart_unref(part); + dc_mimepart_unref(*Box::from_raw(part)); } i += 1 } diff --git a/src/dc_move.rs b/src/dc_move.rs index 69005cc8d..98453e750 100644 --- a/src/dc_move.rs +++ b/src/dc_move.rs @@ -2,6 +2,7 @@ use crate::constants::*; use crate::context::*; use crate::dc_job::*; use crate::dc_msg::*; +use crate::param::Params; pub unsafe fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u32) { if context @@ -31,13 +32,7 @@ pub unsafe fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u3 // 1 = dc message, 2 = reply to dc message if 0 != (*msg).is_dc_message { - dc_job_add( - context, - 200, - (*msg).id as libc::c_int, - 0 as *const libc::c_char, - 0, - ); + dc_job_add(context, 200, (*msg).id as libc::c_int, Params::new(), 0); dc_update_msg_move_state(context, (*msg).rfc724_mid, DC_MOVE_STATE_MOVING); } diff --git a/src/dc_msg.rs b/src/dc_msg.rs index ff3476ab8..1361af3f8 100644 --- a/src/dc_msg.rs +++ b/src/dc_msg.rs @@ -7,8 +7,8 @@ use crate::dc_contact::*; use crate::dc_job::*; use crate::dc_lot::dc_lot_t; use crate::dc_lot::*; -use crate::dc_param::*; use crate::dc_tools::*; +use crate::param::*; use crate::pgp::*; use crate::sql; use crate::stock::StockMessage; @@ -16,7 +16,7 @@ use crate::types::*; use crate::x::*; /* * the structure behind dc_msg_t */ -#[derive(Copy, Clone)] +#[derive(Clone)] #[repr(C)] pub struct dc_msg_t<'a> { pub magic: uint32_t, @@ -41,7 +41,7 @@ pub struct dc_msg_t<'a> { pub starred: libc::c_int, pub chat_blocked: libc::c_int, pub location_id: uint32_t, - pub param: *mut dc_param_t, + pub param: Params, } // handle messages @@ -144,26 +144,30 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch ret += ", Location sent"; } - let e2ee_errors = dc_param_get_int((*msg).param, DC_PARAM_ERRONEOUS_E2EE as i32, 0); + 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 != dc_param_get_int((*msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 0) { + } else if 0 + != (*msg) + .param + .get_int(Param::GuranteeE2ee) + .unwrap_or_default() + { ret += ", Encrypted"; } ret += "\n"; - p = dc_param_get( - (*msg).param, - DC_PARAM_ERROR as i32, - 0 as *const libc::c_char, - ); - if !p.is_null() { - ret += &format!("Error: {}", as_str(p)); - free(p as *mut libc::c_void); + match (*msg).param.get(Param::Error) { + Some(err) => ret += &format!("Error: {}", err), + _ => {} } + p = dc_msg_get_file(msg); if !p.is_null() && 0 != *p.offset(0isize) as libc::c_int { ret += &format!( @@ -190,12 +194,12 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch ret += &format!("Mimetype: {}\n", as_str(p)); free(p as *mut libc::c_void); } - let w = dc_param_get_int((*msg).param, DC_PARAM_WIDTH as i32, 0); - let h = dc_param_get_int((*msg).param, DC_PARAM_HEIGHT as i32, 0); + 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 = dc_param_get_int((*msg).param, DC_PARAM_DURATION as i32, 0); + let duration = (*msg).param.get_int(Param::Duration).unwrap_or_default(); if duration != 0 { ret += &format!("Duration: {} ms\n", duration,); } @@ -233,16 +237,33 @@ pub unsafe fn dc_msg_new_untyped<'a>(context: &'a Context) -> *mut dc_msg_t<'a> // 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: libc::c_int) -> *mut dc_msg_t<'a> { - let mut msg: *mut dc_msg_t; - msg = calloc(1, ::std::mem::size_of::()) as *mut dc_msg_t; - assert!(!msg.is_null()); - (*msg).context = context; - (*msg).magic = 0x11561156i32 as uint32_t; - (*msg).type_0 = viewtype; - (*msg).state = 0; - (*msg).param = dc_param_new(); + let msg = dc_msg_t { + magic: 0x11561156, + id: 0, + from_id: 0, + to_id: 0, + chat_id: 0, + move_state: 0, + type_0: viewtype, + state: 0, + hidden: 0, + timestamp_sort: 0, + timestamp_sent: 0, + timestamp_rcvd: 0, + text: std::ptr::null_mut(), + context, + rfc724_mid: std::ptr::null_mut(), + in_reply_to: std::ptr::null_mut(), + server_folder: std::ptr::null_mut(), + server_uid: 0, + is_dc_message: 0, + starred: 0, + chat_blocked: 0, + location_id: 0, + param: Params::new(), + }; - msg + Box::into_raw(Box::new(msg)) } pub unsafe fn dc_msg_unref(mut msg: *mut dc_msg_t) { @@ -250,9 +271,8 @@ pub unsafe fn dc_msg_unref(mut msg: *mut dc_msg_t) { return; } dc_msg_empty(msg); - dc_param_unref((*msg).param); (*msg).magic = 0i32 as uint32_t; - free(msg as *mut libc::c_void); + Box::from_raw(msg); } pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) { @@ -267,37 +287,38 @@ pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) { (*msg).in_reply_to = 0 as *mut libc::c_char; free((*msg).server_folder as *mut libc::c_void); (*msg).server_folder = 0 as *mut libc::c_char; - dc_param_set_packed((*msg).param, 0 as *const 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 { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; - let mut file: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret = 0 as *mut libc::c_char; + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { - ret = dc_param_get( - (*msg).param, - DC_PARAM_MIMETYPE as i32, - 0 as *const libc::c_char, - ); - if ret.is_null() { - file = dc_param_get((*msg).param, DC_PARAM_FILE as i32, 0 as *const libc::c_char); - if !file.is_null() { - dc_msg_guess_msgtype_from_suffix(file, 0 as *mut libc::c_int, &mut ret); - if ret.is_null() { - ret = dc_strdup( - b"application/octet-stream\x00" as *const u8 as *const libc::c_char, - ) + match (*msg).param.get(Param::MimeType) { + Some(m) => { + ret = to_cstring(m); + } + None => { + if let Some(file) = (*msg).param.get(Param::File) { + let file_c = to_cstring(file); + dc_msg_guess_msgtype_from_suffix(file_c, 0 as *mut libc::c_int, &mut ret); + if ret.is_null() { + ret = dc_strdup( + b"application/octet-stream\x00" as *const u8 as *const libc::c_char, + ) + } + free(file_c as *mut _); } } } } - free(file as *mut libc::c_void); - return if !ret.is_null() { - ret - } else { - dc_strdup(0 as *const libc::c_char) - }; + + if !ret.is_null() { + return ret; + } + + dc_strdup(0 as *const libc::c_char) } #[allow(non_snake_case)] @@ -356,20 +377,20 @@ pub unsafe fn dc_msg_guess_msgtype_from_suffix( } pub unsafe fn dc_msg_get_file(msg: *const dc_msg_t) -> *mut libc::c_char { - let mut file_rel: *mut libc::c_char = 0 as *mut libc::c_char; - let mut file_abs: *mut libc::c_char = 0 as *mut libc::c_char; + let mut file_abs = 0 as *mut libc::c_char; + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { - file_rel = dc_param_get((*msg).param, DC_PARAM_FILE as i32, 0 as *const libc::c_char); - if !file_rel.is_null() { - file_abs = dc_get_abs_path((*msg).context, file_rel) + if let Some(file_rel) = (*msg).param.get(Param::File) { + let file_rel_c = to_cstring(file_rel); + file_abs = dc_get_abs_path((*msg).context, file_rel_c); + free(file_rel_c as *mut _); } } - free(file_rel as *mut libc::c_void); - return if !file_abs.is_null() { + if !file_abs.is_null() { file_abs } else { dc_strdup(0 as *const libc::c_char) - }; + } } /** @@ -407,7 +428,7 @@ pub unsafe fn dc_msg_has_location(msg: *const dc_msg_t) -> bool { * @return None. */ pub unsafe fn dc_msg_set_location( - msg: *const dc_msg_t, + msg: *mut dc_msg_t, latitude: libc::c_double, longitude: libc::c_double, ) { @@ -418,12 +439,8 @@ pub unsafe fn dc_msg_set_location( return; } - dc_param_set_float((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int, latitude); - dc_param_set_float( - (*msg).param, - DC_PARAM_SET_LONGITUDE as libc::c_int, - 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 { @@ -474,10 +491,7 @@ pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id: (*msg).state = row.get(13)?; (*msg).is_dc_message = row.get(14)?; (*msg).text = to_cstring(row.get::<_, String>(15).unwrap_or_default()); - dc_param_set_packed( - (*msg).param, - to_cstring(row.get::<_, String>(16)?) - ); + (*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)?; @@ -520,18 +534,18 @@ pub unsafe fn dc_delete_msgs(context: &Context, msg_ids: *const uint32_t, msg_cn dc_update_msg_chat_id(context, *msg_ids.offset(i as isize), 3i32 as uint32_t); dc_job_add( context, - 110i32, + 110, *msg_ids.offset(i as isize) as libc::c_int, - 0 as *const libc::c_char, - 0i32, + Params::new(), + 0, ); i += 1 } if 0 != msg_cnt { - context.call_cb(Event::MSGS_CHANGED, 0i32 as uintptr_t, 0i32 as uintptr_t); - dc_job_kill_action(context, 105i32); - dc_job_add(context, 105i32, 0i32, 0 as *const libc::c_char, 10i32); + context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t); + dc_job_kill_action(context, 105); + dc_job_add(context, 105, 0, Params::new(), 10); }; } @@ -581,7 +595,7 @@ pub fn dc_markseen_msgs(context: &Context, msg_ids: *const u32, msg_cnt: usize) dc_update_msg_state(context, id, DC_STATE_IN_SEEN); info!(context, 0, "Seen message #{}.", id); - unsafe { dc_job_add(context, 130, id as i32, 0 as *const libc::c_char, 0) }; + unsafe { dc_job_add(context, 130, id as i32, Params::new(), 0) }; send_event = true; } } else if curr_state == DC_STATE_IN_FRESH { @@ -711,81 +725,86 @@ 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 { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; - let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret = 0 as *mut libc::c_char; + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { - pathNfilename = dc_param_get((*msg).param, DC_PARAM_FILE as i32, 0 as *const libc::c_char); - if !pathNfilename.is_null() { - ret = dc_get_filename(pathNfilename) + if let Some(file) = (*msg).param.get(Param::File) { + let file_c = to_cstring(file); + ret = dc_get_filename(file_c); + free(file_c as *mut _); } } - free(pathNfilename as *mut libc::c_void); - return if !ret.is_null() { + if !ret.is_null() { ret } else { dc_strdup(0 as *const libc::c_char) - }; + } } pub unsafe fn dc_msg_get_filebytes(msg: *const dc_msg_t) -> uint64_t { - let mut ret: uint64_t = 0i32 as uint64_t; - let mut file: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret = 0; + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { - file = dc_param_get((*msg).param, DC_PARAM_FILE as i32, 0 as *const libc::c_char); - if !file.is_null() { - ret = dc_get_filebytes((*msg).context, file) + if let Some(file) = (*msg).param.get(Param::File) { + let file_c = to_cstring(file); + ret = dc_get_filebytes((*msg).context, file_c); + free(file_c as *mut _); } } - free(file as *mut libc::c_void); ret } pub unsafe fn dc_msg_get_width(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { - return 0i32; - } - - dc_param_get_int((*msg).param, DC_PARAM_WIDTH as i32, 0) -} - -pub unsafe fn dc_msg_get_height(msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { - return 0i32; - } - - dc_param_get_int((*msg).param, DC_PARAM_HEIGHT as i32, 0) -} - -pub unsafe fn dc_msg_get_duration(msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0; } - dc_param_get_int((*msg).param, DC_PARAM_DURATION as i32, 0) + (*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() || (*msg).magic != 0x11561156 as libc::c_uint { + return 0; + } + + (*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() || (*msg).magic != 0x11561156 as libc::c_uint { + return 0; + } + + (*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() || (*msg).magic != 0x11561156i32 as libc::c_uint { - return 0i32; + if msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint { + return 0; } - if dc_param_get_int((*msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 0) != 0i32 { - return 1i32; + if (*msg) + .param + .get_int(Param::GuranteeE2ee) + .unwrap_or_default() + != 0 + { + return 1; } 0 } pub unsafe fn dc_msg_get_summary<'a>( - msg: *const dc_msg_t<'a>, + msg: *mut dc_msg_t<'a>, mut chat: *const Chat<'a>, ) -> *mut dc_lot_t { let current_block: u64; let ret: *mut dc_lot_t = dc_lot_new(); let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t; let mut chat_to_delete: *mut Chat = 0 as *mut Chat; - if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { + if !(msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint) { if chat.is_null() { chat_to_delete = dc_get_chat((*msg).context, (*msg).chat_id); if chat_to_delete.is_null() { @@ -800,8 +819,8 @@ pub unsafe fn dc_msg_get_summary<'a>( match current_block { 15204159476013091401 => {} _ => { - if (*msg).from_id != 1i32 as libc::c_uint - && ((*chat).type_0 == 120i32 || (*chat).type_0 == 130i32) + if (*msg).from_id != 1 as libc::c_uint + && ((*chat).type_0 == 120 || (*chat).type_0 == 130) { contact = dc_get_contact((*chat).context, (*msg).from_id) } @@ -816,7 +835,7 @@ pub unsafe fn dc_msg_get_summary<'a>( } pub unsafe fn dc_msg_get_summarytext( - msg: *const dc_msg_t, + msg: *mut dc_msg_t, approx_characters: libc::c_int, ) -> *mut libc::c_char { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { @@ -826,7 +845,7 @@ pub unsafe fn dc_msg_get_summarytext( dc_msg_get_summarytext_by_raw( (*msg).type_0, (*msg).text, - (*msg).param, + &mut (*msg).param, approx_characters, (*msg).context, ) @@ -837,7 +856,7 @@ pub unsafe fn dc_msg_get_summarytext( pub unsafe fn dc_msg_get_summarytext_by_raw( type_0: libc::c_int, text: *const libc::c_char, - param: *mut dc_param_t, + param: &mut Params, approx_characters: libc::c_int, context: &Context, ) -> *mut libc::c_char { @@ -853,15 +872,11 @@ pub unsafe fn dc_msg_get_summarytext_by_raw( 50 => prefix = to_cstring(context.stock_str(StockMessage::Video)), 41 => prefix = to_cstring(context.stock_str(StockMessage::VoiceMessage)), 40 | 60 => { - if dc_param_get_int(param, DC_PARAM_CMD as i32, 0) == 6 { + if param.get_int(Param::Cmd) == Some(6) { prefix = to_cstring(context.stock_str(StockMessage::AcSetupMsgSubject)); append_text = 0i32 } else { - pathNfilename = dc_param_get( - param, - DC_PARAM_FILE as i32, - b"ErrFilename\x00" as *const u8 as *const libc::c_char, - ); + pathNfilename = to_cstring(param.get(Param::File).unwrap_or_else(|| "ErrFilename")); value = dc_get_filename(pathNfilename); let label = CString::new( context @@ -881,9 +896,9 @@ pub unsafe fn dc_msg_get_summarytext_by_raw( } } _ => { - if dc_param_get_int(param, DC_PARAM_CMD as i32, 0) == 9i32 { + if param.get_int(Param::Cmd) == Some(9) { prefix = to_cstring(context.stock_str(StockMessage::Location)); - append_text = 0i32 + append_text = 0; } } } @@ -946,26 +961,26 @@ pub unsafe fn dc_msg_is_starred(msg: *const dc_msg_t) -> libc::c_int { // TODO should return bool /rtn pub unsafe fn dc_msg_is_forwarded(msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { - return 0i32; + return 0; } - return if 0 != dc_param_get_int((*msg).param, DC_PARAM_FORWARDED as i32, 0) { - 1i32 + if 0 != (*msg).param.get_int(Param::Forwarded).unwrap_or_default() { + 1 } else { - 0i32 - }; + 0 + } } // TODO should return bool /rtn pub unsafe fn dc_msg_is_info(msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { - return 0i32; + return 0; } - let cmd: libc::c_int = dc_param_get_int((*msg).param, DC_PARAM_CMD as i32, 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 || 0 != cmd && cmd != 6i32 { - return 1i32; + return 1; } 0 @@ -992,7 +1007,7 @@ pub unsafe fn dc_msg_is_setupmessage(msg: *const dc_msg_t) -> bool { return false; } - dc_param_get_int((*msg).param, DC_PARAM_CMD as i32, 0) == 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 { @@ -1061,23 +1076,27 @@ pub unsafe fn dc_msg_set_file( if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return; } - dc_param_set((*msg).param, DC_PARAM_FILE as i32, file); - dc_param_set((*msg).param, DC_PARAM_MIMETYPE as i32, filemime); + if !file.is_null() { + (*msg).param.set(Param::File, as_str(file)); + } + if !filemime.is_null() { + (*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() || (*msg).magic != 0x11561156i32 as libc::c_uint { return; } - dc_param_set_int((*msg).param, DC_PARAM_WIDTH as i32, width); - dc_param_set_int((*msg).param, DC_PARAM_HEIGHT as i32, height); + (*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() || (*msg).magic != 0x11561156i32 as libc::c_uint { return; } - dc_param_set_int((*msg).param, DC_PARAM_DURATION as i32, duration); + (*msg).param.set_int(Param::Duration, duration); } pub unsafe fn dc_msg_latefiling_mediasize( @@ -1087,12 +1106,12 @@ pub unsafe fn dc_msg_latefiling_mediasize( duration: libc::c_int, ) { if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { - if width > 0i32 && height > 0i32 { - dc_param_set_int((*msg).param, DC_PARAM_WIDTH as i32, width); - dc_param_set_int((*msg).param, DC_PARAM_HEIGHT as i32, height); + if width > 0 && height > 0 { + (*msg).param.set_int(Param::Width, width); + (*msg).param.set_int(Param::Height, height); } - if duration > 0i32 { - dc_param_set_int((*msg).param, DC_PARAM_DURATION as i32, duration); + if duration > 0 { + (*msg).param.set_int(Param::Duration, duration); } dc_msg_save_param_to_disk(msg); }; @@ -1107,7 +1126,7 @@ pub unsafe fn dc_msg_save_param_to_disk(msg: *mut dc_msg_t) -> bool { (*msg).context, &(*msg).context.sql, "UPDATE msgs SET param=? WHERE id=?;", - params![as_str((*(*msg).param).packed), (*msg).id as i32], + params![(*msg).param.to_string(), (*msg).id as i32], ) .is_ok() } @@ -1197,7 +1216,7 @@ pub unsafe fn dc_set_msg_failed(context: &Context, msg_id: uint32_t, error: *con (*msg).state = DC_STATE_OUT_FAILED; } if !error.is_null() { - dc_param_set((*msg).param, DC_PARAM_ERROR as i32, error); + (*msg).param.set(Param::Error, as_str(error)); error!(context, 0, "{}", as_str(error),); } @@ -1205,7 +1224,7 @@ pub unsafe fn dc_set_msg_failed(context: &Context, msg_id: uint32_t, error: *con context, &context.sql, "UPDATE msgs SET state=?, param=? WHERE id=?;", - params![(*msg).state, as_str((*(*msg).param).packed), msg_id as i32], + params![(*msg).state, (*msg).param.to_string(), msg_id as i32], ) .is_ok() { diff --git a/src/dc_param.rs b/src/dc_param.rs deleted file mode 100644 index 8b0c243ec..000000000 --- a/src/dc_param.rs +++ /dev/null @@ -1,439 +0,0 @@ -use crate::dc_tools::*; -use crate::types::*; -use crate::x::*; - -/// for msgs and jobs -pub const DC_PARAM_FILE: char = 'f'; // string -/// for msgs -pub const DC_PARAM_WIDTH: char = 'w'; // int -/// for msgs -pub const DC_PARAM_HEIGHT: char = 'h'; // int -/// for msgs -pub const DC_PARAM_DURATION: char = 'd'; // int -/// for msgs -pub const DC_PARAM_MIMETYPE: char = 'm'; // string -/// for msgs: incoming: message is encryoted, outgoing: guarantee E2EE or the message is not send -pub const DC_PARAM_GUARANTEE_E2EE: char = 'c'; // int (bool?) -/// for msgs: decrypted with validation errors or without mutual set, if neither 'c' nor 'e' are preset, the messages is only transport encrypted -pub const DC_PARAM_ERRONEOUS_E2EE: char = 'e'; // int -/// for msgs: force unencrypted message, either DC_FP_ADD_AUTOCRYPT_HEADER (1), DC_FP_NO_AUTOCRYPT_HEADER (2) or 0 -pub const DC_PARAM_FORCE_PLAINTEXT: char = 'u'; // int (bool?) -/// for msgs: an incoming message which requests a MDN (aka read receipt) -pub const DC_PARAM_WANTS_MDN: char = 'r'; // int (bool?) -/// for msgs -pub const DC_PARAM_FORWARDED: char = 'a'; // int (bool?) -/// for msgs -pub const DC_PARAM_CMD: char = 'S'; // int -/// for msgs -pub const DC_PARAM_CMD_ARG: char = 'E'; // string -/// for msgs -pub const DC_PARAM_CMD_ARG2: char = 'F'; // string -/// for msgs -pub const DC_PARAM_CMD_ARG3: char = 'G'; // string -/// for msgs -pub const DC_PARAM_CMD_ARG4: char = 'H'; // string -/// for msgs -pub const DC_PARAM_ERROR: char = 'L'; // string -/// for msgs in PREPARING: space-separated list of message IDs of forwarded copies -pub const DC_PARAM_PREP_FORWARDS: char = 'P'; // string -/// for msgs -pub const DC_PARAM_SET_LATITUDE: char = 'l'; // float -/// for msgs -pub const DC_PARAM_SET_LONGITUDE: char = 'n'; // float - -/// for jobs -pub const DC_PARAM_SERVER_FOLDER: char = 'Z'; // string -/// for jobs -pub const DC_PARAM_SERVER_UID: char = 'z'; // int -/// for jobs -pub const DC_PARAM_ALSO_MOVE: char = 'M'; // int (bool?) -/// for jobs: space-separated list of message recipients -pub const DC_PARAM_RECIPIENTS: char = 'R'; // stringap -/// for groups -pub const DC_PARAM_UNPROMOTED: char = 'U'; // int (bool?) -/// for groups and contacts -pub const DC_PARAM_PROFILE_IMAGE: char = 'i'; // string (bytes?) -/// for chats -pub const DC_PARAM_SELFTALK: char = 'K'; - -// missing: 's', 'x', 'g' - -// values for DC_PARAM_FORCE_PLAINTEXT -pub const DC_FP_ADD_AUTOCRYPT_HEADER: u8 = 1; -pub const DC_FP_NO_AUTOCRYPT_HEADER: u8 = 2; - -/// An object for handling key=value parameter lists; for the key, currently only -/// a single character is allowed. -/// -/// The object is used eg. by Chat or dc_msg_t, for readable parameter names, -/// these classes define some DC_PARAM_* constantats. -/// -/// Only for library-internal use. -#[derive(Copy, Clone)] -#[repr(C)] -pub struct dc_param_t { - pub packed: *mut libc::c_char, -} - -// values for DC_PARAM_FORCE_PLAINTEXT -/* user functions */ -pub unsafe fn dc_param_exists(param: *mut dc_param_t, key: libc::c_int) -> libc::c_int { - let mut p2: *mut libc::c_char = 0 as *mut libc::c_char; - if param.is_null() || key == 0i32 { - return 0i32; - } - return if !find_param((*param).packed, key, &mut p2).is_null() { - 1i32 - } else { - 0i32 - }; -} - -unsafe extern "C" fn find_param( - haystack: *mut libc::c_char, - key: libc::c_int, - ret_p2: *mut *mut libc::c_char, -) -> *mut libc::c_char { - let mut p1: *mut libc::c_char; - let mut p2: *mut libc::c_char; - p1 = haystack; - loop { - if p1.is_null() || *p1 as libc::c_int == 0i32 { - return 0 as *mut libc::c_char; - } else { - if *p1 as libc::c_int == key && *p1.offset(1isize) as libc::c_int == '=' as i32 { - break; - } - p1 = strchr(p1, '\n' as i32); - if !p1.is_null() { - p1 = p1.offset(1isize) - } - } - } - p2 = strchr(p1, '\n' as i32); - if p2.is_null() { - p2 = &mut *p1.offset(strlen(p1) as isize) as *mut libc::c_char - } - *ret_p2 = p2; - - p1 -} - -/* the value may be an empty string, "def" is returned only if the value unset. The result must be free()'d in any case. */ -pub unsafe fn dc_param_get( - param: *const dc_param_t, - key: libc::c_int, - def: *const libc::c_char, -) -> *mut libc::c_char { - let mut p1: *mut libc::c_char; - let mut p2: *mut libc::c_char = 0 as *mut libc::c_char; - let bak: libc::c_char; - let ret: *mut libc::c_char; - if param.is_null() || key == 0i32 { - return if !def.is_null() { - dc_strdup(def) - } else { - 0 as *mut libc::c_char - }; - } - p1 = find_param((*param).packed, key, &mut p2); - if p1.is_null() { - return if !def.is_null() { - dc_strdup(def) - } else { - 0 as *mut libc::c_char - }; - } - p1 = p1.offset(2isize); - bak = *p2; - *p2 = 0i32 as libc::c_char; - ret = dc_strdup(p1); - dc_rtrim(ret); - *p2 = bak; - - ret -} - -pub unsafe fn dc_param_get_int( - param: *const dc_param_t, - key: libc::c_int, - def: int32_t, -) -> int32_t { - if param.is_null() || key == 0i32 { - return def; - } - let s = dc_param_get(param, key, 0 as *const libc::c_char); - if s.is_null() { - return def; - } - let ret = as_str(s).parse().unwrap_or_default(); - free(s as *mut libc::c_void); - - ret -} - -/** - * Get value of a parameter. - * - * @memberof dc_param_t - * @param param Parameter object to query. - * @param key Key of the parameter to get, one of the DC_PARAM_* constants. - * @param def Value to return if the parameter is not set. - * @return The stored value or the default value. - */ -pub unsafe fn dc_param_get_float( - param: *const dc_param_t, - key: libc::c_int, - def: libc::c_double, -) -> libc::c_double { - if param.is_null() || key == 0 { - return def; - } - - let str = dc_param_get(param, key, std::ptr::null()); - if str.is_null() { - return def; - } - - let ret = dc_atof(str) as libc::c_double; - free(str as *mut libc::c_void); - - ret -} - -pub unsafe fn dc_param_set( - mut param: *mut dc_param_t, - key: libc::c_int, - value: *const libc::c_char, -) { - let mut old1: *mut libc::c_char; - let mut old2: *mut libc::c_char; - let new1: *mut libc::c_char; - if param.is_null() || key == 0i32 { - return; - } - old1 = (*param).packed; - old2 = 0 as *mut libc::c_char; - if !old1.is_null() { - let p1: *mut libc::c_char; - let mut p2: *mut libc::c_char = 0 as *mut libc::c_char; - p1 = find_param(old1, key, &mut p2); - if !p1.is_null() { - *p1 = 0i32 as libc::c_char; - old2 = p2 - } else if value.is_null() { - return; - } - } - dc_rtrim(old1); - dc_ltrim(old2); - if !old1.is_null() && *old1.offset(0isize) as libc::c_int == 0i32 { - old1 = 0 as *mut libc::c_char - } - if !old2.is_null() && *old2.offset(0isize) as libc::c_int == 0i32 { - old2 = 0 as *mut libc::c_char - } - if !value.is_null() { - new1 = dc_mprintf( - b"%s%s%c=%s%s%s\x00" as *const u8 as *const libc::c_char, - if !old1.is_null() { - old1 - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - if !old1.is_null() { - b"\n\x00" as *const u8 as *const libc::c_char - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - key, - value, - if !old2.is_null() { - b"\n\x00" as *const u8 as *const libc::c_char - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - if !old2.is_null() { - old2 - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - ) - } else { - new1 = dc_mprintf( - b"%s%s%s\x00" as *const u8 as *const libc::c_char, - if !old1.is_null() { - old1 - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - if !old1.is_null() && !old2.is_null() { - b"\n\x00" as *const u8 as *const libc::c_char - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - if !old2.is_null() { - old2 - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - ) - } - free((*param).packed as *mut libc::c_void); - (*param).packed = new1; -} - -pub unsafe fn dc_param_set_int(param: *mut dc_param_t, key: libc::c_int, value: int32_t) { - if param.is_null() || key == 0i32 { - return; - } - let value_str: *mut libc::c_char = dc_mprintf( - b"%i\x00" as *const u8 as *const libc::c_char, - value as libc::c_int, - ); - if value_str.is_null() { - return; - } - dc_param_set(param, key, value_str); - free(value_str as *mut libc::c_void); -} - -/* library-private */ -pub unsafe fn dc_param_new() -> *mut dc_param_t { - let mut param: *mut dc_param_t; - param = calloc(1, ::std::mem::size_of::()) as *mut dc_param_t; - assert!(!param.is_null()); - (*param).packed = calloc(1, 1) as *mut libc::c_char; - - param -} - -pub unsafe fn dc_param_empty(param: *mut dc_param_t) { - if param.is_null() { - return; - } - *(*param).packed.offset(0isize) = 0i32 as libc::c_char; -} - -pub unsafe fn dc_param_unref(param: *mut dc_param_t) { - if param.is_null() { - return; - } - dc_param_empty(param); - free((*param).packed as *mut libc::c_void); - free(param as *mut libc::c_void); -} - -pub unsafe fn dc_param_set_packed(mut param: *mut dc_param_t, packed: *const libc::c_char) { - if param.is_null() { - return; - } - dc_param_empty(param); - if !packed.is_null() { - free((*param).packed as *mut libc::c_void); - (*param).packed = dc_strdup(packed) - }; -} - -pub unsafe fn dc_param_set_urlencoded(mut param: *mut dc_param_t, urlencoded: *const libc::c_char) { - if param.is_null() { - return; - } - dc_param_empty(param); - if !urlencoded.is_null() { - free((*param).packed as *mut libc::c_void); - (*param).packed = dc_strdup(urlencoded); - dc_str_replace( - &mut (*param).packed, - b"&\x00" as *const u8 as *const libc::c_char, - b"\n\x00" as *const u8 as *const libc::c_char, - ); - }; -} - -/** - * Set parameter to a float. - * - * @memberof dc_param_t - * @param param Parameter object to modify. - * @param key Key of the parameter to modify, one of the DC_PARAM_* constants. - * @param value Value to store for key. - * @return None. - */ -pub unsafe fn dc_param_set_float(param: *mut dc_param_t, key: libc::c_int, value: libc::c_double) { - if param.is_null() || key == 0 { - return; - } - - let value_str = dc_ftoa(value); - if value_str.is_null() { - return; - } - dc_param_set(param, key, value_str); - free(value_str as *mut libc::c_void); -} - -#[cfg(test)] -mod tests { - use super::*; - use std::ffi::CStr; - - #[test] - fn test_dc_param() { - unsafe { - let p1: *mut dc_param_t = dc_param_new(); - dc_param_set_packed( - p1, - b"\r\n\r\na=1\nb=2\n\nc = 3 \x00" as *const u8 as *const libc::c_char, - ); - - assert_eq!(dc_param_get_int(p1, 'a' as i32, 0), 1); - assert_eq!(dc_param_get_int(p1, 'b' as i32, 0), 2); - assert_eq!(dc_param_get_int(p1, 'c' as i32, 0), 0); - assert_eq!(dc_param_exists(p1, 'c' as i32), 0); - - dc_param_set_int(p1, 'd' as i32, 4i32); - - assert_eq!(dc_param_get_int(p1, 'd' as i32, 0), 4); - - dc_param_empty(p1); - dc_param_set( - p1, - 'a' as i32, - b"foo\x00" as *const u8 as *const libc::c_char, - ); - dc_param_set_int(p1, 'b' as i32, 2i32); - dc_param_set(p1, 'c' as i32, 0 as *const libc::c_char); - dc_param_set_int(p1, 'd' as i32, 4i32); - - assert_eq!( - CStr::from_ptr((*p1).packed as *const libc::c_char) - .to_str() - .unwrap(), - "a=foo\nb=2\nd=4" - ); - - dc_param_set(p1, 'b' as i32, 0 as *const libc::c_char); - - assert_eq!( - CStr::from_ptr((*p1).packed as *const libc::c_char) - .to_str() - .unwrap(), - "a=foo\nd=4", - ); - - dc_param_set(p1, 'a' as i32, 0 as *const libc::c_char); - dc_param_set(p1, 'd' as i32, 0 as *const libc::c_char); - - assert_eq!( - CStr::from_ptr((*p1).packed as *const libc::c_char) - .to_str() - .unwrap(), - "", - ); - - dc_param_unref(p1); - } - } - -} diff --git a/src/dc_qr.rs b/src/dc_qr.rs index 632ba2c1d..ac9ad1ffe 100644 --- a/src/dc_qr.rs +++ b/src/dc_qr.rs @@ -1,11 +1,13 @@ +use percent_encoding::percent_decode_str; + use crate::context::Context; use crate::dc_chat::*; use crate::dc_contact::*; use crate::dc_lot::*; -use crate::dc_param::*; use crate::dc_strencode::*; use crate::dc_tools::*; use crate::key::*; +use crate::param::*; use crate::peerstate::*; use crate::types::*; use crate::x::*; @@ -54,36 +56,40 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc if !fragment.is_null() { *fragment = 0i32 as libc::c_char; fragment = fragment.offset(1isize); - let param: *mut dc_param_t = dc_param_new(); - dc_param_set_urlencoded(param, fragment); - addr = dc_param_get(param, DC_PARAM_FORWARDED as i32, 0 as *const libc::c_char); + let param: Params = as_str(fragment).parse().expect("invalid params"); + addr = param + .get(Param::Forwarded) + .map(|s| to_cstring(s)) + .unwrap_or_else(|| std::ptr::null_mut()); if !addr.is_null() { - let mut urlencoded: *mut libc::c_char = dc_param_get( - param, - DC_PARAM_SET_LONGITUDE as i32, - 0 as *const libc::c_char, - ); - if !urlencoded.is_null() { - name = dc_urldecode(urlencoded); + if let Some(ref name_enc) = param.get(Param::SetLongitude) { + let name_r = percent_decode_str(name_enc) + .decode_utf8() + .expect("invalid name"); + name = to_cstring(name_r); dc_normalize_name(name); - free(urlencoded as *mut libc::c_void); } - invitenumber = dc_param_get( - param, - DC_PARAM_PROFILE_IMAGE as i32, - 0 as *const libc::c_char, - ); - auth = dc_param_get(param, 's' as i32, 0 as *const libc::c_char); - grpid = dc_param_get(param, 'x' as i32, 0 as *const libc::c_char); + invitenumber = param + .get(Param::ProfileImage) + .map(|s| to_cstring(s)) + .unwrap_or_else(|| std::ptr::null_mut()); + auth = param + .get(Param::Auth) + .map(|s| to_cstring(s)) + .unwrap_or_else(|| std::ptr::null_mut()); + grpid = param + .get(Param::GroupId) + .map(|s| to_cstring(s)) + .unwrap_or_else(|| std::ptr::null_mut()); if !grpid.is_null() { - urlencoded = dc_param_get(param, 'g' as i32, 0 as *const libc::c_char); - if !urlencoded.is_null() { - grpname = dc_urldecode(urlencoded); - free(urlencoded as *mut libc::c_void); + if let Some(grpname_enc) = param.get(Param::GroupName) { + let grpname_r = percent_decode_str(grpname_enc) + .decode_utf8() + .expect("invalid groupname"); + grpname = to_cstring(grpname_r); } } } - dc_param_unref(param); } fingerprint = dc_normalize_fingerprint_c(payload); current_block = 5023038348526654800; diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 342d36ae1..35964de91 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -17,10 +17,10 @@ use crate::dc_location::*; use crate::dc_mimeparser::*; use crate::dc_move::*; use crate::dc_msg::*; -use crate::dc_param::*; use crate::dc_securejoin::*; use crate::dc_strencode::*; use crate::dc_tools::*; +use crate::param::*; use crate::peerstate::*; use crate::sql; use crate::stock::StockMessage; @@ -480,9 +480,8 @@ pub unsafe fn dc_receive_imf( ) } if 0 != mime_parser.is_system_message { - dc_param_set_int( - (*part).param, - 'S' as i32, + + (*part).param.set_int( Param::Cmd, mime_parser.is_system_message, ); } @@ -511,7 +510,7 @@ pub unsafe fn dc_receive_imf( } else { String::new() }, - as_str((*(*part).param).packed), + (*part).param.to_string(), (*part).bytes, hidden, if 0 != save_mime_headers { @@ -743,29 +742,18 @@ pub unsafe fn dc_receive_imf( } } if 0 != mime_parser.is_send_by_messenger || 0 != mdn_consumed { - let param = dc_param_new(); - let server_folder_c = to_cstring(server_folder.as_ref()); - dc_param_set( - param, - DC_PARAM_SERVER_FOLDER as i32, - server_folder_c, - ); - free(server_folder_c as *mut _); - dc_param_set_int( - param, - DC_PARAM_SERVER_UID as i32, - server_uid as i32, - ); + let mut param = Params::new(); + param.set(Param::ServerFolder, server_folder.as_ref()); + param.set_int(Param::ServerUid, server_uid as i32); if 0 != mime_parser.is_send_by_messenger && 0 != context .sql .get_config_int(context, "mvbox_move") .unwrap_or_else(|| 1) { - dc_param_set_int(param, DC_PARAM_ALSO_MOVE as i32, 1); + param.set_int(Param::AlsoMove, 1); } - dc_job_add(context, 120, 0, (*param).packed, 0); - dc_param_unref(param); + dc_job_add(context, 120, 0, param, 0); } } } @@ -833,7 +821,7 @@ pub unsafe fn dc_receive_imf( context, DC_JOB_DELETE_MSG_ON_IMAP, created_db_entries[0].1 as i32, - 0 as *const libc::c_char, + Params::new(), 0, ); } @@ -1226,18 +1214,18 @@ unsafe fn create_or_lookup_group( carray_get(mime_parser.parts, i_0 as libc::c_uint) as *mut dc_mimepart_t; if (*part).type_0 == 20 { - grpimage = dc_param_get( - (*part).param, - DC_PARAM_FILE as i32, - 0 as *const libc::c_char, - ); + grpimage = (*part) + .param + .get(Param::File) + .map(|s| to_cstring(s)) + .unwrap_or_else(|| std::ptr::null_mut()); ok = 1 } i_0 += 1 } } if 0 != ok { - let chat: *mut Chat = dc_chat_new(context); + let chat = dc_chat_new(context); info!( context, 0, @@ -1249,11 +1237,11 @@ unsafe fn create_or_lookup_group( }, ); dc_chat_load_from_db(chat, chat_id); - dc_param_set( - (*chat).param, - DC_PARAM_PROFILE_IMAGE as i32, - grpimage, - ); + if grpimage.is_null() { + (*chat).param.remove(Param::ProfileImage); + } else { + (*chat).param.set(Param::ProfileImage, as_str(grpimage)); + } dc_chat_update_param(chat); dc_chat_unref(chat); free(grpimage as *mut libc::c_void); diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs index bac1148c2..22ed7bcb5 100644 --- a/src/dc_securejoin.rs +++ b/src/dc_securejoin.rs @@ -1,7 +1,7 @@ use std::ffi::CString; use mmime::mailimf_types::*; -use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET}; +use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use crate::aheader::EncryptPreference; use crate::constants::*; @@ -14,12 +14,12 @@ use crate::dc_e2ee::*; use crate::dc_lot::*; use crate::dc_mimeparser::*; use crate::dc_msg::*; -use crate::dc_param::*; use crate::dc_qr::*; use crate::dc_strencode::*; use crate::dc_token::*; use crate::dc_tools::*; use crate::key::*; +use crate::param::*; use crate::peerstate::*; use crate::stock::StockMessage; use crate::types::*; @@ -87,8 +87,8 @@ pub unsafe fn dc_get_securejoin_qr( return cleanup(fingerprint, chat, group_name, group_name_urlencoded); } - let self_addr_urlencoded = utf8_percent_encode(&self_addr, DEFAULT_ENCODE_SET).to_string(); - let self_name_urlencoded = utf8_percent_encode(&self_name, DEFAULT_ENCODE_SET).to_string(); + let self_addr_urlencoded = utf8_percent_encode(&self_addr, NON_ALPHANUMERIC).to_string(); + let self_name_urlencoded = utf8_percent_encode(&self_name, NON_ALPHANUMERIC).to_string(); qr = if 0 != group_chat_id { chat = dc_get_chat(context, group_chat_id); @@ -268,24 +268,31 @@ unsafe fn send_handshake_msg( b"Secure-Join: %s\x00" as *const u8 as *const libc::c_char, step, ); - (*msg).hidden = 1i32; - dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 7); - dc_param_set((*msg).param, DC_PARAM_CMD_ARG as i32, step); + (*msg).hidden = 1; + (*msg).param.set_int(Param::Cmd, 7); + if step.is_null() { + (*msg).param.remove(Param::Arg); + } else { + (*msg).param.set(Param::Arg, as_str(step)); + } if !param2.is_null() { - dc_param_set((*msg).param, DC_PARAM_CMD_ARG2 as i32, param2); + (*msg).param.set(Param::Arg2, as_str(param2)); } if !fingerprint.is_null() { - dc_param_set((*msg).param, DC_PARAM_CMD_ARG3 as i32, fingerprint); + (*msg).param.set(Param::Arg3, as_str(fingerprint)); } if !grpid.is_null() { - dc_param_set((*msg).param, DC_PARAM_CMD_ARG4 as i32, grpid); + (*msg).param.set(Param::Arg4, as_str(grpid)); } 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 { - dc_param_set_int((*msg).param, DC_PARAM_FORCE_PLAINTEXT as i32, 1); + (*msg).param.set_int( + Param::ForcePlaintext, + ForcePlaintext::AddAutocryptHeader as i32, + ); } else { - dc_param_set_int((*msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 1); + (*msg).param.set_int(Param::GuranteeE2ee, 1); } dc_send_msg(context, contact_chat_id, msg); dc_msg_unref(msg); diff --git a/src/lib.rs b/src/lib.rs index 5048d1fd0..66181db63 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ pub mod key; pub mod keyhistory; pub mod keyring; pub mod oauth2; +pub mod param; pub mod peerstate; pub mod pgp; pub mod smtp; @@ -48,7 +49,6 @@ pub mod dc_mimefactory; pub mod dc_mimeparser; pub mod dc_move; pub mod dc_msg; -pub mod dc_param; pub mod dc_qr; pub mod dc_receive_imf; pub mod dc_saxparser; diff --git a/src/oauth2.rs b/src/oauth2.rs index 3d52725eb..04d3deb6a 100644 --- a/src/oauth2.rs +++ b/src/oauth2.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET}; +use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use serde::Deserialize; use crate::context::Context; @@ -321,7 +321,7 @@ fn is_expired(context: &Context) -> bool { } fn replace_in_uri(uri: impl AsRef, key: impl AsRef, value: impl AsRef) -> String { - let value_urlencoded = utf8_percent_encode(value.as_ref(), DEFAULT_ENCODE_SET).to_string(); + let value_urlencoded = utf8_percent_encode(value.as_ref(), NON_ALPHANUMERIC).to_string(); uri.as_ref().replace(key.as_ref(), &value_urlencoded) } @@ -344,7 +344,7 @@ mod tests { fn test_replace_in_uri() { assert_eq!( replace_in_uri("helloworld", "world", "a-b c"), - "helloa-b%20c" + "helloa%2Db%20c" ); } diff --git a/src/param.rs b/src/param.rs new file mode 100644 index 000000000..2919d6e47 --- /dev/null +++ b/src/param.rs @@ -0,0 +1,238 @@ +use std::collections::BTreeMap; +use std::fmt; +use std::str; + +use num_traits::FromPrimitive; + +use crate::error; + +/// Available param keys. +#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash, PartialOrd, Ord, FromPrimitive)] +#[repr(u8)] +pub enum Param { + /// For messages and jobs + File = 'f' as u8, + /// For Messages + Width = 'w' as u8, + /// For Messages + Height = 'h' as u8, + /// For Messages + Duration = 'd' as u8, + /// For Messages + MimeType = 'm' as u8, + /// For Messages: message is encryoted, outgoing: guarantee E2EE or the message is not send + GuranteeE2ee = 'c' as u8, + /// For Messages: decrypted with validation errors or without mutual set, if neither + /// 'c' nor 'e' are preset, the messages is only transport encrypted. + ErroneousE2ee = 'e' as u8, + /// For Messages: force unencrypted message, either `ForcePlaintext::AddAutocryptHeader` (1), + /// `ForcePlaintext::NoAutocryptHeader` (2) or 0. + ForcePlaintext = 'u' as u8, + /// For Messages + WantsMdn = 'r' as u8, + /// For Messages + Forwarded = 'a' as u8, + /// For Messages + Cmd = 'S' as u8, + /// For Messages + Arg = 'E' as u8, + /// For Messages + Arg2 = 'F' as u8, + /// For Messages + Arg3 = 'G' as u8, + /// For Messages + Arg4 = 'H' as u8, + /// For Messages + Error = 'L' as u8, + /// For Messages: space-separated list of messaged IDs of forwarded copies. + PrepForwards = 'P' as u8, + /// For Jobs + SetLatitude = 'l' as u8, + /// For Jobs + SetLongitude = 'n' as u8, + /// For Jobs + ServerFolder = 'Z' as u8, + /// For Jobs + ServerUid = 'z' as u8, + /// For Jobs + AlsoMove = 'M' as u8, + /// For Jobs: space-separated list of message recipients + Recipients = 'R' as u8, + // For Groups + Unpromoted = 'U' as u8, + // For Groups and Contacts + ProfileImage = 'i' as u8, + // For Chats + Selftalk = 'K' as u8, + // For QR + Auth = 's' as u8, + // For QR + GroupId = 'x' as u8, + // For QR + GroupName = 'g' as u8, +} + +/// Possible values for `Param::ForcePlaintext`. +#[derive(PartialEq, Eq, Debug, Clone, Copy, FromPrimitive)] +#[repr(u8)] +pub enum ForcePlaintext { + AddAutocryptHeader = 1, + NoAutocryptHeader = 2, +} + +/// An object for handling key=value parameter lists. +/// +/// The structure is serialized by calling `to_string()` on it. +/// +/// Only for library-internal use. +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct Params { + inner: BTreeMap, +} + +impl fmt::Display for Params { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, (key, value)) in self.inner.iter().enumerate() { + if i > 0 { + write!(f, "\n")?; + } + write!(f, "{}={}", *key as u8 as char, value)?; + } + Ok(()) + } +} + +impl str::FromStr for Params { + type Err = error::Error; + + fn from_str(s: &str) -> std::result::Result { + let mut inner = BTreeMap::new(); + for pair in s.trim().lines() { + let pair = pair.trim(); + if pair.is_empty() { + continue; + } + // TODO: probably nicer using a regex + ensure!(pair.len() > 2, "Invalid key pair: '{}'", pair); + let mut split = pair.splitn(2, '='); + let key = split.next(); + let value = split.next(); + + ensure!(key.is_some(), "Missing key"); + ensure!(value.is_some(), "Missing value"); + + let key = key.unwrap().trim(); + let value = value.unwrap().trim(); + + if let Some(key) = Param::from_u8(key.as_bytes()[0]) { + inner.insert(key, value.to_string()); + } else { + bail!("Unknown key: {}", key); + } + } + + Ok(Params { inner }) + } +} + +impl Params { + /// Create new empty params. + pub fn new() -> Self { + Default::default() + } + + /// Get the value of the given key, return `None` if no value is set. + pub fn get(&self, key: Param) -> Option<&str> { + self.inner.get(&key).map(|s| s.as_str()) + } + + /// Check if the given key is set. + pub fn exists(&self, key: Param) -> bool { + self.inner.contains_key(&key) + } + + /// Set the given key to the passed in value. + pub fn set(&mut self, key: Param, value: impl AsRef) -> &mut Self { + self.inner.insert(key, value.as_ref().to_string()); + self + } + + /// Removes the given key, if it exists. + pub fn remove(&mut self, key: Param) -> &mut Self { + self.inner.remove(&key); + self + } + + /// Check if there are any values in this. + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + /// Returns how many key-value pairs are set. + pub fn len(&self) -> usize { + self.inner.len() + } + + /// Get the given parameter and parse as `i32`. + pub fn get_int(&self, key: Param) -> Option { + self.get(key).and_then(|s| s.parse().ok()) + } + + /// Get the given parameter and parse as `f64`. + pub fn get_float(&self, key: Param) -> Option { + self.get(key).and_then(|s| s.parse().ok()) + } + + /// Set the given paramter to the passed in `i32`. + pub fn set_int(&mut self, key: Param, value: i32) -> &mut Self { + self.set(key, format!("{}", value)); + self + } + + /// Set the given parameter to the passed in `f64` . + pub fn set_float(&mut self, key: Param, value: f64) -> &mut Self { + self.set(key, format!("{}", value)); + self + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_dc_param() { + let mut p1: Params = "\r\n\r\na=1\nf=2\n\nc = 3 ".parse().unwrap(); + + assert_eq!(p1.get_int(Param::Forwarded), Some(1)); + assert_eq!(p1.get_int(Param::File), Some(2)); + assert_eq!(p1.get_int(Param::Height), None); + assert!(!p1.exists(Param::Height)); + + p1.set_int(Param::Duration, 4); + + assert_eq!(p1.get_int(Param::Duration), Some(4)); + + let mut p1 = Params::new(); + + p1.set(Param::Forwarded, "foo") + .set_int(Param::File, 2) + .remove(Param::GuranteeE2ee) + .set_int(Param::Duration, 4); + + assert_eq!(p1.to_string(), "a=foo\nd=4\nf=2"); + + p1.remove(Param::File); + + assert_eq!(p1.to_string(), "a=foo\nd=4",); + assert_eq!(p1.len(), 2); + + p1.remove(Param::Forwarded); + p1.remove(Param::Duration); + + assert_eq!(p1.to_string(), "",); + + assert!(p1.is_empty()); + assert_eq!(p1.len(), 0) + } +} diff --git a/src/sql.rs b/src/sql.rs index 9971ae00d..ab3f00ac0 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -6,9 +6,9 @@ use thread_local_object::ThreadLocal; use crate::constants::*; use crate::context::Context; -use crate::dc_param::*; use crate::dc_tools::*; use crate::error::{Error, Result}; +use crate::param::*; use crate::peerstate::*; use crate::x::*; @@ -954,25 +954,25 @@ pub fn housekeeping(context: &Context) { context, &mut files_in_use, "SELECT param FROM msgs WHERE chat_id!=3 AND type!=10;", - 'f' as i32, + Param::File, ); maybe_add_from_param( context, &mut files_in_use, "SELECT param FROM jobs;", - 'f' as i32, + Param::File, ); maybe_add_from_param( context, &mut files_in_use, "SELECT param FROM chats;", - 'i' as i32, + Param::ProfileImage, ); maybe_add_from_param( context, &mut files_in_use, "SELECT param FROM contacts;", - 'i' as i32, + Param::ProfileImage, ); context @@ -1123,31 +1123,20 @@ fn maybe_add_from_param( context: &Context, files_in_use: &mut HashSet, query: &str, - param_id: libc::c_int, + param_id: Param, ) { - let param = unsafe { dc_param_new() }; - context .sql .query_row(query, NO_PARAMS, |row| { - unsafe { - let v = to_cstring(row.get::<_, String>(0)?); - dc_param_set_packed(param, v as *const _); - let file = dc_param_get(param, param_id, 0 as *const _); - if !file.is_null() { - maybe_add_file(files_in_use, as_str(file)); - free(file as *mut libc::c_void); - } - - free(v as *mut _); + let param: Params = row.get::<_, String>(0)?.parse().unwrap_or_default(); + if let Some(file) = param.get(param_id) { + maybe_add_file(files_in_use, file); } Ok(()) }) .unwrap_or_else(|err| { warn!(context, 0, "sql: failed to add_from_param: {}", err); }); - - unsafe { dc_param_unref(param) }; } #[cfg(test)] diff --git a/tests/stress.rs b/tests/stress.rs index d5518b9e2..c0a4245c1 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -911,7 +911,7 @@ fn test_dc_get_oauth2_url() { let redirect_uri = "chat.delta:/com.b44t.messenger"; let res = dc_get_oauth2_url(&ctx.ctx, addr, redirect_uri); - assert_eq!(res, Some("https://accounts.google.com/o/oauth2/auth?client_id=959970109878-4mvtgf6feshskf7695nfln6002mom908.apps.googleusercontent.com&redirect_uri=chat.delta:/com.b44t.messenger&response_type=code&scope=https%3A%2F%2Fmail.google.com%2F%20email&access_type=offline".into())); + assert_eq!(res, Some("https://accounts.google.com/o/oauth2/auth?client_id=959970109878%2D4mvtgf6feshskf7695nfln6002mom908%2Eapps%2Egoogleusercontent%2Ecom&redirect_uri=chat%2Edelta%3A%2Fcom%2Eb44t%2Emessenger&response_type=code&scope=https%3A%2F%2Fmail.google.com%2F%20email&access_type=offline".into())); } #[test]