mirror of
https://github.com/chatmail/core.git
synced 2026-04-25 01:16:29 +03:00
Prepare for cross compilation to windows (#105)
Prepare for cross compilation to windows
This commit is contained in:
@@ -22,7 +22,7 @@ num-traits = "0.2.6"
|
||||
native-tls = "0.2.3"
|
||||
lettre = "0.9.0"
|
||||
imap = "1.0.1"
|
||||
mmime = { git = "https://github.com/dignifiedquire/mmime" }
|
||||
mmime = {git = "https://github.com/dignifiedquire/mmime"}
|
||||
base64 = "0.10"
|
||||
charset = "0.1"
|
||||
percent-encoding = "1.0"
|
||||
|
||||
@@ -160,10 +160,7 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
|
||||
let mut success: libc::c_int = 0i32;
|
||||
let mut real_spec: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut dir: *mut DIR = 0 as *mut DIR;
|
||||
let mut dir_entry: *mut dirent;
|
||||
let mut read_cnt: libc::c_int = 0i32;
|
||||
let mut name: *mut libc::c_char;
|
||||
if 0 == dc_sqlite3_is_open(&context.sql.clone().read().unwrap()) {
|
||||
dc_log_error(
|
||||
context,
|
||||
@@ -212,8 +209,9 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
|
||||
current_block = 1622411330066726685;
|
||||
} else {
|
||||
/* import a directory */
|
||||
dir = opendir(real_spec);
|
||||
if dir.is_null() {
|
||||
let dir_name = std::path::Path::new(to_str(real_spec));
|
||||
let dir = std::fs::read_dir(dir_name);
|
||||
if dir.is_err() {
|
||||
dc_log_error(
|
||||
context,
|
||||
0i32,
|
||||
@@ -223,22 +221,19 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
|
||||
);
|
||||
current_block = 8522321847195001863;
|
||||
} else {
|
||||
loop {
|
||||
dir_entry = readdir(dir);
|
||||
if dir_entry.is_null() {
|
||||
let dir = dir.unwrap();
|
||||
for entry in dir {
|
||||
if entry.is_err() {
|
||||
break;
|
||||
}
|
||||
name = (*dir_entry).d_name.as_mut_ptr();
|
||||
if strlen(name) >= 4
|
||||
&& strcmp(
|
||||
&mut *name.offset(strlen(name).wrapping_sub(4) as isize),
|
||||
b".eml\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0i32
|
||||
{
|
||||
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: *mut libc::c_char = dc_mprintf(
|
||||
b"%s/%s\x00" as *const u8 as *const libc::c_char,
|
||||
real_spec,
|
||||
name,
|
||||
to_cstring(name).as_ptr(),
|
||||
);
|
||||
dc_log_info(
|
||||
context,
|
||||
@@ -280,13 +275,11 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
|
||||
}
|
||||
}
|
||||
}
|
||||
if !dir.is_null() {
|
||||
closedir(dir);
|
||||
}
|
||||
free(real_spec as *mut libc::c_void);
|
||||
free(suffix as *mut libc::c_void);
|
||||
return success;
|
||||
success
|
||||
}
|
||||
|
||||
unsafe fn log_msg(context: &Context, prefix: *const libc::c_char, msg: *mut dc_msg_t) {
|
||||
let contact: *mut dc_contact_t = dc_get_contact(context, dc_msg_get_from_id(msg));
|
||||
let contact_name: *mut libc::c_char = dc_contact_get_name(contact);
|
||||
|
||||
@@ -46,125 +46,94 @@ unsafe extern "C" fn receive_event(
|
||||
2091 => {}
|
||||
100 => {
|
||||
/* do not show the event as this would fill the screen */
|
||||
printf(
|
||||
b"%s\n\x00" as *const u8 as *const libc::c_char,
|
||||
data2 as *mut libc::c_char,
|
||||
);
|
||||
println!("{}", to_string(data2 as *const _),);
|
||||
}
|
||||
101 => {
|
||||
printf(
|
||||
b"[DC_EVENT_SMTP_CONNECTED] %s\n\x00" as *const u8 as *const libc::c_char,
|
||||
data2 as *mut libc::c_char,
|
||||
);
|
||||
println!("[DC_EVENT_SMTP_CONNECTED] {}", to_string(data2 as *const _));
|
||||
}
|
||||
102 => {
|
||||
printf(
|
||||
b"[DC_EVENT_IMAP_CONNECTED] %s\n\x00" as *const u8 as *const libc::c_char,
|
||||
data2 as *mut libc::c_char,
|
||||
);
|
||||
println!("[DC_EVENT_IMAP_CONNECTED] {}", to_string(data2 as *const _),);
|
||||
}
|
||||
103 => {
|
||||
printf(
|
||||
b"[DC_EVENT_SMTP_MESSAGE_SENT] %s\n\x00" as *const u8 as *const libc::c_char,
|
||||
data2 as *mut libc::c_char,
|
||||
println!(
|
||||
"[DC_EVENT_SMTP_MESSAGE_SENT] {}",
|
||||
to_string(data2 as *const _),
|
||||
);
|
||||
}
|
||||
300 => {
|
||||
printf(
|
||||
b"[Warning] %s\n\x00" as *const u8 as *const libc::c_char,
|
||||
data2 as *mut libc::c_char,
|
||||
);
|
||||
println!("[Warning] {}", to_string(data2 as *const _),);
|
||||
}
|
||||
400 => {
|
||||
printf(
|
||||
b"\x1b[31m[DC_EVENT_ERROR] %s\x1b[0m\n\x00" as *const u8 as *const libc::c_char,
|
||||
data2 as *mut libc::c_char,
|
||||
println!(
|
||||
"\x1b[31m[DC_EVENT_ERROR] {}\x1b[0m",
|
||||
to_string(data2 as *const _),
|
||||
);
|
||||
}
|
||||
401 => {
|
||||
printf(
|
||||
b"\x1b[31m[DC_EVENT_ERROR_NETWORK] first=%i, msg=%s\x1b[0m\n\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
println!(
|
||||
"\x1b[31m[DC_EVENT_ERROR_NETWORK] first={}, msg={}\x1b[0m",
|
||||
data1 as libc::c_int,
|
||||
data2 as *mut libc::c_char,
|
||||
to_string(data2 as *const _),
|
||||
);
|
||||
}
|
||||
410 => {
|
||||
printf(
|
||||
b"\x1b[31m[DC_EVENT_ERROR_SELF_NOT_IN_GROUP] %s\x1b[0m\n\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
data2 as *mut libc::c_char,
|
||||
println!(
|
||||
"\x1b[31m[DC_EVENT_ERROR_SELF_NOT_IN_GROUP] {}\x1b[0m",
|
||||
to_string(data2 as *const _),
|
||||
);
|
||||
}
|
||||
2081 => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_IS_OFFLINE()}}\n\x1b[0m\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
print!("\x1b[33m{{Received DC_EVENT_IS_OFFLINE()}}\n\x1b[0m");
|
||||
}
|
||||
2000 => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_MSGS_CHANGED(%i, %i)}}\n\x1b[0m\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
data1 as libc::c_int,
|
||||
data2 as libc::c_int,
|
||||
print!(
|
||||
"\x1b[33m{{Received DC_EVENT_MSGS_CHANGED({}, {})}}\n\x1b[0m",
|
||||
data1 as libc::c_int, data2 as libc::c_int,
|
||||
);
|
||||
}
|
||||
2030 => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_CONTACTS_CHANGED()}}\n\x1b[0m\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
print!("\x1b[33m{{Received DC_EVENT_CONTACTS_CHANGED()}}\n\x1b[0m");
|
||||
}
|
||||
2035 => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_LOCATION_CHANGED(contact=%i)}}\n\x1b[0m\x00"
|
||||
as *const u8 as *const libc::c_char,
|
||||
print!(
|
||||
"\x1b[33m{{Received DC_EVENT_LOCATION_CHANGED(contact={})}}\n\x1b[0m",
|
||||
data1 as libc::c_int,
|
||||
);
|
||||
}
|
||||
2041 => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_CONFIGURE_PROGRESS(%i \xe2\x80\xb0)}}\n\x1b[0m\x00"
|
||||
as *const u8 as *const libc::c_char,
|
||||
print!(
|
||||
"\x1b[33m{{Received DC_EVENT_CONFIGURE_PROGRESS({} ‰)}}\n\x1b[0m",
|
||||
data1 as libc::c_int,
|
||||
);
|
||||
}
|
||||
2051 => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_IMEX_PROGRESS(%i \xe2\x80\xb0)}}\n\x1b[0m\x00"
|
||||
as *const u8 as *const libc::c_char,
|
||||
print!(
|
||||
"\x1b[33m{{Received DC_EVENT_IMEX_PROGRESS({} ‰)}}\n\x1b[0m",
|
||||
data1 as libc::c_int,
|
||||
);
|
||||
}
|
||||
2052 => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_IMEX_FILE_WRITTEN(%s)}}\n\x1b[0m\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
data1 as *mut libc::c_char,
|
||||
print!(
|
||||
"\x1b[33m{{Received DC_EVENT_IMEX_FILE_WRITTEN({})}}\n\x1b[0m",
|
||||
to_string(data1 as *const _)
|
||||
);
|
||||
}
|
||||
2055 => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_FILE_COPIED(%s)}}\n\x1b[0m\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
data1 as *mut libc::c_char,
|
||||
print!(
|
||||
"\x1b[33m{{Received DC_EVENT_FILE_COPIED({})}}\n\x1b[0m",
|
||||
to_string(data1 as *const _)
|
||||
);
|
||||
}
|
||||
2020 => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_CHAT_MODIFIED(%i)}}\n\x1b[0m\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
print!(
|
||||
"\x1b[33m{{Received DC_EVENT_CHAT_MODIFIED({})}}\n\x1b[0m",
|
||||
data1 as libc::c_int,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
printf(
|
||||
b"\x1b[33m{{Received DC_EVENT_%i(%i, %i)}}\n\x1b[0m\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
event as libc::c_int,
|
||||
data1 as libc::c_int,
|
||||
data2 as libc::c_int,
|
||||
print!(
|
||||
"\x1b[33m{{Received DC_EVENT_{}({}, {})}}\n\x1b[0m",
|
||||
event as libc::c_int, data1 as libc::c_int, data2 as libc::c_int,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -279,16 +248,16 @@ unsafe fn main_0(argc: libc::c_int, argv: *mut *mut libc::c_char) -> libc::c_int
|
||||
|
||||
if argc == 2i32 {
|
||||
if 0 == dc_open(&mut context, *argv.offset(1isize), 0 as *const libc::c_char) {
|
||||
printf(
|
||||
b"ERROR: Cannot open %s.\n\x00" as *const u8 as *const libc::c_char,
|
||||
*argv.offset(1isize),
|
||||
println!(
|
||||
"ERROR: Cannot open {}.",
|
||||
to_string(*argv.offset(1isize) as *const _)
|
||||
);
|
||||
}
|
||||
} else if argc != 1i32 {
|
||||
printf(b"ERROR: Bad arguments\n\x00" as *const u8 as *const libc::c_char);
|
||||
println!("ERROR: Bad arguments");
|
||||
}
|
||||
|
||||
printf(b"Delta Chat Core is awaiting your commands.\n\x00" as *const u8 as *const libc::c_char);
|
||||
println!("Delta Chat Core is awaiting your commands.");
|
||||
|
||||
let mut handles = None;
|
||||
|
||||
@@ -311,19 +280,13 @@ unsafe fn main_0(argc: libc::c_int, argv: *mut *mut libc::c_char) -> libc::c_int
|
||||
handles = None;
|
||||
} else if strcmp(cmd, b"smtp-jobs\x00" as *const u8 as *const libc::c_char) == 0i32 {
|
||||
if 0 != run_threads {
|
||||
printf(
|
||||
b"smtp-jobs are already running in a thread.\n\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
println!("smtp-jobs are already running in a thread.",);
|
||||
} else {
|
||||
dc_perform_smtp_jobs(&ctx.read().unwrap());
|
||||
}
|
||||
} else if strcmp(cmd, b"imap-jobs\x00" as *const u8 as *const libc::c_char) == 0i32 {
|
||||
if 0 != run_threads {
|
||||
printf(
|
||||
b"imap-jobs are already running in a thread.\n\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
println!("imap-jobs are already running in a thread.");
|
||||
} else {
|
||||
dc_perform_imap_jobs(&ctx.read().unwrap());
|
||||
}
|
||||
@@ -336,7 +299,7 @@ unsafe fn main_0(argc: libc::c_int, argv: *mut *mut libc::c_char) -> libc::c_int
|
||||
b"addr\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
if addr.is_null() || *addr.offset(0isize) as libc::c_int == 0i32 {
|
||||
printf(b"oauth2: set addr first.\n\x00" as *const u8 as *const libc::c_char);
|
||||
println!("oauth2: set addr first.");
|
||||
} else {
|
||||
let oauth2_url = dc_get_oauth2_url(
|
||||
&ctx.read().unwrap(),
|
||||
@@ -344,18 +307,15 @@ unsafe fn main_0(argc: libc::c_int, argv: *mut *mut libc::c_char) -> libc::c_int
|
||||
"chat.delta:/com.b44t.messenger",
|
||||
);
|
||||
if oauth2_url.is_none() {
|
||||
printf(
|
||||
b"OAuth2 not available for %s.\n\x00" as *const u8 as *const libc::c_char,
|
||||
addr,
|
||||
);
|
||||
println!("OAuth2 not available for {}.", to_string(addr));
|
||||
} else {
|
||||
println!("Open the following url, set mail_pw to the generated token and server_flags to 2:\n{}", oauth2_url.unwrap());
|
||||
}
|
||||
}
|
||||
free(addr as *mut libc::c_void);
|
||||
} else if strcmp(cmd, b"clear\x00" as *const u8 as *const libc::c_char) == 0i32 {
|
||||
printf(b"\n\n\n\n\x00" as *const u8 as *const libc::c_char);
|
||||
printf(b"\x1b[1;1H\x1b[2J\x00" as *const u8 as *const libc::c_char);
|
||||
println!("\n\n\n");
|
||||
print!("\x1b[1;1H\x1b[2J");
|
||||
} else if strcmp(cmd, b"getqr\x00" as *const u8 as *const libc::c_char) == 0i32
|
||||
|| strcmp(cmd, b"getbadqr\x00" as *const u8 as *const libc::c_char) == 0i32
|
||||
{
|
||||
@@ -374,7 +334,7 @@ unsafe fn main_0(argc: libc::c_int, argv: *mut *mut libc::c_char) -> libc::c_int
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
printf(b"%s\n\x00" as *const u8 as *const libc::c_char, qrstr);
|
||||
println!("{}", to_string(qrstr as *const _));
|
||||
let syscmd: *mut libc::c_char = dc_mprintf(
|
||||
b"qrencode -t ansiutf8 \"%s\" -o -\x00" as *const u8 as *const libc::c_char,
|
||||
qrstr,
|
||||
@@ -395,10 +355,7 @@ unsafe fn main_0(argc: libc::c_int, argv: *mut *mut libc::c_char) -> libc::c_int
|
||||
if !(*cmd.offset(0isize) as libc::c_int == 0i32) {
|
||||
let execute_result: *mut libc::c_char = dc_cmdline(&ctx.read().unwrap(), &cmdline);
|
||||
if !execute_result.is_null() {
|
||||
printf(
|
||||
b"%s\n\x00" as *const u8 as *const libc::c_char,
|
||||
execute_result,
|
||||
);
|
||||
println!("{}", to_string(execute_result as *const _));
|
||||
free(execute_result as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,3 +401,98 @@ pub unsafe fn dc_arr_to_string(arr: *const uint32_t, cnt: libc::c_int) -> *mut l
|
||||
);
|
||||
strdup(to_cstring(res).as_ptr())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[test]
|
||||
fn test_dc_array() {
|
||||
unsafe {
|
||||
let arr = dc_array_new(7 as size_t);
|
||||
assert_eq!(dc_array_get_cnt(arr), 0);
|
||||
|
||||
let mut i: libc::c_int = 0;
|
||||
while i < 1000 {
|
||||
dc_array_add_id(arr, (i + 2) as uint32_t);
|
||||
i += 1
|
||||
}
|
||||
|
||||
assert_eq!(dc_array_get_cnt(arr), 1000);
|
||||
|
||||
i = 0;
|
||||
|
||||
while i < 1000i32 {
|
||||
assert_eq!(
|
||||
dc_array_get_id(arr, i as size_t),
|
||||
(i + 1i32 * 2i32) as libc::c_uint
|
||||
);
|
||||
i += 1
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
dc_array_add_id(arr, 13 as uint32_t);
|
||||
dc_array_add_id(arr, 7 as uint32_t);
|
||||
dc_array_add_id(arr, 666 as uint32_t);
|
||||
dc_array_add_id(arr, 0 as uint32_t);
|
||||
dc_array_add_id(arr, 5000 as uint32_t);
|
||||
|
||||
dc_array_sort_ids(arr);
|
||||
|
||||
assert_eq!(dc_array_get_id(arr, 0 as size_t), 0);
|
||||
assert_eq!(dc_array_get_id(arr, 1 as size_t), 7);
|
||||
assert_eq!(dc_array_get_id(arr, 2 as size_t), 13);
|
||||
assert_eq!(dc_array_get_id(arr, 3 as size_t), 666);
|
||||
|
||||
let str = dc_array_get_string(arr, b"-\x00" as *const u8 as *const libc::c_char);
|
||||
assert_eq!(
|
||||
CStr::from_ptr(str as *const libc::c_char).to_str().unwrap(),
|
||||
"0-7-13-666-5000"
|
||||
);
|
||||
free(str as *mut libc::c_void);
|
||||
|
||||
dc_array_empty(arr);
|
||||
|
||||
dc_array_add_ptr(
|
||||
arr,
|
||||
b"XX\x00" as *const u8 as *const libc::c_char as *mut libc::c_void,
|
||||
);
|
||||
dc_array_add_ptr(
|
||||
arr,
|
||||
b"item1\x00" as *const u8 as *const libc::c_char as *mut libc::c_void,
|
||||
);
|
||||
dc_array_add_ptr(
|
||||
arr,
|
||||
b"bbb\x00" as *const u8 as *const libc::c_char as *mut libc::c_void,
|
||||
);
|
||||
dc_array_add_ptr(
|
||||
arr,
|
||||
b"aaa\x00" as *const u8 as *const libc::c_char as *mut libc::c_void,
|
||||
);
|
||||
dc_array_sort_strings(arr);
|
||||
|
||||
let str = dc_array_get_ptr(arr, 0 as size_t) as *mut libc::c_char;
|
||||
assert_eq!(CStr::from_ptr(str).to_str().unwrap(), "XX");
|
||||
|
||||
let str = dc_array_get_ptr(arr, 1 as size_t) as *mut libc::c_char;
|
||||
assert_eq!(CStr::from_ptr(str).to_str().unwrap(), "aaa");
|
||||
|
||||
let str = dc_array_get_ptr(arr, 2 as size_t) as *mut libc::c_char;
|
||||
assert_eq!(CStr::from_ptr(str).to_str().unwrap(), "bbb");
|
||||
|
||||
let str = dc_array_get_ptr(arr, 3 as size_t) as *mut libc::c_char;
|
||||
assert_eq!(CStr::from_ptr(str).to_str().unwrap(), "item1");
|
||||
|
||||
dc_array_unref(arr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -310,18 +310,6 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id(
|
||||
create_blocked,
|
||||
(*contact).addr,
|
||||
);
|
||||
if 0 != !('K' as i32 == 'K' as i32) as usize {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 40], &[libc::c_char; 40]>(
|
||||
b"dc_create_or_lookup_nchat_by_contact_id\x00",
|
||||
))
|
||||
.as_ptr(),
|
||||
b"../src/dc_chat.c\x00" as *const u8 as *const libc::c_char,
|
||||
1386i32,
|
||||
b"DC_PARAM_SELFTALK==\'K\'\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
stmt = dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), q);
|
||||
if !stmt.is_null() {
|
||||
if !(sqlite3_step(stmt) != 101i32) {
|
||||
|
||||
@@ -1523,7 +1523,7 @@ unsafe fn moz_autoconfigure_starttag_cb(
|
||||
}
|
||||
|
||||
fn read_autoconf_file(context: &Context, url: *const libc::c_char) -> *mut libc::c_char {
|
||||
info!(context, 0, "Testing %s ...", url);
|
||||
info!(context, 0, "Testing {} ...", to_string(url));
|
||||
|
||||
match reqwest::Client::new()
|
||||
.get(to_str(url))
|
||||
|
||||
@@ -848,13 +848,16 @@ pub unsafe fn dc_get_contact_encrinfo(
|
||||
fingerprint_other_unverified,
|
||||
);
|
||||
} else {
|
||||
let c_addr = peerstate.addr.as_ref().map(to_cstring);
|
||||
let c_addr = peerstate.addr.as_ref().map(to_cstring).unwrap_or_default();
|
||||
let addr_ptr = if peerstate.addr.is_some() {
|
||||
c_addr.as_ptr()
|
||||
} else {
|
||||
std::ptr::null()
|
||||
};
|
||||
|
||||
cat_fingerprint(
|
||||
&mut ret,
|
||||
c_addr
|
||||
.map(|a| a.as_ptr())
|
||||
.unwrap_or_else(|| std::ptr::null()),
|
||||
addr_ptr,
|
||||
fingerprint_other_verified,
|
||||
fingerprint_other_unverified,
|
||||
);
|
||||
|
||||
552
src/dc_imex.rs
552
src/dc_imex.rs
@@ -49,73 +49,63 @@ pub unsafe fn dc_imex_has_backup(
|
||||
) -> *mut libc::c_char {
|
||||
let mut ret: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut ret_backup_time = 0;
|
||||
let dir_handle: *mut DIR;
|
||||
let mut dir_entry: *mut dirent;
|
||||
let prefix_len = strlen(b"delta-chat\x00" as *const u8 as *const libc::c_char);
|
||||
let suffix_len = strlen(b"bak\x00" as *const u8 as *const libc::c_char);
|
||||
let mut curr_pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut test_sql: Option<dc_sqlite3_t> = None;
|
||||
dir_handle = opendir(dir_name);
|
||||
if dir_handle.is_null() {
|
||||
dc_log_info(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup check: Cannot open directory \"%s\".\x00" as *const u8 as *const libc::c_char,
|
||||
dir_name,
|
||||
);
|
||||
} else {
|
||||
loop {
|
||||
dir_entry = readdir(dir_handle);
|
||||
if dir_entry.is_null() {
|
||||
break;
|
||||
}
|
||||
let name: *const libc::c_char = (*dir_entry).d_name.as_mut_ptr();
|
||||
let name_len = strlen(name);
|
||||
if name_len > prefix_len
|
||||
&& strncmp(
|
||||
name,
|
||||
b"delta-chat\x00" as *const u8 as *const libc::c_char,
|
||||
prefix_len,
|
||||
) == 0i32
|
||||
&& name_len > suffix_len
|
||||
&& strncmp(
|
||||
&*name.offset((name_len - suffix_len - 1) as isize),
|
||||
b".bak\x00" as *const u8 as *const libc::c_char,
|
||||
suffix_len,
|
||||
) == 0i32
|
||||
{
|
||||
free(curr_pathNfilename as *mut libc::c_void);
|
||||
curr_pathNfilename = dc_mprintf(
|
||||
b"%s/%s\x00" as *const u8 as *const libc::c_char,
|
||||
dir_name,
|
||||
name,
|
||||
);
|
||||
if test_sql.is_some() {
|
||||
let mut test_sql = test_sql.take().unwrap();
|
||||
dc_sqlite3_unref(context, &mut test_sql);
|
||||
}
|
||||
let mut sql = dc_sqlite3_new();
|
||||
if 0 != dc_sqlite3_open(context, &mut sql, curr_pathNfilename, 0x1i32) {
|
||||
let curr_backup_time = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&mut sql,
|
||||
b"backup_time\x00" as *const u8 as *const libc::c_char,
|
||||
0i32,
|
||||
) as u64;
|
||||
if curr_backup_time > 0 && curr_backup_time > ret_backup_time {
|
||||
free(ret as *mut libc::c_void);
|
||||
ret = curr_pathNfilename;
|
||||
ret_backup_time = curr_backup_time;
|
||||
curr_pathNfilename = 0 as *mut libc::c_char
|
||||
|
||||
let dir = std::path::Path::new(to_str(dir_name));
|
||||
|
||||
if dir.is_dir() {
|
||||
match std::fs::read_dir(dir) {
|
||||
Ok(dir_handle) => {
|
||||
for entry in dir_handle {
|
||||
if entry.is_err() {
|
||||
continue;
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
let name_f = entry.file_name();
|
||||
let name = name_f.to_string_lossy();
|
||||
if name.starts_with("delta-chat") && name.ends_with(".bak") {
|
||||
free(curr_pathNfilename as *mut libc::c_void);
|
||||
curr_pathNfilename = dc_mprintf(
|
||||
b"%s/%s\x00" as *const u8 as *const libc::c_char,
|
||||
dir_name,
|
||||
to_cstring(name).as_ptr(),
|
||||
);
|
||||
if test_sql.is_some() {
|
||||
let mut test_sql = test_sql.take().unwrap();
|
||||
dc_sqlite3_unref(context, &mut test_sql);
|
||||
}
|
||||
let mut sql = dc_sqlite3_new();
|
||||
if 0 != dc_sqlite3_open(context, &mut sql, curr_pathNfilename, 0x1i32) {
|
||||
let curr_backup_time = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&mut sql,
|
||||
b"backup_time\x00" as *const u8 as *const libc::c_char,
|
||||
0,
|
||||
) as u64;
|
||||
if curr_backup_time > 0 && curr_backup_time > ret_backup_time {
|
||||
free(ret as *mut libc::c_void);
|
||||
ret = curr_pathNfilename;
|
||||
ret_backup_time = curr_backup_time;
|
||||
curr_pathNfilename = 0 as *mut libc::c_char
|
||||
}
|
||||
}
|
||||
test_sql = Some(sql);
|
||||
}
|
||||
}
|
||||
test_sql = Some(sql);
|
||||
}
|
||||
Err(_) => {
|
||||
dc_log_info(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup check: Cannot open directory \"%s\".\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
dir_name,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if !dir_handle.is_null() {
|
||||
closedir(dir_handle);
|
||||
}
|
||||
|
||||
free(curr_pathNfilename as *mut libc::c_void);
|
||||
if let Some(ref mut sql) = test_sql {
|
||||
dc_sqlite3_unref(context, sql);
|
||||
@@ -1109,269 +1099,239 @@ The macro avoids weird values of 0% or 100% while still working. */
|
||||
unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_int {
|
||||
let mut current_block: u64;
|
||||
let mut success: libc::c_int = 0i32;
|
||||
let mut closed: libc::c_int = 0i32;
|
||||
let dest_pathNfilename: *mut libc::c_char;
|
||||
let now = time();
|
||||
let mut dir_handle: *mut DIR = 0 as *mut DIR;
|
||||
let mut dir_entry: *mut dirent;
|
||||
let prefix_len = strlen(b"delta-chat\x00" as *const u8 as *const libc::c_char);
|
||||
let suffix_len = strlen(b"bak\x00" as *const u8 as *const libc::c_char);
|
||||
let mut closed: libc::c_int;
|
||||
|
||||
let mut curr_pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut buf: *mut libc::c_void = 0 as *mut libc::c_void;
|
||||
let mut buf_bytes: size_t = 0i32 as size_t;
|
||||
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
||||
let mut total_files_cnt: libc::c_int;
|
||||
let mut processed_files_cnt: libc::c_int = 0i32;
|
||||
let mut delete_dest_file: libc::c_int = 0i32;
|
||||
let mut dest_sql: Option<dc_sqlite3_t> = None;
|
||||
/* get a fine backup file name (the name includes the date so that multiple backup instances are possible)
|
||||
FIXME: we should write to a temporary file first and rename it on success. this would guarantee the backup is complete. however, currently it is not clear it the import exists in the long run (may be replaced by a restore-from-imap)*/
|
||||
// get a fine backup file name (the name includes the date so that multiple backup instances are possible)
|
||||
// FIXME: we should write to a temporary file first and rename it on success. this would guarantee the backup is complete. however, currently it is not clear it the import exists in the long run (may be replaced by a restore-from-imap)
|
||||
let now = time();
|
||||
let res = chrono::NaiveDateTime::from_timestamp(now as i64, 0)
|
||||
.format("delta-chat-%Y-%m-%d.bak")
|
||||
.to_string();
|
||||
let buffer = to_cstring(res);
|
||||
dest_pathNfilename = dc_get_fine_pathNfilename(context, dir, buffer.as_ptr());
|
||||
let dest_pathNfilename = dc_get_fine_pathNfilename(context, dir, buffer.as_ptr());
|
||||
if dest_pathNfilename.is_null() {
|
||||
dc_log_error(
|
||||
context,
|
||||
0i32,
|
||||
b"Cannot get backup file name.\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
dc_housekeeping(context);
|
||||
dc_sqlite3_try_execute(
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
dc_housekeeping(context);
|
||||
dc_sqlite3_try_execute(
|
||||
context,
|
||||
&context.sql.clone().read().unwrap(),
|
||||
b"VACUUM;\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
dc_sqlite3_close(context, &mut context.sql.clone().write().unwrap());
|
||||
closed = 1i32;
|
||||
dc_log_info(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup \"%s\" to \"%s\".\x00" as *const u8 as *const libc::c_char,
|
||||
context.get_dbfile(),
|
||||
dest_pathNfilename,
|
||||
);
|
||||
if !(0 == dc_copy_file(context, context.get_dbfile(), dest_pathNfilename)) {
|
||||
/* error already logged */
|
||||
dc_sqlite3_open(
|
||||
context,
|
||||
&context.sql.clone().read().unwrap(),
|
||||
b"VACUUM;\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
dc_sqlite3_close(context, &mut context.sql.clone().write().unwrap());
|
||||
closed = 1i32;
|
||||
dc_log_info(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup \"%s\" to \"%s\".\x00" as *const u8 as *const libc::c_char,
|
||||
&mut context.sql.clone().write().unwrap(),
|
||||
context.get_dbfile(),
|
||||
dest_pathNfilename,
|
||||
0i32,
|
||||
);
|
||||
if !(0 == dc_copy_file(context, context.get_dbfile(), dest_pathNfilename)) {
|
||||
closed = 0i32;
|
||||
/* add all files as blobs to the database copy (this does not require the source to be locked, neigher the destination as it is used only here) */
|
||||
/*for logging only*/
|
||||
let mut sql = dc_sqlite3_new();
|
||||
if 0 != dc_sqlite3_open(context, &mut sql, dest_pathNfilename, 0i32) {
|
||||
/* error already logged */
|
||||
dc_sqlite3_open(
|
||||
if 0 == dc_sqlite3_table_exists(
|
||||
context,
|
||||
&mut context.sql.clone().write().unwrap(),
|
||||
context.get_dbfile(),
|
||||
0i32,
|
||||
);
|
||||
closed = 0i32;
|
||||
/* add all files as blobs to the database copy (this does not require the source to be locked, neigher the destination as it is used only here) */
|
||||
/*for logging only*/
|
||||
let mut sql = dc_sqlite3_new();
|
||||
if 0 != dc_sqlite3_open(context, &mut sql, dest_pathNfilename, 0i32) {
|
||||
/* error already logged */
|
||||
if 0 == dc_sqlite3_table_exists(
|
||||
context,
|
||||
&mut sql,
|
||||
b"backup_blobs\x00" as *const u8 as *const libc::c_char,
|
||||
) {
|
||||
if 0 ==
|
||||
dc_sqlite3_execute(context, &mut sql,
|
||||
b"CREATE TABLE backup_blobs (id INTEGER PRIMARY KEY, file_name, file_content);\x00"
|
||||
as *const u8 as
|
||||
*const libc::c_char) {
|
||||
&mut sql,
|
||||
b"backup_blobs\x00" as *const u8 as *const libc::c_char,
|
||||
) {
|
||||
if 0 ==
|
||||
dc_sqlite3_execute(context, &mut sql,
|
||||
b"CREATE TABLE backup_blobs (id INTEGER PRIMARY KEY, file_name, file_content);\x00"
|
||||
as *const u8 as
|
||||
*const libc::c_char) {
|
||||
/* error already logged */
|
||||
current_block = 11487273724841241105;
|
||||
} else { current_block = 14648156034262866959; }
|
||||
} else {
|
||||
current_block = 14648156034262866959;
|
||||
}
|
||||
match current_block {
|
||||
11487273724841241105 => {}
|
||||
_ => {
|
||||
total_files_cnt = 0i32;
|
||||
dir_handle = opendir(context.get_blobdir());
|
||||
if dir_handle.is_null() {
|
||||
dc_log_error(
|
||||
} else {
|
||||
current_block = 14648156034262866959;
|
||||
}
|
||||
match current_block {
|
||||
11487273724841241105 => {}
|
||||
_ => {
|
||||
let mut total_files_cnt = 0;
|
||||
let dir = std::path::Path::new(to_str(context.get_blobdir()));
|
||||
let dir_handle = std::fs::read_dir(dir);
|
||||
if dir_handle.is_err() {
|
||||
dc_log_error(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup: Cannot get info for blob-directory \"%s\".\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
);
|
||||
} else {
|
||||
let dir_handle = dir_handle.unwrap();
|
||||
total_files_cnt += dir_handle.filter(|r| r.is_ok()).count();
|
||||
|
||||
if total_files_cnt > 0 {
|
||||
// scan directory, pass 2: copy files
|
||||
let dir_handle = std::fs::read_dir(dir);
|
||||
if dir_handle.is_err() {
|
||||
dc_log_error(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup: Cannot copy from blob-directory \"%s\".\x00"
|
||||
as *const u8
|
||||
as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
);
|
||||
} else {
|
||||
let dir_handle = dir_handle.unwrap();
|
||||
stmt = dc_sqlite3_prepare(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup: Cannot get info for blob-directory \"%s\".\x00"
|
||||
as *const u8
|
||||
as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
&mut sql,
|
||||
b"INSERT INTO backup_blobs (file_name, file_content) VALUES (?, ?);\x00"
|
||||
as *const u8 as
|
||||
*const libc::c_char
|
||||
);
|
||||
} else {
|
||||
loop {
|
||||
dir_entry = readdir(dir_handle);
|
||||
if dir_entry.is_null() {
|
||||
break;
|
||||
}
|
||||
total_files_cnt += 1
|
||||
}
|
||||
closedir(dir_handle);
|
||||
dir_handle = 0 as *mut DIR;
|
||||
if total_files_cnt > 0i32 {
|
||||
/* scan directory, pass 2: copy files */
|
||||
dir_handle = opendir(context.get_blobdir());
|
||||
if dir_handle.is_null() {
|
||||
dc_log_error(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup: Cannot copy from blob-directory \"%s\".\x00"
|
||||
as *const u8
|
||||
as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
);
|
||||
current_block = 11487273724841241105;
|
||||
} else {
|
||||
stmt =
|
||||
dc_sqlite3_prepare(
|
||||
context,
|
||||
&mut sql,
|
||||
b"INSERT INTO backup_blobs (file_name, file_content) VALUES (?, ?);\x00"
|
||||
as *const u8 as
|
||||
*const libc::c_char);
|
||||
loop {
|
||||
dir_entry = readdir(dir_handle);
|
||||
if dir_entry.is_null() {
|
||||
current_block = 2631791190359682872;
|
||||
break;
|
||||
|
||||
let mut processed_files_cnt = 0;
|
||||
for entry in dir_handle {
|
||||
if entry.is_err() {
|
||||
current_block = 2631791190359682872;
|
||||
break;
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
if context
|
||||
.running_state
|
||||
.clone()
|
||||
.read()
|
||||
.unwrap()
|
||||
.shall_stop_ongoing
|
||||
{
|
||||
delete_dest_file = 1;
|
||||
current_block = 11487273724841241105;
|
||||
break;
|
||||
} else {
|
||||
processed_files_cnt += 1;
|
||||
let mut permille =
|
||||
processed_files_cnt * 1000 / total_files_cnt;
|
||||
if permille < 10 {
|
||||
permille = 10;
|
||||
}
|
||||
if context
|
||||
.running_state
|
||||
.clone()
|
||||
.read()
|
||||
.unwrap()
|
||||
.shall_stop_ongoing
|
||||
{
|
||||
delete_dest_file = 1i32;
|
||||
current_block = 11487273724841241105;
|
||||
break;
|
||||
} else {
|
||||
processed_files_cnt += 1;
|
||||
let mut permille: libc::c_int =
|
||||
processed_files_cnt * 1000i32 / total_files_cnt;
|
||||
if permille < 10i32 {
|
||||
permille = 10i32
|
||||
}
|
||||
if permille > 990i32 {
|
||||
permille = 990i32
|
||||
}
|
||||
(context.cb)(
|
||||
context,
|
||||
Event::IMEX_PROGRESS,
|
||||
permille as uintptr_t,
|
||||
0i32 as uintptr_t,
|
||||
if permille > 990 {
|
||||
permille = 990;
|
||||
}
|
||||
(context.cb)(
|
||||
context,
|
||||
Event::IMEX_PROGRESS,
|
||||
permille as uintptr_t,
|
||||
0i32 as uintptr_t,
|
||||
);
|
||||
|
||||
let name_f = entry.file_name();
|
||||
let name = name_f.to_string_lossy();
|
||||
if name.starts_with("delt-chat") && name.ends_with(".bak") {
|
||||
// dc_log_info(context, 0, "Backup: Skipping \"%s\".", name);
|
||||
free(curr_pathNfilename as *mut libc::c_void);
|
||||
let name_c = to_cstring(name);
|
||||
curr_pathNfilename = dc_mprintf(
|
||||
b"%s/%s\x00" as *const u8 as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
name_c.as_ptr(),
|
||||
);
|
||||
/* name without path; may also be `.` or `..` */
|
||||
let name: *mut libc::c_char =
|
||||
(*dir_entry).d_name.as_mut_ptr();
|
||||
let name_len = strlen(name);
|
||||
if !(name_len == 1
|
||||
&& *name.offset(0isize) as libc::c_int
|
||||
== '.' as i32
|
||||
|| name_len == 2
|
||||
&& *name.offset(0isize) as libc::c_int
|
||||
== '.' as i32
|
||||
&& *name.offset(1isize) as libc::c_int
|
||||
== '.' as i32
|
||||
|| name_len > prefix_len
|
||||
&& strncmp(
|
||||
name,
|
||||
b"delta-chat\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
prefix_len,
|
||||
) == 0i32
|
||||
&& name_len > suffix_len
|
||||
&& strncmp(
|
||||
&mut *name.offset(
|
||||
(name_len - suffix_len - 1) as isize,
|
||||
),
|
||||
b".bak\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
suffix_len,
|
||||
) == 0i32)
|
||||
free(buf);
|
||||
if 0 == dc_read_file(
|
||||
context,
|
||||
curr_pathNfilename,
|
||||
&mut buf,
|
||||
&mut buf_bytes,
|
||||
) || buf.is_null()
|
||||
|| buf_bytes <= 0
|
||||
{
|
||||
//dc_log_info(context, 0, "Backup: Skipping \"%s\".", name);
|
||||
free(curr_pathNfilename as *mut libc::c_void);
|
||||
curr_pathNfilename = dc_mprintf(
|
||||
b"%s/%s\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
name,
|
||||
);
|
||||
free(buf);
|
||||
if 0 == dc_read_file(
|
||||
context,
|
||||
curr_pathNfilename,
|
||||
&mut buf,
|
||||
&mut buf_bytes,
|
||||
) || buf.is_null()
|
||||
|| buf_bytes <= 0
|
||||
{
|
||||
continue;
|
||||
}
|
||||
sqlite3_bind_text(stmt, 1i32, name, -1i32, None);
|
||||
sqlite3_bind_blob(
|
||||
stmt,
|
||||
2i32,
|
||||
buf,
|
||||
buf_bytes as libc::c_int,
|
||||
None,
|
||||
);
|
||||
if sqlite3_step(stmt) != 101i32 {
|
||||
dc_log_error(context,
|
||||
0i32,
|
||||
b"Disk full? Cannot add file \"%s\" to backup.\x00"
|
||||
as
|
||||
*const u8
|
||||
as
|
||||
*const libc::c_char,
|
||||
curr_pathNfilename);
|
||||
/* this is not recoverable! writing to the sqlite database should work! */
|
||||
current_block = 11487273724841241105;
|
||||
break;
|
||||
} else {
|
||||
sqlite3_reset(stmt);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
sqlite3_bind_text(
|
||||
stmt,
|
||||
1i32,
|
||||
name_c.as_ptr(),
|
||||
-1i32,
|
||||
None,
|
||||
);
|
||||
sqlite3_bind_blob(
|
||||
stmt,
|
||||
2i32,
|
||||
buf,
|
||||
buf_bytes as libc::c_int,
|
||||
None,
|
||||
);
|
||||
if sqlite3_step(stmt) != 101i32 {
|
||||
dc_log_error(
|
||||
context,
|
||||
0i32,
|
||||
b"Disk full? Cannot add file \"%s\" to backup.\x00"
|
||||
as *const u8
|
||||
as *const libc::c_char,
|
||||
curr_pathNfilename,
|
||||
);
|
||||
/* this is not recoverable! writing to the sqlite database should work! */
|
||||
current_block = 11487273724841241105;
|
||||
break;
|
||||
} else {
|
||||
sqlite3_reset(stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dc_log_info(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup: No files to copy.\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
);
|
||||
current_block = 2631791190359682872;
|
||||
}
|
||||
match current_block {
|
||||
11487273724841241105 => {}
|
||||
_ => {
|
||||
dc_sqlite3_set_config_int(
|
||||
context,
|
||||
&mut sql,
|
||||
b"backup_time\x00" as *const u8 as *const libc::c_char,
|
||||
now as int32_t,
|
||||
);
|
||||
(context.cb)(
|
||||
context,
|
||||
Event::IMEX_FILE_WRITTEN,
|
||||
dest_pathNfilename as uintptr_t,
|
||||
0i32 as uintptr_t,
|
||||
);
|
||||
success = 1i32
|
||||
}
|
||||
} else {
|
||||
dc_log_info(
|
||||
context,
|
||||
0i32,
|
||||
b"Backup: No files to copy.\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
);
|
||||
current_block = 2631791190359682872;
|
||||
}
|
||||
match current_block {
|
||||
11487273724841241105 => {}
|
||||
_ => {
|
||||
dc_sqlite3_set_config_int(
|
||||
context,
|
||||
&mut sql,
|
||||
b"backup_time\x00" as *const u8 as *const libc::c_char,
|
||||
now as int32_t,
|
||||
);
|
||||
(context.cb)(
|
||||
context,
|
||||
Event::IMEX_FILE_WRITTEN,
|
||||
dest_pathNfilename as uintptr_t,
|
||||
0i32 as uintptr_t,
|
||||
);
|
||||
success = 1i32
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dest_sql = Some(sql);
|
||||
}
|
||||
}
|
||||
if !dir_handle.is_null() {
|
||||
closedir(dir_handle);
|
||||
dest_sql = Some(sql);
|
||||
}
|
||||
if 0 != closed {
|
||||
dc_sqlite3_open(
|
||||
@@ -1407,8 +1367,6 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
Maybe we should make the "default" key handlong also a little bit smarter
|
||||
(currently, the last imported key is the standard key unless it contains the string "legacy" in its name) */
|
||||
let mut imported_cnt: libc::c_int = 0i32;
|
||||
let mut dir_handle = 0 as *mut DIR;
|
||||
let mut dir_entry: *mut dirent;
|
||||
let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut path_plus_name: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut set_default: libc::c_int;
|
||||
@@ -1420,8 +1378,9 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
// a pointer inside buf2, MUST NOT be free()'d
|
||||
let mut buf2_headerline: *const libc::c_char = 0 as *const libc::c_char;
|
||||
if !dir_name.is_null() {
|
||||
dir_handle = opendir(dir_name);
|
||||
if dir_handle.is_null() {
|
||||
let dir = std::path::Path::new(to_str(dir_name));
|
||||
let dir_handle = std::fs::read_dir(dir);
|
||||
if dir_handle.is_err() {
|
||||
dc_log_error(
|
||||
context,
|
||||
0i32,
|
||||
@@ -1429,13 +1388,16 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
dir_name,
|
||||
);
|
||||
} else {
|
||||
loop {
|
||||
dir_entry = readdir(dir_handle);
|
||||
if dir_entry.is_null() {
|
||||
let dir_handle = dir_handle.unwrap();
|
||||
for entry in dir_handle {
|
||||
if entry.is_err() {
|
||||
break;
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
free(suffix as *mut libc::c_void);
|
||||
suffix = dc_get_filesuffix_lc((*dir_entry).d_name.as_mut_ptr());
|
||||
let name_f = entry.file_name();
|
||||
let name_c = to_cstring(name_f.to_string_lossy());
|
||||
suffix = dc_get_filesuffix_lc(name_c.as_ptr());
|
||||
if suffix.is_null()
|
||||
|| strcmp(suffix, b"asc\x00" as *const u8 as *const libc::c_char) != 0i32
|
||||
{
|
||||
@@ -1445,7 +1407,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
path_plus_name = dc_mprintf(
|
||||
b"%s/%s\x00" as *const u8 as *const libc::c_char,
|
||||
dir_name,
|
||||
(*dir_entry).d_name.as_mut_ptr(),
|
||||
name_c.as_ptr(),
|
||||
);
|
||||
dc_log_info(
|
||||
context,
|
||||
@@ -1489,7 +1451,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
}
|
||||
set_default = 1i32;
|
||||
if !strstr(
|
||||
(*dir_entry).d_name.as_mut_ptr(),
|
||||
name_c.as_ptr(),
|
||||
b"legacy\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
.is_null()
|
||||
@@ -1518,9 +1480,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
}
|
||||
}
|
||||
}
|
||||
if !dir_handle.is_null() {
|
||||
closedir(dir_handle);
|
||||
}
|
||||
|
||||
free(suffix as *mut libc::c_void);
|
||||
free(path_plus_name as *mut libc::c_void);
|
||||
free(buf as *mut libc::c_void);
|
||||
|
||||
@@ -94,16 +94,14 @@ macro_rules! info {
|
||||
($ctx:expr, $data1:expr, $msg:expr) => {
|
||||
info!($ctx, $data1, $msg,)
|
||||
};
|
||||
($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {
|
||||
($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {{
|
||||
let formatted = format!($msg, $($args),*);
|
||||
let formatted_c = crate::dc_tools::to_cstring(formatted);
|
||||
unsafe {
|
||||
dc_log_info(
|
||||
$ctx,
|
||||
$data1,
|
||||
std::ffi::CString::new($msg).unwrap().as_ptr(),
|
||||
$($args),*
|
||||
)
|
||||
($ctx.cb)($ctx, crate::constants::Event::INFO, $data1 as uintptr_t,
|
||||
crate::dc_tools::dc_strdup(formatted_c.as_ptr()) as uintptr_t)
|
||||
}
|
||||
};
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
@@ -112,13 +110,11 @@ macro_rules! warn {
|
||||
warn!($ctx, $data1, $msg,)
|
||||
};
|
||||
($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {
|
||||
let formatted = format!($msg, $($args),*);
|
||||
let formatted_c = crate::dc_tools::to_cstring(formatted);
|
||||
unsafe {
|
||||
dc_log_warning(
|
||||
$ctx,
|
||||
$data1,
|
||||
std::ffi::CString::new($msg).unwrap().as_ptr(),
|
||||
$($args),*
|
||||
)
|
||||
($ctx.cb)($ctx, crate::constants::Event::WARNING, $data1 as libc::uintptr_t,
|
||||
crate::dc_tools::dc_strdup(formatted_c.as_ptr()) as libc::uintptr_t)
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -129,13 +125,11 @@ macro_rules! error {
|
||||
error!($ctx, $data1, $msg,)
|
||||
};
|
||||
($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {
|
||||
let formatted = format!($msg, $($args),*);
|
||||
let formatted_c = crate::dc_tools::to_cstring(formatted);
|
||||
unsafe {
|
||||
dc_log_error(
|
||||
$ctx,
|
||||
$data1,
|
||||
std::ffi::CString::new($msg).unwrap().as_ptr(),
|
||||
$($args),*
|
||||
)
|
||||
($ctx.cb)($ctx, crate::constants::Event::ERROR, $data1 as uintptr_t,
|
||||
crate::dc_tools::dc_strdup(formatted_c.as_ptr()) as uintptr_t)
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -146,14 +140,11 @@ macro_rules! log_event {
|
||||
log_event!($ctx, $data1, $msg,)
|
||||
};
|
||||
($ctx:expr, $event:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {
|
||||
let formatted = format!($msg, $($args),*);
|
||||
let formatted_c = crate::dc_tools::to_cstring(formatted);
|
||||
unsafe {
|
||||
dc_log_event(
|
||||
$ctx,
|
||||
$event,
|
||||
$data1,
|
||||
std::ffi::CString::new($msg).unwrap().as_ptr(),
|
||||
$($args),*
|
||||
)
|
||||
($ctx.cb)($ctx, $event, $data1 as uintptr_t,
|
||||
crate::dc_tools::dc_strdup(formatted_c.as_ptr()) as uintptr_t)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -372,3 +372,68 @@ pub unsafe fn dc_param_set_float(param: *mut dc_param_t, key: libc::c_int, value
|
||||
dc_param_set(param, key, value_str);
|
||||
free(value_str as *mut libc::c_void);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[test]
|
||||
fn test_dc_param() {
|
||||
unsafe {
|
||||
let p1: *mut dc_param_t = dc_param_new();
|
||||
dc_param_set_packed(
|
||||
p1,
|
||||
b"\r\n\r\na=1\nb=2\n\nc = 3 \x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
|
||||
assert_eq!(dc_param_get_int(p1, 'a' as i32, 0), 1);
|
||||
assert_eq!(dc_param_get_int(p1, 'b' as i32, 0), 2);
|
||||
assert_eq!(dc_param_get_int(p1, 'c' as i32, 0), 0);
|
||||
assert_eq!(dc_param_exists(p1, 'c' as i32), 0);
|
||||
|
||||
dc_param_set_int(p1, 'd' as i32, 4i32);
|
||||
|
||||
assert_eq!(dc_param_get_int(p1, 'd' as i32, 0), 4);
|
||||
|
||||
dc_param_empty(p1);
|
||||
dc_param_set(
|
||||
p1,
|
||||
'a' as i32,
|
||||
b"foo\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
dc_param_set_int(p1, 'b' as i32, 2i32);
|
||||
dc_param_set(p1, 'c' as i32, 0 as *const libc::c_char);
|
||||
dc_param_set_int(p1, 'd' as i32, 4i32);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr((*p1).packed as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"a=foo\nb=2\nd=4"
|
||||
);
|
||||
|
||||
dc_param_set(p1, 'b' as i32, 0 as *const libc::c_char);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr((*p1).packed as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"a=foo\nd=4",
|
||||
);
|
||||
|
||||
dc_param_set(p1, 'a' as i32, 0 as *const libc::c_char);
|
||||
dc_param_set(p1, 'd' as i32, 0 as *const libc::c_char);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr((*p1).packed as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"",
|
||||
);
|
||||
|
||||
dc_param_unref(p1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
15
src/dc_qr.rs
15
src/dc_qr.rs
@@ -245,13 +245,20 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
|
||||
if addr.is_null() || invitenumber.is_null() || auth.is_null() {
|
||||
if let Some(peerstate) = peerstate {
|
||||
(*qr_parsed).state = 210i32;
|
||||
let c_addr = peerstate.addr.as_ref().map(to_cstring);
|
||||
let c_addr = peerstate
|
||||
.addr
|
||||
.as_ref()
|
||||
.map(to_cstring)
|
||||
.unwrap_or_default();
|
||||
let addr_ptr = if peerstate.addr.is_some() {
|
||||
c_addr.as_ptr()
|
||||
} else {
|
||||
std::ptr::null()
|
||||
};
|
||||
(*qr_parsed).id = dc_add_or_lookup_contact(
|
||||
context,
|
||||
0 as *const libc::c_char,
|
||||
c_addr
|
||||
.map(|a| a.as_ptr())
|
||||
.unwrap_or_else(|| std::ptr::null()),
|
||||
addr_ptr,
|
||||
0x80i32,
|
||||
0 as *mut libc::c_int,
|
||||
);
|
||||
|
||||
@@ -726,58 +726,11 @@ pub unsafe fn dc_sqlite3_open(
|
||||
as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
if 0 != !(DC_MOVE_STATE_UNDEFINED as libc::c_int == 0) as usize {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>(
|
||||
b"dc_sqlite3_open\x00",
|
||||
))
|
||||
.as_ptr(),
|
||||
b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char,
|
||||
559,
|
||||
b"DC_MOVE_STATE_UNDEFINED == 0\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
if 0 != !(DC_MOVE_STATE_PENDING as libc::c_int == 1) as usize {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>(
|
||||
b"dc_sqlite3_open\x00",
|
||||
))
|
||||
.as_ptr(),
|
||||
b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char,
|
||||
560,
|
||||
b"DC_MOVE_STATE_PENDING == 1\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
if 0 != !(DC_MOVE_STATE_STAY as libc::c_int == 2) as usize {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>(
|
||||
b"dc_sqlite3_open\x00",
|
||||
))
|
||||
.as_ptr(),
|
||||
b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char,
|
||||
561,
|
||||
b"DC_MOVE_STATE_STAY == 2\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
if 0 != !(DC_MOVE_STATE_MOVING as libc::c_int == 3) as usize {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>(
|
||||
b"dc_sqlite3_open\x00",
|
||||
))
|
||||
.as_ptr(),
|
||||
b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char,
|
||||
562,
|
||||
b"DC_MOVE_STATE_MOVING == 3\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
assert_eq!(DC_MOVE_STATE_UNDEFINED as libc::c_int, 0);
|
||||
assert_eq!(DC_MOVE_STATE_PENDING as libc::c_int, 1);
|
||||
assert_eq!(DC_MOVE_STATE_STAY as libc::c_int, 2);
|
||||
assert_eq!(DC_MOVE_STATE_MOVING as libc::c_int, 3);
|
||||
|
||||
dbversion = 48;
|
||||
dc_sqlite3_set_config_int(
|
||||
context,
|
||||
@@ -926,18 +879,7 @@ pub unsafe fn dc_sqlite3_open(
|
||||
context.get_blobdir(),
|
||||
);
|
||||
dc_ensure_no_slash(repl_from);
|
||||
if 0 != !('f' as i32 == 'f' as i32) as usize {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>(
|
||||
b"dc_sqlite3_open\x00",
|
||||
))
|
||||
.as_ptr(),
|
||||
b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char,
|
||||
656,
|
||||
b"\'f\'==DC_PARAM_FILE\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
|
||||
let mut q3: *mut libc::c_char =
|
||||
sqlite3_mprintf(b"UPDATE msgs SET param=replace(param, \'f=%q/\', \'f=$BLOBDIR/\');\x00"
|
||||
as *const u8 as
|
||||
@@ -945,19 +887,6 @@ pub unsafe fn dc_sqlite3_open(
|
||||
repl_from);
|
||||
dc_sqlite3_execute(context, sql, q3);
|
||||
sqlite3_free(q3 as *mut libc::c_void);
|
||||
if 0 != !('i' as i32 == 'i' as i32) as usize {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>(
|
||||
b"dc_sqlite3_open\x00",
|
||||
))
|
||||
.as_ptr(),
|
||||
b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char,
|
||||
661,
|
||||
b"\'i\'==DC_PARAM_PROFILE_IMAGE\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
q3 =
|
||||
sqlite3_mprintf(b"UPDATE chats SET param=replace(param, \'i=%q/\', \'i=$BLOBDIR/\');\x00"
|
||||
as *const u8 as
|
||||
@@ -1400,8 +1329,6 @@ pub unsafe fn dc_sqlite3_get_rowid2(
|
||||
|
||||
pub unsafe fn dc_housekeeping(context: &Context) {
|
||||
let stmt;
|
||||
let dir_handle;
|
||||
let mut dir_entry;
|
||||
let mut files_in_use = HashSet::new();
|
||||
let mut path = 0 as *mut libc::c_char;
|
||||
let mut unreferenced_count = 0;
|
||||
@@ -1454,8 +1381,9 @@ pub unsafe fn dc_housekeeping(context: &Context) {
|
||||
files_in_use.len() as libc::c_int,
|
||||
);
|
||||
/* go through directory and delete unused files */
|
||||
dir_handle = opendir(context.get_blobdir());
|
||||
if dir_handle.is_null() {
|
||||
let p = std::path::Path::new(to_str(context.get_blobdir()));
|
||||
let dir_handle = std::fs::read_dir(p);
|
||||
if dir_handle.is_err() {
|
||||
dc_log_warning(
|
||||
context,
|
||||
0,
|
||||
@@ -1463,40 +1391,34 @@ pub unsafe fn dc_housekeeping(context: &Context) {
|
||||
context.get_blobdir(),
|
||||
);
|
||||
} else {
|
||||
let dir_handle = dir_handle.unwrap();
|
||||
/* avoid deletion of files that are just created to build a message object */
|
||||
let diff = std::time::Duration::from_secs(60 * 60);
|
||||
let keep_files_newer_than = std::time::SystemTime::now().checked_sub(diff).unwrap();
|
||||
|
||||
loop {
|
||||
dir_entry = readdir(dir_handle);
|
||||
if dir_entry.is_null() {
|
||||
for entry in dir_handle {
|
||||
if entry.is_err() {
|
||||
break;
|
||||
}
|
||||
/* name without path or `.` or `..` */
|
||||
let name: *const libc::c_char = (*dir_entry).d_name.as_mut_ptr();
|
||||
let name_len: libc::c_int = strlen(name) as libc::c_int;
|
||||
if name_len == 1 && *name.offset(0isize) as libc::c_int == '.' as i32
|
||||
|| name_len == 2
|
||||
&& *name.offset(0isize) as libc::c_int == '.' as i32
|
||||
&& *name.offset(1isize) as libc::c_int == '.' as i32
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if is_file_in_use(&mut files_in_use, 0 as *const libc::c_char, name)
|
||||
let entry = entry.unwrap();
|
||||
let name_f = entry.file_name();
|
||||
let name_c = to_cstring(name_f.to_string_lossy());
|
||||
|
||||
if is_file_in_use(&mut files_in_use, 0 as *const libc::c_char, name_c.as_ptr())
|
||||
|| is_file_in_use(
|
||||
&mut files_in_use,
|
||||
b".increation\x00" as *const u8 as *const libc::c_char,
|
||||
name,
|
||||
name_c.as_ptr(),
|
||||
)
|
||||
|| is_file_in_use(
|
||||
&mut files_in_use,
|
||||
b".waveform\x00" as *const u8 as *const libc::c_char,
|
||||
name,
|
||||
name_c.as_ptr(),
|
||||
)
|
||||
|| is_file_in_use(
|
||||
&mut files_in_use,
|
||||
b"-preview.jpg\x00" as *const u8 as *const libc::c_char,
|
||||
name,
|
||||
name_c.as_ptr(),
|
||||
)
|
||||
{
|
||||
continue;
|
||||
@@ -1506,7 +1428,7 @@ pub unsafe fn dc_housekeeping(context: &Context) {
|
||||
path = dc_mprintf(
|
||||
b"%s/%s\x00" as *const u8 as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
name,
|
||||
name_c.as_ptr(),
|
||||
);
|
||||
|
||||
match std::fs::metadata(std::ffi::CStr::from_ptr(path).to_str().unwrap()) {
|
||||
@@ -1525,7 +1447,7 @@ pub unsafe fn dc_housekeeping(context: &Context) {
|
||||
b"Housekeeping: Keeping new unreferenced file #%i: %s\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
unreferenced_count,
|
||||
name,
|
||||
name_c.as_ptr(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -1538,14 +1460,12 @@ pub unsafe fn dc_housekeeping(context: &Context) {
|
||||
b"Housekeeping: Deleting unreferenced file #%i: %s\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
unreferenced_count,
|
||||
name,
|
||||
name_c.as_ptr(),
|
||||
);
|
||||
dc_delete_file(context, path);
|
||||
}
|
||||
}
|
||||
if !dir_handle.is_null() {
|
||||
closedir(dir_handle);
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
free(path as *mut libc::c_void);
|
||||
|
||||
@@ -245,23 +245,18 @@ unsafe fn quote_word(
|
||||
// col = (*mmapstr).len as libc::c_int;
|
||||
cur = word;
|
||||
while i < size {
|
||||
let mut do_quote_char: libc::c_int = 0;
|
||||
match *cur as libc::c_int {
|
||||
44 | 58 | 33 | 34 | 35 | 36 | 64 | 91 | 92 | 93 | 94 | 96 | 123 | 124 | 125 | 126
|
||||
| 61 | 63 | 95 => do_quote_char = 1i32,
|
||||
let mut do_quote_char = false;
|
||||
match *cur as u8 as char {
|
||||
',' | ':' | '!' | '"' | '#' | '$' | '@' | '[' | '\\' | ']' | '^' | '`' | '{' | '|'
|
||||
| '}' | '~' | '=' | '?' | '_' => do_quote_char = true,
|
||||
_ => {
|
||||
if *cur as libc::c_uchar as libc::c_int >= 128i32 {
|
||||
do_quote_char = 1i32
|
||||
if *cur as u8 >= 128 {
|
||||
do_quote_char = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if 0 != do_quote_char {
|
||||
snprintf(
|
||||
hex.as_mut_ptr(),
|
||||
4,
|
||||
b"=%2.2X\x00" as *const u8 as *const libc::c_char,
|
||||
*cur as libc::c_uchar as libc::c_int,
|
||||
);
|
||||
if do_quote_char {
|
||||
print_hex(hex.as_mut_ptr(), cur);
|
||||
if mmap_string_append(mmapstr, hex.as_mut_ptr()).is_null() {
|
||||
return false;
|
||||
}
|
||||
@@ -716,6 +711,15 @@ pub unsafe fn dc_decode_ext_header(to_decode: *const libc::c_char) -> *mut libc:
|
||||
};
|
||||
}
|
||||
|
||||
unsafe fn print_hex(target: *mut libc::c_char, cur: *const libc::c_char) {
|
||||
assert!(!target.is_null());
|
||||
assert!(!cur.is_null());
|
||||
|
||||
let bytes = std::slice::from_raw_parts(cur as *const _, strlen(cur));
|
||||
let raw = to_cstring(format!("={}", &hex::encode_upper(bytes)[..2]));
|
||||
libc::memcpy(target as *mut _, raw.as_ptr() as *const _, 4);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -882,4 +886,74 @@ mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_print_hex() {
|
||||
let mut hex: [libc::c_char; 4] = [0; 4];
|
||||
let cur = b"helloworld" as *const u8 as *const libc::c_char;
|
||||
unsafe { print_hex(hex.as_mut_ptr(), cur) };
|
||||
assert_eq!(to_string(hex.as_ptr() as *const _), "=68");
|
||||
|
||||
let cur = b":" as *const u8 as *const libc::c_char;
|
||||
unsafe { print_hex(hex.as_mut_ptr(), cur) };
|
||||
assert_eq!(to_string(hex.as_ptr() as *const _), "=3A");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_urlencode_urldecode() {
|
||||
unsafe {
|
||||
let buf1 =
|
||||
dc_urlencode(b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr(buf1 as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"Bj%C3%B6rn+Petersen"
|
||||
);
|
||||
|
||||
let buf2 = dc_urldecode(buf1);
|
||||
|
||||
assert_eq!(
|
||||
strcmp(
|
||||
buf2,
|
||||
b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char
|
||||
),
|
||||
0
|
||||
);
|
||||
|
||||
free(buf1 as *mut libc::c_void);
|
||||
free(buf2 as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_encode_decode_modified_utf7() {
|
||||
unsafe {
|
||||
let buf1 = dc_encode_modified_utf7(
|
||||
b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char,
|
||||
1,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr(buf1 as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"Bj&APY-rn_Petersen"
|
||||
);
|
||||
|
||||
let buf2 = dc_decode_modified_utf7(buf1, 1);
|
||||
|
||||
assert_eq!(
|
||||
strcmp(
|
||||
buf2,
|
||||
b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char
|
||||
),
|
||||
0
|
||||
);
|
||||
|
||||
free(buf1 as *mut libc::c_void);
|
||||
free(buf2 as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
143
src/dc_tools.rs
143
src/dc_tools.rs
@@ -243,28 +243,13 @@ pub unsafe fn dc_null_terminate(
|
||||
}
|
||||
|
||||
pub unsafe fn dc_binary_to_uc_hex(buf: *const uint8_t, bytes: size_t) -> *mut libc::c_char {
|
||||
let mut hex: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut i;
|
||||
if !(buf.is_null() || bytes <= 0) {
|
||||
hex = calloc(
|
||||
::std::mem::size_of::<libc::c_char>(),
|
||||
bytes.wrapping_mul(2).wrapping_add(1),
|
||||
) as *mut libc::c_char;
|
||||
if !hex.is_null() {
|
||||
i = 0;
|
||||
while i < bytes {
|
||||
snprintf(
|
||||
&mut *hex.offset((i * 2) as isize) as *mut libc::c_char,
|
||||
3,
|
||||
b"%02X\x00" as *const u8 as *const libc::c_char,
|
||||
*buf.offset(i as isize) as libc::c_int,
|
||||
);
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
if buf.is_null() || bytes == 0 {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
hex
|
||||
let buf = std::slice::from_raw_parts(buf, bytes);
|
||||
let raw = hex::encode_upper(buf);
|
||||
strdup(to_cstring(raw).as_ptr())
|
||||
}
|
||||
|
||||
/* remove all \r characters from string */
|
||||
@@ -1271,21 +1256,20 @@ pub unsafe fn dc_create_folder(
|
||||
let mut success = 0;
|
||||
let pathNfilename_abs = dc_get_abs_path(context, pathNfilename);
|
||||
{
|
||||
let p = std::path::Path::new(
|
||||
std::ffi::CStr::from_ptr(pathNfilename_abs)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
);
|
||||
let p = std::path::Path::new(to_str(pathNfilename_abs));
|
||||
if !p.exists() {
|
||||
if mkdir(pathNfilename_abs, 0o755i32 as libc::mode_t) != 0i32 {
|
||||
dc_log_warning(
|
||||
context,
|
||||
0i32,
|
||||
b"Cannot create directory \"%s\".\x00" as *const u8 as *const libc::c_char,
|
||||
pathNfilename,
|
||||
);
|
||||
} else {
|
||||
success = 1;
|
||||
match fs::create_dir_all(p) {
|
||||
Ok(_) => {
|
||||
success = 1;
|
||||
}
|
||||
Err(_err) => {
|
||||
dc_log_warning(
|
||||
context,
|
||||
0i32,
|
||||
b"Cannot create directory \"%s\".\x00" as *const u8 as *const libc::c_char,
|
||||
pathNfilename,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
success = 1;
|
||||
@@ -1821,4 +1805,95 @@ mod tests {
|
||||
free(str as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_binary_to_uc_hex() {
|
||||
let buf = vec![0, 1, 2, 3, 255];
|
||||
|
||||
let raw = unsafe { dc_binary_to_uc_hex(buf.as_ptr(), buf.len()) };
|
||||
let res = to_string(raw);
|
||||
assert_eq!(res, "00010203FF");
|
||||
|
||||
unsafe { free(raw as *mut _) };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_replace_bad_utf8_chars_1() {
|
||||
unsafe {
|
||||
let buf1 = strdup(b"ol\xc3\xa1 mundo <>\"\'& \xc3\xa4\xc3\x84\xc3\xb6\xc3\x96\xc3\xbc\xc3\x9c\xc3\x9f foo\xc3\x86\xc3\xa7\xc3\x87 \xe2\x99\xa6&noent;\x00" as *const u8 as *const libc::c_char);
|
||||
let buf2 = strdup(buf1);
|
||||
|
||||
dc_replace_bad_utf8_chars(buf2);
|
||||
|
||||
assert_eq!(strcmp(buf1, buf2), 0);
|
||||
|
||||
free(buf1 as *mut libc::c_void);
|
||||
free(buf2 as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_replace_bad_utf8_chars_2() {
|
||||
unsafe {
|
||||
let buf1 = strdup(b"ISO-String with Ae: \xc4\x00" as *const u8 as *const libc::c_char);
|
||||
let buf2 = strdup(buf1);
|
||||
|
||||
dc_replace_bad_utf8_chars(buf2);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr(buf2 as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"ISO-String with Ae: _"
|
||||
);
|
||||
|
||||
free(buf1 as *mut libc::c_void);
|
||||
free(buf2 as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_replace_bad_utf8_chars_3() {
|
||||
unsafe {
|
||||
let buf1 = strdup(b"\x00" as *const u8 as *const libc::c_char);
|
||||
let buf2 = strdup(buf1);
|
||||
|
||||
dc_replace_bad_utf8_chars(buf2);
|
||||
|
||||
assert_eq!(*buf2.offset(0), 0);
|
||||
|
||||
free(buf1 as *mut libc::c_void);
|
||||
free(buf2 as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_replace_bad_utf8_chars_4() {
|
||||
unsafe {
|
||||
dc_replace_bad_utf8_chars(0 as *mut libc::c_char);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_create_id() {
|
||||
unsafe {
|
||||
let buf = dc_create_id();
|
||||
assert_eq!(strlen(buf), 11);
|
||||
free(buf as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_utf8_strlen() {
|
||||
unsafe {
|
||||
assert_eq!(
|
||||
dc_utf8_strlen(b"c\x00" as *const u8 as *const libc::c_char),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
dc_utf8_strlen(b"\xc3\xa4\x00" as *const u8 as *const libc::c_char),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
230
src/imap.rs
230
src/imap.rs
@@ -5,7 +5,6 @@ use std::time::{Duration, SystemTime};
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_log::*;
|
||||
use crate::dc_loginparam::*;
|
||||
use crate::dc_sqlite3::*;
|
||||
use crate::dc_tools::{to_str, to_string};
|
||||
@@ -441,10 +440,10 @@ impl Imap {
|
||||
context,
|
||||
Event::ERROR_NETWORK,
|
||||
0,
|
||||
format!(
|
||||
"Could not connect to IMAP-server {}:{}. ({})",
|
||||
imap_server, imap_port, err
|
||||
),
|
||||
"Could not connect to IMAP-server {}:{}. ({})",
|
||||
imap_server,
|
||||
imap_port,
|
||||
err
|
||||
);
|
||||
|
||||
return 0;
|
||||
@@ -459,13 +458,7 @@ impl Imap {
|
||||
1
|
||||
}
|
||||
Err((err, _)) => {
|
||||
log_event!(
|
||||
context,
|
||||
Event::ERROR_NETWORK,
|
||||
0,
|
||||
format!("Cannot login ({})", err),
|
||||
);
|
||||
|
||||
log_event!(context, Event::ERROR_NETWORK, 0, "Cannot login ({})", err);
|
||||
self.unsetup_handle(context);
|
||||
|
||||
0
|
||||
@@ -560,9 +553,8 @@ impl Imap {
|
||||
s += c;
|
||||
s
|
||||
});
|
||||
let caps_list_c = std::ffi::CString::new(caps_list).unwrap();
|
||||
|
||||
info!(context, 0, "IMAP-capabilities:%s", caps_list_c.as_ptr());
|
||||
info!(context, 0, "IMAP-capabilities:{}", caps_list);
|
||||
|
||||
let mut config = self.config.write().unwrap();
|
||||
config.can_idle = can_idle;
|
||||
@@ -641,12 +633,7 @@ impl Imap {
|
||||
// deselect existing folder, if needed (it's also done implicitly by SELECT, however, without EXPUNGE then)
|
||||
if self.config.read().unwrap().selected_folder_needs_expunge {
|
||||
if let Some(ref folder) = self.config.read().unwrap().selected_folder {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Expunge messages in \"%s\".",
|
||||
CString::new(folder.to_owned()).unwrap().as_ptr()
|
||||
);
|
||||
info!(context, 0, "Expunge messages in \"{}\".", folder);
|
||||
|
||||
// A CLOSE-SELECT is considerably faster than an EXPUNGE-SELECT, see
|
||||
// https://tools.ietf.org/html/rfc3501#section-6.4.2
|
||||
@@ -677,7 +664,9 @@ impl Imap {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
format!("Cannot select folder: {}; {:?}.", folder.as_ref(), err)
|
||||
"Cannot select folder: {}; {:?}.",
|
||||
folder.as_ref(),
|
||||
err
|
||||
);
|
||||
|
||||
let mut config = self.config.write().unwrap();
|
||||
@@ -721,8 +710,8 @@ impl Imap {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Cannot fetch from \"%s\" - not connected.",
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
"Cannot fetch from \"{}\" - not connected.",
|
||||
folder.as_ref()
|
||||
);
|
||||
|
||||
return 0;
|
||||
@@ -732,8 +721,8 @@ impl Imap {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder \"%s\" for fetching.",
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
"Cannot select folder \"{}\" for fetching.",
|
||||
folder.as_ref()
|
||||
);
|
||||
|
||||
return 0;
|
||||
@@ -749,8 +738,8 @@ impl Imap {
|
||||
error!(
|
||||
context,
|
||||
0,
|
||||
"Cannot get UIDVALIDITY for folder \"%s\".",
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
"Cannot get UIDVALIDITY for folder \"{}\".",
|
||||
folder.as_ref(),
|
||||
);
|
||||
|
||||
return 0;
|
||||
@@ -760,12 +749,7 @@ impl Imap {
|
||||
// first time this folder is selected or UIDVALIDITY has changed, init lastseenuid and save it to config
|
||||
|
||||
if mailbox.exists == 0 {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Folder \"%s\" is empty.",
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr()
|
||||
);
|
||||
info!(context, 0, "Folder \"{}\" is empty.", folder.as_ref());
|
||||
|
||||
// set lastseenuid=0 for empty folders.
|
||||
// id we do not do this here, we'll miss the first message
|
||||
@@ -780,15 +764,13 @@ impl Imap {
|
||||
let set = format!("{}", mailbox.exists);
|
||||
match session.fetch(set, PREFETCH_FLAGS) {
|
||||
Ok(list) => list,
|
||||
Err(err) => {
|
||||
Err(_err) => {
|
||||
self.config.write().unwrap().should_reconnect = true;
|
||||
|
||||
eprintln!("fetch error: {:?}", err);
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"No result returned for folder \"%s\".",
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr()
|
||||
"No result returned for folder \"{}\".",
|
||||
folder.as_ref()
|
||||
);
|
||||
|
||||
return 0;
|
||||
@@ -810,10 +792,10 @@ impl Imap {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"lastseenuid initialized to %i for %s@%i",
|
||||
last_seen_uid as libc::c_int,
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
uid_validity as libc::c_int
|
||||
"lastseenuid initialized to {} for {}@{}",
|
||||
last_seen_uid,
|
||||
folder.as_ref(),
|
||||
uid_validity,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -858,9 +840,9 @@ impl Imap {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Read error for message %s from \"%s\", trying over later.",
|
||||
message_id_c.as_ptr(),
|
||||
folder_c.as_ptr()
|
||||
"Read error for message {} from \"{}\", trying over later.",
|
||||
message_id,
|
||||
folder.as_ref()
|
||||
);
|
||||
|
||||
read_errors += 1;
|
||||
@@ -870,9 +852,9 @@ impl Imap {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Skipping message %s from \"%s\" by precheck.",
|
||||
message_id_c.as_ptr(),
|
||||
folder_c.as_ptr()
|
||||
"Skipping message {} from \"{}\" by precheck.",
|
||||
message_id,
|
||||
folder.as_ref(),
|
||||
);
|
||||
}
|
||||
if cur_uid > new_last_seen_uid {
|
||||
@@ -891,18 +873,18 @@ impl Imap {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"%i mails read from \"%s\" with %i errors.",
|
||||
read_cnt as libc::c_int,
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
read_errors as libc::c_int,
|
||||
"{} mails read from \"{}\" with {} errors.",
|
||||
read_cnt,
|
||||
folder.as_ref(),
|
||||
read_errors
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"%i mails read from \"%s\".",
|
||||
read_cnt as libc::c_int,
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr()
|
||||
"{} mails read from \"{}\".",
|
||||
read_cnt,
|
||||
folder.as_ref()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -953,13 +935,11 @@ impl Imap {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!(
|
||||
"Error on fetching message #%i from folder \"%s\"; retry=%i; error={}.",
|
||||
err
|
||||
),
|
||||
server_uid as libc::c_int,
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
self.should_reconnect() as libc::c_int,
|
||||
"Error on fetching message #{} from folder \"{}\"; retry={}; error={}.",
|
||||
server_uid,
|
||||
folder.as_ref(),
|
||||
self.should_reconnect(),
|
||||
err
|
||||
);
|
||||
|
||||
if self.should_reconnect() {
|
||||
@@ -978,9 +958,9 @@ impl Imap {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Message #%i does not exist in folder \"%s\".",
|
||||
server_uid as libc::c_int,
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
"Message #{} does not exist in folder \"{}\".",
|
||||
server_uid,
|
||||
folder.as_ref()
|
||||
);
|
||||
} else {
|
||||
let msg = &msgs[0];
|
||||
@@ -1089,11 +1069,7 @@ impl Imap {
|
||||
self.config.write().unwrap().should_reconnect = true;
|
||||
}
|
||||
_ => {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!("IMAP-IDLE returns unknown value: {:?}", err)
|
||||
);
|
||||
warn!(context, 0, "IMAP-IDLE returns unknown value: {}", err);
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1204,12 +1180,10 @@ impl Imap {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Skip moving message; message %s/%i is already in %s...",
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
uid as libc::c_int,
|
||||
CString::new(dest_folder.as_ref().to_owned())
|
||||
.unwrap()
|
||||
.as_ptr()
|
||||
"Skip moving message; message {}/{} is already in {}...",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
dest_folder.as_ref()
|
||||
);
|
||||
|
||||
res = DC_ALREADY_DONE;
|
||||
@@ -1217,20 +1191,18 @@ impl Imap {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Moving message %s/%i to %s...",
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
uid as libc::c_int,
|
||||
CString::new(dest_folder.as_ref().to_owned())
|
||||
.unwrap()
|
||||
.as_ptr()
|
||||
"Moving message {}/{} to {}...",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
dest_folder.as_ref()
|
||||
);
|
||||
|
||||
if self.select_folder(context, Some(folder.as_ref())) == 0 {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder %s for moving message.",
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
"Cannot select folder {} for moving message.",
|
||||
folder.as_ref()
|
||||
);
|
||||
} else {
|
||||
let moved = if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
||||
@@ -1240,16 +1212,14 @@ impl Imap {
|
||||
true
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("move error: {:?}", err);
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Cannot move message, fallback to COPY/DELETE %s/%i to %s...",
|
||||
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
|
||||
uid as libc::c_int,
|
||||
CString::new(dest_folder.as_ref().to_owned())
|
||||
.unwrap()
|
||||
.as_ptr()
|
||||
"Cannot move message, fallback to COPY/DELETE {}/{} to {}: {}",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
dest_folder.as_ref(),
|
||||
err
|
||||
);
|
||||
|
||||
false
|
||||
@@ -1326,22 +1296,20 @@ impl Imap {
|
||||
if uid == 0 {
|
||||
res = DC_FAILED
|
||||
} else if self.is_connected() {
|
||||
let folder_c = CString::new(folder.as_ref().to_owned()).unwrap();
|
||||
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Marking message %s/%i as seen...",
|
||||
folder_c.as_ptr(),
|
||||
uid as libc::c_int
|
||||
"Marking message {}/{} as seen...",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
);
|
||||
|
||||
if self.select_folder(context, Some(folder)) == 0 {
|
||||
if self.select_folder(context, Some(folder.as_ref())) == 0 {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder %s for setting SEEN flag.",
|
||||
folder_c.as_ptr(),
|
||||
"Cannot select folder {} for setting SEEN flag.",
|
||||
folder.as_ref(),
|
||||
);
|
||||
} else if self.add_flag(uid, "\\Seen") == 0 {
|
||||
warn!(context, 0, "Cannot mark message as seen.",);
|
||||
@@ -1369,21 +1337,20 @@ impl Imap {
|
||||
if uid == 0 {
|
||||
res = DC_FAILED;
|
||||
} else if self.is_connected() {
|
||||
let folder_c = CString::new(folder.as_ref().to_owned()).unwrap();
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Marking message %s/%i as $MDNSent...",
|
||||
folder_c.as_ptr(),
|
||||
uid as libc::c_int
|
||||
"Marking message {}/{} as $MDNSent...",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
);
|
||||
|
||||
if self.select_folder(context, Some(folder)) == 0 {
|
||||
if self.select_folder(context, Some(folder.as_ref())) == 0 {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder %s for setting $MDNSent flag.",
|
||||
folder_c.as_ptr(),
|
||||
"Cannot select folder {} for setting $MDNSent flag.",
|
||||
folder.as_ref()
|
||||
);
|
||||
} else {
|
||||
// Check if the folder can handle the `$MDNSent` flag (see RFC 3503). If so, and not
|
||||
@@ -1447,13 +1414,11 @@ impl Imap {
|
||||
res
|
||||
};
|
||||
|
||||
let msg = if res == DC_SUCCESS {
|
||||
"$MDNSent just set and MDN will be sent."
|
||||
if res == DC_SUCCESS {
|
||||
info!(context, 0, "$MDNSent just set and MDN will be sent.");
|
||||
} else {
|
||||
"$MDNSent already set and MDN already sent."
|
||||
};
|
||||
|
||||
info!(context, 0, msg);
|
||||
info!(context, 0, "$MDNSent already set and MDN already sent.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = DC_SUCCESS;
|
||||
@@ -1491,22 +1456,18 @@ impl Imap {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
format!(
|
||||
"Marking message \"{}\", {}/{} for deletion...",
|
||||
message_id.as_ref(),
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
)
|
||||
"Marking message \"{}\", {}/{} for deletion...",
|
||||
message_id.as_ref(),
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
);
|
||||
|
||||
if self.select_folder(context, Some(&folder)) == 0 {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!(
|
||||
"Cannot select folder {} for deleting message.",
|
||||
folder.as_ref()
|
||||
)
|
||||
"Cannot select folder {} for deleting message.",
|
||||
folder.as_ref()
|
||||
);
|
||||
} else {
|
||||
let set = format!("{}", server_uid);
|
||||
@@ -1526,12 +1487,10 @@ impl Imap {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!(
|
||||
"Cannot delete on IMAP, {}/{} does not match {}.",
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
message_id.as_ref(),
|
||||
)
|
||||
"Cannot delete on IMAP, {}/{} does not match {}.",
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
message_id.as_ref(),
|
||||
);
|
||||
*server_uid = 0;
|
||||
}
|
||||
@@ -1542,11 +1501,9 @@ impl Imap {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!(
|
||||
"Cannot delete on IMAP, {}/{} not found.",
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
)
|
||||
"Cannot delete on IMAP, {}/{} not found.",
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
);
|
||||
*server_uid = 0;
|
||||
}
|
||||
@@ -1594,12 +1551,7 @@ impl Imap {
|
||||
});
|
||||
|
||||
if mvbox_folder.is_none() && 0 != (flags as usize & DC_CREATE_MVBOX) {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Creating MVBOX-folder \"%s\"...",
|
||||
b"DeltaChat\x00" as *const u8 as *const libc::c_char
|
||||
);
|
||||
info!(context, 0, "Creating MVBOX-folder \"DeltaChat\"...",);
|
||||
|
||||
if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
||||
match session.create("DeltaChat") {
|
||||
|
||||
@@ -10,7 +10,6 @@ use pgp::types::{KeyTrait, SecretKeyTrait};
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_log::*;
|
||||
use crate::dc_sqlite3::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::types::*;
|
||||
@@ -281,7 +280,7 @@ impl Key {
|
||||
strlen(file_content),
|
||||
)
|
||||
} {
|
||||
error!(context, 0, "Cannot write key to %s", file);
|
||||
error!(context, 0, "Cannot write key to {}", to_string(file));
|
||||
false
|
||||
} else {
|
||||
true
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#![allow(
|
||||
mutable_transmutes,
|
||||
non_camel_case_types,
|
||||
non_snake_case,
|
||||
non_upper_case_globals,
|
||||
@@ -7,12 +6,7 @@
|
||||
non_camel_case_types,
|
||||
non_snake_case
|
||||
)]
|
||||
#![feature(
|
||||
c_variadic,
|
||||
const_raw_ptr_to_usize_cast,
|
||||
extern_types,
|
||||
ptr_wrapping_offset_from
|
||||
)]
|
||||
#![feature(c_variadic, ptr_wrapping_offset_from)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
|
||||
@@ -5,7 +5,6 @@ use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::context::Context;
|
||||
use crate::dc_log::*;
|
||||
use crate::dc_sqlite3::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::types::*;
|
||||
@@ -125,8 +124,7 @@ pub fn dc_get_oauth2_access_token(
|
||||
if response.is_err() {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!("Error calling OAuth2 at {}: {:?}", token_url, response)
|
||||
0, "Error calling OAuth2 at {}: {:?}", token_url, response
|
||||
);
|
||||
return None;
|
||||
}
|
||||
@@ -135,11 +133,9 @@ pub fn dc_get_oauth2_access_token(
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!(
|
||||
"Error calling OAuth2 at {}: {:?}",
|
||||
token_url,
|
||||
response.status()
|
||||
)
|
||||
"Error calling OAuth2 at {}: {:?}",
|
||||
token_url,
|
||||
response.status()
|
||||
);
|
||||
return None;
|
||||
}
|
||||
@@ -148,11 +144,7 @@ pub fn dc_get_oauth2_access_token(
|
||||
if parsed.is_err() {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!(
|
||||
"Failed to parse OAuth2 JSON response from {}: error: {:?}",
|
||||
token_url, parsed
|
||||
)
|
||||
0, "Failed to parse OAuth2 JSON response from {}: error: {:?}", token_url, parsed
|
||||
);
|
||||
return None;
|
||||
}
|
||||
@@ -251,11 +243,7 @@ impl Oauth2 {
|
||||
// }
|
||||
let response = reqwest::Client::new().get(&userinfo_url).send();
|
||||
if response.is_err() {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!("Error getting userinfo: {:?}", response)
|
||||
);
|
||||
warn!(context, 0, "Error getting userinfo: {:?}", response);
|
||||
return None;
|
||||
}
|
||||
let mut response = response.unwrap();
|
||||
@@ -263,7 +251,8 @@ impl Oauth2 {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!("Error getting userinfo: {:?}", response.status())
|
||||
"Error getting userinfo: {:?}",
|
||||
response.status()
|
||||
);
|
||||
return None;
|
||||
}
|
||||
@@ -272,8 +261,7 @@ impl Oauth2 {
|
||||
if parsed.is_err() {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!("Failed to parse userinfo JSON response: {:?}", parsed)
|
||||
0, "Failed to parse userinfo JSON response: {:?}", parsed
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -543,22 +543,17 @@ impl<'a> Peerstate<'a> {
|
||||
as *const u8 as *const libc::c_char)
|
||||
};
|
||||
|
||||
let addr_c = self.addr.as_ref().map(|fp| to_cstring(fp));
|
||||
let c_addr = self.addr.as_ref().map(to_cstring).unwrap_or_default();
|
||||
let addr_ptr = if self.addr.is_some() {
|
||||
c_addr.as_ptr()
|
||||
} else {
|
||||
std::ptr::null()
|
||||
};
|
||||
|
||||
unsafe { sqlite3_bind_int64(stmt, 1, self.last_seen as sqlite3_int64) };
|
||||
unsafe { sqlite3_bind_int64(stmt, 2, self.last_seen_autocrypt as sqlite3_int64) };
|
||||
unsafe { sqlite3_bind_int64(stmt, 3, self.gossip_timestamp as sqlite3_int64) };
|
||||
unsafe {
|
||||
sqlite3_bind_text(
|
||||
stmt,
|
||||
4,
|
||||
addr_c
|
||||
.map(|addr| addr.as_ptr())
|
||||
.unwrap_or_else(|| std::ptr::null()),
|
||||
-1,
|
||||
SQLITE_TRANSIENT(),
|
||||
)
|
||||
};
|
||||
unsafe { sqlite3_bind_text(stmt, 4, addr_ptr, -1, SQLITE_TRANSIENT()) };
|
||||
|
||||
if unsafe { sqlite3_step(stmt) } == 101 {
|
||||
success = true;
|
||||
|
||||
15
src/smtp.rs
15
src/smtp.rs
@@ -1,4 +1,4 @@
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::ffi::CStr;
|
||||
|
||||
use lettre::smtp::client::net::*;
|
||||
use lettre::*;
|
||||
@@ -10,7 +10,6 @@ use crate::dc_log::*;
|
||||
use crate::dc_loginparam::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::oauth2::*;
|
||||
use crate::x::*;
|
||||
|
||||
pub struct Smtp {
|
||||
transport: Option<lettre::smtp::SmtpTransport>,
|
||||
@@ -141,11 +140,7 @@ impl Smtp {
|
||||
1
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
format!("SMTP: failed to establish connection {:?}", err)
|
||||
);
|
||||
warn!(context, 0, "SMTP: failed to establish connection {:?}", err);
|
||||
0
|
||||
}
|
||||
}
|
||||
@@ -180,11 +175,7 @@ impl Smtp {
|
||||
1
|
||||
}
|
||||
Err(err) => {
|
||||
let error_msg = format!("SMTP failed to send message: {:?}", err);
|
||||
let msg = CString::new(error_msg).unwrap();
|
||||
self.error = unsafe { strdup(msg.as_ptr()) };
|
||||
|
||||
warn!(context, 0, "%s", msg,);
|
||||
warn!(context, 0, "SMTP failed to send message: {}", err);
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::constants::Event;
|
||||
use crate::context::Context;
|
||||
|
||||
pub use libc::{dirent, tm, DIR, FILE};
|
||||
pub use libsqlite3_sys::*;
|
||||
pub use mmime::carray::*;
|
||||
pub use mmime::clist::*;
|
||||
@@ -68,7 +67,6 @@ pub type __uint16_t = libc::uint16_t;
|
||||
pub type __int32_t = libc::int32_t;
|
||||
pub type __uint64_t = libc::uint64_t;
|
||||
|
||||
pub type pid_t = libc::pid_t;
|
||||
pub type size_t = libc::size_t;
|
||||
pub type ssize_t = libc::ssize_t;
|
||||
pub type uint32_t = libc::c_uint;
|
||||
|
||||
86
src/x.rs
86
src/x.rs
@@ -1,24 +1,38 @@
|
||||
use crate::dc_strbuilder::dc_strbuilder_t;
|
||||
use crate::dc_tools::*;
|
||||
use crate::types::*;
|
||||
|
||||
pub use libc::{
|
||||
atoi, calloc, close, closedir, exit, fclose, fgets, fopen, fread, free, fseek, ftell, fwrite,
|
||||
malloc, memcmp, memcpy, memmove, memset, mkdir, open, opendir, printf, read, readdir, realloc,
|
||||
remove, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncmp, strncpy, strrchr, strspn,
|
||||
strstr, strtol, system, tolower, write,
|
||||
atoi, calloc, exit, free, malloc, memcmp, memcpy, memmove, memset, realloc, strcat, strchr,
|
||||
strcmp, strcpy, strcspn, strlen, strncmp, strncpy, strrchr, strspn, strstr, strtol, system,
|
||||
tolower, write,
|
||||
};
|
||||
|
||||
pub unsafe fn strdup(s: *const libc::c_char) -> *mut libc::c_char {
|
||||
let slen = libc::strlen(s);
|
||||
let result = libc::malloc(slen + 1);
|
||||
if s.is_null() {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
let slen = strlen(s);
|
||||
let result = malloc(slen + 1);
|
||||
if result.is_null() {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
libc::memcpy(result, s as *const _, slen + 1);
|
||||
memcpy(result, s as *const _, slen + 1);
|
||||
result as *mut _
|
||||
}
|
||||
|
||||
pub fn strndup(s: *const libc::c_char, n: libc::c_ulong) -> *mut libc::c_char {
|
||||
if s.is_null() {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
let s_r = to_str(s);
|
||||
let end = std::cmp::min(n as usize, s_r.len());
|
||||
unsafe { strdup(to_cstring(&s_r[..end]).as_ptr()) }
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn clock() -> libc::clock_t;
|
||||
pub fn qsort(
|
||||
@@ -29,14 +43,6 @@ extern "C" {
|
||||
unsafe extern "C" fn(_: *const libc::c_void, _: *const libc::c_void) -> libc::c_int,
|
||||
>,
|
||||
);
|
||||
pub fn pow(_: libc::c_double, _: libc::c_double) -> libc::c_double;
|
||||
pub fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char;
|
||||
pub fn strftime(
|
||||
_: *mut libc::c_char,
|
||||
_: size_t,
|
||||
_: *const libc::c_char,
|
||||
_: *const tm,
|
||||
) -> size_t;
|
||||
pub fn atol(_: *const libc::c_char) -> libc::c_long;
|
||||
pub fn vsnprintf(
|
||||
_: *mut libc::c_char,
|
||||
@@ -45,48 +51,12 @@ extern "C" {
|
||||
_: ::std::ffi::VaList,
|
||||
) -> libc::c_int;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn __assert_rtn(
|
||||
_: *const libc::c_char,
|
||||
_: *const libc::c_char,
|
||||
_: libc::c_int,
|
||||
_: *const libc::c_char,
|
||||
) -> !;
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
fn __assert(
|
||||
_: *const libc::c_char,
|
||||
_: *const libc::c_char,
|
||||
_: libc::c_int,
|
||||
_: *const libc::c_char,
|
||||
) -> !;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub(crate) fn snprintf(
|
||||
s: *mut libc::c_char,
|
||||
n: libc::size_t,
|
||||
format: *const libc::c_char,
|
||||
_: ...
|
||||
) -> libc::c_int;
|
||||
|
||||
// -- DC Methods
|
||||
|
||||
pub fn dc_strbuilder_catf(_: *mut dc_strbuilder_t, format: *const libc::c_char, _: ...);
|
||||
pub fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char;
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) use libc::snprintf;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub unsafe extern "C" fn __assert_rtn(
|
||||
a: *const libc::c_char,
|
||||
b: *const libc::c_char,
|
||||
c: libc::c_int,
|
||||
d: *const libc::c_char,
|
||||
) -> ! {
|
||||
__assert(a, b, c, d)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub use libc::atof;
|
||||
|
||||
@@ -133,6 +103,7 @@ pub(crate) unsafe fn strncasecmp(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::dc_tools::to_string;
|
||||
|
||||
#[test]
|
||||
fn test_atox() {
|
||||
@@ -141,4 +112,17 @@ mod tests {
|
||||
assert_eq!(atoi(b"\x00" as *const u8 as *const libc::c_char), 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strndup() {
|
||||
unsafe {
|
||||
let res = strndup(b"helloworld\x00" as *const u8 as *const libc::c_char, 4);
|
||||
assert_eq!(
|
||||
to_string(res),
|
||||
to_string(b"hell\x00" as *const u8 as *const libc::c_char)
|
||||
);
|
||||
assert_eq!(strlen(res), 4);
|
||||
free(res as *mut _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2023
tests/stress.rs
2023
tests/stress.rs
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user