Compare commits

..

2 Commits

Author SHA1 Message Date
jikstra
42b56cc53e cargo fmt 2019-08-13 00:19:49 +02:00
jikstra
80c727ee9f dc_get_chat_contacts should always return an array and never a null
pointer otherwise we break the ffi interface
2019-08-13 00:17:41 +02:00
22 changed files with 2936 additions and 2562 deletions

9
Cargo.lock generated
View File

@@ -467,7 +467,6 @@ dependencies = [
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
"charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"deltachat_derive 0.1.0",
"failure 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)",
@@ -502,14 +501,6 @@ dependencies = [
"thread-local-object 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "deltachat_derive"
version = "0.1.0"
dependencies = [
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "deltachat_ffi"
version = "1.0.0-alpha.3"

View File

@@ -10,7 +10,6 @@ cc = "1.0.35"
pkg-config = "0.3"
[dependencies]
deltachat_derive = { path = "./deltachat_derive" }
libc = "0.2.51"
pgp = { version = "0.2", default-features = false }
hex = "0.3.2"
@@ -54,8 +53,7 @@ pretty_env_logger = "0.3.0"
[workspace]
members = [
"deltachat-ffi",
"deltachat_derive",
"deltachat-ffi"
]
[[example]]

View File

@@ -89,14 +89,6 @@ $ cargo test --all
$ cargo build -p deltachat_ffi --release
```
### Expensive tests
Some tests are expensive and marked with `#[ignore]`, to run these
use the `--ignored` argument to the test binary (not to cargo itself):
```sh
$ cargo test -- --ignored
```
## Features
- `vendored`: When using Openssl for TLS, this bundles a vendored version.

View File

@@ -545,7 +545,7 @@ pub unsafe extern "C" fn dc_get_chat_contacts(
assert!(!context.is_null());
let context = &*context;
dc_array_t::from(dc_chat::dc_get_chat_contacts(context, chat_id)).into_raw()
dc_chat::dc_get_chat_contacts(context, chat_id)
}
#[no_mangle]
@@ -817,7 +817,7 @@ pub unsafe extern "C" fn dc_get_contacts(
};
match Contact::get_all(context, flags, query) {
Ok(contacts) => dc_array_t::from(contacts).into_raw(),
Ok(contacts) => contacts,
Err(_) => std::ptr::null_mut(),
}
}

View File

@@ -1,12 +0,0 @@
[package]
name = "deltachat_derive"
version = "0.1.0"
authors = ["Dmitry Bogatov <KAction@debian.org>"]
edition = "2018"
[lib]
proc-macro = true
[dependencies]
syn = "0.14.4"
quote = "0.6.3"

View File

@@ -1,45 +0,0 @@
#![recursion_limit = "128"]
extern crate proc_macro;
use crate::proc_macro::TokenStream;
use quote::quote;
use syn;
// For now, assume (not check) that these macroses are applied to enum without
// data. If this assumption is violated, compiler error will point to
// generated code, which is not very user-friendly.
#[proc_macro_derive(ToSql)]
pub fn to_sql_derive(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let name = &ast.ident;
let gen = quote! {
impl rusqlite::types::ToSql for #name {
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
let num = *self as i64;
let value = rusqlite::types::Value::Integer(num);
let output = rusqlite::types::ToSqlOutput::Owned(value);
std::result::Result::Ok(output)
}
}
};
gen.into()
}
#[proc_macro_derive(FromSql)]
pub fn from_sql_derive(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let name = &ast.ident;
let gen = quote! {
impl rusqlite::types::FromSql for #name {
fn column_result(col: rusqlite::types::ValueRef) -> rusqlite::types::FromSqlResult<Self> {
let inner = rusqlite::types::FromSql::column_result(col)?;
num_traits::FromPrimitive::from_i64(inner).ok_or(rusqlite::types::FromSqlError::InvalidType)
}
}
};
gen.into()
}

View File

