diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 5cd387981..7b8786861 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -1217,19 +1217,18 @@ pub unsafe extern "C" fn dc_delete_contact( } #[no_mangle] -pub unsafe extern "C" fn dc_get_contact<'a>( +pub unsafe extern "C" fn dc_get_contact( context: *mut dc_context_t, contact_id: u32, -) -> *mut dc_contact_t<'a> { +) -> *mut dc_contact_t { if context.is_null() { eprintln!("ignoring careless call to dc_get_contact()"); return ptr::null_mut(); } - let context = &*context; Contact::get_by_id(context, contact_id) - .map(|contact| Box::into_raw(Box::new(contact))) + .map(|contact| Box::into_raw(Box::new(ContactWrapper { context, contact }))) .unwrap_or_else(|_| std::ptr::null_mut()) } @@ -2299,8 +2298,20 @@ pub unsafe extern "C" fn dc_msg_latefiling_mediasize( // dc_contact_t +/// FFI struct for [dc_contact_t] +/// +/// This is the structure behind [dc_contact_t] which is the opaque +/// structure representing a contact in the FFI API. It exists +/// because the FFI API has a refernce from the message to the +/// context, but the Rust API does not, so the FFI layer needs to glue +/// these together. +pub struct ContactWrapper { + context: *const dc_context_t, + contact: contact::Contact, +} + #[no_mangle] -pub type dc_contact_t<'a> = contact::Contact<'a>; +pub type dc_contact_t = ContactWrapper; #[no_mangle] pub unsafe extern "C" fn dc_contact_unref(contact: *mut dc_contact_t) { @@ -2308,7 +2319,6 @@ pub unsafe extern "C" fn dc_contact_unref(contact: *mut dc_contact_t) { eprintln!("ignoring careless call to dc_contact_unref()"); return; } - Box::from_raw(contact); } @@ -2318,10 +2328,8 @@ pub unsafe extern "C" fn dc_contact_get_id(contact: *mut dc_contact_t) -> u32 { eprintln!("ignoring careless call to dc_contact_get_id()"); return 0; } - - let contact = &*contact; - - contact.get_id() + let ffi_contact = &*contact; + ffi_contact.contact.get_id() } #[no_mangle] @@ -2330,10 +2338,8 @@ pub unsafe extern "C" fn dc_contact_get_addr(contact: *mut dc_contact_t) -> *mut eprintln!("ignoring careless call to dc_contact_get_addr()"); return dc_strdup(ptr::null()); } - - let contact = &*contact; - - contact.get_addr().strdup() + let ffi_contact = &*contact; + ffi_contact.contact.get_addr().strdup() } #[no_mangle] @@ -2342,10 +2348,8 @@ pub unsafe extern "C" fn dc_contact_get_name(contact: *mut dc_contact_t) -> *mut eprintln!("ignoring careless call to dc_contact_get_name()"); return dc_strdup(ptr::null()); } - - let contact = &*contact; - - contact.get_name().strdup() + let ffi_contact = &*contact; + ffi_contact.contact.get_name().strdup() } #[no_mangle] @@ -2356,10 +2360,8 @@ pub unsafe extern "C" fn dc_contact_get_display_name( eprintln!("ignoring careless call to dc_contact_get_display_name()"); return dc_strdup(ptr::null()); } - - let contact = &*contact; - - contact.get_display_name().strdup() + let ffi_contact = &*contact; + ffi_contact.contact.get_display_name().strdup() } #[no_mangle] @@ -2370,10 +2372,8 @@ pub unsafe extern "C" fn dc_contact_get_name_n_addr( eprintln!("ignoring careless call to dc_contact_get_name_n_addr()"); return dc_strdup(ptr::null()); } - - let contact = &*contact; - - contact.get_name_n_addr().strdup() + let ffi_contact = &*contact; + ffi_contact.contact.get_name_n_addr().strdup() } #[no_mangle] @@ -2384,10 +2384,8 @@ pub unsafe extern "C" fn dc_contact_get_first_name( eprintln!("ignoring careless call to dc_contact_get_first_name()"); return dc_strdup(ptr::null()); } - - let contact = &*contact; - - contact.get_first_name().strdup() + let ffi_contact = &*contact; + ffi_contact.contact.get_first_name().strdup() } #[no_mangle] @@ -2398,11 +2396,10 @@ pub unsafe extern "C" fn dc_contact_get_profile_image( eprintln!("ignoring careless call to dc_contact_get_profile_image()"); return ptr::null_mut(); // NULL explicitly defined as "no profile image" } - - let contact = &*contact; - - contact - .get_profile_image() + let ffi_contact = &*contact; + ffi_contact + .contact + .get_profile_image(&*ffi_contact.context) .map(|p| p.to_str().unwrap().to_string().strdup()) .unwrap_or_else(|| std::ptr::null_mut()) } @@ -2413,10 +2410,8 @@ pub unsafe extern "C" fn dc_contact_get_color(contact: *mut dc_contact_t) -> u32 eprintln!("ignoring careless call to dc_contact_get_color()"); return 0; } - - let contact = &*contact; - - contact.get_color() + let ffi_contact = &*contact; + ffi_contact.contact.get_color() } #[no_mangle] @@ -2425,10 +2420,8 @@ pub unsafe extern "C" fn dc_contact_is_blocked(contact: *mut dc_contact_t) -> li eprintln!("ignoring careless call to dc_contact_is_blocked()"); return 0; } - - let contact = &*contact; - - contact.is_blocked() as libc::c_int + let ffi_contact = &*contact; + ffi_contact.contact.is_blocked() as libc::c_int } #[no_mangle] @@ -2437,10 +2430,8 @@ pub unsafe extern "C" fn dc_contact_is_verified(contact: *mut dc_contact_t) -> l eprintln!("ignoring careless call to dc_contact_is_verified()"); return 0; } - - let contact = &*contact; - - contact.is_verified() as libc::c_int + let ffi_contact = &*contact; + ffi_contact.contact.is_verified(&*ffi_contact.context) as libc::c_int } // dc_lot_t diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index aaf734713..3df2ab041 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -301,7 +301,7 @@ unsafe fn log_contactlist(context: &Context, contacts: &Vec) { if let Ok(contact) = Contact::get_by_id(context, contact_id) { let name = contact.get_name(); let addr = contact.get_addr(); - let verified_state = contact.is_verified(); + let verified_state = contact.is_verified(context); let verified_str = if VerifiedStatus::Unverified != verified_state { if verified_state == VerifiedStatus::BidirectVerified { " √√" diff --git a/src/chat.rs b/src/chat.rs index 277990652..6aa74d6fe 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -189,7 +189,7 @@ impl Chat { let contacts = get_chat_contacts(context, self.id); if !contacts.is_empty() { if let Ok(contact) = Contact::get_by_id(context, contacts[0]) { - return contact.get_profile_image(); + return contact.get_profile_image(context); } } } @@ -1365,7 +1365,7 @@ pub fn add_contact_to_chat_ex( } else { // else continue and send status mail if chat.typ == Chattype::VerifiedGroup { - if contact.is_verified() != VerifiedStatus::BidirectVerified { + if contact.is_verified(context) != VerifiedStatus::BidirectVerified { error!( context, "Only bidirectional verified contacts can be added to verified groups." diff --git a/src/contact.rs b/src/contact.rs index d483e7044..c67a46a2f 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -31,8 +31,7 @@ const DC_ORIGIN_MIN_CONTACT_LIST: i32 = 0x100; /// For this purpose, internally, two names are tracked - /// authorized-name and given-name. /// By default, these names are equal, but functions working with contact names -pub struct Contact<'a> { - context: &'a Context, +pub struct Contact { /// The contact ID. /// /// Special message IDs: @@ -139,11 +138,10 @@ pub enum VerifiedStatus { BidirectVerified = 2, } -impl<'a> Contact<'a> { - pub fn load_from_db(context: &'a Context, contact_id: u32) -> Result { +impl Contact { + pub fn load_from_db(context: &Context, contact_id: u32) -> Result { if contact_id == DC_CONTACT_ID_SELF { let contact = Contact { - context, id: contact_id, name: context.stock_str(StockMessage::SelfMsg).into(), authname: "".into(), @@ -162,7 +160,6 @@ impl<'a> Contact<'a> { params![contact_id as i32], |row| { let contact = Self { - context, id: contact_id, name: row.get::<_, String>(0)?, authname: row.get::<_, String>(4)?, @@ -181,7 +178,7 @@ impl<'a> Contact<'a> { } /// Check if a contact is blocked. - pub fn is_blocked_load(context: &'a Context, id: u32) -> bool { + pub fn is_blocked_load(context: &Context, id: u32) -> bool { Self::load_from_db(context, id) .map(|contact| contact.blocked) .unwrap_or_default() @@ -766,9 +763,9 @@ impl<'a> Contact<'a> { /// Get the contact's profile image. /// This is the image set by each remote user on their own /// using dc_set_config(context, "selfavatar", image). - pub fn get_profile_image(&self) -> Option { + pub fn get_profile_image(&self, context: &Context) -> Option { if self.id == DC_CONTACT_ID_SELF { - if let Some(p) = self.context.get_config(Config::Selfavatar) { + if let Some(p) = context.get_config(Config::Selfavatar) { return Some(PathBuf::from(p)); } } @@ -789,14 +786,18 @@ impl<'a> Contact<'a> { /// /// The UI may draw a checkbox or something like that beside verified contacts. /// - pub fn is_verified(&self) -> VerifiedStatus { - self.is_verified_ex(None) + pub fn is_verified(&self, context: &Context) -> VerifiedStatus { + self.is_verified_ex(context, None) } /// Same as `Contact::is_verified` but allows speeding up things /// by adding the peerstate belonging to the contact. /// If you do not have the peerstate available, it is loaded automatically. - pub fn is_verified_ex(&self, peerstate: Option<&Peerstate<'a>>) -> VerifiedStatus { + pub fn is_verified_ex( + &self, + context: &Context, + peerstate: Option<&Peerstate>, + ) -> VerifiedStatus { // We're always sort of secured-verified as we could verify the key on this device any time with the key // on this device if self.id == DC_CONTACT_ID_SELF { @@ -809,7 +810,7 @@ impl<'a> Contact<'a> { } } - let peerstate = Peerstate::from_addr(self.context, &self.context.sql, &self.addr); + let peerstate = Peerstate::from_addr(context, &context.sql, &self.addr); if let Some(ps) = peerstate { if ps.verified_key().is_some() { return VerifiedStatus::BidirectVerified; diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index a9aa67402..4740245c7 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -1760,7 +1760,8 @@ unsafe fn check_verified_properties( let peerstate = Peerstate::from_addr(context, &context.sql, contact.get_addr()); if peerstate.is_none() - || contact.is_verified_ex(peerstate.as_ref()) != VerifiedStatus::BidirectVerified + || contact.is_verified_ex(context, peerstate.as_ref()) + != VerifiedStatus::BidirectVerified { verify_fail("The sender of this message is not verified.".into()); return 0; diff --git a/src/securejoin.rs b/src/securejoin.rs index c07aeb346..1ce0a0268 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -617,7 +617,7 @@ pub fn handle_securejoin_handshake( ==== Step 8 in "Out-of-band verified groups" protocol ==== ============================================================ */ if let Ok(contact) = Contact::get_by_id(context, contact_id) { - if contact.is_verified() == VerifiedStatus::Unverified { + if contact.is_verified(context) == VerifiedStatus::Unverified { warn!(context, "vg-member-added-received invalid.",); return ret; }