mirror of
https://github.com/chatmail/core.git
synced 2026-04-09 17:12:15 +03:00
Compare commits
2 Commits
fix_progre
...
fix_null_p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42b56cc53e | ||
|
|
80c727ee9f |
9
Cargo.lock
generated
9
Cargo.lock
generated
@@ -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"
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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.");
|
||||
|
||||
@@ -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)?,
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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()
|
||||
|
||||
151
src/dc_array.rs
151
src/dc_array.rs
@@ -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) };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
116
src/dc_chat.rs
116
src/dc_chat.rs
@@ -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
|
||||
|
||||
1269
src/dc_configure.rs
1269
src/dc_configure.rs
File diff suppressed because it is too large
Load Diff
172
src/dc_e2ee.rs
172
src/dc_e2ee.rs
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
473
src/dc_job.rs
473
src/dc_job.rs
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user