@@ -125,7 +125,7 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
return 0;
}
let ok_to_continue;
let mut current_block: u64;
let mut success: libc::c_int = 0;
let real_spec: *mut libc::c_char;
let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char;
@@ -138,71 +138,77 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
.sql
.set_config(context, "import_spec", Some(as_str(real_spec)))
.unwrap();
ok_to_continue = true;
current_block = 7149356873433890176;
} else {
let rs = context.sql.get_config(context, "import_spec");
if rs.is_none() {
error!(context, 0, "Import: No file or folder given.");
ok_to_continue = false;
current_block = 8522321847195001863;
} else {
ok_to_continue = true;
current_block = 7149356873433890176;
}
real_spec = rs.unwrap_or_default().strdup();
}
if ok_to_continue {
let ok_to_continue2;
suffix = dc_get_filesuffix_lc(real_spec);
if !suffix.is_null() && strcmp(suffix, b"eml\x00" as *const u8 as *const libc::c_char) == 0
{
if 0 != dc_poke_eml_file(context, real_spec) {
read_cnt += 1
}
ok_to_continue2 = true;
} else {
/* import a directory */
let dir_name = std::path::Path::new(as_str(real_spec));
let dir = std::fs::read_dir(dir_name);
if dir.is_err() {
error!(
context,
0,
"Import: Cannot open directory \"{}\".",
as_str(real_spec),
);
ok_to_continue2 = false;
match current_block {
8522321847195001863 => {}
_ => {
suffix = dc_get_filesuffix_lc(real_spec);
if !suffix.is_null()
&& strcmp(suffix, b"eml\x00" as *const u8 as *const libc::c_char) == 0
{
if 0 != dc_poke_eml_file(context, real_spec) {
read_cnt += 1
}
current_block = 1622411330066726685;
} else {
let dir = dir.unwrap();
for entry in dir {
if entry.is_err() {
break;
}
let entry = entry.unwrap();
let name_f = entry.file_name();
let name = name_f.to_string_lossy();
if name.ends_with(".eml") {
let path_plus_name = format!("{}/{}", as_str(real_spec), name);
info!(context, 0, "Import: {}", path_plus_name);
let path_plus_name_c = CString::yolo(path_plus_name);
if 0 != dc_poke_eml_file(context, path_plus_name_c.as_ptr()) {
read_cnt += 1
/* import a directory */
let dir_name = std::path::Path::new(as_str(real_spec));
let dir = std::fs::read_dir(dir_name);
if dir.is_err() {
error!(
context,
0,
"Import: Cannot open directory \"{}\".",
as_str(real_spec),
);
current_block = 8522321847195001863;
} else {
let dir = dir.unwrap();
for entry in dir {
if entry.is_err() {
break;
}
let entry = entry.unwrap();
let name_f = entry.file_name();
let name = name_f.to_string_lossy();
if name.ends_with(".eml") {
let path_plus_name = format!("{}/{}", as_str(real_spec), name);
info!(context, 0, "Import: {}", path_plus_name);
let path_plus_name_c = CString::yolo(path_plus_name);
if 0 != dc_poke_eml_file(context, path_plus_name_c.as_ptr()) {
read_cnt += 1
}
}
}
current_block = 1622411330066726685;
}
ok_to_continue2 = true;
}
}
if ok_to_continue2 {
info!(
context,
0,
"Import: {} items read from \"{}\".",
read_cnt,
as_str(real_spec)
);
if read_cnt > 0 {
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
match current_block {
8522321847195001863 => {}
_ => {
info!(
context,
0,
"Import: {} items read from \"{}\".",
read_cnt,
as_str(real_spec)
);
if read_cnt > 0 {
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
}
success = 1
}
}
success = 1
}
}
@@ -295,12 +301,13 @@ unsafe fn log_msglist(context: &Context, msglist: *mut dc_array_t) {
}
}
unsafe fn log_contactlist(context: &Context, contacts: &Vec<u32>) {
let mut contacts = contacts.clone();
if !contacts.contains(&1) {
contacts.push(1);
unsafe fn log_contactlist(context: &Context, contacts: *mut dc_array_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);
}
for contact_id in contacts {
let cnt = dc_array_get_cnt(contacts);
for i in 0..cnt {
let contact_id = dc_array_get_id(contacts, i as size_t);
let line;
let mut line2 = "".to_string();
if let Ok(contact) = Contact::get_by_id(context, contact_id) {
@@ -464,7 +471,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
event <event-id to test>\n\
fileinfo <file>\n\
clear -- clear screen\n\
exit or quit\n\
exit\n\
============================================="
),
},
@@ -828,14 +835,16 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
ensure!(!sel_chat.is_null(), "No chat selected.");
let contacts = dc_get_chat_contacts(context, dc_chat_get_id(sel_chat));
ensure!(!contacts.is_null(), "Failed to retreive contacts");
info!(context, 0, "Memberlist:");
log_contactlist(context, &contacts);
log_contactlist(context, contacts);
println!(
"{} contacts\nLocation streaming: {}",
contacts.len(),
dc_array_get_cnt(contacts),
dc_is_sending_locations_to_chat(context, dc_chat_get_id(sel_chat)),
);
dc_array_unref(contacts);
}
"getlocations" => {
let contact_id = arg1.parse().unwrap_or_default();
@@ -1055,8 +1064,13 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
},
Some(arg1),
)?;
log_contactlist(context, &contacts);
println!("{} contacts.", contacts.len());
if !contacts.is_null() {
log_contactlist(context, contacts);
println!("{} contacts.", dc_array_get_cnt(contacts) as libc::c_int,);
dc_array_unref(contacts);
} else {
bail!("");
}
}
"addcontact" => {
ensure!(!arg1.is_empty(), "Arguments [<name>] <addr> expected.");

View File

@@ -335,8 +335,8 @@ const CONTACT_COMMANDS: [&'static str; 6] = [
"delcontact",
"cleanupcontacts",
];
const MISC_COMMANDS: [&'static str; 9] = [
"getqr", "getbadqr", "checkqr", "event", "fileinfo", "clear", "exit", "quit", "help",
const MISC_COMMANDS: [&'static str; 8] = [
"getqr", "getbadqr", "checkqr", "event", "fileinfo", "clear", "exit", "help",
];
impl Hinter for DcHelper {
@@ -550,7 +550,7 @@ unsafe fn handle_cmd(line: &str, ctx: Arc<RwLock<Context>>) -> Result<ExitResult
dc_join_securejoin(&ctx.read().unwrap(), arg1_c);
}
}
"exit" | "quit" => return Ok(ExitResult::Exit),
"exit" => return Ok(ExitResult::Exit),
_ => dc_cmdline(&ctx.read().unwrap(), line)?,
}

View File

@@ -1,11 +1,13 @@
//! Constants
#![allow(non_camel_case_types)]
use deltachat_derive::*;
use num_traits::{FromPrimitive, ToPrimitive};
use rusqlite as sql;
use rusqlite::types::*;
pub const DC_VERSION_STR: &'static [u8; 14] = b"1.0.0-alpha.3\x00";
#[repr(u8)]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql)]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum MoveState {
Undefined = 0,
Pending = 1,
@@ -13,23 +15,20 @@ pub enum MoveState {
Moving = 3,
}
// some defaults
pub const DC_E2EE_DEFAULT_ENABLED: i32 = 1;
pub const DC_MDNS_DEFAULT_ENABLED: i32 = 1;
pub const DC_INBOX_WATCH_DEFAULT: i32 = 1;
pub const DC_SENTBOX_WATCH_DEFAULT: i32 = 1;
pub const DC_MVBOX_WATCH_DEFAULT: i32 = 1;
pub const DC_MVBOX_MOVE_DEFAULT: i32 = 1;
impl ToSql for MoveState {
fn to_sql(&self) -> sql::Result<ToSqlOutput> {
let num = *self as i64;
pub const DC_CHAT_NOT_BLOCKED: i32 = 0;
pub const DC_CHAT_MANUALLY_BLOCKED: i32 = 1;
pub const DC_CHAT_DEADDROP_BLOCKED: i32 = 2;
Ok(ToSqlOutput::Owned(Value::Integer(num)))
}
}
pub const DC_IMAP_SEEN: u32 = 0x1;
pub const DC_HANDSHAKE_CONTINUE_NORMAL_PROCESSING: i32 = 0x01;
pub const DC_HANDSHAKE_STOP_NORMAL_PROCESSING: i32 = 0x02;
pub const DC_HANDSHAKE_ADD_DELETE_JOB: i32 = 0x04;
impl FromSql for MoveState {
fn column_result(col: ValueRef) -> FromSqlResult<Self> {
let inner = FromSql::column_result(col)?;
FromPrimitive::from_i64(inner).ok_or(FromSqlError::InvalidType)
}
}
pub const DC_GCL_ARCHIVED_ONLY: usize = 0x01;
pub const DC_GCL_NO_SPECIALS: usize = 0x02;
@@ -88,6 +87,8 @@ pub const DC_CHAT_TYPE_SINGLE: i32 = 100;
pub const DC_CHAT_TYPE_GROUP: i32 = 120;
pub const DC_CHAT_TYPE_VERIFIED_GROUP: i32 = 130;
pub const DC_CHAT_MAGIC: u32 = 0xc4a7c4a7;
pub const DC_MSG_ID_MARKER1: usize = 1;
pub const DC_MSG_ID_DAYMARKER: usize = 9;
pub const DC_MSG_ID_LAST_SPECIAL: usize = 9;
@@ -167,7 +168,7 @@ pub const DC_LP_IMAP_SOCKET_FLAGS: usize =
pub const DC_LP_SMTP_SOCKET_FLAGS: usize =
(DC_LP_SMTP_SOCKET_STARTTLS | DC_LP_SMTP_SOCKET_SSL | DC_LP_SMTP_SOCKET_PLAIN);
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, FromSql, ToSql)]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
#[repr(i32)]
pub enum Viewtype {
Unknown = 0,
@@ -222,6 +223,23 @@ mod tests {
}
}
impl ToSql for Viewtype {
fn to_sql(&self) -> sql::Result<ToSqlOutput> {
let num: i64 = self
.to_i64()
.expect("impossible: Viewtype -> i64 conversion failed");
Ok(ToSqlOutput::Owned(Value::Integer(num)))
}
}
impl FromSql for Viewtype {
fn column_result(col: ValueRef) -> FromSqlResult<Self> {
let inner = FromSql::column_result(col)?;
FromPrimitive::from_i64(inner).ok_or(FromSqlError::InvalidType)
}
}
// These constants are used as events
// reported to the callback given to dc_context_new().
// If you do not want to handle an event, it is always safe to return 0,

View File

@@ -472,13 +472,13 @@ impl<'a> Contact<'a> {
context: &Context,
listflags: u32,
query: Option<impl AsRef<str>>,
) -> Result<Vec<u32>> {
) -> Result<*mut dc_array_t> {
let self_addr = context
.get_config(Config::ConfiguredAddr)
.unwrap_or_default();
let mut add_self = false;
let mut ret = Vec::new();
let mut ret = dc_array_t::new(100);
if (listflags & DC_GCL_VERIFIED_ONLY) > 0 || query.is_some() {
let s3str_like_cmd = format!(
@@ -509,7 +509,7 @@ impl<'a> Contact<'a> {
|row| row.get::<_, i32>(0),
|ids| {
for id in ids {
ret.push(id? as u32);
ret.add_id(id? as u32);
}
Ok(())
},
@@ -537,7 +537,7 @@ impl<'a> Contact<'a> {
|row| row.get::<_, i32>(0),
|ids| {
for id in ids {
ret.push(id? as u32);
ret.add_id(id? as u32);
}
Ok(())
}
@@ -545,10 +545,10 @@ impl<'a> Contact<'a> {
}
if 0 != listflags & DC_GCL_ADD_SELF as u32 && add_self {
ret.push(DC_CONTACT_ID_SELF as u32);
ret.add_id(DC_CONTACT_ID_SELF as u32);
}
Ok(ret)
Ok(ret.into_raw())
}
pub fn get_blocked_cnt(context: &Context) -> usize {
@@ -572,13 +572,13 @@ impl<'a> Contact<'a> {
params![DC_CONTACT_ID_LAST_SPECIAL as i32],
|row| row.get::<_, i32>(0),
|ids| {
let mut ret = Vec::new();
let mut ret = dc_array_t::new(100);
for id in ids {
ret.push(id? as u32);
ret.add_id(id? as u32);
}
Ok(dc_array_t::from(ret).into_raw())
Ok(ret.into_raw())
},
)
.unwrap_or_else(|_| std::ptr::null_mut())

View File

@@ -39,8 +39,6 @@ pub struct Context {
pub bob: Arc<RwLock<BobStatus>>,
pub last_smeared_timestamp: Arc<RwLock<i64>>,
pub running_state: Arc<RwLock<RunningState>>,
/// Mutex to avoid generating the key for the user more than once.
pub generating_key_mutex: Mutex<()>,
}
unsafe impl std::marker::Send for Context {}
@@ -171,7 +169,6 @@ pub fn dc_context_new(
))),
probe_imap_network: Arc::new(RwLock::new(false)),
perform_inbox_jobs_needed: Arc::new(RwLock::new(false)),
generating_key_mutex: Mutex::new(()),
}
}
@@ -499,12 +496,13 @@ pub fn dc_get_fresh_msgs(context: &Context) -> *mut dc_array_t {
&[10, 9, if 0 != show_deaddrop { 2 } else { 0 }],
|row| row.get(0),
|rows| {
let mut ret = Vec::new();
let mut ret = dc_array_t::new(128);
for row in rows {
let id: u32 = row?;
ret.push(id);
let id = row?;
ret.add_id(id);
}
Ok(dc_array_t::from(ret).into_raw())
Ok(ret.into_raw())
},
)
.unwrap()
@@ -538,7 +536,7 @@ pub fn dc_search_msgs(
AND ct.blocked=0 AND (m.txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp DESC,m.id DESC;"
};
let mut ret = Vec::new();
let mut ret = dc_array_t::new(100);
let success = context
.sql
@@ -548,7 +546,7 @@ pub fn dc_search_msgs(
|row| row.get::<_, i32>(0),
|rows| {
for id in rows {
ret.push(id? as u32);
ret.add_id(id? as u32);
}
Ok(())
},
@@ -556,7 +554,7 @@ pub fn dc_search_msgs(
.is_ok();
if success {
return dc_array_t::from(ret).into_raw();
return ret.into_raw();
}
std::ptr::null_mut()

View File

@@ -147,12 +147,6 @@ impl dc_array_t {
}
}
impl From<Vec<u32>> for dc_array_t {
fn from(array: Vec<u32>) -> Self {
dc_array_t::Uint(array.iter().map(|&x| x as uintptr_t).collect())
}
}
impl From<Vec<dc_location>> for dc_array_t {
fn from(array: Vec<dc_location>) -> Self {
dc_array_t::Locations(array)
@@ -160,18 +154,22 @@ impl From<Vec<dc_location>> for dc_array_t {
}
pub unsafe fn dc_array_unref(array: *mut dc_array_t) {
assert!(!array.is_null());
if array.is_null() {
return;
}
Box::from_raw(array);
}
pub unsafe fn dc_array_add_uint(array: *mut dc_array_t, item: uintptr_t) {
assert!(!array.is_null());
(*array).add_uint(item);
if !array.is_null() {
(*array).add_uint(item);
}
}
pub unsafe fn dc_array_add_id(array: *mut dc_array_t, item: uint32_t) {
assert!(!array.is_null());
(*array).add_id(item);
if !array.is_null() {
(*array).add_id(item);
}
}
pub unsafe fn dc_array_add_ptr(array: *mut dc_array_t, item: *mut libc::c_void) {
@@ -179,62 +177,97 @@ pub unsafe fn dc_array_add_ptr(array: *mut dc_array_t, item: *mut libc::c_void)
}
pub unsafe fn dc_array_get_cnt(array: *const dc_array_t) -> size_t {
assert!(!array.is_null());
(*array).len()
if array.is_null() {
0
} else {
(*array).len()
}
}
pub unsafe fn dc_array_get_uint(array: *const dc_array_t, index: size_t) -> uintptr_t {
assert!(!array.is_null());
(*array).get_uint(index)
if array.is_null() || index >= (*array).len() {
0
} else {
(*array).get_uint(index)
}
}
pub unsafe fn dc_array_get_id(array: *const dc_array_t, index: size_t) -> uint32_t {
assert!(!array.is_null());
(*array).get_id(index)
if array.is_null() || index >= (*array).len() {
0
} else {
(*array).get_id(index)
}
}
pub unsafe fn dc_array_get_ptr(array: *const dc_array_t, index: size_t) -> *mut libc::c_void {
assert!(!array.is_null());
(*array).get_ptr(index)
if array.is_null() || index >= (*array).len() {
std::ptr::null_mut()
} else {
(*array).get_ptr(index)
}
}
pub unsafe fn dc_array_get_latitude(array: *const dc_array_t, index: size_t) -> libc::c_double {
assert!(!array.is_null());
(*array).get_latitude(index)
if array.is_null() || index >= (*array).len() {
0.0
} else {
(*array).get_latitude(index)
}
}
pub unsafe fn dc_array_get_longitude(array: *const dc_array_t, index: size_t) -> libc::c_double {
assert!(!array.is_null());
(*array).get_longitude(index)
if array.is_null() || index >= (*array).len() {
0.0
} else {
(*array).get_longitude(index)
}
}
pub unsafe fn dc_array_get_accuracy(array: *const dc_array_t, index: size_t) -> libc::c_double {
assert!(!array.is_null());
(*array).get_accuracy(index)
if array.is_null() || index >= (*array).len() {
0.0
} else {
(*array).get_accuracy(index)
}
}
pub unsafe fn dc_array_get_timestamp(array: *const dc_array_t, index: size_t) -> i64 {
assert!(!array.is_null());
(*array).get_timestamp(index)
if array.is_null() || index >= (*array).len() {
0
} else {
(*array).get_timestamp(index)
}
}
pub unsafe fn dc_array_get_chat_id(array: *const dc_array_t, index: size_t) -> uint32_t {
assert!(!array.is_null());
(*array).get_chat_id(index)
if array.is_null() || index >= (*array).len() {
0
} else {
(*array).get_chat_id(index)
}
}
pub unsafe fn dc_array_get_contact_id(array: *const dc_array_t, index: size_t) -> uint32_t {
assert!(!array.is_null());
(*array).get_contact_id(index)
if array.is_null() || index >= (*array).len() {
0
} else {
(*array).get_contact_id(index)
}
}
pub unsafe fn dc_array_get_msg_id(array: *const dc_array_t, index: size_t) -> uint32_t {
assert!(!array.is_null());
(*array).get_msg_id(index)
if array.is_null() || index >= (*array).len() {
0
} else {
(*array).get_msg_id(index)
}
}
pub unsafe fn dc_array_get_marker(array: *const dc_array_t, index: size_t) -> *mut libc::c_char {
assert!(!array.is_null());
if array.is_null() || index >= (*array).len() {
return std::ptr::null_mut();
}
if let dc_array_t::Locations(v) = &*array {
if let Some(s) = &v[index].marker {
@@ -243,7 +276,7 @@ pub unsafe fn dc_array_get_marker(array: *const dc_array_t, index: size_t) -> *m
std::ptr::null_mut()
}
} else {
panic!("Not an array of locations");
std::ptr::null_mut()
}
}
@@ -258,7 +291,9 @@ pub unsafe fn dc_array_get_marker(array: *const dc_array_t, index: size_t) -> *m
* 1=Location was reported independently.
*/
pub unsafe fn dc_array_is_independent(array: *const dc_array_t, index: size_t) -> libc::c_int {
assert!(!array.is_null());
if array.is_null() || index >= (*array).len() {
return 0;
}
if let dc_array_t::Locations(v) = &*array {
v[index].independent as libc::c_int
@@ -272,8 +307,9 @@ pub unsafe fn dc_array_search_id(
needle: uint32_t,
ret_index: *mut size_t,
) -> bool {
assert!(!array.is_null());
if array.is_null() {
return false;
}
if let Some(i) = (*array).search_id(needle as uintptr_t) {
if !ret_index.is_null() {
*ret_index = i
@@ -285,8 +321,9 @@ pub unsafe fn dc_array_search_id(
}
pub unsafe fn dc_array_get_raw(array: *const dc_array_t) -> *const uintptr_t {
assert!(!array.is_null());
if array.is_null() {
return 0 as *const uintptr_t;
}
if let dc_array_t::Uint(v) = &*array {
v.as_ptr()
} else {
@@ -303,24 +340,27 @@ pub fn dc_array_new_locations(initsize: size_t) -> *mut dc_array_t {
}
pub unsafe fn dc_array_empty(array: *mut dc_array_t) {
assert!(!array.is_null());
if array.is_null() {
return;
}
(*array).clear()
}
pub unsafe fn dc_array_duplicate(array: *const dc_array_t) -> *mut dc_array_t {
assert!(!array.is_null());
(*array).clone().into_raw()
if array.is_null() {
std::ptr::null_mut()
} else {
(*array).clone().into_raw()
}
}
pub unsafe fn dc_array_get_string(
array: *const dc_array_t,
sep: *const libc::c_char,
) -> *mut libc::c_char {
assert!(!array.is_null());
assert!(!sep.is_null());
if array.is_null() || sep.is_null() {
return dc_strdup(b"\x00" as *const u8 as *const libc::c_char);
}
if let dc_array_t::Uint(v) = &*array {
let cnt = v.len();
let sep = as_str(sep);
@@ -366,6 +406,10 @@ mod tests {
);
}
assert_eq!(dc_array_get_id(arr, -1i32 as size_t), 0);
assert_eq!(dc_array_get_id(arr, 1000 as size_t), 0);
assert_eq!(dc_array_get_id(arr, 1001 as size_t), 0);
dc_array_empty(arr);
assert_eq!(dc_array_get_cnt(arr), 0);
@@ -393,15 +437,4 @@ mod tests {
dc_array_unref(arr);
}
}
#[test]
#[should_panic]
fn test_dc_array_out_of_bounds() {
let arr = dc_array_new(7);
for i in 0..1000 {
unsafe { dc_array_add_id(arr, (i + 2) as uint32_t) };
}
unsafe { dc_array_get_id(arr, 1000) };
}
}

View File

@@ -24,6 +24,7 @@ use crate::x::*;
*/
#[derive(Clone)]
pub struct Chat<'a> {
magic: u32,
pub id: uint32_t,
pub type_0: libc::c_int,
pub name: *mut libc::c_char,
@@ -64,6 +65,7 @@ pub unsafe fn dc_create_chat_by_msg_id(context: &Context, msg_id: uint32_t) -> u
pub unsafe fn dc_chat_new<'a>(context: &'a Context) -> *mut Chat<'a> {
let chat = Chat {
magic: DC_CHAT_MAGIC,
id: 0,
type_0: 0,
name: std::ptr::null_mut(),
@@ -79,16 +81,17 @@ pub unsafe fn dc_chat_new<'a>(context: &'a Context) -> *mut Chat<'a> {
Box::into_raw(Box::new(chat))
}
pub unsafe fn dc_chat_unref(chat: *mut Chat) {
if chat.is_null() {
pub unsafe fn dc_chat_unref(mut chat: *mut Chat) {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return;
}
dc_chat_empty(chat);
(*chat).magic = 0;
Box::from_raw(chat);
}
pub unsafe fn dc_chat_empty(mut chat: *mut Chat) {
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return;
}
free((*chat).name as *mut libc::c_void);
@@ -117,7 +120,7 @@ pub fn dc_block_chat(context: &Context, chat_id: u32, new_blocking: libc::c_int)
}
pub fn dc_chat_load_from_db(chat: *mut Chat, chat_id: u32) -> bool {
if chat.is_null() {
if chat.is_null() || unsafe { (*chat).magic != DC_CHAT_MAGIC } {
return false;
}
unsafe { dc_chat_empty(chat) };
@@ -807,7 +810,7 @@ unsafe fn get_parent_mime_headers(
}
pub unsafe fn dc_chat_is_self_talk(chat: *const Chat) -> libc::c_int {
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return 0;
}
(*chat).param.exists(Param::Selftalk) as libc::c_int
@@ -1069,7 +1072,7 @@ pub fn dc_get_chat_msgs(
flags: uint32_t,
marker1before: uint32_t,
) -> *mut dc_array_t {
let mut ret = Vec::new();
let mut ret = dc_array_t::new(512);
let mut last_day = 0;
let cnv_to_local = dc_gm2local_offset();
@@ -1079,17 +1082,17 @@ pub fn dc_get_chat_msgs(
for row in rows {
let (curr_id, ts) = row?;
if curr_id as u32 == marker1before {
ret.push(DC_MSG_ID_MARKER1 as u32);
ret.add_id(1);
}
if 0 != flags & 0x1 {
let curr_local_timestamp = ts + cnv_to_local;
let curr_day = (curr_local_timestamp / 86400) as libc::c_int;
if curr_day != last_day {
ret.push(DC_MSG_ID_LAST_SPECIAL as u32);
ret.add_id(9);
last_day = curr_day;
}
}
ret.push(curr_id as u32);
ret.add_id(curr_id as u32);
}
Ok(())
};
@@ -1137,7 +1140,7 @@ pub fn dc_get_chat_msgs(
};
if success.is_ok() {
dc_array_t::from(ret).into_raw()
ret.into_raw()
} else {
0 as *mut dc_array_t
}
@@ -1250,11 +1253,11 @@ pub fn dc_get_chat_media(
],
|row| row.get::<_, i32>(0),
|ids| {
let mut ret = Vec::new();
let mut ret = dc_array_t::new(100);
for id in ids {
ret.push(id? as u32);
ret.add_id(id? as u32);
}
Ok(dc_array_t::from(ret).into_raw())
Ok(ret.into_raw())
}
).unwrap_or_else(|_| std::ptr::null_mut())
}
@@ -1403,28 +1406,42 @@ pub fn dc_delete_chat(context: &Context, chat_id: u32) -> bool {
true
}
pub fn dc_get_chat_contacts(context: &Context, chat_id: u32) -> Vec<u32> {
pub fn dc_get_chat_contacts(context: &Context, chat_id: u32) -> *mut dc_array_t {
/* Normal chats do not include SELF. Group chats do (as it may happen that one is deleted from a
groupchat but the chats stays visible, moreover, this makes displaying lists easier) */
if chat_id == 1 {
return Vec::new();
let ret = if chat_id != 1 {
// we could also create a list for all contacts in the deaddrop by searching contacts belonging to chats with
// chats.blocked=2, however, currently this is not needed
context
.sql
.query_map(
"SELECT cc.contact_id FROM chats_contacts cc \
LEFT JOIN contacts c ON c.id=cc.contact_id WHERE cc.chat_id=? \
ORDER BY c.id=1, LOWER(c.name||c.addr), c.id;",
params![chat_id as i32],
|row| row.get::<_, i32>(0),
|ids| {
let mut ret = dc_array_t::new(100);
for id in ids {
ret.add_id(id? as u32);
}
Ok(ret.into_raw())
},
)
.ok()
} else {
None
};
if let Some(chat_contacts) = ret {
chat_contacts
} else {
dc_array_t::new(0).into_raw()
}
// we could also create a list for all contacts in the deaddrop by searching contacts belonging to chats with
// chats.blocked=2, however, currently this is not needed
context
.sql
.query_map(
"SELECT cc.contact_id FROM chats_contacts cc \
LEFT JOIN contacts c ON c.id=cc.contact_id WHERE cc.chat_id=? \
ORDER BY c.id=1, LOWER(c.name||c.addr), c.id;",
params![chat_id],
|row| row.get::<_, u32>(0),
|ids| ids.collect::<Result<Vec<_>, _>>().map_err(Into::into),
)
.unwrap_or_default()
}
pub unsafe fn dc_get_chat(context: &Context, chat_id: uint32_t) -> *mut Chat {
@@ -2009,21 +2026,21 @@ pub unsafe fn dc_forward_msgs(
}
pub unsafe fn dc_chat_get_id(chat: *const Chat) -> uint32_t {
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return 0i32 as uint32_t;
}
(*chat).id
}
pub unsafe fn dc_chat_get_type(chat: *const Chat) -> libc::c_int {
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return 0i32;
}
(*chat).type_0
}
pub unsafe fn dc_chat_get_name(chat: *const Chat) -> *mut libc::c_char {
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char);
}
dc_strdup((*chat).name)
@@ -2031,7 +2048,7 @@ pub unsafe fn dc_chat_get_name(chat: *const Chat) -> *mut libc::c_char {
pub unsafe fn dc_chat_get_subtitle(chat: *const Chat) -> *mut libc::c_char {
/* returns either the address or the number of chat members */
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char);
}
@@ -2088,8 +2105,9 @@ pub fn dc_get_chat_contact_cnt(context: &Context, chat_id: u32) -> libc::c_int {
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_abs: *mut libc::c_char = 0 as *mut libc::c_char;
let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t;
if !chat.is_null() {
if !(chat.is_null() || (*chat).magic != DC_CHAT_MAGIC) {
image_rel = (*chat)
.param
.get(Param::ProfileImage)
@@ -2098,9 +2116,9 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char
if !image_rel.is_null() && 0 != *image_rel.offset(0isize) as libc::c_int {
image_abs = dc_get_abs_path((*chat).context, image_rel)
} else if (*chat).type_0 == DC_CHAT_TYPE_SINGLE {
let contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
if !contacts.is_empty() {
if let Ok(contact) = Contact::get_by_id((*chat).context, contacts[0]) {
contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
if !(*contacts).is_empty() {
if let Ok(contact) = Contact::get_by_id((*chat).context, (*contacts).get_id(0)) {
if let Some(img) = contact.get_profile_image() {
image_abs = img.strdup();
}
@@ -2110,18 +2128,20 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char
}
free(image_rel as *mut libc::c_void);
dc_array_unref(contacts);
image_abs
}
pub unsafe fn dc_chat_get_color(chat: *const Chat) -> uint32_t {
let mut color: uint32_t = 0i32 as uint32_t;
let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t;
if !chat.is_null() {
if !(chat.is_null() || (*chat).magic != DC_CHAT_MAGIC) {
if (*chat).type_0 == DC_CHAT_TYPE_SINGLE {
let contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
if !contacts.is_empty() {
if let Ok(contact) = Contact::get_by_id((*chat).context, contacts[0]) {
contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
if !(*contacts).is_empty() {
if let Ok(contact) = Contact::get_by_id((*chat).context, (*contacts).get_id(0)) {
color = contact.get_color();
}
}
@@ -2130,12 +2150,14 @@ pub unsafe fn dc_chat_get_color(chat: *const Chat) -> uint32_t {
}
}
dc_array_unref(contacts);
color
}
// TODO should return bool /rtn
pub unsafe fn dc_chat_get_archived(chat: *const Chat) -> libc::c_int {
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return 0i32;
}
(*chat).archived
@@ -2143,7 +2165,7 @@ pub unsafe fn dc_chat_get_archived(chat: *const Chat) -> libc::c_int {
// TODO should return bool /rtn
pub unsafe fn dc_chat_is_unpromoted(chat: *const Chat) -> libc::c_int {
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return 0;
}
(*chat).param.get_int(Param::Unpromoted).unwrap_or_default() as libc::c_int
@@ -2151,7 +2173,7 @@ pub unsafe fn dc_chat_is_unpromoted(chat: *const Chat) -> libc::c_int {
// TODO should return bool /rtn
pub unsafe fn dc_chat_is_verified(chat: *const Chat) -> libc::c_int {
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return 0i32;
}
((*chat).type_0 == 130i32) as libc::c_int
@@ -2159,7 +2181,7 @@ pub unsafe fn dc_chat_is_verified(chat: *const Chat) -> libc::c_int {
// TODO should return bool /rtn
pub unsafe fn dc_chat_is_sending_locations(chat: *const Chat) -> libc::c_int {
if chat.is_null() {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
return 0i32;
}
(*chat).is_sending_locations

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
//! End-to-end encryption support.
use std::collections::HashSet;
use std::ffi::CStr;
use std::str::FromStr;
@@ -100,11 +98,9 @@ pub unsafe fn dc_e2ee_encrypt(
let addr = context.sql.get_config(context, "configured_addr");
if let Some(addr) = addr {
let pubkey_ret = load_or_generate_self_public_key(context, &addr).map_err(|err| {
error!(context, 0, "Failed to load public key: {}", err);
err
});
if let Ok(public_key) = pubkey_ret {
if let Some(public_key) =
load_or_generate_self_public_key(context, &addr, in_out_message)
{
/*only for random-seed*/
if prefer_encrypt == EncryptPreference::Mutual || 0 != e2ee_guaranteed {
do_encrypt = 1i32;
@@ -479,52 +475,65 @@ unsafe fn new_data_part(
return 0 as *mut mailmime;
}
/// Load public key from database or generate a new one.
///
/// This will load a public key from the database, generating and
/// storing a new one when one doesn't exist yet. Care is taken to
/// only generate one key per context even when multiple threads call
/// this function concurrently.
fn load_or_generate_self_public_key(context: &Context, self_addr: impl AsRef<str>) -> Result<Key> {
if let Some(key) = Key::from_self_public(context, &self_addr, &context.sql) {
return Ok(key);
}
let _guard = context.generating_key_mutex.lock().unwrap();
/*******************************************************************************
* Generate Keypairs
******************************************************************************/
unsafe fn load_or_generate_self_public_key(
context: &Context,
self_addr: impl AsRef<str>,
_random_data_mime: *mut mailmime,
) -> Option<Key> {
/* avoid double creation (we unlock the database during creation) */
static mut S_IN_KEY_CREATION: libc::c_int = 0;
// Check again in case the key was generated while we were waiting for the lock.
if let Some(key) = Key::from_self_public(context, &self_addr, &context.sql) {
return Ok(key);
let mut key = Key::from_self_public(context, &self_addr, &context.sql);
if key.is_some() {
return key;
}
let start = std::time::Instant::now();
/* create the keypair - this may take a moment, however, as this is in a thread, this is no big deal */
if 0 != S_IN_KEY_CREATION {
return None;
}
let key_creation_here = 1;
S_IN_KEY_CREATION = 1;
let start = clock();
info!(
context,
0, "Generating keypair with {} bits, e={} ...", 2048, 65537,
);
match dc_pgp_create_keypair(&self_addr) {
Some((public_key, private_key)) => {
match dc_key_save_self_keypair(
if let Some((public_key, private_key)) = dc_pgp_create_keypair(&self_addr) {
if !dc_key_save_self_keypair(
context,
&public_key,
&private_key,
&self_addr,
1i32,
&context.sql,
) {
/*set default*/
warn!(context, 0, "Cannot save keypair.",);
} else {
info!(
context,
&public_key,
&private_key,
&self_addr,
1,
&context.sql,
) {
true => {
info!(
context,
0,
"Keypair generated in {:.3}s.",
start.elapsed().as_secs()
);
Ok(public_key)
}
false => Err(format_err!("Failed to save keypair")),
}
0,
"Keypair generated in {:.3}s.",
clock().wrapping_sub(start) as libc::c_double / 1000000 as libc::c_double,
);
}
None => Err(format_err!("Failed to generate keypair")),
key = Some(public_key);
} else {
warn!(context, 0, "Cannot create keypair.");
}
if 0 != key_creation_here {
S_IN_KEY_CREATION = 0;
}
key
}
/* returns 1 if sth. was decrypted, 0 in other cases */
@@ -544,18 +553,20 @@ pub unsafe fn dc_e2ee_decrypt(
let mut public_keyring_for_validate = Keyring::default();
let mut gossip_headers: *mut mailimf_fields = 0 as *mut mailimf_fields;
if !(in_out_message.is_null() || imffields.is_null()) {
let mut field: *mut mailimf_field =
mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int);
if !field.is_null() && !(*field).fld_data.fld_from.is_null() {
from = mailimf_find_first_addr((*(*field).fld_data.fld_from).frm_mb_list)
}
field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int);
if !field.is_null() && !(*field).fld_data.fld_orig_date.is_null() {
let orig_date: *mut mailimf_orig_date = (*field).fld_data.fld_orig_date;
if !orig_date.is_null() {
message_time = dc_timestamp_from_date((*orig_date).dt_date_time);
if message_time != 0 && message_time > time() {
message_time = time()
if !imffields.is_null() {
let mut field: *mut mailimf_field =
mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int);
if !field.is_null() && !(*field).fld_data.fld_from.is_null() {
from = mailimf_find_first_addr((*(*field).fld_data.fld_from).frm_mb_list)
}
field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int);
if !field.is_null() && !(*field).fld_data.fld_orig_date.is_null() {
let orig_date: *mut mailimf_orig_date = (*field).fld_data.fld_orig_date;
if !orig_date.is_null() {
message_time = dc_timestamp_from_date((*orig_date).dt_date_time);
if message_time != 0 && message_time > time() {
message_time = time()
}
}
}
}
@@ -1039,7 +1050,8 @@ pub unsafe fn dc_e2ee_thanks(helper: &mut dc_e2ee_helper_t) {
/// Ensures a private key exists for the configured user.
///
/// Normally the private key is generated when the first message is
/// sent but in a few locations there are no such guarantees,
/// sent (allowing the use of some extra random seed from the message
/// content) but in a few locations there are no such guarantees,
/// e.g. when exporting keys, and calling this function ensures a
/// private key will be present.
///
@@ -1052,7 +1064,10 @@ pub fn dc_ensure_secret_key_exists(context: &Context) -> Result<String> {
"Failed to get self address, ",
"cannot ensure secret key if not configured."
)))?;
load_or_generate_self_public_key(context, &self_addr)?;
unsafe {
load_or_generate_self_public_key(context, &self_addr, 0 as *mut mailmime)
.ok_or(format_err!("Failed to generate private key."))?;
}
Ok(self_addr)
}
@@ -1139,47 +1154,4 @@ Sent with my Delta Chat Messenger: https://delta.chat";
unsafe { free(decrypted_mime as *mut _) };
}
mod load_or_generate_self_public_key {
use super::*;
#[test]
fn test_existing() {
let t = dummy_context();
let addr = configure_alice_keypair(&t.ctx);
let key = load_or_generate_self_public_key(&t.ctx, addr);
assert!(key.is_ok());
}
#[test]
#[ignore] // generating keys is expensive
fn test_generate() {
let t = dummy_context();
let addr = "alice@example.org";
let key0 = load_or_generate_self_public_key(&t.ctx, addr);
assert!(key0.is_ok());
let key1 = load_or_generate_self_public_key(&t.ctx, addr);
assert!(key1.is_ok());
assert_eq!(key0.unwrap(), key1.unwrap());
}
#[test]
#[ignore]
fn test_generate_concurrent() {
use std::sync::Arc;
use std::thread;
let t = dummy_context();
let ctx = Arc::new(t.ctx);
let ctx0 = Arc::clone(&ctx);
let thr0 =
thread::spawn(move || load_or_generate_self_public_key(&ctx0, "alice@example.org"));
let ctx1 = Arc::clone(&ctx);
let thr1 =
thread::spawn(move || load_or_generate_self_public_key(&ctx1, "alice@example.org"));
let res0 = thr0.join().unwrap();
let res1 = thr1.join().unwrap();
assert_eq!(res0.unwrap(), res1.unwrap());
}
}
}

View File

@@ -292,7 +292,7 @@ unsafe fn dc_suspend_smtp_thread(context: &Context, suspend: bool) {
#[allow(non_snake_case)]
unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) {
let ok_to_continue;
let mut current_block: u64;
let mut filename: *mut libc::c_char = 0 as *mut libc::c_char;
let mut buf: *mut libc::c_void = 0 as *mut libc::c_void;
let mut buf_bytes: size_t = 0i32 as size_t;
@@ -304,89 +304,101 @@ unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) {
if !connected {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
ok_to_continue = false;
current_block = 14216916617354591294;
} else {
ok_to_continue = true;
current_block = 13109137661213826276;
}
} else {
ok_to_continue = true;
current_block = 13109137661213826276;
}
if ok_to_continue {
let filename_s = job.param.get(Param::File).unwrap_or_default();
filename = filename_s.strdup();
if strlen(filename) == 0 {
warn!(context, 0, "Missing file name for job {}", job.job_id,);
} else if !(0 == dc_read_file(context, filename, &mut buf, &mut buf_bytes)) {
let recipients = job.param.get(Param::Recipients);
if recipients.is_none() {
warn!(context, 0, "Missing recipients for job {}", job.job_id,);
} else {
let recipients_list = recipients
.unwrap()
.split("\x1e")
.filter_map(|addr| match lettre::EmailAddress::new(addr.to_string()) {
Ok(addr) => Some(addr),
Err(err) => {
eprintln!("WARNING: invalid recipient: {} {:?}", addr, err);
None
}
})
.collect::<Vec<_>>();
/* if there is a msg-id and it does not exist in the db, cancel sending.
this happends if dc_delete_msgs() was called
before the generated mime was sent out */
let ok_to_continue1;
if 0 != job.foreign_id {
if 0 == dc_msg_exists(context, job.foreign_id) {
warn!(
context,
0, "Message {} for job {} does not exist", job.foreign_id, job.job_id,
);
ok_to_continue1 = false;
} else {
ok_to_continue1 = true;
}
match current_block {
13109137661213826276 => {
let filename_s = job.param.get(Param::File).unwrap_or_default();
filename = filename_s.strdup();
if strlen(filename) == 0 {
warn!(context, 0, "Missing file name for job {}", job.job_id,);
} else if !(0 == dc_read_file(context, filename, &mut buf, &mut buf_bytes)) {
let recipients = job.param.get(Param::Recipients);
if recipients.is_none() {
warn!(context, 0, "Missing recipients for job {}", job.job_id,);
} else {
ok_to_continue1 = true;
}
if ok_to_continue1 {
/* send message */
let body = std::slice::from_raw_parts(buf as *const u8, buf_bytes).to_vec();
if 0 == context
.smtp
.lock()
let recipients_list = recipients
.unwrap()
.send(context, recipients_list, body)
{
context.smtp.lock().unwrap().disconnect();
dc_job_try_again_later(
job,
-1i32,
(*&mut context.smtp.clone().lock().unwrap()).error,
);
} else {
dc_delete_file(context, filename_s);
if 0 != job.foreign_id {
dc_update_msg_state(context, job.foreign_id, DC_STATE_OUT_DELIVERED);
let chat_id: i32 = context
.sql
.query_row_col(
context,
"SELECT chat_id FROM msgs WHERE id=?",
params![job.foreign_id as i32],
0,
)
.unwrap_or_default();
context.call_cb(
Event::MSG_DELIVERED,
chat_id as uintptr_t,
job.foreign_id as uintptr_t,
.split("\x1e")
.filter_map(|addr| match lettre::EmailAddress::new(addr.to_string()) {
Ok(addr) => Some(addr),
Err(err) => {
eprintln!("WARNING: invalid recipient: {} {:?}", addr, err);
None
}
})
.collect::<Vec<_>>();
/* if there is a msg-id and it does not exist in the db, cancel sending.
this happends if dc_delete_msgs() was called
before the generated mime was sent out */
if 0 != job.foreign_id {
if 0 == dc_msg_exists(context, job.foreign_id) {
warn!(
context,
0,
"Message {} for job {} does not exist",
job.foreign_id,
job.job_id,
);
current_block = 14216916617354591294;
} else {
current_block = 11194104282611034094;
}
} else {
current_block = 11194104282611034094;
}
match current_block {
14216916617354591294 => {}
_ => {
/* send message */
let body =
std::slice::from_raw_parts(buf as *const u8, buf_bytes).to_vec();
if 0 == context.smtp.lock().unwrap().send(
context,
recipients_list,
body,
) {
context.smtp.lock().unwrap().disconnect();
dc_job_try_again_later(
job,
-1i32,
(*&mut context.smtp.clone().lock().unwrap()).error,
);
} else {
dc_delete_file(context, filename_s);
if 0 != job.foreign_id {
dc_update_msg_state(
context,
job.foreign_id,
DC_STATE_OUT_DELIVERED,
);
let chat_id: i32 = context
.sql
.query_row_col(
context,
"SELECT chat_id FROM msgs WHERE id=?",
params![job.foreign_id as i32],
0,
)
.unwrap_or_default();
context.call_cb(
Event::MSG_DELIVERED,
chat_id as uintptr_t,
job.foreign_id as uintptr_t,
);
}
}
}
}
}
}
}
_ => {}
}
free(buf);
free(filename as *mut libc::c_void);
@@ -405,7 +417,7 @@ pub unsafe fn dc_job_try_again_later(
#[allow(non_snake_case)]
unsafe fn dc_job_do_DC_JOB_MOVE_MSG(context: &Context, job: &mut dc_job_t) {
let ok_to_continue;
let mut current_block: u64;
let msg = dc_msg_new_untyped(context);
let mut dest_uid: uint32_t = 0i32 as uint32_t;
@@ -415,46 +427,75 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(context: &Context, job: &mut dc_job_t) {
connect_to_inbox(context, &inbox);
if !inbox.is_connected() {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
ok_to_continue = false;
current_block = 2238328302157162973;
} else {
ok_to_continue = true;
current_block = 2473556513754201174;
}
} else {
ok_to_continue = true;
current_block = 2473556513754201174;
}
if ok_to_continue {
if dc_msg_load_from_db(msg, context, job.foreign_id) {
if context
.sql
.get_config_int(context, "folders_configured")
.unwrap_or_default()
< 3
{
inbox.configure_folders(context, 0x1i32);
}
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
if let Some(dest_folder) = dest_folder {
let server_folder = (*msg).server_folder.as_ref().unwrap();
match inbox.mv(
context,
server_folder,
(*msg).server_uid,
&dest_folder,
&mut dest_uid,
) as libc::c_uint
match current_block {
2473556513754201174 => {
if dc_msg_load_from_db(msg, context, job.foreign_id) {
if context
.sql
.get_config_int(context, "folders_configured")
.unwrap_or_default()
< 3
{
1 => {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
inbox.configure_folders(context, 0x1i32);
}
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
if let Some(dest_folder) = dest_folder {
let server_folder = (*msg).server_folder.as_ref().unwrap();
match inbox.mv(
context,
server_folder,
(*msg).server_uid,
&dest_folder,
&mut dest_uid,
) as libc::c_uint
{
1 => {
current_block = 6379107252614456477;
match current_block {
12072121998757195963 => {
dc_update_server_uid(
context,
(*msg).rfc724_mid,
&dest_folder,
dest_uid,
);
}
_ => {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
}
}
}
3 => {
current_block = 12072121998757195963;
match current_block {
12072121998757195963 => {
dc_update_server_uid(
context,
(*msg).rfc724_mid,
&dest_folder,
dest_uid,
);
}
_ => {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
}
}
}
0 | 2 | _ => {}
}
3 => {
dc_update_server_uid(context, (*msg).rfc724_mid, &dest_folder, dest_uid);
}
0 | 2 | _ => {}
}
}
}
_ => {}
}
dc_msg_unref(msg);
@@ -473,7 +514,7 @@ fn connect_to_inbox(context: &Context, inbox: &Imap) -> libc::c_int {
#[allow(non_snake_case)]
unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context: &Context, job: &mut dc_job_t) {
let ok_to_continue;
let current_block: u64;
let folder = job
.param
.get(Param::ServerFolder)
@@ -487,39 +528,44 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context: &Context, job: &mut dc_
connect_to_inbox(context, &inbox);
if !inbox.is_connected() {
dc_job_try_again_later(job, 3, 0 as *const libc::c_char);
ok_to_continue = false;
current_block = 2670689566614003383;
} else {
ok_to_continue = true;
current_block = 11006700562992250127;
}
} else {
ok_to_continue = true;
current_block = 11006700562992250127;
}
if ok_to_continue {
if inbox.set_seen(context, &folder, uid) == 0 {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
}
if 0 != job.param.get_int(Param::AlsoMove).unwrap_or_default() {
if context
.sql
.get_config_int(context, "folders_configured")
.unwrap_or_default()
< 3
{
inbox.configure_folders(context, 0x1i32);
match current_block {
11006700562992250127 => {
if inbox.set_seen(context, &folder, uid) == 0 {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
}
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
if let Some(dest_folder) = dest_folder {
if 1 == inbox.mv(context, folder, uid, dest_folder, &mut dest_uid) as libc::c_uint {
dc_job_try_again_later(job, 3, 0 as *const libc::c_char);
if 0 != job.param.get_int(Param::AlsoMove).unwrap_or_default() {
if context
.sql
.get_config_int(context, "folders_configured")
.unwrap_or_default()
< 3
{
inbox.configure_folders(context, 0x1i32);
}
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
if let Some(dest_folder) = dest_folder {
if 1 == inbox.mv(context, folder, uid, dest_folder, &mut dest_uid)
as libc::c_uint
{
dc_job_try_again_later(job, 3, 0 as *const libc::c_char);
}
}
}
}
_ => {}
}
}
#[allow(non_snake_case)]
unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &Context, job: &mut dc_job_t) {
let ok_to_continue;
let mut current_block: u64;
let msg: *mut dc_msg_t = dc_msg_new_untyped(context);
let inbox = context.inbox.read().unwrap();
@@ -527,44 +573,130 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &Context, job: &mut dc_
connect_to_inbox(context, &inbox);
if !inbox.is_connected() {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
ok_to_continue = false;
current_block = 17792648348530113339;
} else {
ok_to_continue = true;
current_block = 15240798224410183470;
}
} else {
ok_to_continue = true;
current_block = 15240798224410183470;
}
if ok_to_continue {
if dc_msg_load_from_db(msg, context, job.foreign_id) {
let server_folder = (*msg).server_folder.as_ref().unwrap();
match inbox.set_seen(context, server_folder, (*msg).server_uid) as libc::c_uint {
0 => {}
1 => {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
}
_ => {
if 0 != (*msg).param.get_int(Param::WantsMdn).unwrap_or_default()
&& 0 != context
.sql
.get_config_int(context, "mdns_enabled")
.unwrap_or_else(|| 1)
{
let folder = (*msg).server_folder.as_ref().unwrap();
match inbox.set_mdnsent(context, folder, (*msg).server_uid) as libc::c_uint
{
1 => {
match current_block {
15240798224410183470 => {
if dc_msg_load_from_db(msg, context, job.foreign_id) {
let server_folder = (*msg).server_folder.as_ref().unwrap();
match inbox.set_seen(context, server_folder, (*msg).server_uid) as libc::c_uint {
0 => {}
1 => {
current_block = 12392248546350854223;
match current_block {
12392248546350854223 => {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
}
3 => {
dc_send_mdn(context, (*msg).id);
_ => {
if 0 != (*msg).param.get_int(Param::WantsMdn).unwrap_or_default()
&& 0 != context
.sql
.get_config_int(context, "mdns_enabled")
.unwrap_or_else(|| 1)
{
let folder = (*msg).server_folder.as_ref().unwrap();
match inbox.set_mdnsent(context, folder, (*msg).server_uid)
as libc::c_uint
{
1 => {
current_block = 4016212065805849280;
match current_block {
6186957421461061791 => {
dc_send_mdn(context, (*msg).id);
}
_ => {
dc_job_try_again_later(
job,
3i32,
0 as *const libc::c_char,
);
}
}
}
3 => {
current_block = 6186957421461061791;
match current_block {
6186957421461061791 => {
dc_send_mdn(context, (*msg).id);
}
_ => {
dc_job_try_again_later(
job,
3i32,
0 as *const libc::c_char,
);
}
}
}
0 | 2 | _ => {}
}
}
}
}
}
_ => {
current_block = 7746791466490516765;
match current_block {
12392248546350854223 => {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
}
_ => {
if 0 != (*msg).param.get_int(Param::WantsMdn).unwrap_or_default()
&& 0 != context
.sql
.get_config_int(context, "mdns_enabled")
.unwrap_or_else(|| 1)
{
let folder = (*msg).server_folder.as_ref().unwrap();
match inbox.set_mdnsent(context, folder, (*msg).server_uid)
as libc::c_uint
{
1 => {
current_block = 4016212065805849280;
match current_block {
6186957421461061791 => {
dc_send_mdn(context, (*msg).id);
}
_ => {
dc_job_try_again_later(
job,
3i32,
0 as *const libc::c_char,
);
}
}
}
3 => {
current_block = 6186957421461061791;
match current_block {
6186957421461061791 => {
dc_send_mdn(context, (*msg).id);
}
_ => {
dc_job_try_again_later(
job,
3i32,
0 as *const libc::c_char,
);
}
}
}
0 | 2 | _ => {}
}
}
}
0 | 2 | _ => {}
}
}
}
}
}
_ => {}
}
dc_msg_unref(msg);
}
@@ -731,6 +863,7 @@ pub unsafe fn dc_interrupt_imap_idle(context: &Context) {
#[allow(non_snake_case)]
unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context: &Context, job: &mut dc_job_t) {
let mut current_block: u64;
let mut delete_from_server: libc::c_int = 1i32;
let msg: *mut dc_msg_t = dc_msg_new_untyped(context);
let inbox = context.inbox.read().unwrap();
@@ -739,7 +872,6 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context: &Context, job: &mut dc_jo
|| (*msg).rfc724_mid.is_null()
|| *(*msg).rfc724_mid.offset(0isize) as libc::c_int == 0i32)
{
let ok_to_continue1;
/* eg. device messages have no Message-ID */
if dc_rfc724_mid_cnt(context, (*msg).rfc724_mid) != 1i32 {
info!(
@@ -750,35 +882,38 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context: &Context, job: &mut dc_jo
}
/* if this is the last existing part of the message, we delete the message from the server */
if 0 != delete_from_server {
let ok_to_continue;
if !inbox.is_connected() {
connect_to_inbox(context, &inbox);
if !inbox.is_connected() {
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
ok_to_continue = false;
current_block = 8913536887710889399;
} else {
ok_to_continue = true;
current_block = 5399440093318478209;
}
} else {
ok_to_continue = true;
current_block = 5399440093318478209;
}
if ok_to_continue {
let mid = CStr::from_ptr((*msg).rfc724_mid).to_str().unwrap();
let server_folder = (*msg).server_folder.as_ref().unwrap();
if 0 == inbox.delete_msg(context, mid, server_folder, &mut (*msg).server_uid) {
dc_job_try_again_later(job, -1i32, 0 as *const libc::c_char);
ok_to_continue1 = false;
} else {
ok_to_continue1 = true;
match current_block {
8913536887710889399 => {}
_ => {
let mid = CStr::from_ptr((*msg).rfc724_mid).to_str().unwrap();
let server_folder = (*msg).server_folder.as_ref().unwrap();
if 0 == inbox.delete_msg(context, mid, server_folder, &mut (*msg).server_uid) {
dc_job_try_again_later(job, -1i32, 0 as *const libc::c_char);
current_block = 8913536887710889399;
} else {
current_block = 17407779659766490442;
}
}
} else {
ok_to_continue1 = false;
}
} else {
ok_to_continue1 = true;
current_block = 17407779659766490442;
}
if ok_to_continue1 {
dc_delete_msg_from_db(context, (*msg).id);
match current_block {
8913536887710889399 => {}
_ => {
dc_delete_msg_from_db(context, (*msg).id);
}
}
}
dc_msg_unref(msg);

View File

@@ -11,6 +11,7 @@ use crate::x::*;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct dc_lot_t {
pub magic: uint32_t,
pub text1_meaning: libc::c_int,
pub text1: *mut libc::c_char,
pub text2: *mut libc::c_char,
@@ -37,13 +38,14 @@ pub unsafe fn dc_lot_new() -> *mut dc_lot_t {
lot = calloc(1, ::std::mem::size_of::<dc_lot_t>()) as *mut dc_lot_t;
assert!(!lot.is_null());
(*lot).magic = 0x107107i32 as uint32_t;
(*lot).text1_meaning = 0i32;
lot
}
pub unsafe fn dc_lot_empty(mut lot: *mut dc_lot_t) {
if lot.is_null() {
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
return;
}
free((*lot).text1 as *mut libc::c_void);
@@ -62,16 +64,17 @@ pub unsafe fn dc_lot_empty(mut lot: *mut dc_lot_t) {
(*lot).id = 0i32 as uint32_t;
}
pub unsafe fn dc_lot_unref(set: *mut dc_lot_t) {
if set.is_null() {
pub unsafe fn dc_lot_unref(mut set: *mut dc_lot_t) {
if set.is_null() || (*set).magic != 0x107107i32 as libc::c_uint {
return;
}
dc_lot_empty(set);
(*set).magic = 0i32 as uint32_t;
free(set as *mut libc::c_void);
}
pub unsafe fn dc_lot_get_text1(lot: *const dc_lot_t) -> *mut libc::c_char {
if lot.is_null() {
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
return 0 as *mut libc::c_char;
}
@@ -79,7 +82,7 @@ pub unsafe fn dc_lot_get_text1(lot: *const dc_lot_t) -> *mut libc::c_char {
}
pub unsafe fn dc_lot_get_text2(lot: *const dc_lot_t) -> *mut libc::c_char {
if lot.is_null() {
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
return 0 as *mut libc::c_char;
}
@@ -87,7 +90,7 @@ pub unsafe fn dc_lot_get_text2(lot: *const dc_lot_t) -> *mut libc::c_char {
}
pub unsafe fn dc_lot_get_text1_meaning(lot: *const dc_lot_t) -> libc::c_int {
if lot.is_null() {
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
return 0i32;
}
@@ -95,7 +98,7 @@ pub unsafe fn dc_lot_get_text1_meaning(lot: *const dc_lot_t) -> libc::c_int {
}
pub unsafe fn dc_lot_get_state(lot: *const dc_lot_t) -> libc::c_int {
if lot.is_null() {
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
return 0i32;
}
@@ -103,7 +106,7 @@ pub unsafe fn dc_lot_get_state(lot: *const dc_lot_t) -> libc::c_int {
}
pub unsafe fn dc_lot_get_id(lot: *const dc_lot_t) -> uint32_t {
if lot.is_null() {
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
return 0i32 as uint32_t;
}
@@ -111,7 +114,7 @@ pub unsafe fn dc_lot_get_id(lot: *const dc_lot_t) -> uint32_t {
}
pub unsafe fn dc_lot_get_timestamp(lot: *const dc_lot_t) -> i64 {
if lot.is_null() {
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
return 0;
}
@@ -127,7 +130,7 @@ pub unsafe fn dc_lot_fill(
contact: Option<&Contact>,
context: &Context,
) {
if lot.is_null() || msg.is_null() {
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint || msg.is_null() {
return;
}
if (*msg).state == 19i32 {

View File

@@ -161,7 +161,12 @@ pub unsafe fn dc_mimeparser_parse(
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int {
mimeparser.subject = dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value)
}
if !dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Version").is_null() {
if !dc_mimeparser_lookup_optional_field(
mimeparser,
b"Chat-Version\x00" as *const u8 as *const libc::c_char,
)
.is_null()
{
mimeparser.is_send_by_messenger = 1i32
}
if !dc_mimeparser_lookup_field(mimeparser, "Autocrypt-Setup-Message").is_null() {
@@ -196,7 +201,10 @@ pub unsafe fn dc_mimeparser_parse(
}
}
} else {
optional_field = dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Content");
optional_field = dc_mimeparser_lookup_optional_field(
mimeparser,
b"Chat-Content\x00" as *const u8 as *const libc::c_char,
);
if !optional_field.is_null() && !(*optional_field).fld_value.is_null() {
if strcmp(
(*optional_field).fld_value,
@@ -304,7 +312,11 @@ pub unsafe fn dc_mimeparser_parse(
}
if mimeparser.parts.len() == 1 {
if mimeparser.parts[0].type_0 == 40i32 {
if !dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Voice-Message").is_null()
if !dc_mimeparser_lookup_optional_field(
mimeparser,
b"Chat-Voice-Message\x00" as *const u8 as *const libc::c_char,
)
.is_null()
{
let part_mut = &mut mimeparser.parts[0];
part_mut.type_0 = 41i32
@@ -312,7 +324,10 @@ pub unsafe fn dc_mimeparser_parse(
}
let part = &mimeparser.parts[0];
if part.type_0 == 40i32 || part.type_0 == 41i32 || part.type_0 == 50i32 {
let field_0 = dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Duration");
let field_0 = dc_mimeparser_lookup_optional_field(
mimeparser,
b"Chat-Duration\x00" as *const u8 as *const libc::c_char,
);
if !field_0.is_null() {
let duration_ms: libc::c_int = dc_atoi_null_is_0((*field_0).fld_value);
if duration_ms > 0i32 && duration_ms < 24i32 * 60i32 * 60i32 * 1000i32 {
@@ -323,8 +338,10 @@ pub unsafe fn dc_mimeparser_parse(
}
}
if 0 == mimeparser.decrypting_failed {
let dn_field: *const mailimf_optional_field =
dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Disposition-Notification-To");
let dn_field: *const mailimf_optional_field = dc_mimeparser_lookup_optional_field(
mimeparser,
b"Chat-Disposition-Notification-To\x00" as *const u8 as *const libc::c_char,
);
if !dn_field.is_null() && dc_mimeparser_get_last_nonmeta(mimeparser).is_some() {
let mut mb_list: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list;
let mut index_0: size_t = 0i32 as size_t;
@@ -442,11 +459,11 @@ pub fn dc_mimeparser_lookup_field(
pub unsafe fn dc_mimeparser_lookup_optional_field(
mimeparser: &dc_mimeparser_t,
field_name: &str,
field_name: *const libc::c_char,
) -> *mut mailimf_optional_field {
let field = mimeparser
.header
.get(field_name)
.get(as_str(field_name))
.map(|v| *v)
.unwrap_or_else(|| std::ptr::null_mut());
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
@@ -1167,7 +1184,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
/* check header directly as is_send_by_messenger is not yet set up */
let is_msgrmsg = (!dc_mimeparser_lookup_optional_field(
&mimeparser,
"Chat-Version",
b"Chat-Version\x00" as *const u8 as *const libc::c_char,
)
.is_null())
as libc::c_int;
@@ -1535,8 +1552,10 @@ pub unsafe fn dc_mimeparser_is_mailinglist_message(mimeparser: &dc_mimeparser_t)
if !dc_mimeparser_lookup_field(&mimeparser, "List-Id").is_null() {
return 1i32;
}
let precedence: *mut mailimf_optional_field =
dc_mimeparser_lookup_optional_field(mimeparser, "Precedence");
let precedence: *mut mailimf_optional_field = dc_mimeparser_lookup_optional_field(
mimeparser,
b"Precedence\x00" as *const u8 as *const libc::c_char,
);
if !precedence.is_null() {
if strcasecmp(
(*precedence).fld_value,

View File

@@ -20,6 +20,7 @@ use std::ptr;
#[derive(Clone)]
#[repr(C)]
pub struct dc_msg_t<'a> {
pub magic: uint32_t,
pub id: uint32_t,
pub from_id: uint32_t,
pub to_id: uint32_t,
@@ -221,6 +222,7 @@ pub unsafe fn dc_msg_new_untyped<'a>(context: &'a Context) -> *mut dc_msg_t<'a>
// approx. max. length returned by dc_get_msg_info()
pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut dc_msg_t<'a> {
let msg = dc_msg_t {
magic: 0x11561156,
id: 0,
from_id: 0,
to_id: 0,
@@ -248,16 +250,17 @@ pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut d
Box::into_raw(Box::new(msg))
}
pub unsafe fn dc_msg_unref(msg: *mut dc_msg_t) {
if msg.is_null() {
pub unsafe fn dc_msg_unref(mut msg: *mut dc_msg_t) {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return;
}
dc_msg_empty(msg);
(*msg).magic = 0i32 as uint32_t;
Box::from_raw(msg);
}
pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return;
}
free((*msg).rfc724_mid as *mut libc::c_void);
@@ -271,7 +274,7 @@ pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) {
pub unsafe fn dc_msg_get_filemime(msg: *const dc_msg_t) -> *mut libc::c_char {
let mut ret = 0 as *mut libc::c_char;
if !msg.is_null() {
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
match (*msg).param.get(Param::MimeType) {
Some(m) => {
ret = m.strdup();
@@ -355,7 +358,7 @@ pub unsafe fn dc_msg_guess_msgtype_from_suffix(
pub unsafe fn dc_msg_get_file(msg: *const dc_msg_t) -> *mut libc::c_char {
let mut file_abs = 0 as *mut libc::c_char;
if !msg.is_null() {
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
if let Some(file_rel) = (*msg).param.get(Param::File) {
let file_rel_c = CString::yolo(file_rel);
file_abs = dc_get_abs_path((*msg).context, file_rel_c.as_ptr());
@@ -378,7 +381,7 @@ pub unsafe fn dc_msg_get_file(msg: *const dc_msg_t) -> *mut libc::c_char {
* @return 1=Message has location bound to it, 0=No location bound to message.
*/
pub unsafe fn dc_msg_has_location(msg: *const dc_msg_t) -> bool {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return false;
}
@@ -407,7 +410,10 @@ pub unsafe fn dc_msg_set_location(
latitude: libc::c_double,
longitude: libc::c_double,
) {
if msg.is_null() || (latitude == 0.0 && longitude == 0.0) {
if msg.is_null()
|| (*msg).magic != 0x11561156i32 as libc::c_uint
|| (latitude == 0.0 && longitude == 0.0)
{
return;
}
@@ -416,7 +422,7 @@ pub unsafe fn dc_msg_set_location(
}
pub unsafe fn dc_msg_get_timestamp(msg: *const dc_msg_t) -> i64 {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0;
}
return if 0 != (*msg).timestamp_sent {
@@ -654,7 +660,7 @@ pub unsafe fn dc_get_msg<'a>(context: &'a Context, msg_id: uint32_t) -> *mut dc_
}
pub unsafe fn dc_msg_get_id(msg: *const dc_msg_t) -> uint32_t {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0i32 as uint32_t;
}
@@ -662,7 +668,7 @@ pub unsafe fn dc_msg_get_id(msg: *const dc_msg_t) -> uint32_t {
}
pub unsafe fn dc_msg_get_from_id(msg: *const dc_msg_t) -> uint32_t {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0i32 as uint32_t;
}
@@ -670,7 +676,7 @@ pub unsafe fn dc_msg_get_from_id(msg: *const dc_msg_t) -> uint32_t {
}
pub unsafe fn dc_msg_get_chat_id(msg: *const dc_msg_t) -> uint32_t {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0i32 as uint32_t;
}
return if 0 != (*msg).chat_blocked {
@@ -681,7 +687,7 @@ pub unsafe fn dc_msg_get_chat_id(msg: *const dc_msg_t) -> uint32_t {
}
pub unsafe fn dc_msg_get_viewtype(msg: *const dc_msg_t) -> Viewtype {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return Viewtype::Unknown;
}
@@ -689,7 +695,7 @@ pub unsafe fn dc_msg_get_viewtype(msg: *const dc_msg_t) -> Viewtype {
}
pub unsafe fn dc_msg_get_state(msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0i32;
}
@@ -697,7 +703,7 @@ pub unsafe fn dc_msg_get_state(msg: *const dc_msg_t) -> libc::c_int {
}
pub unsafe fn dc_msg_get_received_timestamp(msg: *const dc_msg_t) -> i64 {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0;
}
@@ -705,7 +711,7 @@ pub unsafe fn dc_msg_get_received_timestamp(msg: *const dc_msg_t) -> i64 {
}
pub unsafe fn dc_msg_get_sort_timestamp(msg: *const dc_msg_t) -> i64 {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0;
}
@@ -713,7 +719,7 @@ pub unsafe fn dc_msg_get_sort_timestamp(msg: *const dc_msg_t) -> i64 {
}
pub unsafe fn dc_msg_get_text(msg: *const dc_msg_t) -> *mut libc::c_char {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return dc_strdup(0 as *const libc::c_char);
}
if let Some(ref text) = (*msg).text {
@@ -727,7 +733,7 @@ pub unsafe fn dc_msg_get_text(msg: *const dc_msg_t) -> *mut libc::c_char {
pub unsafe fn dc_msg_get_filename(msg: *const dc_msg_t) -> *mut libc::c_char {
let mut ret = 0 as *mut libc::c_char;
if !msg.is_null() {
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
if let Some(file) = (*msg).param.get(Param::File) {
let file_c = CString::yolo(file);
ret = dc_get_filename(file_c.as_ptr());
@@ -741,7 +747,7 @@ pub unsafe fn dc_msg_get_filename(msg: *const dc_msg_t) -> *mut libc::c_char {
}
pub unsafe fn dc_msg_get_filebytes(msg: *const dc_msg_t) -> uint64_t {
if !msg.is_null() {
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
if let Some(file) = (*msg).param.get(Param::File) {
return dc_get_filebytes((*msg).context, &file);
}
@@ -751,7 +757,7 @@ pub unsafe fn dc_msg_get_filebytes(msg: *const dc_msg_t) -> uint64_t {
}
pub unsafe fn dc_msg_get_width(msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0;
}
@@ -759,7 +765,7 @@ pub unsafe fn dc_msg_get_width(msg: *const dc_msg_t) -> libc::c_int {
}
pub unsafe fn dc_msg_get_height(msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint {
return 0;
}
@@ -767,7 +773,7 @@ pub unsafe fn dc_msg_get_height(msg: *const dc_msg_t) -> libc::c_int {
}
pub unsafe fn dc_msg_get_duration(msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint {
return 0;
}
@@ -776,7 +782,7 @@ pub unsafe fn dc_msg_get_duration(msg: *const dc_msg_t) -> libc::c_int {
// TODO should return bool /rtn
pub unsafe fn dc_msg_get_showpadlock(msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint {
return 0;
}
if (*msg)
@@ -799,7 +805,7 @@ pub unsafe fn dc_msg_get_summary<'a>(
let ret: *mut dc_lot_t = dc_lot_new();
let mut chat_to_delete: *mut Chat = 0 as *mut Chat;
if !msg.is_null() {
if !(msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint) {
if chat.is_null() {
chat_to_delete = dc_get_chat((*msg).context, (*msg).chat_id);
if chat_to_delete.is_null() {
@@ -830,7 +836,7 @@ pub unsafe fn dc_msg_get_summarytext(
msg: *mut dc_msg_t,
approx_characters: libc::c_int,
) -> *mut libc::c_char {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return dc_strdup(0 as *const libc::c_char);
}
@@ -941,7 +947,7 @@ pub unsafe fn dc_msg_has_deviating_timestamp(msg: *const dc_msg_t) -> libc::c_in
// TODO should return bool /rtn
pub unsafe fn dc_msg_is_sent(msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0;
}
if (*msg).state >= DC_STATE_OUT_DELIVERED {
@@ -952,7 +958,7 @@ pub unsafe fn dc_msg_is_sent(msg: *const dc_msg_t) -> libc::c_int {
}
pub unsafe fn dc_msg_is_starred(msg: *const dc_msg_t) -> bool {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return false;
}
0 != (*msg).starred
@@ -960,7 +966,7 @@ pub unsafe fn dc_msg_is_starred(msg: *const dc_msg_t) -> bool {
// TODO should return bool /rtn
pub unsafe fn dc_msg_is_forwarded(msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0;
}
if 0 != (*msg).param.get_int(Param::Forwarded).unwrap_or_default() {
@@ -972,7 +978,7 @@ pub unsafe fn dc_msg_is_forwarded(msg: *const dc_msg_t) -> libc::c_int {
// TODO should return bool /rtn
pub unsafe fn dc_msg_is_info(msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0;
}
let cmd = (*msg).param.get_int(Param::Cmd).unwrap_or_default();
@@ -988,7 +994,7 @@ pub unsafe fn dc_msg_is_info(msg: *const dc_msg_t) -> libc::c_int {
// TODO should return bool /rtn
pub unsafe fn dc_msg_is_increation(msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0;
}
@@ -1000,7 +1006,10 @@ pub unsafe fn dc_msg_is_increation(msg: *const dc_msg_t) -> libc::c_int {
}
pub unsafe fn dc_msg_is_setupmessage(msg: *const dc_msg_t) -> bool {
if msg.is_null() || (*msg).type_0 != Viewtype::File {
if msg.is_null()
|| (*msg).magic != 0x11561156i32 as libc::c_uint
|| (*msg).type_0 != Viewtype::File
{
return false;
}
@@ -1056,7 +1065,7 @@ pub unsafe fn dc_msg_get_setupcodebegin(msg: *const dc_msg_t) -> *mut libc::c_ch
}
pub unsafe fn dc_msg_set_text(mut msg: *mut dc_msg_t, text: *const libc::c_char) {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return;
}
(*msg).text = if text.is_null() {
@@ -1071,7 +1080,7 @@ pub unsafe fn dc_msg_set_file(
file: *const libc::c_char,
filemime: *const libc::c_char,
) {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return;
}
if !file.is_null() {
@@ -1083,7 +1092,7 @@ pub unsafe fn dc_msg_set_file(
}
pub unsafe fn dc_msg_set_dimension(msg: *mut dc_msg_t, width: libc::c_int, height: libc::c_int) {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return;
}
(*msg).param.set_int(Param::Width, width);
@@ -1091,7 +1100,7 @@ pub unsafe fn dc_msg_set_dimension(msg: *mut dc_msg_t, width: libc::c_int, heigh
}
pub unsafe fn dc_msg_set_duration(msg: *mut dc_msg_t, duration: libc::c_int) {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return;
}
(*msg).param.set_int(Param::Duration, duration);
@@ -1103,7 +1112,7 @@ pub unsafe fn dc_msg_latefiling_mediasize(
height: libc::c_int,
duration: libc::c_int,
) {
if !msg.is_null() {
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
if width > 0 && height > 0 {
(*msg).param.set_int(Param::Width, width);
(*msg).param.set_int(Param::Height, height);
@@ -1116,7 +1125,7 @@ pub unsafe fn dc_msg_latefiling_mediasize(
}
pub unsafe fn dc_msg_save_param_to_disk(msg: *mut dc_msg_t) -> bool {
if msg.is_null() {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return false;
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@ use crate::aheader::EncryptPreference;
use crate::constants::*;
use crate::contact::*;
use crate::context::Context;
use crate::dc_array::*;
use crate::dc_chat::*;
use crate::dc_configure::*;
use crate::dc_e2ee::*;
@@ -295,12 +296,14 @@ unsafe fn send_handshake_msg(
}
unsafe fn chat_id_2_contact_id(context: &Context, contact_chat_id: uint32_t) -> uint32_t {
let contacts = dc_get_chat_contacts(context, contact_chat_id);
if contacts.len() == 1 {
contacts[0]
} else {
0
let mut contact_id: uint32_t = 0i32 as uint32_t;
let contacts: *mut dc_array_t = dc_get_chat_contacts(context, contact_chat_id);
if !(dc_array_get_cnt(contacts) != 1) {
contact_id = dc_array_get_id(contacts, 0i32 as size_t)
}
dc_array_unref(contacts);
contact_id
}
unsafe fn fingerprint_equals_sender(
@@ -314,8 +317,8 @@ unsafe fn fingerprint_equals_sender(
let mut fingerprint_equal: libc::c_int = 0i32;
let contacts = dc_get_chat_contacts(context, contact_chat_id);
if contacts.len() == 1 {
if let Ok(contact) = Contact::load_from_db(context, contacts[0]) {
if !(dc_array_get_cnt(contacts) != 1) {
if let Ok(contact) = Contact::load_from_db(context, dc_array_get_id(contacts, 0)) {
if let Some(peerstate) = Peerstate::from_addr(context, &context.sql, contact.get_addr())
{
let fingerprint_normalized = dc_normalize_fingerprint(as_str(fingerprint));
@@ -329,6 +332,7 @@ unsafe fn fingerprint_equals_sender(
return 0;
}
}
dc_array_unref(contacts);
fingerprint_equal
}

View File

@@ -10,6 +10,7 @@ use deltachat::config;
use deltachat::constants::*;
use deltachat::contact::*;
use deltachat::context::*;
use deltachat::dc_array::*;
use deltachat::dc_chat::*;
use deltachat::dc_configure::*;
use deltachat::dc_imex::*;
@@ -742,14 +743,22 @@ fn test_dc_mimeparser_with_context() {
"inner-subject",
);
let mut of: *mut mailimf_optional_field =
dc_mimeparser_lookup_optional_field(&mimeparser, "X-Special-A");
let mut of: *mut mailimf_optional_field = dc_mimeparser_lookup_optional_field(
&mimeparser,
b"X-Special-A\x00" as *const u8 as *const libc::c_char,
);
assert_eq!(as_str((*of).fld_value as *const libc::c_char), "special-a",);
of = dc_mimeparser_lookup_optional_field(&mimeparser, "Foo");
of = dc_mimeparser_lookup_optional_field(
&mimeparser,
b"Foo\x00" as *const u8 as *const libc::c_char,
);
assert_eq!(as_str((*of).fld_value as *const libc::c_char), "Bar",);
of = dc_mimeparser_lookup_optional_field(&mimeparser, "Chat-Version");
of = dc_mimeparser_lookup_optional_field(
&mimeparser,
b"Chat-Version\x00" as *const u8 as *const libc::c_char,
);
assert_eq!(as_str((*of).fld_value as *const libc::c_char), "1.0",);
assert_eq!(mimeparser.parts.len(), 1);
@@ -800,16 +809,19 @@ fn test_get_contacts() {
unsafe {
let context = create_test_context();
let contacts = Contact::get_all(&context.ctx, 0, Some("some2")).unwrap();
assert_eq!(contacts.len(), 0);
assert_eq!(dc_array_get_cnt(contacts), 0);
dc_array_unref(contacts);
let id = Contact::create(&context.ctx, "bob", "bob@mail.de").unwrap();
assert_ne!(id, 0);
let contacts = Contact::get_all(&context.ctx, 0, Some("bob")).unwrap();
assert_eq!(contacts.len(), 1);
assert_eq!(dc_array_get_cnt(contacts), 1);
dc_array_unref(contacts);
let contacts = Contact::get_all(&context.ctx, 0, Some("alice")).unwrap();
assert_eq!(contacts.len(), 0);
assert_eq!(dc_array_get_cnt(contacts), 0);
dc_array_unref(contacts);
}
}