refactor: rusty contact

* refactor(contact): rename and rusty memory allocations
* refactor(contact): use enum to indidcate origin
* refactor(contact): safe blocking and unblocking api
* refactor(contact): only safe and no more cstrings
This commit is contained in:
Friedel Ziegelmayer
2019-08-07 22:20:48 +02:00
committed by GitHub
parent 760332262d
commit ea6972118a
22 changed files with 1566 additions and 1631 deletions

10
Cargo.lock generated
View File

@@ -471,6 +471,7 @@ dependencies = [
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"imap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "imap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lettre 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "lettre 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -927,6 +928,14 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "itertools"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "0.4.4" version = "0.4.4"
@@ -2762,6 +2771,7 @@ dependencies = [
"checksum imap-proto 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4e77b1d61faf028893531b071cc5584cdd02b6186cebe7f7168ffd8d591339a" "checksum imap-proto 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4e77b1d61faf028893531b071cc5584cdd02b6186cebe7f7168ffd8d591339a"
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"

View File

@@ -44,6 +44,7 @@ strum_macros = "0.15.0"
thread-local-object = "0.1.0" thread-local-object = "0.1.0"
backtrace = "0.3.33" backtrace = "0.3.33"
byteorder = "1.3.1" byteorder = "1.3.1"
itertools = "0.8.0"
[dev-dependencies] [dev-dependencies]
tempfile = "3.0" tempfile = "3.0"

View File

@@ -14,7 +14,8 @@ extern crate num_traits;
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use std::str::FromStr; use std::str::FromStr;
use deltachat::dc_tools::StrExt; use deltachat::contact::Contact;
use deltachat::dc_tools::{as_str, StrExt};
use deltachat::*; use deltachat::*;
// TODO: constants // TODO: constants
@@ -701,7 +702,7 @@ pub unsafe extern "C" fn dc_marknoticed_contact(context: *mut dc_context_t, cont
assert!(!context.is_null()); assert!(!context.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_marknoticed_contact(context, contact_id) Contact::mark_noticed(context, contact_id)
} }
#[no_mangle] #[no_mangle]
@@ -748,7 +749,7 @@ pub unsafe extern "C" fn dc_get_msg<'a>(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_may_be_valid_addr(addr: *mut libc::c_char) -> libc::c_int { pub unsafe extern "C" fn dc_may_be_valid_addr(addr: *mut libc::c_char) -> libc::c_int {
assert!(!addr.is_null()); assert!(!addr.is_null());
dc_contact::dc_may_be_valid_addr(addr) as libc::c_int contact::may_be_valid_addr(as_str(addr)) as libc::c_int
} }
#[no_mangle] #[no_mangle]
@@ -760,7 +761,7 @@ pub unsafe extern "C" fn dc_lookup_contact_id_by_addr(
assert!(!addr.is_null()); assert!(!addr.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_lookup_contact_id_by_addr(context, addr) Contact::lookup_id_by_addr(context, as_str(addr))
} }
#[no_mangle] #[no_mangle]
@@ -771,9 +772,15 @@ pub unsafe extern "C" fn dc_create_contact(
) -> u32 { ) -> u32 {
assert!(!context.is_null()); assert!(!context.is_null());
assert!(!addr.is_null()); assert!(!addr.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_create_contact(context, name, addr) let name = if name.is_null() { "" } else { as_str(name) };
match Contact::create(context, name, as_str(addr)) {
Ok(id) => id,
Err(_) => 0,
}
} }
#[no_mangle] #[no_mangle]
@@ -785,7 +792,10 @@ pub unsafe extern "C" fn dc_add_address_book(
assert!(!addr_book.is_null()); assert!(!addr_book.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_add_address_book(context, addr_book) match Contact::add_address_book(context, as_str(addr_book)) {
Ok(cnt) => cnt as libc::c_int,
Err(_) => 0,
}
} }
#[no_mangle] #[no_mangle]
@@ -797,7 +807,16 @@ pub unsafe extern "C" fn dc_get_contacts(
assert!(!context.is_null()); assert!(!context.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_get_contacts(context, flags, query) let query = if query.is_null() {
None
} else {
Some(as_str(query))
};
match Contact::get_all(context, flags, query) {
Ok(contacts) => contacts,
Err(_) => std::ptr::null_mut(),
}
} }
#[no_mangle] #[no_mangle]
@@ -805,7 +824,7 @@ pub unsafe extern "C" fn dc_get_blocked_cnt(context: *mut dc_context_t) -> libc:
assert!(!context.is_null()); assert!(!context.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_get_blocked_cnt(context) Contact::get_blocked_cnt(context) as libc::c_int
} }
#[no_mangle] #[no_mangle]
@@ -815,7 +834,7 @@ pub unsafe extern "C" fn dc_get_blocked_contacts(
assert!(!context.is_null()); assert!(!context.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_get_blocked_contacts(context) Contact::get_all_blocked(context)
} }
#[no_mangle] #[no_mangle]
@@ -827,7 +846,11 @@ pub unsafe extern "C" fn dc_block_contact(
assert!(!context.is_null()); assert!(!context.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_block_contact(context, contact_id, block) if block == 0 {
Contact::unblock(context, contact_id);
} else {
Contact::block(context, contact_id);
}
} }
#[no_mangle] #[no_mangle]
@@ -838,7 +861,7 @@ pub unsafe extern "C" fn dc_get_contact_encrinfo(
assert!(!context.is_null()); assert!(!context.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_get_contact_encrinfo(context, contact_id) Contact::get_encrinfo(context, contact_id).strdup()
} }
#[no_mangle] #[no_mangle]
@@ -849,18 +872,23 @@ pub unsafe extern "C" fn dc_delete_contact(
assert!(!context.is_null()); assert!(!context.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_delete_contact(context, contact_id) as libc::c_int match Contact::delete(context, contact_id) {
Ok(_) => 1,
Err(_) => 0,
}
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_get_contact<'a>( pub unsafe extern "C" fn dc_get_contact<'a>(
context: *mut dc_context_t, context: *mut dc_context_t,
contact_id: u32, contact_id: u32,
) -> *mut dc_contact::dc_contact_t<'a> { ) -> *mut dc_contact_t<'a> {
assert!(!context.is_null()); assert!(!context.is_null());
let context = &*context; let context = &*context;
dc_contact::dc_get_contact(context, contact_id) Contact::get_by_id(context, contact_id)
.map(|contact| Box::into_raw(Box::new(contact)))
.unwrap_or_else(|_| std::ptr::null_mut())
} }
#[no_mangle] #[no_mangle]
@@ -1634,99 +1662,103 @@ pub unsafe extern "C" fn dc_msg_latefiling_mediasize(
// dc_contact_t // dc_contact_t
#[no_mangle] #[no_mangle]
pub type dc_contact_t<'a> = dc_contact::dc_contact_t<'a>; pub type dc_contact_t<'a> = contact::Contact<'a>;
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_unref(contact: *mut dc_contact::dc_contact_t) { pub unsafe extern "C" fn dc_contact_unref(contact: *mut dc_contact_t) {
assert!(!contact.is_null()); assert!(!contact.is_null());
Box::from_raw(contact);
dc_contact::dc_contact_unref(contact)
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_get_id(contact: *mut dc_contact::dc_contact_t) -> u32 { pub unsafe extern "C" fn dc_contact_get_id(contact: *mut dc_contact_t) -> u32 {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_get_id(contact) contact.get_id()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_get_addr( pub unsafe extern "C" fn dc_contact_get_addr(contact: *mut dc_contact_t) -> *mut libc::c_char {
contact: *mut dc_contact::dc_contact_t,
) -> *mut libc::c_char {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_get_addr(contact) contact.get_addr().strdup()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_get_name( pub unsafe extern "C" fn dc_contact_get_name(contact: *mut dc_contact_t) -> *mut libc::c_char {
contact: *mut dc_contact::dc_contact_t,
) -> *mut libc::c_char {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_get_name(contact) contact.get_name().strdup()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_get_display_name( pub unsafe extern "C" fn dc_contact_get_display_name(
contact: *mut dc_contact::dc_contact_t, contact: *mut dc_contact_t,
) -> *mut libc::c_char { ) -> *mut libc::c_char {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_get_display_name(contact) contact.get_display_name().strdup()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_get_name_n_addr( pub unsafe extern "C" fn dc_contact_get_name_n_addr(
contact: *mut dc_contact::dc_contact_t, contact: *mut dc_contact_t,
) -> *mut libc::c_char { ) -> *mut libc::c_char {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_get_name_n_addr(contact) contact.get_name_n_addr().strdup()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_get_first_name( pub unsafe extern "C" fn dc_contact_get_first_name(
contact: *mut dc_contact::dc_contact_t, contact: *mut dc_contact_t,
) -> *mut libc::c_char { ) -> *mut libc::c_char {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_get_first_name(contact) contact.get_first_name().strdup()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_get_profile_image( pub unsafe extern "C" fn dc_contact_get_profile_image(
contact: *mut dc_contact::dc_contact_t, contact: *mut dc_contact_t,
) -> *mut libc::c_char { ) -> *mut libc::c_char {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_get_profile_image(contact) contact
.get_profile_image()
.map(|s| s.strdup())
.unwrap_or_else(|| std::ptr::null_mut())
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_get_color(contact: *mut dc_contact::dc_contact_t) -> u32 { pub unsafe extern "C" fn dc_contact_get_color(contact: *mut dc_contact_t) -> u32 {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_get_color(contact) contact.get_color()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_is_blocked( pub unsafe extern "C" fn dc_contact_is_blocked(contact: *mut dc_contact_t) -> libc::c_int {
contact: *mut dc_contact::dc_contact_t,
) -> libc::c_int {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_is_blocked(contact) contact.is_blocked() as libc::c_int
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_contact_is_verified( pub unsafe extern "C" fn dc_contact_is_verified(contact: *mut dc_contact_t) -> libc::c_int {
contact: *mut dc_contact::dc_contact_t,
) -> libc::c_int {
assert!(!contact.is_null()); assert!(!contact.is_null());
let contact = &*contact;
dc_contact::dc_contact_is_verified(contact) contact.is_verified() as libc::c_int
} }
// dc_lot_t // dc_lot_t

View File

@@ -4,11 +4,11 @@ use std::str::FromStr;
use deltachat::chatlist::*; use deltachat::chatlist::*;
use deltachat::config; use deltachat::config;
use deltachat::constants::*; use deltachat::constants::*;
use deltachat::contact::*;
use deltachat::context::*; use deltachat::context::*;
use deltachat::dc_array::*; use deltachat::dc_array::*;
use deltachat::dc_chat::*; use deltachat::dc_chat::*;
use deltachat::dc_configure::*; use deltachat::dc_configure::*;
use deltachat::dc_contact::*;
use deltachat::dc_imex::*; use deltachat::dc_imex::*;
use deltachat::dc_job::*; use deltachat::dc_job::*;
use deltachat::dc_location::*; use deltachat::dc_location::*;
@@ -218,9 +218,10 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
} }
unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: *mut dc_msg_t) { unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: *mut dc_msg_t) {
let contact: *mut dc_contact_t = dc_get_contact(context, dc_msg_get_from_id(msg)); let contact = Contact::get_by_id(context, dc_msg_get_from_id(msg)).expect("invalid contact");
let contact_name: *mut libc::c_char = dc_contact_get_name(contact); let contact_name = contact.get_name();
let contact_id: libc::c_int = dc_contact_get_id(contact) as libc::c_int; let contact_id = contact.get_id();
let statestr = match dc_msg_get_state(msg) { let statestr = match dc_msg_get_state(msg) {
DC_STATE_OUT_PENDING => " o", DC_STATE_OUT_PENDING => " o",
DC_STATE_OUT_DELIVERED => "", DC_STATE_OUT_DELIVERED => "",
@@ -229,7 +230,7 @@ unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: *mut dc_msg_t
_ => "", _ => "",
}; };
let temp2 = dc_timestamp_to_str(dc_msg_get_timestamp(msg)); let temp2 = dc_timestamp_to_str(dc_msg_get_timestamp(msg));
let msgtext: *mut libc::c_char = dc_msg_get_text(msg); let msgtext = dc_msg_get_text(msg);
info!( info!(
context, context,
0, 0,
@@ -242,7 +243,7 @@ unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: *mut dc_msg_t
"" ""
}, },
if dc_msg_has_location(msg) { "📍" } else { "" }, if dc_msg_has_location(msg) { "📍" } else { "" },
as_str(contact_name), &contact_name,
contact_id, contact_id,
as_str(msgtext), as_str(msgtext),
if dc_msg_is_starred(msg) { "" } else { "" }, if dc_msg_is_starred(msg) { "" } else { "" },
@@ -264,8 +265,6 @@ unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: *mut dc_msg_t
&temp2, &temp2,
); );
free(msgtext as *mut libc::c_void); free(msgtext as *mut libc::c_void);
free(contact_name as *mut libc::c_void);
dc_contact_unref(contact);
} }
unsafe fn log_msglist(context: &Context, msglist: *mut dc_array_t) { unsafe fn log_msglist(context: &Context, msglist: *mut dc_array_t) {
@@ -303,7 +302,6 @@ unsafe fn log_msglist(context: &Context, msglist: *mut dc_array_t) {
} }
unsafe fn log_contactlist(context: &Context, contacts: *mut dc_array_t) { unsafe fn log_contactlist(context: &Context, contacts: *mut dc_array_t) {
let mut contact: *mut dc_contact_t;
if !dc_array_search_id(contacts, 1 as uint32_t, 0 as *mut size_t) { if !dc_array_search_id(contacts, 1 as uint32_t, 0 as *mut size_t) {
dc_array_add_id(contacts, 1 as uint32_t); dc_array_add_id(contacts, 1 as uint32_t);
} }
@@ -312,13 +310,12 @@ unsafe fn log_contactlist(context: &Context, contacts: *mut dc_array_t) {
let contact_id = dc_array_get_id(contacts, i as size_t); let contact_id = dc_array_get_id(contacts, i as size_t);
let line; let line;
let mut line2 = "".to_string(); let mut line2 = "".to_string();
contact = dc_get_contact(context, contact_id); if let Ok(contact) = Contact::get_by_id(context, contact_id) {
if !contact.is_null() { let name = contact.get_name();
let name: *mut libc::c_char = dc_contact_get_name(contact); let addr = contact.get_addr();
let addr: *mut libc::c_char = dc_contact_get_addr(contact); let verified_state = contact.is_verified();
let verified_state: libc::c_int = dc_contact_is_verified(contact); let verified_str = if VerifiedStatus::Unverified != verified_state {
let verified_str = if 0 != verified_state { if verified_state == VerifiedStatus::BidirectVerified {
if verified_state == 2 {
" √√" " √√"
} else { } else {
"" ""
@@ -328,28 +325,26 @@ unsafe fn log_contactlist(context: &Context, contacts: *mut dc_array_t) {
}; };
line = format!( line = format!(
"{}{} <{}>", "{}{} <{}>",
if !name.is_null() && 0 != *name.offset(0isize) as libc::c_int { if !name.is_empty() {
as_str(name) &name
} else { } else {
"<name unset>" "<name unset>"
}, },
verified_str, verified_str,
if !addr.is_null() && 0 != *addr.offset(0isize) as libc::c_int { if !addr.is_empty() {
as_str(addr) &addr
} else { } else {
"addr unset" "addr unset"
} }
); );
let peerstate = Peerstate::from_addr(context, &context.sql, as_str(addr)); let peerstate = Peerstate::from_addr(context, &context.sql, &addr);
if peerstate.is_some() && contact_id != 1 as libc::c_uint { if peerstate.is_some() && contact_id != 1 as libc::c_uint {
line2 = format!( line2 = format!(
", prefer-encrypt={}", ", prefer-encrypt={}",
peerstate.as_ref().unwrap().prefer_encrypt peerstate.as_ref().unwrap().prefer_encrypt
); );
} }
dc_contact_unref(contact);
free(name as *mut libc::c_void);
free(addr as *mut libc::c_void);
info!(context, 0, "Contact#{}: {}{}", contact_id, line, line2); info!(context, 0, "Contact#{}: {}{}", contact_id, line, line2);
} }
} }
@@ -1060,15 +1055,15 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
dc_delete_msgs(context, ids.as_mut_ptr(), 1); dc_delete_msgs(context, ids.as_mut_ptr(), 1);
} }
"listcontacts" | "contacts" | "listverified" => { "listcontacts" | "contacts" | "listverified" => {
let contacts = dc_get_contacts( let contacts = Contact::get_all(
context, context,
if arg0 == "listverified" { if arg0 == "listverified" {
0x1 | 0x2 0x1 | 0x2
} else { } else {
0x2 0x2
}, },
arg1_c, Some(arg1),
); )?;
if !contacts.is_null() { if !contacts.is_null() {
log_contactlist(context, contacts); log_contactlist(context, contacts);
println!("{} contacts.", dc_array_get_cnt(contacts) as libc::c_int,); println!("{} contacts.", dc_array_get_cnt(contacts) as libc::c_int,);
@@ -1081,33 +1076,22 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
ensure!(!arg1.is_empty(), "Arguments [<name>] <addr> expected."); ensure!(!arg1.is_empty(), "Arguments [<name>] <addr> expected.");
if !arg2.is_empty() { if !arg2.is_empty() {
let book = dc_mprintf( let book = format!("{}\n{}", arg1, arg2);
b"%s\n%s\x00" as *const u8 as *const libc::c_char, Contact::add_address_book(context, book)?;
arg1_c,
arg2_c,
);
dc_add_address_book(context, book);
free(book as *mut libc::c_void);
} else { } else {
if 0 == dc_create_contact(context, 0 as *const libc::c_char, arg1_c) { Contact::create(context, "", arg1)?;
bail!("Failed to create contact");
}
} }
} }
"contactinfo" => { "contactinfo" => {
ensure!(!arg1.is_empty(), "Argument <contact-id> missing."); ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
let contact_id = arg1.parse()?; let contact_id = arg1.parse()?;
let contact = dc_get_contact(context, contact_id); let contact = Contact::get_by_id(context, contact_id)?;
let name_n_addr = dc_contact_get_name_n_addr(contact); let name_n_addr = contact.get_name_n_addr();
let mut res = format!("Contact info for: {}:\n\n", as_str(name_n_addr),); let mut res = format!("Contact info for: {}:\n\n", name_n_addr);
free(name_n_addr as *mut libc::c_void);
dc_contact_unref(contact);
let encrinfo = dc_get_contact_encrinfo(context, contact_id); res += &Contact::get_encrinfo(context, contact_id);
res += as_str(encrinfo);
free(encrinfo as *mut libc::c_void);
let chatlist = Chatlist::try_load(context, 0, None, Some(contact_id))?; let chatlist = Chatlist::try_load(context, 0, None, Some(contact_id))?;
let chatlist_cnt = chatlist.len(); let chatlist_cnt = chatlist.len();
@@ -1130,9 +1114,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
} }
"delcontact" => { "delcontact" => {
ensure!(!arg1.is_empty(), "Argument <contact-id> missing."); ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
if !dc_delete_contact(context, arg1.parse()?) { Contact::delete(context, arg1.parse()?)?;
bail!("Failed to delete contact");
}
} }
"checkqr" => { "checkqr" => {
ensure!(!arg1.is_empty(), "Argument <qr-content> missing."); ensure!(!arg1.is_empty(), "Argument <qr-content> missing.");

View File

@@ -1,6 +1,6 @@
extern crate deltachat; extern crate deltachat;
use std::ffi::{CStr, CString}; use std::ffi::CStr;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use std::{thread, time}; use std::{thread, time};
use tempfile::tempdir; use tempfile::tempdir;
@@ -8,10 +8,10 @@ use tempfile::tempdir;
use deltachat::chatlist::*; use deltachat::chatlist::*;
use deltachat::config; use deltachat::config;
use deltachat::constants::Event; use deltachat::constants::Event;
use deltachat::contact::*;
use deltachat::context::*; use deltachat::context::*;
use deltachat::dc_chat::*; use deltachat::dc_chat::*;
use deltachat::dc_configure::*; use deltachat::dc_configure::*;
use deltachat::dc_contact::*;
use deltachat::dc_job::{ use deltachat::dc_job::{
dc_perform_imap_fetch, dc_perform_imap_idle, dc_perform_imap_jobs, dc_perform_smtp_idle, dc_perform_imap_fetch, dc_perform_imap_idle, dc_perform_imap_jobs, dc_perform_smtp_idle,
dc_perform_smtp_jobs, dc_perform_smtp_jobs,
@@ -93,9 +93,9 @@ fn main() {
thread::sleep(duration); thread::sleep(duration);
let email = CString::new("dignifiedquire@gmail.com").unwrap();
println!("sending a message"); println!("sending a message");
let contact_id = dc_create_contact(&ctx, std::ptr::null(), email.as_ptr()); let contact_id =
Contact::create(&ctx, "dignifiedquire", "dignifiedquire@gmail.com").unwrap();
let chat_id = dc_create_chat_by_contact_id(&ctx, contact_id); let chat_id = dc_create_chat_by_contact_id(&ctx, contact_id);
dc_send_text_msg(&ctx, chat_id, "Hi, here is my first message!".into()); dc_send_text_msg(&ctx, chat_id, "Hi, here is my first message!".into());

View File

@@ -6,7 +6,7 @@ use std::{fmt, str};
use mmime::mailimf_types::*; use mmime::mailimf_types::*;
use crate::constants::*; use crate::constants::*;
use crate::dc_contact::*; use crate::contact::*;
use crate::dc_tools::as_str; use crate::dc_tools::as_str;
use crate::key::*; use crate::key::*;
@@ -94,7 +94,7 @@ impl Aheader {
match Self::from_str(value) { match Self::from_str(value) {
Ok(test) => { Ok(test) => {
if dc_addr_cmp(&test.addr, as_str(wanted_from)) { if addr_cmp(&test.addr, as_str(wanted_from)) {
if fine_header.is_none() { if fine_header.is_none() {
fine_header = Some(test); fine_header = Some(test);
} else { } else {

View File

@@ -1,7 +1,7 @@
use crate::constants::*; use crate::constants::*;
use crate::contact::*;
use crate::context::*; use crate::context::*;
use crate::dc_chat::*; use crate::dc_chat::*;
use crate::dc_contact::*;
use crate::dc_lot::*; use crate::dc_lot::*;
use crate::dc_msg::*; use crate::dc_msg::*;
use crate::dc_tools::*; use crate::dc_tools::*;
@@ -261,7 +261,7 @@ impl<'a> Chatlist<'a> {
} }
let lastmsg_id = self.ids[index].1; let lastmsg_id = self.ids[index].1;
let mut lastcontact = 0 as *mut dc_contact_t; let mut lastcontact = None;
if chat.is_null() { if chat.is_null() {
chat = dc_chat_new(self.context); chat = dc_chat_new(self.context);
@@ -282,8 +282,7 @@ impl<'a> Chatlist<'a> {
&& ((*chat).type_0 == DC_CHAT_TYPE_GROUP && ((*chat).type_0 == DC_CHAT_TYPE_GROUP
|| (*chat).type_0 == DC_CHAT_TYPE_VERIFIED_GROUP) || (*chat).type_0 == DC_CHAT_TYPE_VERIFIED_GROUP)
{ {
lastcontact = dc_contact_new(self.context); lastcontact = Contact::load_from_db(self.context, (*lastmsg).from_id).ok();
dc_contact_load_from_db(lastcontact, &self.context.sql, (*lastmsg).from_id);
} }
lastmsg lastmsg
} else { } else {
@@ -295,11 +294,10 @@ impl<'a> Chatlist<'a> {
} else if lastmsg.is_null() || (*lastmsg).from_id == DC_CONTACT_ID_SELF as u32 { } else if lastmsg.is_null() || (*lastmsg).from_id == DC_CONTACT_ID_SELF as u32 {
(*ret).text2 = self.context.stock_str(StockMessage::NoMessages).strdup(); (*ret).text2 = self.context.stock_str(StockMessage::NoMessages).strdup();
} else { } else {
dc_lot_fill(ret, lastmsg, chat, lastcontact, self.context); dc_lot_fill(ret, lastmsg, chat, lastcontact.as_ref(), self.context);
} }
dc_msg_unref(lastmsg); dc_msg_unref(lastmsg);
dc_contact_unref(lastcontact);
ret ret
} }

1093
src/contact.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,9 @@
use std::sync::{Arc, Condvar, Mutex, RwLock}; use std::sync::{Arc, Condvar, Mutex, RwLock};
use crate::constants::*; use crate::constants::*;
use crate::contact::*;
use crate::dc_array::*; use crate::dc_array::*;
use crate::dc_chat::*; use crate::dc_chat::*;
use crate::dc_contact::*;
use crate::dc_job::*; use crate::dc_job::*;
use crate::dc_jobthread::*; use crate::dc_jobthread::*;
use crate::dc_loginparam::*; use crate::dc_loginparam::*;
@@ -346,7 +346,7 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char {
let chats = dc_get_chat_cnt(context) as usize; let chats = dc_get_chat_cnt(context) as usize;
let real_msgs = dc_get_real_msg_cnt(context) as usize; let real_msgs = dc_get_real_msg_cnt(context) as usize;
let deaddrop_msgs = dc_get_deaddrop_msg_cnt(context) as usize; let deaddrop_msgs = dc_get_deaddrop_msg_cnt(context) as usize;
let contacts = dc_get_real_contact_cnt(context) as usize; let contacts = Contact::get_real_cnt(context) as usize;
let is_configured = context let is_configured = context
.sql .sql
.get_config_int(context, "configured") .get_config_int(context, "configured")

View File

@@ -2,9 +2,9 @@ use std::ffi::CString;
use crate::chatlist::*; use crate::chatlist::*;
use crate::constants::*; use crate::constants::*;
use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_array::*; use crate::dc_array::*;
use crate::dc_contact::*;
use crate::dc_job::*; use crate::dc_job::*;
use crate::dc_msg::*; use crate::dc_msg::*;
use crate::dc_tools::*; use crate::dc_tools::*;
@@ -52,7 +52,7 @@ pub unsafe fn dc_create_chat_by_msg_id(context: &Context, msg_id: uint32_t) -> u
dc_unblock_chat(context, (*chat).id); dc_unblock_chat(context, (*chat).id);
send_event = 1i32 send_event = 1i32
} }
dc_scaleup_contact_origin(context, (*msg).from_id, 0x800i32); Contact::scaleup_origin_by_id(context, (*msg).from_id, Origin::CreateChat);
} }
dc_msg_unref(msg); dc_msg_unref(msg);
@@ -206,7 +206,9 @@ pub unsafe fn dc_create_chat_by_contact_id(context: &Context, contact_id: uint32
dc_unblock_chat(context, chat_id); dc_unblock_chat(context, chat_id);
send_event = 1i32 send_event = 1i32
} }
} else if !dc_real_contact_exists(context, contact_id) && contact_id != 1i32 as libc::c_uint { } else if !Contact::real_exists_by_id(context, contact_id)
&& contact_id != DC_CONTACT_ID_SELF as u32
{
warn!( warn!(
context, context,
0, "Cannot create chat, contact {} does not exist.", contact_id as libc::c_int, 0, "Cannot create chat, contact {} does not exist.", contact_id as libc::c_int,
@@ -222,7 +224,7 @@ pub unsafe fn dc_create_chat_by_contact_id(context: &Context, contact_id: uint32
if 0 != chat_id { if 0 != chat_id {
send_event = 1; send_event = 1;
} }
dc_scaleup_contact_origin(context, contact_id, 0x800i32); Contact::scaleup_origin_by_id(context, contact_id, Origin::CreateChat);
} }
if 0 != send_event { if 0 != send_event {
context.call_cb(Event::MSGS_CHANGED, 0i32 as uintptr_t, 0i32 as uintptr_t); context.call_cb(Event::MSGS_CHANGED, 0i32 as uintptr_t, 0i32 as uintptr_t);
@@ -239,8 +241,6 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id(
) { ) {
let mut chat_id = 0; let mut chat_id = 0;
let mut chat_blocked = 0; let mut chat_blocked = 0;
let contact: *mut dc_contact_t;
let chat_name: *mut libc::c_char;
if !ret_chat_id.is_null() { if !ret_chat_id.is_null() {
*ret_chat_id = 0; *ret_chat_id = 0;
@@ -264,14 +264,8 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id(
} }
return; return;
} }
contact = dc_contact_new(context); if let Ok(contact) = Contact::load_from_db(context, contact_id) {
if dc_contact_load_from_db(contact, &context.sql, contact_id) { let chat_name = contact.get_display_name();
chat_name =
if !(*contact).name.is_null() && 0 != *(*contact).name.offset(0isize) as libc::c_int {
(*contact).name
} else {
(*contact).addr
};
if sql::execute( if sql::execute(
context, context,
@@ -279,10 +273,10 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id(
format!( format!(
"INSERT INTO chats (type, name, param, blocked, grpid) VALUES({}, '{}', '{}', {}, '{}')", "INSERT INTO chats (type, name, param, blocked, grpid) VALUES({}, '{}', '{}', {}, '{}')",
100, 100,
as_str(chat_name), chat_name,
if contact_id == 1 { "K=1" } else { "" }, if contact_id == DC_CONTACT_ID_SELF as u32 { "K=1" } else { "" },
create_blocked, create_blocked,
as_str((*contact).addr), contact.get_addr(),
), ),
params![], params![],
).is_ok() { ).is_ok() {
@@ -291,7 +285,7 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id(
&context.sql, &context.sql,
"chats", "chats",
"grpid", "grpid",
as_str((*contact).addr), contact.get_addr(),
); );
sql::execute( sql::execute(
@@ -303,7 +297,6 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id(
} }
} }
dc_contact_unref(contact);
if !ret_chat_id.is_null() { if !ret_chat_id.is_null() {
*ret_chat_id = chat_id *ret_chat_id = chat_id
} }
@@ -1542,15 +1535,18 @@ pub unsafe fn dc_add_contact_to_chat_ex(
) -> libc::c_int { ) -> libc::c_int {
let mut OK_TO_CONTINUE = true; let mut OK_TO_CONTINUE = true;
let mut success: libc::c_int = 0; let mut success: libc::c_int = 0;
let contact: *mut dc_contact_t = dc_get_contact(context, contact_id); let contact = Contact::get_by_id(context, contact_id);
let chat: *mut Chat = dc_chat_new(context); let chat: *mut Chat = dc_chat_new(context);
let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context);
if !(contact.is_null() || chat_id <= 9 as libc::c_uint) { if !(contact.is_err() || chat_id <= 9 as libc::c_uint) {
dc_reset_gossiped_timestamp(context, chat_id); dc_reset_gossiped_timestamp(context, chat_id);
let contact = contact.unwrap();
/*this also makes sure, not contacts are added to special or normal chats*/ /*this also makes sure, not contacts are added to special or normal chats*/
if !(0 == real_group_exists(context, chat_id) if !(0 == real_group_exists(context, chat_id)
|| !dc_real_contact_exists(context, contact_id) && contact_id != 1 as libc::c_uint || !Contact::real_exists_by_id(context, contact_id)
&& contact_id != DC_CONTACT_ID_SELF as u32
|| !dc_chat_load_from_db(chat, chat_id)) || !dc_chat_load_from_db(chat, chat_id))
{ {
if !(dc_is_contact_in_chat(context, chat_id, 1 as uint32_t) == 1) { if !(dc_is_contact_in_chat(context, chat_id, 1 as uint32_t) == 1) {
@@ -1572,7 +1568,7 @@ pub unsafe fn dc_add_contact_to_chat_ex(
.sql .sql
.get_config(context, "configured_addr") .get_config(context, "configured_addr")
.unwrap_or_default(); .unwrap_or_default();
if as_str((*contact).addr) != &self_addr { if contact.get_addr() != &self_addr {
// ourself is added using DC_CONTACT_ID_SELF, do not add it explicitly. // ourself is added using DC_CONTACT_ID_SELF, do not add it explicitly.
// if SELF is not in the group, members cannot be added at all. // if SELF is not in the group, members cannot be added at all.
@@ -1584,7 +1580,7 @@ pub unsafe fn dc_add_contact_to_chat_ex(
} else { } else {
// else continue and send status mail // else continue and send status mail
if (*chat).type_0 == 130 { if (*chat).type_0 == 130 {
if dc_contact_is_verified(contact) != 2 { if contact.is_verified() != VerifiedStatus::BidirectVerified {
error!( error!(
context, 0, context, 0,
"Only bidirectional verified contacts can be added to verified groups." "Only bidirectional verified contacts can be added to verified groups."
@@ -1603,14 +1599,12 @@ pub unsafe fn dc_add_contact_to_chat_ex(
(*msg).type_0 = Viewtype::Text; (*msg).type_0 = Viewtype::Text;
(*msg).text = Some(context.stock_system_msg( (*msg).text = Some(context.stock_system_msg(
StockMessage::MsgAddMember, StockMessage::MsgAddMember,
as_str((*contact).addr), contact.get_addr(),
"", "",
DC_CONTACT_ID_SELF as uint32_t, DC_CONTACT_ID_SELF as uint32_t,
)); ));
(*msg).param.set_int(Param::Cmd, 4); (*msg).param.set_int(Param::Cmd, 4);
if !(*contact).addr.is_null() { (*msg).param.set(Param::Arg, contact.get_addr());
(*msg).param.set(Param::Arg, as_str((*contact).addr));
}
(*msg).param.set_int(Param::Arg2, flags); (*msg).param.set_int(Param::Arg2, flags);
(*msg).id = dc_send_msg(context, chat_id, msg); (*msg).id = dc_send_msg(context, chat_id, msg);
context.call_cb( context.call_cb(
@@ -1627,7 +1621,6 @@ pub unsafe fn dc_add_contact_to_chat_ex(
} }
} }
dc_chat_unref(chat); dc_chat_unref(chat);
dc_contact_unref(contact);
dc_msg_unref(msg); dc_msg_unref(msg);
success success
@@ -1689,13 +1682,12 @@ pub unsafe fn dc_remove_contact_from_chat(
chat_id: u32, chat_id: u32,
contact_id: u32, contact_id: u32,
) -> libc::c_int { ) -> libc::c_int {
let mut success: libc::c_int = 0; let mut success = 0;
let contact: *mut dc_contact_t = dc_get_contact(context, contact_id);
let chat: *mut Chat = dc_chat_new(context); let chat: *mut Chat = dc_chat_new(context);
let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context);
if !(chat_id <= 9 as libc::c_uint if !(chat_id <= 9 as libc::c_uint
|| contact_id <= 9 as libc::c_uint && contact_id != 1 as libc::c_uint) || contact_id <= 9 as libc::c_uint && contact_id != DC_CONTACT_ID_SELF as u32)
{ {
/* we do not check if "contact_id" exists but just delete all records with the id from chats_contacts */ /* we do not check if "contact_id" exists but just delete all records with the id from chats_contacts */
/* this allows to delete pending references to deleted contacts. Of course, this should _not_ happen. */ /* this allows to delete pending references to deleted contacts. Of course, this should _not_ happen. */
@@ -1709,10 +1701,10 @@ pub unsafe fn dc_remove_contact_from_chat(
); );
} else { } else {
/* we should respect this - whatever we send to the group, it gets discarded anyway! */ /* we should respect this - whatever we send to the group, it gets discarded anyway! */
if !contact.is_null() { if let Ok(contact) = Contact::get_by_id(context, contact_id) {
if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 { if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
(*msg).type_0 = Viewtype::Text; (*msg).type_0 = Viewtype::Text;
if (*contact).id == 1 as libc::c_uint { if contact.id == DC_CONTACT_ID_SELF as u32 {
dc_set_group_explicitly_left(context, (*chat).grpid); dc_set_group_explicitly_left(context, (*chat).grpid);
(*msg).text = Some(context.stock_system_msg( (*msg).text = Some(context.stock_system_msg(
StockMessage::MsgGroupLeft, StockMessage::MsgGroupLeft,
@@ -1723,15 +1715,13 @@ pub unsafe fn dc_remove_contact_from_chat(
} else { } else {
(*msg).text = Some(context.stock_system_msg( (*msg).text = Some(context.stock_system_msg(
StockMessage::MsgDelMember, StockMessage::MsgDelMember,
as_str((*contact).addr), contact.get_addr(),
"", "",
DC_CONTACT_ID_SELF as u32, DC_CONTACT_ID_SELF as u32,
)); ));
} }
(*msg).param.set_int(Param::Cmd, 5); (*msg).param.set_int(Param::Cmd, 5);
if !(*contact).addr.is_null() { (*msg).param.set(Param::Arg, contact.get_addr());
(*msg).param.set(Param::Arg, as_str((*contact).addr));
}
(*msg).id = dc_send_msg(context, chat_id, msg); (*msg).id = dc_send_msg(context, chat_id, msg);
context.call_cb( context.call_cb(
Event::MSGS_CHANGED, Event::MSGS_CHANGED,
@@ -1756,7 +1746,6 @@ pub unsafe fn dc_remove_contact_from_chat(
} }
dc_chat_unref(chat); dc_chat_unref(chat);
dc_contact_unref(contact);
dc_msg_unref(msg); dc_msg_unref(msg);
success success
@@ -1947,7 +1936,6 @@ pub unsafe fn dc_forward_msgs(
let msg = dc_msg_new_untyped(context); let msg = dc_msg_new_untyped(context);
let chat = dc_chat_new(context); let chat = dc_chat_new(context);
let contact = dc_contact_new(context);
let mut created_db_entries = Vec::new(); let mut created_db_entries = Vec::new();
let mut curr_timestamp: i64; let mut curr_timestamp: i64;
@@ -1981,7 +1969,7 @@ pub unsafe fn dc_forward_msgs(
break; break;
} }
let original_param = (*msg).param.clone(); let original_param = (*msg).param.clone();
if (*msg).from_id != 1 { if (*msg).from_id != DC_CONTACT_ID_SELF as u32 {
(*msg).param.set_int(Param::Forwarded, 1); (*msg).param.set_int(Param::Forwarded, 1);
} }
(*msg).param.remove(Param::GuranteeE2ee); (*msg).param.remove(Param::GuranteeE2ee);
@@ -2027,7 +2015,6 @@ pub unsafe fn dc_forward_msgs(
created_db_entries[i + 1] as uintptr_t, created_db_entries[i + 1] as uintptr_t,
); );
} }
dc_contact_unref(contact);
dc_msg_unref(msg); dc_msg_unref(msg);
dc_chat_unref(chat); dc_chat_unref(chat);
} }
@@ -2113,7 +2100,7 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char
let mut image_rel: *mut libc::c_char = 0 as *mut libc::c_char; let mut image_rel: *mut libc::c_char = 0 as *mut libc::c_char;
let mut image_abs: *mut libc::c_char = 0 as *mut libc::c_char; let mut image_abs: *mut libc::c_char = 0 as *mut libc::c_char;
let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t; 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) { if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) {
image_rel = (*chat) image_rel = (*chat)
.param .param
@@ -2125,15 +2112,17 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char
} else if (*chat).type_0 == 100i32 { } else if (*chat).type_0 == 100i32 {
contacts = dc_get_chat_contacts((*chat).context, (*chat).id); contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
if !(*contacts).is_empty() { if !(*contacts).is_empty() {
contact = dc_get_contact((*chat).context, (*contacts).get_id(0)); if let Ok(contact) = Contact::get_by_id((*chat).context, (*contacts).get_id(0)) {
image_abs = dc_contact_get_profile_image(contact) if let Some(img) = contact.get_profile_image() {
image_abs = img.strdup();
}
}
} }
} }
} }
free(image_rel as *mut libc::c_void); free(image_rel as *mut libc::c_void);
dc_array_unref(contacts); dc_array_unref(contacts);
dc_contact_unref(contact);
image_abs image_abs
} }
@@ -2141,13 +2130,14 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char
pub unsafe fn dc_chat_get_color(chat: *const Chat) -> uint32_t { pub unsafe fn dc_chat_get_color(chat: *const Chat) -> uint32_t {
let mut color: uint32_t = 0i32 as uint32_t; let mut color: uint32_t = 0i32 as uint32_t;
let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t; 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) { if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) {
if (*chat).type_0 == 100i32 { if (*chat).type_0 == 100i32 {
contacts = dc_get_chat_contacts((*chat).context, (*chat).id); contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
if !(*contacts).is_empty() { if !(*contacts).is_empty() {
contact = dc_get_contact((*chat).context, (*contacts).get_id(0)); if let Ok(contact) = Contact::get_by_id((*chat).context, (*contacts).get_id(0)) {
color = dc_str_to_color((*contact).addr) as uint32_t color = contact.get_color();
}
} }
} else { } else {
color = dc_str_to_color((*chat).name) as uint32_t color = dc_str_to_color((*chat).name) as uint32_t
@@ -2155,7 +2145,6 @@ pub unsafe fn dc_chat_get_color(chat: *const Chat) -> uint32_t {
} }
dc_array_unref(contacts); dc_array_unref(contacts);
dc_contact_unref(contact);
color color
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_chat::*; use crate::dc_chat::*;
use crate::dc_contact::*;
use crate::dc_msg::*; use crate::dc_msg::*;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::stock::StockMessage; use crate::stock::StockMessage;
@@ -129,7 +129,7 @@ pub unsafe fn dc_lot_fill(
mut lot: *mut dc_lot_t, mut lot: *mut dc_lot_t,
msg: *mut dc_msg_t, msg: *mut dc_msg_t,
chat: *const Chat, chat: *const Chat,
contact: *const dc_contact_t, contact: Option<&Contact>,
context: &Context, context: &Context,
) { ) {
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint || msg.is_null() { if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint || msg.is_null() {
@@ -150,16 +150,24 @@ pub unsafe fn dc_lot_fill(
(*lot).text1 = 0 as *mut libc::c_char; (*lot).text1 = 0 as *mut libc::c_char;
(*lot).text1_meaning = 0i32 (*lot).text1_meaning = 0i32
} else if (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32 { } else if (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32 {
if 0 != dc_msg_is_info(msg) || contact.is_null() { if 0 != dc_msg_is_info(msg) || contact.is_none() {
(*lot).text1 = 0 as *mut libc::c_char; (*lot).text1 = 0 as *mut libc::c_char;
(*lot).text1_meaning = 0i32 (*lot).text1_meaning = 0i32
} else { } else {
if !chat.is_null() && (*chat).id == 1i32 as libc::c_uint { if !chat.is_null() && (*chat).id == 1i32 as libc::c_uint {
(*lot).text1 = dc_contact_get_display_name(contact) if let Some(contact) = contact {
(*lot).text1 = contact.get_display_name().strdup();
} else {
(*lot).text1 = std::ptr::null_mut();
}
} else { } else {
(*lot).text1 = dc_contact_get_first_name(contact) if let Some(contact) = contact {
(*lot).text1 = contact.get_first_name().strdup();
} else {
(*lot).text1 = std::ptr::null_mut();
}
} }
(*lot).text1_meaning = 2i32 (*lot).text1_meaning = 2i32;
} }
} }

View File

@@ -12,9 +12,9 @@ use mmime::other::*;
use std::ptr; use std::ptr;
use crate::constants::*; use crate::constants::*;
use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_chat::*; use crate::dc_chat::*;
use crate::dc_contact::*;
use crate::dc_e2ee::*; use crate::dc_e2ee::*;
use crate::dc_location::*; use crate::dc_location::*;
use crate::dc_msg::*; use crate::dc_msg::*;
@@ -294,7 +294,6 @@ pub unsafe fn dc_mimefactory_load_mdn(
} }
let mut success = 0; let mut success = 0;
let mut contact = 0 as *mut dc_contact_t;
(*factory).recipients_names = clist_new(); (*factory).recipients_names = clist_new();
(*factory).recipients_addr = clist_new(); (*factory).recipients_addr = clist_new();
@@ -306,24 +305,19 @@ pub unsafe fn dc_mimefactory_load_mdn(
.unwrap_or_else(|| 1) .unwrap_or_else(|| 1)
{ {
// MDNs not enabled - check this is late, in the job. the use may have changed its choice while offline ... // MDNs not enabled - check this is late, in the job. the use may have changed its choice while offline ...
contact = dc_contact_new((*factory).context); if !dc_msg_load_from_db((*factory).msg, (*factory).context, msg_id) {
if !(!dc_msg_load_from_db((*factory).msg, (*factory).context, msg_id) return success;
|| !dc_contact_load_from_db( }
contact,
&(*factory).context.sql, if let Ok(contact) = Contact::load_from_db((*factory).context, (*(*factory).msg).from_id) {
(*(*factory).msg).from_id, if !(contact.is_blocked() || (*(*factory).msg).chat_id <= 9 as libc::c_uint) {
))
{
if !(0 != (*contact).blocked || (*(*factory).msg).chat_id <= 9 as libc::c_uint) {
// Do not send MDNs trash etc.; chats.blocked is already checked by the caller in dc_markseen_msgs() // Do not send MDNs trash etc.; chats.blocked is already checked by the caller in dc_markseen_msgs()
if !((*(*factory).msg).from_id <= 9 as libc::c_uint) { if !((*(*factory).msg).from_id <= 9 as libc::c_uint) {
clist_insert_after( clist_insert_after(
(*factory).recipients_names, (*factory).recipients_names,
(*(*factory).recipients_names).last, (*(*factory).recipients_names).last,
(if !(*contact).authname.is_null() (if !contact.get_authname().is_empty() {
&& 0 != *(*contact).authname.offset(0isize) as libc::c_int contact.get_authname().strdup()
{
dc_strdup((*contact).authname)
} else { } else {
0 as *mut libc::c_char 0 as *mut libc::c_char
}) as *mut libc::c_void, }) as *mut libc::c_void,
@@ -331,7 +325,7 @@ pub unsafe fn dc_mimefactory_load_mdn(
clist_insert_after( clist_insert_after(
(*factory).recipients_addr, (*factory).recipients_addr,
(*(*factory).recipients_addr).last, (*(*factory).recipients_addr).last,
dc_strdup((*contact).addr) as *mut libc::c_void, contact.get_addr().strdup() as *mut libc::c_void,
); );
load_from(factory); load_from(factory);
(*factory).timestamp = dc_create_smeared_timestamp((*factory).context); (*factory).timestamp = dc_create_smeared_timestamp((*factory).context);
@@ -346,8 +340,6 @@ pub unsafe fn dc_mimefactory_load_mdn(
} }
} }
dc_contact_unref(contact);
success success
} }

View File

@@ -11,8 +11,8 @@ use mmime::mailmime_types::*;
use mmime::mmapstring::*; use mmime::mmapstring::*;
use mmime::other::*; use mmime::other::*;
use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_contact::*;
use crate::dc_e2ee::*; use crate::dc_e2ee::*;
use crate::dc_location::*; use crate::dc_location::*;
use crate::dc_simplify::*; use crate::dc_simplify::*;
@@ -422,7 +422,7 @@ pub unsafe fn mailimf_find_first_addr(mb_list: *const mailimf_mailbox_list) -> *
0 as *mut libc::c_void 0 as *mut libc::c_void
}) as *mut mailimf_mailbox; }) as *mut mailimf_mailbox;
if !mb.is_null() && !(*mb).mb_addr_spec.is_null() { if !mb.is_null() && !(*mb).mb_addr_spec.is_null() {
return dc_addr_normalize((*mb).mb_addr_spec); return addr_normalize(as_str((*mb).mb_addr_spec)).strdup();
} }
cur = if !cur.is_null() { cur = if !cur.is_null() {
(*cur).next (*cur).next
@@ -1565,7 +1565,7 @@ pub unsafe fn dc_mimeparser_sender_equals_recipient(mimeparser: &dc_mimeparser_t
let fld: *const mailimf_field; let fld: *const mailimf_field;
let mut fld_from: *const mailimf_from = 0 as *const mailimf_from; let mut fld_from: *const mailimf_from = 0 as *const mailimf_from;
let mb: *mut mailimf_mailbox; let mb: *mut mailimf_mailbox;
let mut from_addr_norm: *mut libc::c_char = 0 as *mut libc::c_char;
if !(*mimeparser).header_root.is_null() { if !(*mimeparser).header_root.is_null() {
/* get From: and check there is exactly one sender */ /* get From: and check there is exactly one sender */
fld = mailimf_find_field(mimeparser.header_root, MAILIMF_FIELD_FROM as libc::c_int); fld = mailimf_find_field(mimeparser.header_root, MAILIMF_FIELD_FROM as libc::c_int);
@@ -1584,17 +1584,16 @@ pub unsafe fn dc_mimeparser_sender_equals_recipient(mimeparser: &dc_mimeparser_t
0 as *mut libc::c_void 0 as *mut libc::c_void
}) as *mut mailimf_mailbox; }) as *mut mailimf_mailbox;
if !mb.is_null() { if !mb.is_null() {
from_addr_norm = dc_addr_normalize((*mb).mb_addr_spec); let from_addr_norm = addr_normalize(as_str((*mb).mb_addr_spec));
let recipients = mailimf_get_recipients(mimeparser.header_root); let recipients = mailimf_get_recipients(mimeparser.header_root);
if recipients.len() == 1 { if recipients.len() == 1 {
if recipients.contains(as_str(from_addr_norm)) { if recipients.contains(from_addr_norm) {
sender_equals_recipient = 1i32; sender_equals_recipient = 1i32;
} }
} }
} }
} }
} }
free(from_addr_norm as *mut libc::c_void);
sender_equals_recipient sender_equals_recipient
} }
@@ -1691,15 +1690,15 @@ pub unsafe fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet<
/* ****************************************************************************** /* ******************************************************************************
* low-level-tools for getting a list of all recipients * low-level-tools for getting a list of all recipients
******************************************************************************/ ******************************************************************************/
#[allow(non_snake_case)] #[allow(non_snake_case)]
unsafe fn mailimf_get_recipients__add_addr( unsafe fn mailimf_get_recipients__add_addr(
recipients: &mut HashSet<String>, recipients: &mut HashSet<String>,
mb: *mut mailimf_mailbox, mb: *mut mailimf_mailbox,
) { ) {
if !mb.is_null() { if !mb.is_null() {
let addr_norm: *mut libc::c_char = dc_addr_normalize((*mb).mb_addr_spec); let addr_norm = addr_normalize(as_str((*mb).mb_addr_spec));
recipients.insert(to_string(addr_norm)); recipients.insert(addr_norm.into());
free(addr_norm as *mut libc::c_void);
}; };
} }

View File

@@ -1,9 +1,9 @@
use std::ffi::CString; use std::ffi::CString;
use crate::constants::*; use crate::constants::*;
use crate::contact::*;
use crate::context::*; use crate::context::*;
use crate::dc_chat::*; use crate::dc_chat::*;
use crate::dc_contact::*;
use crate::dc_job::*; use crate::dc_job::*;
use crate::dc_lot::dc_lot_t; use crate::dc_lot::dc_lot_t;
use crate::dc_lot::*; use crate::dc_lot::*;
@@ -48,12 +48,10 @@ pub struct dc_msg_t<'a> {
// handle messages // handle messages
pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_char { pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_char {
let msg = dc_msg_new_untyped(context); let msg = dc_msg_new_untyped(context);
let contact_from = dc_contact_new(context);
let mut p: *mut libc::c_char; let mut p: *mut libc::c_char;
let mut ret = String::new(); let mut ret = String::new();
dc_msg_load_from_db(msg, context, msg_id); dc_msg_load_from_db(msg, context, msg_id);
dc_contact_load_from_db(contact_from, &context.sql, (*msg).from_id);
let rawtxt: Option<String> = context.sql.query_row_col( let rawtxt: Option<String> = context.sql.query_row_col(
context, context,
@@ -65,7 +63,6 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
if rawtxt.is_none() { if rawtxt.is_none() {
ret += &format!("Cannot load message #{}.", msg_id as usize); ret += &format!("Cannot load message #{}.", msg_id as usize);
dc_msg_unref(msg); dc_msg_unref(msg);
dc_contact_unref(contact_from);
return ret.strdup(); return ret.strdup();
} }
let rawtxt = rawtxt.unwrap(); let rawtxt = rawtxt.unwrap();
@@ -74,12 +71,14 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
let fts = dc_timestamp_to_str(dc_msg_get_timestamp(msg)); let fts = dc_timestamp_to_str(dc_msg_get_timestamp(msg));
ret += &format!("Sent: {}", fts); ret += &format!("Sent: {}", fts);
p = dc_contact_get_name_n_addr(contact_from); let name = Contact::load_from_db(context, (*msg).from_id)
ret += &format!(" by {}", to_string(p)); .map(|contact| contact.get_name_n_addr())
free(p as *mut libc::c_void); .unwrap_or_default();
ret += &format!(" by {}", name);
ret += "\n"; ret += "\n";
if (*msg).from_id != 1 as libc::c_uint { if (*msg).from_id != DC_CONTACT_ID_SELF as libc::c_uint {
let s = dc_timestamp_to_str(if 0 != (*msg).timestamp_rcvd { let s = dc_timestamp_to_str(if 0 != (*msg).timestamp_rcvd {
(*msg).timestamp_rcvd (*msg).timestamp_rcvd
} else { } else {
@@ -92,7 +91,6 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
if (*msg).from_id == 2 || (*msg).to_id == 2 { if (*msg).from_id == 2 || (*msg).to_id == 2 {
// device-internal message, no further details needed // device-internal message, no further details needed
dc_msg_unref(msg); dc_msg_unref(msg);
dc_contact_unref(contact_from);
return ret.strdup(); return ret.strdup();
} }
@@ -112,14 +110,11 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
let fts = dc_timestamp_to_str(ts); let fts = dc_timestamp_to_str(ts);
ret += &format!("Read: {}", fts); ret += &format!("Read: {}", fts);
let contact = dc_contact_new(context); let name = Contact::load_from_db(context, contact_id as u32)
dc_contact_load_from_db(contact, &context.sql, contact_id as u32); .map(|contact| contact.get_name_n_addr())
.unwrap_or_default();
p = dc_contact_get_name_n_addr(contact);
ret += &format!(" by {}", as_str(p));
free(p as *mut libc::c_void);
dc_contact_unref(contact);
ret += &format!(" by {}", name);
ret += "\n"; ret += "\n";
} }
Ok(()) Ok(())
@@ -210,7 +205,6 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
} }
dc_msg_unref(msg); dc_msg_unref(msg);
dc_contact_unref(contact_from);
ret.strdup() ret.strdup()
} }
@@ -794,8 +788,8 @@ pub unsafe fn dc_msg_get_summary<'a>(
) -> *mut dc_lot_t { ) -> *mut dc_lot_t {
let current_block: u64; let current_block: u64;
let ret: *mut dc_lot_t = dc_lot_new(); 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; let mut chat_to_delete: *mut Chat = 0 as *mut Chat;
if !(msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint) { if !(msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint) {
if chat.is_null() { if chat.is_null() {
chat_to_delete = dc_get_chat((*msg).context, (*msg).chat_id); chat_to_delete = dc_get_chat((*msg).context, (*msg).chat_id);
@@ -811,16 +805,19 @@ pub unsafe fn dc_msg_get_summary<'a>(
match current_block { match current_block {
15204159476013091401 => {} 15204159476013091401 => {}
_ => { _ => {
if (*msg).from_id != 1 as libc::c_uint let contact = if (*msg).from_id != DC_CONTACT_ID_SELF as libc::c_uint
&& ((*chat).type_0 == 120 || (*chat).type_0 == 130) && ((*chat).type_0 == 120 || (*chat).type_0 == 130)
{ {
contact = dc_get_contact((*chat).context, (*msg).from_id) Contact::get_by_id((*chat).context, (*msg).from_id).ok()
} } else {
dc_lot_fill(ret, msg, chat, contact, (*msg).context); None
};
dc_lot_fill(ret, msg, chat, contact.as_ref(), (*msg).context);
} }
} }
} }
dc_contact_unref(contact);
dc_chat_unref(chat_to_delete); dc_chat_unref(chat_to_delete);
ret ret
@@ -1572,12 +1569,8 @@ mod tests {
let d = test::dummy_context(); let d = test::dummy_context();
let ctx = &d.ctx; let ctx = &d.ctx;
let contact = dc_create_contact( let contact =
ctx, Contact::create(ctx, "", "dest@example.com").expect("failed to create contact");
b"\x00".as_ptr().cast(),
b"dest@example.com\x00".as_ptr().cast(),
);
assert!(contact != 0);
let res = ctx.set_config(Config::ConfiguredAddr, Some("self@example.com")); let res = ctx.set_config(Config::ConfiguredAddr, Some("self@example.com"));
assert!(res.is_ok()); assert!(res.is_ok());

View File

@@ -1,8 +1,8 @@
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_chat::*; use crate::dc_chat::*;
use crate::dc_contact::*;
use crate::dc_lot::*; use crate::dc_lot::*;
use crate::dc_strencode::*; use crate::dc_strencode::*;
use crate::dc_tools::*; use crate::dc_tools::*;
@@ -66,8 +66,7 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
let name_r = percent_decode_str(name_enc) let name_r = percent_decode_str(name_enc)
.decode_utf8() .decode_utf8()
.expect("invalid name"); .expect("invalid name");
name = name_r.strdup(); name = normalize_name(name_r).strdup();
dc_normalize_name(name);
} }
invitenumber = param invitenumber = param
.get(Param::ProfileImage) .get(Param::ProfileImage)
@@ -186,7 +185,7 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
b";\x00" as *const u8 as *const libc::c_char, b";\x00" as *const u8 as *const libc::c_char,
b",\x00" as *const u8 as *const libc::c_char, b",\x00" as *const u8 as *const libc::c_char,
); );
dc_normalize_name(name); name = normalize_name(as_str(name)).strdup();
} }
} }
} }
@@ -204,10 +203,10 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
let mut temp: *mut libc::c_char = dc_urldecode(addr); let mut temp: *mut libc::c_char = dc_urldecode(addr);
free(addr as *mut libc::c_void); free(addr as *mut libc::c_void);
addr = temp; addr = temp;
temp = dc_addr_normalize(addr); temp = addr_normalize(as_str(addr)).strdup();
free(addr as *mut libc::c_void); free(addr as *mut libc::c_void);
addr = temp; addr = temp;
if !dc_may_be_valid_addr(addr) { if !may_be_valid_addr(as_str(addr)) {
(*qr_parsed).state = 400i32; (*qr_parsed).state = 400i32;
(*qr_parsed).text1 = dc_strdup( (*qr_parsed).text1 = dc_strdup(
b"Bad e-mail address.\x00" as *const u8 as *const libc::c_char, b"Bad e-mail address.\x00" as *const u8 as *const libc::c_char,
@@ -248,19 +247,19 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
if addr.is_null() || invitenumber.is_null() || auth.is_null() { if addr.is_null() || invitenumber.is_null() || auth.is_null() {
if let Some(peerstate) = peerstate { if let Some(peerstate) = peerstate {
(*qr_parsed).state = 210i32; (*qr_parsed).state = 210i32;
let addr_ptr = if let Some(ref addr) = peerstate.addr { let addr = peerstate
addr.strdup() .addr
} else { .as_ref()
std::ptr::null() .map(|s| s.as_str())
}; .unwrap_or_else(|| "");
(*qr_parsed).id = dc_add_or_lookup_contact( (*qr_parsed).id = Contact::add_or_lookup(
context, context,
0 as *const libc::c_char, "",
addr_ptr, addr,
0x80i32, Origin::UnhandledQrScan,
0 as *mut libc::c_int, )
); .map(|(id, _)| id)
free(addr_ptr as *mut _); .unwrap_or_default();
dc_create_or_lookup_nchat_by_contact_id( dc_create_or_lookup_nchat_by_contact_id(
context, context,
(*qr_parsed).id, (*qr_parsed).id,
@@ -286,26 +285,28 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
} else { } else {
(*qr_parsed).state = 200i32 (*qr_parsed).state = 200i32
} }
(*qr_parsed).id = dc_add_or_lookup_contact( (*qr_parsed).id = Contact::add_or_lookup(
context, context,
name, as_str(name),
addr, as_str(addr),
0x80i32, Origin::UnhandledQrScan,
0 as *mut libc::c_int, )
); .map(|(id, _)| id)
.unwrap_or_default();
(*qr_parsed).fingerprint = dc_strdup(fingerprint); (*qr_parsed).fingerprint = dc_strdup(fingerprint);
(*qr_parsed).invitenumber = dc_strdup(invitenumber); (*qr_parsed).invitenumber = dc_strdup(invitenumber);
(*qr_parsed).auth = dc_strdup(auth) (*qr_parsed).auth = dc_strdup(auth)
} }
} else if !addr.is_null() { } else if !addr.is_null() {
(*qr_parsed).state = 320i32; (*qr_parsed).state = 320i32;
(*qr_parsed).id = dc_add_or_lookup_contact( (*qr_parsed).id = Contact::add_or_lookup(
context, context,
name, as_str(name),
addr, as_str(addr),
0x80i32, Origin::UnhandledQrScan,
0 as *mut libc::c_int,
) )
.map(|(id, _)| id)
.unwrap_or_default();
} else if strstr( } else if strstr(
qr, qr,
b"http://\x00" as *const u8 as *const libc::c_char, b"http://\x00" as *const u8 as *const libc::c_char,

View File

@@ -8,10 +8,10 @@ use mmime::other::*;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use crate::constants::*; use crate::constants::*;
use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_array::*; use crate::dc_array::*;
use crate::dc_chat::*; use crate::dc_chat::*;
use crate::dc_contact::*;
use crate::dc_job::*; use crate::dc_job::*;
use crate::dc_location::*; use crate::dc_location::*;
use crate::dc_mimeparser::*; use crate::dc_mimeparser::*;
@@ -38,7 +38,7 @@ pub unsafe fn dc_receive_imf(
let mut current_block: u64; let mut current_block: u64;
/* the function returns the number of created messages in the database */ /* the function returns the number of created messages in the database */
let mut incoming: libc::c_int = 1; let mut incoming: libc::c_int = 1;
let mut incoming_origin: libc::c_int = 0; let mut incoming_origin = Origin::Unknown;
let mut to_self: libc::c_int = 0; let mut to_self: libc::c_int = 0;
let mut from_id: uint32_t = 0 as uint32_t; let mut from_id: uint32_t = 0 as uint32_t;
let mut from_id_blocked: libc::c_int = 0; let mut from_id_blocked: libc::c_int = 0;
@@ -103,7 +103,7 @@ pub unsafe fn dc_receive_imf(
dc_add_or_lookup_contacts_by_mailbox_list( dc_add_or_lookup_contacts_by_mailbox_list(
context, context,
(*fld_from).frm_mb_list, (*fld_from).frm_mb_list,
0x10, Origin::IncomingUnknownFrom,
from_list, from_list,
&mut check_self, &mut check_self,
); );
@@ -114,7 +114,8 @@ pub unsafe fn dc_receive_imf(
} }
} else if dc_array_get_cnt(from_list) >= 1 { } else if dc_array_get_cnt(from_list) >= 1 {
from_id = dc_array_get_id(from_list, 0 as size_t); from_id = dc_array_get_id(from_list, 0 as size_t);
incoming_origin = dc_get_contact_origin(context, from_id, &mut from_id_blocked) incoming_origin =
Contact::get_origin_by_id(context, from_id, &mut from_id_blocked)
} }
dc_array_unref(from_list); dc_array_unref(from_list);
} }
@@ -127,11 +128,11 @@ pub unsafe fn dc_receive_imf(
context, context,
(*fld_to).to_addr_list, (*fld_to).to_addr_list,
if 0 == incoming { if 0 == incoming {
0x4000 Origin::OutgoingTo
} else if incoming_origin >= 0x100 { } else if incoming_origin.is_verified() {
0x400 Origin::IncomingTo
} else { } else {
0x40 Origin::IncomingUnknownTo
}, },
to_ids, to_ids,
&mut to_self, &mut to_self,
@@ -147,11 +148,11 @@ pub unsafe fn dc_receive_imf(
context, context,
(*fld_cc).cc_addr_list, (*fld_cc).cc_addr_list,
if 0 == incoming { if 0 == incoming {
0x2000 Origin::OutgoingCc
} else if incoming_origin >= 0x100 { } else if incoming_origin.is_verified() {
0x200 Origin::IncomingCc
} else { } else {
0x20 Origin::IncomingUnknownCc
}, },
to_ids, to_ids,
0 as *mut libc::c_int, 0 as *mut libc::c_int,
@@ -253,7 +254,7 @@ pub unsafe fn dc_receive_imf(
if chat_id == 0 as libc::c_uint { if chat_id == 0 as libc::c_uint {
let create_blocked: libc::c_int = if 0 != test_normal_chat_id let create_blocked: libc::c_int = if 0 != test_normal_chat_id
&& test_normal_chat_id_blocked == 0 && test_normal_chat_id_blocked == 0
|| incoming_origin >= 0x7fffffff || incoming_origin.is_start_new_chat()
{ {
0 0
} else { } else {
@@ -285,7 +286,7 @@ pub unsafe fn dc_receive_imf(
} }
if chat_id == 0 as libc::c_uint { if chat_id == 0 as libc::c_uint {
let create_blocked_0: libc::c_int = let create_blocked_0: libc::c_int =
if incoming_origin >= 0x7fffffff || from_id == to_id { if incoming_origin.is_start_new_chat() || from_id == to_id {
0 0
} else { } else {
2 2
@@ -309,16 +310,20 @@ pub unsafe fn dc_receive_imf(
} else if 0 } else if 0
!= dc_is_reply_to_known_message(context, &mime_parser) != dc_is_reply_to_known_message(context, &mime_parser)
{ {
dc_scaleup_contact_origin(context, from_id, 0x100); Contact::scaleup_origin_by_id(
context,
from_id,
Origin::IncomingReplyTo,
);
info!( info!(
context, context,
0, 0,
"Message is a reply to a known message, mark sender as known.", "Message is a reply to a known message, mark sender as known.",
); );
incoming_origin = if incoming_origin > 0x100 { incoming_origin = if incoming_origin.is_verified() {
incoming_origin incoming_origin
} else { } else {
0x100 Origin::IncomingReplyTo
} }
} }
} }
@@ -327,8 +332,8 @@ pub unsafe fn dc_receive_imf(
chat_id = 3 as uint32_t chat_id = 3 as uint32_t
} }
if 0 != chat_id_blocked && state == 10 { if 0 != chat_id_blocked && state == 10 {
if incoming_origin < 0x100 && msgrmsg == 0 { if !incoming_origin.is_verified() && msgrmsg == 0 {
state = 13 state = 13;
} }
} }
} else { } else {
@@ -353,12 +358,13 @@ pub unsafe fn dc_receive_imf(
} }
} }
if chat_id == 0 as libc::c_uint && 0 != allow_creation { if chat_id == 0 as libc::c_uint && 0 != allow_creation {
let create_blocked_1: libc::c_int = let create_blocked_1: libc::c_int = if 0 != msgrmsg
if 0 != msgrmsg && !dc_is_contact_blocked(context, to_id) { && !Contact::is_blocked_load(context, to_id)
0 {
} else { 0
2 } else {
}; 2
};
dc_create_or_lookup_nchat_by_contact_id( dc_create_or_lookup_nchat_by_contact_id(
context, context,
to_id, to_id,
@@ -777,28 +783,34 @@ pub unsafe fn dc_receive_imf(
if !mime_parser.location_kml.is_none() if !mime_parser.location_kml.is_none()
&& chat_id > DC_CHAT_ID_LAST_SPECIAL as libc::c_uint && chat_id > DC_CHAT_ID_LAST_SPECIAL as libc::c_uint
{ {
let contact = dc_get_contact(context, from_id); if !mime_parser.location_kml.as_ref().unwrap().addr.is_null() {
if !mime_parser.location_kml.as_ref().unwrap().addr.is_null() if let Ok(contact) = Contact::get_by_id(context, from_id) {
&& !contact.is_null() if !contact.get_addr().is_empty()
&& !(*contact).addr.is_null() && contact.get_addr().to_lowercase()
&& strcasecmp( == as_str(mime_parser.location_kml.as_ref().unwrap().addr)
(*contact).addr, .to_lowercase()
mime_parser.location_kml.as_ref().unwrap().addr, {
) == 0 let newest_location_id = dc_save_locations(
{ context,
let newest_location_id = dc_save_locations( chat_id,
context, from_id,
chat_id, &mime_parser.location_kml.as_ref().unwrap().locations,
from_id, 0,
&mime_parser.location_kml.as_ref().unwrap().locations, );
0, if newest_location_id != 0
); && hidden == 0
if newest_location_id != 0 && hidden == 0 && !location_id_written { && !location_id_written
dc_set_msg_location_id(context, insert_msg_id, newest_location_id); {
dc_set_msg_location_id(
context,
insert_msg_id,
newest_location_id,
);
}
send_event = true;
}
} }
send_event = true;
} }
dc_contact_unref(contact);
} }
if send_event { if send_event {
context.call_cb( context.call_cb(
@@ -1014,9 +1026,8 @@ unsafe fn create_or_lookup_group(
if !optional_field.is_null() { if !optional_field.is_null() {
X_MrRemoveFromGrp = (*optional_field).fld_value; X_MrRemoveFromGrp = (*optional_field).fld_value;
mime_parser.is_system_message = 5; mime_parser.is_system_message = 5;
let left_group: libc::c_int = let left_group = (Contact::lookup_id_by_addr(context, as_str(X_MrRemoveFromGrp))
(dc_lookup_contact_id_by_addr(context, X_MrRemoveFromGrp) == from_id as u32) as libc::c_int;
== from_id as libc::c_uint) as libc::c_int;
better_msg = context.stock_system_msg( better_msg = context.stock_system_msg(
if 0 != left_group { if 0 != left_group {
StockMessage::MsgGroupLeft StockMessage::MsgGroupLeft
@@ -1125,7 +1136,7 @@ unsafe fn create_or_lookup_group(
&& !grpname.is_null() && !grpname.is_null()
&& X_MrRemoveFromGrp.is_null() && X_MrRemoveFromGrp.is_null()
&& (0 == group_explicitly_left && (0 == group_explicitly_left
|| !X_MrAddToGrp.is_null() && dc_addr_cmp(&self_addr, as_str(X_MrAddToGrp))) || !X_MrAddToGrp.is_null() && addr_cmp(&self_addr, as_str(X_MrAddToGrp)))
{ {
/*otherwise, a pending "quit" message may pop up*/ /*otherwise, a pending "quit" message may pop up*/
/*re-create explicitly left groups only if ourself is re-added*/ /*re-create explicitly left groups only if ourself is re-added*/
@@ -1255,17 +1266,20 @@ unsafe fn create_or_lookup_group(
params![chat_id as i32], params![chat_id as i32],
) )
.ok(); .ok();
if skip.is_null() || !dc_addr_cmp(&self_addr, as_str(skip)) { if skip.is_null() || !addr_cmp(&self_addr, as_str(skip)) {
dc_add_to_chat_contacts_table(context, chat_id, 1); dc_add_to_chat_contacts_table(context, chat_id, 1);
} }
if from_id > 9 { if from_id > 9 {
if !dc_addr_equals_contact(context, &self_addr, from_id as u32) if !Contact::addr_equals_contact(
&& (skip.is_null() context,
|| !dc_addr_equals_contact( &self_addr,
context, from_id as u32,
to_string(skip), ) && (skip.is_null()
from_id as u32, || !Contact::addr_equals_contact(
)) context,
to_string(skip),
from_id as u32,
))
{ {
dc_add_to_chat_contacts_table( dc_add_to_chat_contacts_table(
context, context,
@@ -1277,9 +1291,13 @@ unsafe fn create_or_lookup_group(
i = 0; i = 0;
while i < to_ids_cnt { while i < to_ids_cnt {
let to_id = dc_array_get_id(to_ids, i as size_t); let to_id = dc_array_get_id(to_ids, i as size_t);
if !dc_addr_equals_contact(context, &self_addr, to_id) if !Contact::addr_equals_contact(context, &self_addr, to_id)
&& (skip.is_null() && (skip.is_null()
|| !dc_addr_equals_contact(context, to_string(skip), to_id)) || !Contact::addr_equals_contact(
context,
to_string(skip),
to_id,
))
{ {
dc_add_to_chat_contacts_table(context, chat_id, to_id); dc_add_to_chat_contacts_table(context, chat_id, to_id);
} }
@@ -1604,26 +1622,21 @@ unsafe fn check_verified_properties(
to_ids: *const dc_array_t, to_ids: *const dc_array_t,
failure_reason: *mut *mut libc::c_char, failure_reason: *mut *mut libc::c_char,
) -> libc::c_int { ) -> libc::c_int {
let contact = dc_contact_new(context);
let verify_fail = |reason: String| { let verify_fail = |reason: String| {
*failure_reason = format!("{}. See \"Info\" for details.", reason).strdup(); *failure_reason = format!("{}. See \"Info\" for details.", reason).strdup();
warn!(context, 0, "{}", reason); warn!(context, 0, "{}", reason);
}; };
let cleanup = || { let contact = match Contact::load_from_db(context, from_id) {
dc_contact_unref(contact); Ok(contact) => contact,
Err(_err) => {
verify_fail("Internal Error; cannot load contact".into());
return 0;
}
}; };
if !dc_contact_load_from_db(contact, &context.sql, from_id) {
verify_fail("Internal Error; cannot load contact".into());
cleanup();
return 0;
}
if 0 == mimeparser.e2ee_helper.encrypted { if 0 == mimeparser.e2ee_helper.encrypted {
verify_fail("This message is not encrypted".into()); verify_fail("This message is not encrypted".into());
cleanup();
return 0; return 0;
} }
@@ -1632,18 +1645,18 @@ unsafe fn check_verified_properties(
// this check is skipped for SELF as there is no proper SELF-peerstate // this check is skipped for SELF as there is no proper SELF-peerstate
// and results in group-splits otherwise. // and results in group-splits otherwise.
if from_id != 1 { if from_id != 1 {
let peerstate = Peerstate::from_addr(context, &context.sql, as_str((*contact).addr)); let peerstate = Peerstate::from_addr(context, &context.sql, contact.get_addr());
if peerstate.is_none() || dc_contact_is_verified_ex(contact, peerstate.as_ref()) != 2 { if peerstate.is_none()
|| contact.is_verified_ex(peerstate.as_ref()) != VerifiedStatus::BidirectVerified
{
verify_fail("The sender of this message is not verified.".into()); verify_fail("The sender of this message is not verified.".into());
cleanup();
return 0; return 0;
} }
if let Some(peerstate) = peerstate { if let Some(peerstate) = peerstate {
if !peerstate.has_verified_key(&mimeparser.e2ee_helper.signatures) { if !peerstate.has_verified_key(&mimeparser.e2ee_helper.signatures) {
verify_fail("The message was sent with non-verified encryption.".into()); verify_fail("The message was sent with non-verified encryption.".into());
cleanup();
return 0; return 0;
} }
} }
@@ -1665,7 +1678,6 @@ unsafe fn check_verified_properties(
); );
if rows.is_err() { if rows.is_err() {
cleanup();
return 0; return 0;
} }
for (to_addr, mut is_verified) in rows.unwrap().into_iter() { for (to_addr, mut is_verified) in rows.unwrap().into_iter() {
@@ -1686,7 +1698,7 @@ unsafe fn check_verified_properties(
context, context,
0, 0,
"{} has verfied {}.", "{} has verfied {}.",
as_str((*contact).addr), contact.get_addr(),
to_addr, to_addr,
); );
let fp = peerstate.gossip_key_fingerprint.clone(); let fp = peerstate.gossip_key_fingerprint.clone();
@@ -1702,7 +1714,6 @@ unsafe fn check_verified_properties(
"{} is not a member of this verified group", "{} is not a member of this verified group",
to_addr to_addr
)); ));
cleanup();
return 0; return 0;
} }
} }
@@ -1883,7 +1894,7 @@ fn is_msgrmsg_rfc724_mid(context: &Context, rfc724_mid: *const libc::c_char) ->
unsafe fn dc_add_or_lookup_contacts_by_address_list( unsafe fn dc_add_or_lookup_contacts_by_address_list(
context: &Context, context: &Context,
adr_list: *const mailimf_address_list, adr_list: *const mailimf_address_list,
origin: libc::c_int, origin: Origin,
ids: *mut dc_array_t, ids: *mut dc_array_t,
check_self: *mut libc::c_int, check_self: *mut libc::c_int,
) { ) {
@@ -1933,7 +1944,7 @@ unsafe fn dc_add_or_lookup_contacts_by_address_list(
unsafe fn dc_add_or_lookup_contacts_by_mailbox_list( unsafe fn dc_add_or_lookup_contacts_by_mailbox_list(
context: &Context, context: &Context,
mb_list: *const mailimf_mailbox_list, mb_list: *const mailimf_mailbox_list,
origin: libc::c_int, origin: Origin,
ids: *mut dc_array_t, ids: *mut dc_array_t,
check_self: *mut libc::c_int, check_self: *mut libc::c_int,
) { ) {
@@ -1971,7 +1982,7 @@ unsafe fn add_or_lookup_contact_by_addr(
context: &Context, context: &Context,
display_name_enc: *const libc::c_char, display_name_enc: *const libc::c_char,
addr_spec: *const libc::c_char, addr_spec: *const libc::c_char,
origin: libc::c_int, origin: Origin,
ids: *mut dc_array_t, ids: *mut dc_array_t,
mut check_self: *mut libc::c_int, mut check_self: *mut libc::c_int,
) { ) {
@@ -1989,7 +2000,7 @@ unsafe fn add_or_lookup_contact_by_addr(
.get_config(context, "configured_addr") .get_config(context, "configured_addr")
.unwrap_or_default(); .unwrap_or_default();
if dc_addr_cmp(self_addr, as_str(addr_spec)) { if addr_cmp(self_addr, as_str(addr_spec)) {
*check_self = 1; *check_self = 1;
} }
@@ -1997,20 +2008,15 @@ unsafe fn add_or_lookup_contact_by_addr(
return; return;
} }
/* add addr_spec if missing, update otherwise */ /* add addr_spec if missing, update otherwise */
let mut display_name_dec = 0 as *mut libc::c_char; let mut display_name_dec = "".to_string();
if !display_name_enc.is_null() { if !display_name_enc.is_null() {
display_name_dec = dc_decode_header_words(display_name_enc); let tmp = as_str(dc_decode_header_words(display_name_enc));
dc_normalize_name(display_name_dec); display_name_dec = normalize_name(&tmp);
} }
/*can be NULL*/ /*can be NULL*/
let row_id = dc_add_or_lookup_contact( let row_id = Contact::add_or_lookup(context, display_name_dec, as_str(addr_spec), origin)
context, .map(|(id, _)| id)
display_name_dec, .unwrap_or_default();
addr_spec,
origin,
0 as *mut libc::c_int,
);
free(display_name_dec as *mut libc::c_void);
if 0 != row_id { if 0 != row_id {
if !dc_array_search_id(ids, row_id, 0 as *mut size_t) { if !dc_array_search_id(ids, row_id, 0 as *mut size_t) {
dc_array_add_id(ids, row_id); dc_array_add_id(ids, row_id);

View File

@@ -5,11 +5,11 @@ use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
use crate::aheader::EncryptPreference; use crate::aheader::EncryptPreference;
use crate::constants::*; use crate::constants::*;
use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_array::*; use crate::dc_array::*;
use crate::dc_chat::*; use crate::dc_chat::*;
use crate::dc_configure::*; use crate::dc_configure::*;
use crate::dc_contact::*;
use crate::dc_e2ee::*; use crate::dc_e2ee::*;
use crate::dc_lot::*; use crate::dc_lot::*;
use crate::dc_mimeparser::*; use crate::dc_mimeparser::*;
@@ -315,30 +315,23 @@ unsafe fn fingerprint_equals_sender(
return 0; return 0;
} }
let mut fingerprint_equal: libc::c_int = 0i32; let mut fingerprint_equal: libc::c_int = 0i32;
let contacts: *mut dc_array_t = dc_get_chat_contacts(context, contact_chat_id); let contacts = dc_get_chat_contacts(context, contact_chat_id);
let contact: *mut dc_contact_t = dc_contact_new(context);
if !(dc_array_get_cnt(contacts) != 1) { if !(dc_array_get_cnt(contacts) != 1) {
if !dc_contact_load_from_db( if let Ok(contact) = Contact::load_from_db(context, dc_array_get_id(contacts, 0)) {
contact, if let Some(peerstate) = Peerstate::from_addr(context, &context.sql, contact.get_addr())
&context.sql, {
dc_array_get_id(contacts, 0i32 as size_t), let fingerprint_normalized = dc_normalize_fingerprint(as_str(fingerprint));
) { if peerstate.public_key_fingerprint.is_some()
&& &fingerprint_normalized == peerstate.public_key_fingerprint.as_ref().unwrap()
{
fingerprint_equal = 1;
}
}
} else {
return 0; return 0;
} }
if let Some(peerstate) =
Peerstate::from_addr(context, &context.sql, as_str((*contact).addr))
{
let fingerprint_normalized = dc_normalize_fingerprint(as_str(fingerprint));
if peerstate.public_key_fingerprint.is_some()
&& &fingerprint_normalized == peerstate.public_key_fingerprint.as_ref().unwrap()
{
fingerprint_equal = 1;
}
}
} }
dc_contact_unref(contact);
dc_array_unref(contacts); dc_array_unref(contacts);
fingerprint_equal fingerprint_equal
@@ -360,7 +353,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
let mut contact_chat_id_blocked: libc::c_int = 0i32; let mut contact_chat_id_blocked: libc::c_int = 0i32;
let mut grpid: *mut libc::c_char = 0 as *mut libc::c_char; let mut grpid: *mut libc::c_char = 0 as *mut libc::c_char;
let mut ret: libc::c_int = 0i32; let mut ret: libc::c_int = 0i32;
let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t;
if !(contact_id <= 9i32 as libc::c_uint) { if !(contact_id <= 9i32 as libc::c_uint) {
step = lookup_field(mimeparser, "Secure-Join"); step = lookup_field(mimeparser, "Secure-Join");
if !step.is_null() { if !step.is_null() {
@@ -572,7 +565,11 @@ pub unsafe fn dc_handle_securejoin_handshake(
); );
current_block = 4378276786830486580; current_block = 4378276786830486580;
} else { } else {
dc_scaleup_contact_origin(context, contact_id, 0x1000000i32); Contact::scaleup_origin_by_id(
context,
contact_id,
Origin::SecurejoinInvited,
);
info!(context, 0, "Auth verified.",); info!(context, 0, "Auth verified.",);
secure_connection_established(context, contact_chat_id); secure_connection_established(context, contact_chat_id);
context.call_cb( context.call_cb(
@@ -699,16 +696,23 @@ pub unsafe fn dc_handle_securejoin_handshake(
); );
current_block = 4378276786830486580; current_block = 4378276786830486580;
} else { } else {
dc_scaleup_contact_origin(context, contact_id, 0x2000000i32); Contact::scaleup_origin_by_id(
context,
contact_id,
Origin::SecurejoinJoined,
);
context.call_cb( context.call_cb(
Event::CONTACTS_CHANGED, Event::CONTACTS_CHANGED,
0i32 as uintptr_t, 0i32 as uintptr_t,
0i32 as uintptr_t, 0i32 as uintptr_t,
); );
if 0 != join_vg { if 0 != join_vg {
if 0 == dc_addr_equals_self( if !addr_equals_self(
context, context,
lookup_field(mimeparser, "Chat-Group-Member-Added"), as_str(lookup_field(
mimeparser,
"Chat-Group-Member-Added",
)),
) { ) {
info!( info!(
context, context,
@@ -756,22 +760,26 @@ pub unsafe fn dc_handle_securejoin_handshake(
==== Alice - the inviter side ==== ==== Alice - the inviter side ====
==== Step 8 in "Out-of-band verified groups" protocol ==== ==== Step 8 in "Out-of-band verified groups" protocol ====
============================================================ */ ============================================================ */
contact = dc_get_contact(context, contact_id); if let Ok(contact) = Contact::get_by_id(context, contact_id) {
if contact.is_null() || 0 == dc_contact_is_verified(contact) { if contact.is_verified() == VerifiedStatus::Unverified {
warn!(context, 0, "vg-member-added-received invalid.",);
current_block = 4378276786830486580;
} else {
context.call_cb(
Event::SECUREJOIN_INVITER_PROGRESS,
contact_id as uintptr_t,
800i32 as uintptr_t,
);
context.call_cb(
Event::SECUREJOIN_INVITER_PROGRESS,
contact_id as uintptr_t,
1000i32 as uintptr_t,
);
current_block = 10256747982273457880;
}
} else {
warn!(context, 0, "vg-member-added-received invalid.",); warn!(context, 0, "vg-member-added-received invalid.",);
current_block = 4378276786830486580; current_block = 4378276786830486580;
} else {
context.call_cb(
Event::SECUREJOIN_INVITER_PROGRESS,
contact_id as uintptr_t,
800i32 as uintptr_t,
);
context.call_cb(
Event::SECUREJOIN_INVITER_PROGRESS,
contact_id as uintptr_t,
1000i32 as uintptr_t,
);
current_block = 10256747982273457880;
} }
} else { } else {
current_block = 10256747982273457880; current_block = 10256747982273457880;
@@ -786,7 +794,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
} }
} }
} }
dc_contact_unref(contact);
free(scanned_fingerprint_of_alice as *mut libc::c_void); free(scanned_fingerprint_of_alice as *mut libc::c_void);
free(auth as *mut libc::c_void); free(auth as *mut libc::c_void);
free(own_fingerprint as *mut libc::c_void); free(own_fingerprint as *mut libc::c_void);
@@ -802,23 +810,20 @@ unsafe fn end_bobs_joining(context: &Context, status: libc::c_int) {
unsafe fn secure_connection_established(context: &Context, contact_chat_id: uint32_t) { unsafe fn secure_connection_established(context: &Context, contact_chat_id: uint32_t) {
let contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id); let contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id);
let contact: *mut dc_contact_t = dc_get_contact(context, contact_id); let contact = Contact::get_by_id(context, contact_id);
let msg = CString::new(context.stock_string_repl_str( let addr = if let Ok(ref contact) = contact {
StockMessage::ContactVerified, contact.get_addr()
if !contact.is_null() { } else {
as_str((*contact).addr) "?"
} else { };
"?" let msg =
}, CString::new(context.stock_string_repl_str(StockMessage::ContactVerified, addr)).unwrap();
))
.unwrap();
dc_add_device_msg(context, contact_chat_id, msg.as_ptr()); dc_add_device_msg(context, contact_chat_id, msg.as_ptr());
context.call_cb( context.call_cb(
Event::CHAT_MODIFIED, Event::CHAT_MODIFIED,
contact_chat_id as uintptr_t, contact_chat_id as uintptr_t,
0i32 as uintptr_t, 0i32 as uintptr_t,
); );
dc_contact_unref(contact);
} }
unsafe fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> *const libc::c_char { unsafe fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> *const libc::c_char {
@@ -844,11 +849,11 @@ unsafe fn could_not_establish_secure_connection(
details: *const libc::c_char, details: *const libc::c_char,
) { ) {
let contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id); let contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id);
let contact = dc_get_contact(context, contact_id); let contact = Contact::get_by_id(context, contact_id);
let msg = context.stock_string_repl_str( let msg = context.stock_string_repl_str(
StockMessage::ContactNotVerified, StockMessage::ContactNotVerified,
if !contact.is_null() { if let Ok(ref contact) = contact {
as_str((*contact).addr) contact.get_addr()
} else { } else {
"?" "?"
}, },
@@ -856,7 +861,6 @@ unsafe fn could_not_establish_secure_connection(
let msg_c = CString::new(msg.as_str()).unwrap(); let msg_c = CString::new(msg.as_str()).unwrap();
dc_add_device_msg(context, contact_chat_id, msg_c.as_ptr()); dc_add_device_msg(context, contact_chat_id, msg_c.as_ptr());
error!(context, 0, "{} ({})", msg, as_str(details)); error!(context, 0, "{} ({})", msg, as_str(details));
dc_contact_unref(contact);
} }
unsafe fn mark_peer_as_verified( unsafe fn mark_peer_as_verified(

View File

@@ -539,32 +539,32 @@ pub unsafe fn dc_str_to_clist(
list list
} }
/* the colors must fulfill some criterions as:
- contrast to black and to white
- work as a text-color
- being noticeable on a typical map
- harmonize together while being different enough
(therefore, we cannot just use random rgb colors :) */
const COLORS: [u32; 16] = [
0xe56555, 0xf28c48, 0x8e85ee, 0x76c84d, 0x5bb6cc, 0x549cdd, 0xd25c99, 0xb37800, 0xf23030,
0x39b249, 0xbb243b, 0x964078, 0x66874f, 0x308ab9, 0x127ed0, 0xbe450c,
];
pub fn dc_str_to_color_safe(s: impl AsRef<str>) -> u32 {
let str_lower = s.as_ref().to_lowercase();
let mut checksum = 0;
let bytes = str_lower.as_bytes();
for i in 0..str_lower.len() {
checksum += (i + 1) * bytes[i] as usize;
checksum %= 0xffffff;
}
let color_index = checksum % COLORS.len();
COLORS[color_index]
}
pub unsafe fn dc_str_to_color(str: *const libc::c_char) -> libc::c_int { pub unsafe fn dc_str_to_color(str: *const libc::c_char) -> libc::c_int {
let str_lower: *mut libc::c_char = dc_strlower(str); let str_lower: *mut libc::c_char = dc_strlower(str);
/* the colors must fulfill some criterions as:
- contrast to black and to white
- work as a text-color
- being noticeable on a typical map
- harmonize together while being different enough
(therefore, we cannot just use random rgb colors :) */
static mut COLORS: [uint32_t; 16] = [
0xe56555i32 as uint32_t,
0xf28c48i32 as uint32_t,
0x8e85eei32 as uint32_t,
0x76c84di32 as uint32_t,
0x5bb6cci32 as uint32_t,
0x549cddi32 as uint32_t,
0xd25c99i32 as uint32_t,
0xb37800i32 as uint32_t,
0xf23030i32 as uint32_t,
0x39b249i32 as uint32_t,
0xbb243bi32 as uint32_t,
0x964078i32 as uint32_t,
0x66874fi32 as uint32_t,
0x308ab9i32 as uint32_t,
0x127ed0i32 as uint32_t,
0xbe450ci32 as uint32_t,
];
let mut checksum: libc::c_int = 0i32; let mut checksum: libc::c_int = 0i32;
let str_len: libc::c_int = strlen(str_lower) as libc::c_int; let str_len: libc::c_int = strlen(str_lower) as libc::c_int;
let mut i: libc::c_int = 0i32; let mut i: libc::c_int = 0i32;

View File

@@ -21,6 +21,7 @@ pub mod aheader;
pub mod chatlist; pub mod chatlist;
pub mod config; pub mod config;
pub mod constants; pub mod constants;
pub mod contact;
pub mod context; pub mod context;
pub mod imap; pub mod imap;
pub mod key; pub mod key;
@@ -39,7 +40,6 @@ pub mod x;
pub mod dc_array; pub mod dc_array;
pub mod dc_chat; pub mod dc_chat;
pub mod dc_configure; pub mod dc_configure;
pub mod dc_contact;
pub mod dc_dehtml; pub mod dc_dehtml;
pub mod dc_e2ee; pub mod dc_e2ee;
pub mod dc_imex; pub mod dc_imex;

View File

@@ -1,12 +1,11 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::ffi::CString;
use strum::EnumProperty; use strum::EnumProperty;
use strum_macros::EnumProperty; use strum_macros::EnumProperty;
use crate::constants::Event; use crate::constants::Event;
use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_contact::*;
use crate::dc_tools::*; use crate::dc_tools::*;
use libc::free; use libc::free;
@@ -200,40 +199,30 @@ impl Context {
from_id: u32, from_id: u32,
) -> String { ) -> String {
let insert1 = if id == StockMessage::MsgAddMember || id == StockMessage::MsgDelMember { let insert1 = if id == StockMessage::MsgAddMember || id == StockMessage::MsgDelMember {
unsafe { let contact_id = Contact::lookup_id_by_addr(self, param1.as_ref());
let param1_c = CString::new(param1.as_ref()).unwrap(); if contact_id != 0 {
let contact_id = dc_lookup_contact_id_by_addr(self, param1_c.as_ptr()); Contact::get_by_id(self, contact_id)
if contact_id != 0 { .map(|contact| contact.get_name_n_addr())
let contact = dc_get_contact(self, contact_id); .unwrap_or_default()
let displayname = dc_contact_get_name_n_addr(contact); } else {
let ret = to_string(displayname); param1.as_ref().to_string()
free(contact as *mut libc::c_void);
free(displayname as *mut libc::c_void);
ret
} else {
param1.as_ref().to_string()
}
} }
} else { } else {
param1.as_ref().to_string() param1.as_ref().to_string()
}; };
let action = self.stock_string_repl_str2(id, insert1, param2.as_ref().to_string()); let action = self.stock_string_repl_str2(id, insert1, param2.as_ref().to_string());
let action1 = action.trim_end_matches('.'); let action1 = action.trim_end_matches('.');
match from_id { match from_id {
0 => action, 0 => action,
1 => self.stock_string_repl_str(StockMessage::MsgActionByMe, action1), // DC_CONTACT_ID_SELF 1 => self.stock_string_repl_str(StockMessage::MsgActionByMe, action1), // DC_CONTACT_ID_SELF
_ => unsafe { _ => {
let contact = dc_get_contact(self, from_id); let displayname = Contact::get_by_id(self, from_id)
let displayname = dc_contact_get_display_name(contact); .map(|contact| contact.get_name_n_addr())
let ret = self.stock_string_repl_str2( .unwrap_or_default();
StockMessage::MsgActionByUser,
action1, self.stock_string_repl_str2(StockMessage::MsgActionByUser, action1, &displayname)
as_str(displayname), }
);
free(contact as *mut libc::c_void);
free(displayname as *mut libc::c_void);
ret
},
} }
} }
} }
@@ -343,11 +332,7 @@ mod tests {
#[test] #[test]
fn test_stock_system_msg_add_member_by_me_with_displayname() { fn test_stock_system_msg_add_member_by_me_with_displayname() {
let t = dummy_context(); let t = dummy_context();
unsafe { Contact::create(&t.ctx, "Alice", "alice@example.com").expect("failed to create contact");
let name = CString::new("Alice").unwrap();
let addr = CString::new("alice@example.com").unwrap();
assert!(dc_create_contact(&t.ctx, name.as_ptr(), addr.as_ptr()) > 0);
}
assert_eq!( assert_eq!(
t.ctx.stock_system_msg( t.ctx.stock_system_msg(
StockMessage::MsgAddMember, StockMessage::MsgAddMember,
@@ -356,23 +341,17 @@ mod tests {
DC_CONTACT_ID_SELF as u32 DC_CONTACT_ID_SELF as u32
), ),
"Member Alice (alice@example.com) added by me." "Member Alice (alice@example.com) added by me."
) );
} }
#[test] #[test]
fn test_stock_system_msg_add_member_by_other_with_displayname() { fn test_stock_system_msg_add_member_by_other_with_displayname() {
let t = dummy_context(); let t = dummy_context();
let contact_id = unsafe { let contact_id = {
let name = CString::new("Alice").unwrap(); Contact::create(&t.ctx, "Alice", "alice@example.com")
let addr = CString::new("alice@example.com").unwrap(); .expect("Failed to create contact Alice");
assert!( let id =
dc_create_contact(&t.ctx, name.as_ptr(), addr.as_ptr()) > 0, Contact::create(&t.ctx, "Bob", "bob@example.com").expect("failed to create bob");
"Failed to create contact Alice"
);
let name = CString::new("Bob").unwrap();
let addr = CString::new("bob@example.com").unwrap();
let id = dc_create_contact(&t.ctx, name.as_ptr(), addr.as_ptr());
assert!(id > 0, "Failed to create contact Bob");
id id
}; };
assert_eq!( assert_eq!(
@@ -382,8 +361,8 @@ mod tests {
"", "",
contact_id, contact_id,
), ),
"Member Alice (alice@example.com) added by Bob." "Member Alice (alice@example.com) added by Bob (bob@example.com)."
) );
} }
#[test] #[test]
@@ -403,21 +382,13 @@ mod tests {
#[test] #[test]
fn test_stock_system_msg_grp_name_other() { fn test_stock_system_msg_grp_name_other() {
let t = dummy_context(); let t = dummy_context();
let contact_id = unsafe { let id = Contact::create(&t.ctx, "Alice", "alice@example.com")
let name = CString::new("Alice").unwrap(); .expect("failed to create contact");
let addr = CString::new("alice@example.com").unwrap();
let id = dc_create_contact(&t.ctx, name.as_ptr(), addr.as_ptr());
assert!(id > 0, "Failed to create contact Alice");
id
};
assert_eq!( assert_eq!(
t.ctx.stock_system_msg( t.ctx
StockMessage::MsgGrpName, .stock_system_msg(StockMessage::MsgGrpName, "Some chat", "Other chat", id,),
"Some chat", "Group name changed from \"Some chat\" to \"Other chat\" by Alice (alice@example.com)."
"Other chat",
contact_id
),
"Group name changed from \"Some chat\" to \"Other chat\" by Alice."
) )
} }
} }

View File

@@ -8,11 +8,11 @@ use tempfile::{tempdir, TempDir};
use deltachat::config; use deltachat::config;
use deltachat::constants::*; use deltachat::constants::*;
use deltachat::contact::*;
use deltachat::context::*; use deltachat::context::*;
use deltachat::dc_array::*; use deltachat::dc_array::*;
use deltachat::dc_chat::*; use deltachat::dc_chat::*;
use deltachat::dc_configure::*; use deltachat::dc_configure::*;
use deltachat::dc_contact::*;
use deltachat::dc_imex::*; use deltachat::dc_imex::*;
use deltachat::dc_location::*; use deltachat::dc_location::*;
use deltachat::dc_lot::*; use deltachat::dc_lot::*;
@@ -890,22 +890,18 @@ fn test_stress_tests() {
fn test_get_contacts() { fn test_get_contacts() {
unsafe { unsafe {
let context = create_test_context(); let context = create_test_context();
let name = CString::yolo("some2"); let contacts = Contact::get_all(&context.ctx, 0, Some("some2")).unwrap();
let contacts = dc_get_contacts(&context.ctx, 0, name.as_ptr());
assert_eq!(dc_array_get_cnt(contacts), 0); assert_eq!(dc_array_get_cnt(contacts), 0);
dc_array_unref(contacts); dc_array_unref(contacts);
let name = CString::yolo("bob"); let id = Contact::create(&context.ctx, "bob", "bob@mail.de").unwrap();
let email = CString::yolo("bob@mail.de");
let id = dc_create_contact(&context.ctx, name.as_ptr(), email.as_ptr());
assert_ne!(id, 0); assert_ne!(id, 0);
let contacts = dc_get_contacts(&context.ctx, 0, name.as_ptr()); let contacts = Contact::get_all(&context.ctx, 0, Some("bob")).unwrap();
assert_eq!(dc_array_get_cnt(contacts), 1); assert_eq!(dc_array_get_cnt(contacts), 1);
dc_array_unref(contacts); dc_array_unref(contacts);
let name2 = CString::yolo("alice"); let contacts = Contact::get_all(&context.ctx, 0, Some("alice")).unwrap();
let contacts = dc_get_contacts(&context.ctx, 0, name2.as_ptr());
assert_eq!(dc_array_get_cnt(contacts), 0); assert_eq!(dc_array_get_cnt(contacts), 0);
dc_array_unref(contacts); dc_array_unref(contacts);
} }
@@ -915,10 +911,7 @@ fn test_get_contacts() {
fn test_chat() { fn test_chat() {
unsafe { unsafe {
let context = create_test_context(); let context = create_test_context();
let name = CString::yolo("bob"); let contact1 = Contact::create(&context.ctx, "bob", "bob@mail.de").unwrap();
let email = CString::yolo("bob@mail.de");
let contact1 = dc_create_contact(&context.ctx, name.as_ptr(), email.as_ptr());
assert_ne!(contact1, 0); assert_ne!(contact1, 0);
let chat_id = dc_create_chat_by_contact_id(&context.ctx, contact1); let chat_id = dc_create_chat_by_contact_id(&context.ctx, contact1);