mirror of
https://github.com/chatmail/core.git
synced 2026-05-04 05:46:29 +03:00
refactor: safe sql access
This commit is contained in:
712
src/context.rs
712
src/context.rs
@@ -21,6 +21,49 @@ use crate::smtp::*;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
const CONFIG_KEYS: [&'static str; 33] = [
|
||||
"addr",
|
||||
"mail_server",
|
||||
"mail_user",
|
||||
"mail_pw",
|
||||
"mail_port",
|
||||
"send_server",
|
||||
"send_user",
|
||||
"send_pw",
|
||||
"send_port",
|
||||
"server_flags",
|
||||
"imap_folder",
|
||||
"displayname",
|
||||
"selfstatus",
|
||||
"selfavatar",
|
||||
"e2ee_enabled",
|
||||
"mdns_enabled",
|
||||
"inbox_watch",
|
||||
"sentbox_watch",
|
||||
"mvbox_watch",
|
||||
"mvbox_move",
|
||||
"show_emails",
|
||||
"save_mime_headers",
|
||||
"configured_addr",
|
||||
"configured_mail_server",
|
||||
"configured_mail_user",
|
||||
"configured_mail_pw",
|
||||
"configured_mail_port",
|
||||
"configured_send_server",
|
||||
"configured_send_user",
|
||||
"configured_send_pw",
|
||||
"configured_send_port",
|
||||
"configured_server_flags",
|
||||
"configured",
|
||||
];
|
||||
|
||||
// deprecated
|
||||
const SYS_CONFIG_KEYS: [&'static str; 3] = [
|
||||
"sys.version",
|
||||
"sys.msgsize_max_recommended",
|
||||
"sys.config_keys",
|
||||
];
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Context {
|
||||
pub userdata: *mut libc::c_void,
|
||||
@@ -186,7 +229,7 @@ unsafe fn cb_receive_imf(
|
||||
context: &Context,
|
||||
imf_raw_not_terminated: *const libc::c_char,
|
||||
imf_raw_bytes: size_t,
|
||||
server_folder: *const libc::c_char,
|
||||
server_folder: &str,
|
||||
server_uid: uint32_t,
|
||||
flags: uint32_t,
|
||||
) {
|
||||
@@ -203,7 +246,7 @@ unsafe fn cb_receive_imf(
|
||||
unsafe fn cb_precheck_imf(
|
||||
context: &Context,
|
||||
rfc724_mid: *const libc::c_char,
|
||||
server_folder: *const libc::c_char,
|
||||
server_folder: &str,
|
||||
server_uid: uint32_t,
|
||||
) -> libc::c_int {
|
||||
let mut rfc724_mid_exists: libc::c_int = 0i32;
|
||||
@@ -229,7 +272,7 @@ unsafe fn cb_precheck_imf(
|
||||
rfc724_mid,
|
||||
);
|
||||
mark_seen = 1i32
|
||||
} else if strcmp(old_server_folder, server_folder) != 0i32 {
|
||||
} else if as_str(old_server_folder) != server_folder {
|
||||
dc_log_info(
|
||||
context,
|
||||
0i32,
|
||||
@@ -238,7 +281,7 @@ unsafe fn cb_precheck_imf(
|
||||
);
|
||||
dc_update_msg_move_state(context, rfc724_mid, DC_MOVE_STATE_STAY);
|
||||
}
|
||||
if strcmp(old_server_folder, server_folder) != 0i32 || old_server_uid != server_uid {
|
||||
if as_str(old_server_folder) != server_folder || old_server_uid != server_uid {
|
||||
dc_update_server_uid(context, rfc724_mid, server_folder, server_uid);
|
||||
}
|
||||
dc_do_heuristics_moves(context, server_folder, msg_id);
|
||||
@@ -257,7 +300,12 @@ unsafe fn cb_precheck_imf(
|
||||
}
|
||||
|
||||
unsafe fn cb_set_config(context: &Context, key: *const libc::c_char, value: *const libc::c_char) {
|
||||
dc_sqlite3_set_config(context, &context.sql, key, value);
|
||||
let v = if value.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(as_str(value))
|
||||
};
|
||||
dc_sqlite3_set_config(context, &context.sql, as_str(key), v);
|
||||
}
|
||||
|
||||
/* *
|
||||
@@ -272,7 +320,17 @@ unsafe fn cb_get_config(
|
||||
key: *const libc::c_char,
|
||||
def: *const libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
dc_sqlite3_get_config(context, &context.sql, key, def)
|
||||
let d = if def.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(as_str(def))
|
||||
};
|
||||
let res = dc_sqlite3_get_config(context, &context.sql, as_str(key), d);
|
||||
if let Some(res) = res {
|
||||
strdup(to_cstring(res).as_ptr())
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_context_unref(context: &mut Context) {
|
||||
@@ -355,52 +413,48 @@ pub unsafe fn dc_get_blobdir(context: &Context) -> *mut libc::c_char {
|
||||
dc_strdup(*context.blobdir.clone().read().unwrap())
|
||||
}
|
||||
|
||||
pub unsafe fn dc_set_config(
|
||||
context: &Context,
|
||||
key: *const libc::c_char,
|
||||
value: *const libc::c_char,
|
||||
) -> libc::c_int {
|
||||
pub fn dc_set_config(context: &Context, key: impl AsRef<str>, value: Option<&str>) -> libc::c_int {
|
||||
let mut ret = 0;
|
||||
let mut rel_path = 0 as *mut libc::c_char;
|
||||
|
||||
if key.is_null() || 0 == is_settable_config_key(key) {
|
||||
if !is_settable_config_key(key.as_ref()) {
|
||||
return 0;
|
||||
}
|
||||
if strcmp(key, b"selfavatar\x00" as *const u8 as *const libc::c_char) == 0 && !value.is_null() {
|
||||
rel_path = dc_strdup(value);
|
||||
if !(0 == dc_make_rel_and_copy(context, &mut rel_path)) {
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, rel_path)
|
||||
|
||||
match key.as_ref() {
|
||||
"selfavatar" if value.is_some() => {
|
||||
let mut rel_path = unsafe { dc_strdup(to_cstring(value.unwrap()).as_ptr()) };
|
||||
if 0 != unsafe { dc_make_rel_and_copy(context, &mut rel_path) } {
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, Some(as_str(rel_path)));
|
||||
}
|
||||
unsafe { free(rel_path as *mut libc::c_void) };
|
||||
}
|
||||
} else if strcmp(key, b"inbox_watch\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, value);
|
||||
dc_interrupt_imap_idle(context);
|
||||
} else if strcmp(
|
||||
key,
|
||||
b"sentbox_watch\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
{
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, value);
|
||||
dc_interrupt_sentbox_idle(context);
|
||||
} else if strcmp(key, b"mvbox_watch\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, value);
|
||||
dc_interrupt_mvbox_idle(context);
|
||||
} else if strcmp(key, b"selfstatus\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
let def = dc_stock_str(context, 13);
|
||||
ret = dc_sqlite3_set_config(
|
||||
context,
|
||||
&context.sql,
|
||||
key,
|
||||
if value.is_null() || strcmp(value, def) == 0 {
|
||||
0 as *const libc::c_char
|
||||
"inbox_watch" => {
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, value);
|
||||
unsafe { dc_interrupt_imap_idle(context) };
|
||||
}
|
||||
"sentbox_watch" => {
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, value);
|
||||
unsafe { dc_interrupt_sentbox_idle(context) };
|
||||
}
|
||||
"mvbox_watch" => {
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, value);
|
||||
unsafe { dc_interrupt_mvbox_idle(context) };
|
||||
}
|
||||
"selfstatus" => {
|
||||
let def = unsafe { dc_stock_str(context, 13) };
|
||||
let val = if value.is_none() || value.unwrap() == as_str(def) {
|
||||
None
|
||||
} else {
|
||||
value
|
||||
},
|
||||
);
|
||||
free(def as *mut libc::c_void);
|
||||
} else {
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, value);
|
||||
};
|
||||
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, val);
|
||||
unsafe { free(def as *mut libc::c_void) };
|
||||
}
|
||||
_ => {
|
||||
ret = dc_sqlite3_set_config(context, &context.sql, key, value);
|
||||
}
|
||||
}
|
||||
free(rel_path as *mut libc::c_void);
|
||||
ret
|
||||
}
|
||||
|
||||
@@ -408,303 +462,136 @@ pub unsafe fn dc_set_config(
|
||||
* INI-handling, Information
|
||||
******************************************************************************/
|
||||
|
||||
unsafe fn is_settable_config_key(key: *const libc::c_char) -> libc::c_int {
|
||||
let mut i = 0;
|
||||
while i
|
||||
< (::std::mem::size_of::<[*const libc::c_char; 33]>())
|
||||
.wrapping_div(::std::mem::size_of::<*mut libc::c_char>())
|
||||
{
|
||||
if strcmp(key, config_keys[i as usize]) == 0 {
|
||||
return 1;
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
0
|
||||
fn is_settable_config_key(key: impl AsRef<str>) -> bool {
|
||||
CONFIG_KEYS
|
||||
.into_iter()
|
||||
.find(|c| **c == key.as_ref())
|
||||
.is_some()
|
||||
}
|
||||
|
||||
static mut config_keys: [*const libc::c_char; 33] = [
|
||||
b"addr\x00" as *const u8 as *const libc::c_char,
|
||||
b"mail_server\x00" as *const u8 as *const libc::c_char,
|
||||
b"mail_user\x00" as *const u8 as *const libc::c_char,
|
||||
b"mail_pw\x00" as *const u8 as *const libc::c_char,
|
||||
b"mail_port\x00" as *const u8 as *const libc::c_char,
|
||||
b"send_server\x00" as *const u8 as *const libc::c_char,
|
||||
b"send_user\x00" as *const u8 as *const libc::c_char,
|
||||
b"send_pw\x00" as *const u8 as *const libc::c_char,
|
||||
b"send_port\x00" as *const u8 as *const libc::c_char,
|
||||
b"server_flags\x00" as *const u8 as *const libc::c_char,
|
||||
b"imap_folder\x00" as *const u8 as *const libc::c_char,
|
||||
b"displayname\x00" as *const u8 as *const libc::c_char,
|
||||
b"selfstatus\x00" as *const u8 as *const libc::c_char,
|
||||
b"selfavatar\x00" as *const u8 as *const libc::c_char,
|
||||
b"e2ee_enabled\x00" as *const u8 as *const libc::c_char,
|
||||
b"mdns_enabled\x00" as *const u8 as *const libc::c_char,
|
||||
b"inbox_watch\x00" as *const u8 as *const libc::c_char,
|
||||
b"sentbox_watch\x00" as *const u8 as *const libc::c_char,
|
||||
b"mvbox_watch\x00" as *const u8 as *const libc::c_char,
|
||||
b"mvbox_move\x00" as *const u8 as *const libc::c_char,
|
||||
b"show_emails\x00" as *const u8 as *const libc::c_char,
|
||||
b"save_mime_headers\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_addr\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_mail_server\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_mail_user\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_mail_pw\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_mail_port\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_send_server\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_send_user\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_send_pw\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_send_port\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured_server_flags\x00" as *const u8 as *const libc::c_char,
|
||||
b"configured\x00" as *const u8 as *const libc::c_char,
|
||||
];
|
||||
|
||||
pub unsafe fn dc_get_config(context: &Context, key: *const libc::c_char) -> *mut libc::c_char {
|
||||
let mut value = 0 as *mut libc::c_char;
|
||||
if !key.is_null()
|
||||
&& *key.offset(0isize) as libc::c_int == 's' as i32
|
||||
&& *key.offset(1isize) as libc::c_int == 'y' as i32
|
||||
&& *key.offset(2isize) as libc::c_int == 's' as i32
|
||||
&& *key.offset(3isize) as libc::c_int == '.' as i32
|
||||
{
|
||||
return get_sys_config_str(key);
|
||||
pub fn dc_get_config(context: &Context, key: impl AsRef<str>) -> String {
|
||||
if key.as_ref().starts_with("sys") {
|
||||
return get_sys_config_str(key.as_ref());
|
||||
}
|
||||
|
||||
if key.is_null() || 0 == is_gettable_config_key(key) {
|
||||
return dc_strdup(b"\x00" as *const u8 as *const libc::c_char);
|
||||
if !is_gettable_config_key(key.as_ref()) {
|
||||
return "".into();
|
||||
}
|
||||
|
||||
if strcmp(key, b"selfavatar\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
let rel_path: *mut libc::c_char =
|
||||
dc_sqlite3_get_config(context, &context.sql, key, 0 as *const libc::c_char);
|
||||
if !rel_path.is_null() {
|
||||
value = dc_get_abs_path(context, rel_path);
|
||||
free(rel_path as *mut libc::c_void);
|
||||
let value = match key.as_ref() {
|
||||
"selfavatar" => {
|
||||
let rel_path = dc_sqlite3_get_config(context, &context.sql, key.as_ref(), None);
|
||||
rel_path.map(|p| {
|
||||
let v = unsafe { dc_get_abs_path(context, to_cstring(p).as_ptr()) };
|
||||
let r = to_string(v);
|
||||
unsafe { free(v as *mut _) };
|
||||
r
|
||||
})
|
||||
}
|
||||
} else {
|
||||
value = dc_sqlite3_get_config(context, &context.sql, key, 0 as *const libc::c_char)
|
||||
}
|
||||
|
||||
if value.is_null() {
|
||||
if strcmp(key, b"e2ee_enabled\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1)
|
||||
} else if strcmp(key, b"mdns_enabled\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1)
|
||||
} else if strcmp(key, b"imap_folder\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
value = dc_strdup(b"INBOX\x00" as *const u8 as *const libc::c_char)
|
||||
} else if strcmp(key, b"inbox_watch\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1)
|
||||
} else if strcmp(
|
||||
key,
|
||||
b"sentbox_watch\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
{
|
||||
value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1)
|
||||
} else if strcmp(key, b"mvbox_watch\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1)
|
||||
} else if strcmp(key, b"mvbox_move\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1)
|
||||
} else if strcmp(key, b"show_emails\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 0)
|
||||
} else if strcmp(key, b"selfstatus\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
value = dc_stock_str(context, 13)
|
||||
} else {
|
||||
value = dc_mprintf(b"\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
|
||||
unsafe fn is_gettable_config_key(key: *const libc::c_char) -> libc::c_int {
|
||||
let mut i = 0;
|
||||
while i
|
||||
< (::std::mem::size_of::<[*const libc::c_char; 3]>())
|
||||
.wrapping_div(::std::mem::size_of::<*mut libc::c_char>())
|
||||
{
|
||||
if strcmp(key, sys_config_keys[i as usize]) == 0 {
|
||||
return 1;
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
||||
is_settable_config_key(key)
|
||||
}
|
||||
|
||||
// deprecated
|
||||
static mut sys_config_keys: [*const libc::c_char; 3] = [
|
||||
b"sys.version\x00" as *const u8 as *const libc::c_char,
|
||||
b"sys.msgsize_max_recommended\x00" as *const u8 as *const libc::c_char,
|
||||
b"sys.config_keys\x00" as *const u8 as *const libc::c_char,
|
||||
];
|
||||
|
||||
unsafe fn get_sys_config_str(key: *const libc::c_char) -> *mut libc::c_char {
|
||||
if strcmp(key, b"sys.version\x00" as *const u8 as *const libc::c_char) == 0 {
|
||||
return dc_strdup(DC_VERSION_STR as *const u8 as *const libc::c_char);
|
||||
} else if strcmp(
|
||||
key,
|
||||
b"sys.msgsize_max_recommended\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
{
|
||||
return dc_mprintf(
|
||||
b"%i\x00" as *const u8 as *const libc::c_char,
|
||||
24 * 1024 * 1024 / 4 * 3,
|
||||
);
|
||||
} else if strcmp(
|
||||
key,
|
||||
b"sys.config_keys\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
{
|
||||
return get_config_keys_str();
|
||||
} else {
|
||||
return dc_strdup(0 as *const libc::c_char);
|
||||
_ => dc_sqlite3_get_config(context, &context.sql, key.as_ref(), None),
|
||||
};
|
||||
|
||||
if value.is_some() {
|
||||
return value.unwrap();
|
||||
}
|
||||
|
||||
match key.as_ref() {
|
||||
"e2ee_enabled" => "1".into(),
|
||||
"mdns_enabled" => "1".into(),
|
||||
"imap_folder" => "INBOX".into(),
|
||||
"inbox_watch" => "1".into(),
|
||||
"sentbox_watch" | "mvbox_watch" | "mvbox_move" => "1".into(),
|
||||
"show_emails" => "0".into(),
|
||||
"selfstatus" => {
|
||||
let s = unsafe { dc_stock_str(context, 13) };
|
||||
let res = to_string(s);
|
||||
unsafe { free(s as *mut _) };
|
||||
res
|
||||
}
|
||||
_ => "".into(),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn get_config_keys_str() -> *mut libc::c_char {
|
||||
let mut ret = String::new();
|
||||
let mut i = 0;
|
||||
while i
|
||||
< (::std::mem::size_of::<[*const libc::c_char; 33]>())
|
||||
.wrapping_div(::std::mem::size_of::<*mut libc::c_char>())
|
||||
{
|
||||
if !ret.is_empty() {
|
||||
ret += " ";
|
||||
}
|
||||
ret += &to_string(config_keys[i as usize]);
|
||||
i += 1
|
||||
}
|
||||
fn is_gettable_config_key(key: impl AsRef<str>) -> bool {
|
||||
SYS_CONFIG_KEYS
|
||||
.into_iter()
|
||||
.find(|c| **c == key.as_ref())
|
||||
.is_some()
|
||||
|| is_settable_config_key(key)
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
while i
|
||||
< (::std::mem::size_of::<[*const libc::c_char; 3]>())
|
||||
.wrapping_div(::std::mem::size_of::<*mut libc::c_char>())
|
||||
{
|
||||
if !ret.is_empty() {
|
||||
ret += " ";
|
||||
}
|
||||
ret += &to_string(sys_config_keys[i as usize]);
|
||||
i += 1
|
||||
fn get_sys_config_str(key: impl AsRef<str>) -> String {
|
||||
match key.as_ref() {
|
||||
"sys.version" => std::str::from_utf8(DC_VERSION_STR).unwrap().into(),
|
||||
"sys.msgsize_max_recommended" => format!("{}", 24 * 1024 * 1024 / 4 * 3),
|
||||
"sys.config_keys" => get_config_keys_str(),
|
||||
_ => "".into(),
|
||||
}
|
||||
}
|
||||
|
||||
strdup(to_cstring(ret).as_ptr())
|
||||
fn get_config_keys_str() -> String {
|
||||
let keys = &CONFIG_KEYS[..].join(" ");
|
||||
let sys_keys = &SYS_CONFIG_KEYS[..].join(" ");
|
||||
|
||||
format!("{} {}", keys, sys_keys)
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char {
|
||||
let unset = "0";
|
||||
let l = dc_loginparam_new();
|
||||
let l2 = dc_loginparam_new();
|
||||
dc_loginparam_read(
|
||||
context,
|
||||
l,
|
||||
&context.sql,
|
||||
b"\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
dc_loginparam_read(
|
||||
context,
|
||||
l2,
|
||||
&context.sql,
|
||||
b"configured_\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
let displayname = dc_sqlite3_get_config(
|
||||
context,
|
||||
&context.sql,
|
||||
b"displayname\x00" as *const u8 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
);
|
||||
let l = dc_loginparam_read(context, &context.sql, "");
|
||||
let l2 = dc_loginparam_read(context, &context.sql, "configured_");
|
||||
let displayname = dc_sqlite3_get_config(context, &context.sql, "displayname", None);
|
||||
let chats = dc_get_chat_cnt(context) as usize;
|
||||
let real_msgs = dc_get_real_msg_cnt(context) as usize;
|
||||
let deaddrop_msgs = dc_get_deaddrop_msg_cnt(context) as usize;
|
||||
let contacts = dc_get_real_contact_cnt(context) as usize;
|
||||
let is_configured = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&context.sql,
|
||||
b"configured\x00" as *const u8 as *const libc::c_char,
|
||||
0,
|
||||
);
|
||||
let dbversion = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&context.sql,
|
||||
b"dbversion\x00" as *const u8 as *const libc::c_char,
|
||||
0,
|
||||
);
|
||||
let e2ee_enabled = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&context.sql,
|
||||
b"e2ee_enabled\x00" as *const u8 as *const libc::c_char,
|
||||
1,
|
||||
);
|
||||
let mdns_enabled = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&context.sql,
|
||||
b"mdns_enabled\x00" as *const u8 as *const libc::c_char,
|
||||
1,
|
||||
);
|
||||
let mut stmt = dc_sqlite3_prepare(
|
||||
context,
|
||||
&context.sql,
|
||||
b"SELECT COUNT(*) FROM keypairs;\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
sqlite3_step(stmt);
|
||||
let prv_key_cnt = sqlite3_column_int(stmt, 0);
|
||||
sqlite3_finalize(stmt);
|
||||
stmt = dc_sqlite3_prepare(
|
||||
context,
|
||||
&context.sql,
|
||||
b"SELECT COUNT(*) FROM acpeerstates;\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
sqlite3_step(stmt);
|
||||
let pub_key_cnt = sqlite3_column_int(stmt, 0);
|
||||
sqlite3_finalize(stmt);
|
||||
let fingerprint_str =
|
||||
if let Some(key) = Key::from_self_public(context, (*l2).addr, &context.sql) {
|
||||
key.fingerprint()
|
||||
} else {
|
||||
"<Not yet calculated>".into()
|
||||
};
|
||||
let is_configured = dc_sqlite3_get_config_int(context, &context.sql, "configured", 0);
|
||||
let dbversion = dc_sqlite3_get_config_int(context, &context.sql, "dbversion", 0);
|
||||
let e2ee_enabled = dc_sqlite3_get_config_int(context, &context.sql, "e2ee_enabled", 1);
|
||||
let mdns_enabled = dc_sqlite3_get_config_int(context, &context.sql, "mdns_enabled", 1);
|
||||
|
||||
let l_readable_str = dc_loginparam_get_readable(l);
|
||||
let l2_readable_str = dc_loginparam_get_readable(l2);
|
||||
let inbox_watch = dc_sqlite3_get_config_int(
|
||||
let prv_key_cnt: Option<isize> = dc_sqlite3_query_row(
|
||||
context,
|
||||
&context.sql,
|
||||
b"inbox_watch\x00" as *const u8 as *const libc::c_char,
|
||||
1,
|
||||
);
|
||||
let sentbox_watch = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&context.sql,
|
||||
b"sentbox_watch\x00" as *const u8 as *const libc::c_char,
|
||||
1,
|
||||
);
|
||||
let mvbox_watch = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&context.sql,
|
||||
b"mvbox_watch\x00" as *const u8 as *const libc::c_char,
|
||||
1,
|
||||
);
|
||||
let mvbox_move = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&context.sql,
|
||||
b"mvbox_move\x00" as *const u8 as *const libc::c_char,
|
||||
1,
|
||||
);
|
||||
let folders_configured = dc_sqlite3_get_config_int(
|
||||
context,
|
||||
&context.sql,
|
||||
b"folders_configured\x00" as *const u8 as *const libc::c_char,
|
||||
"SELECT COUNT(*) FROM keypairs;",
|
||||
rusqlite::NO_PARAMS,
|
||||
0,
|
||||
);
|
||||
|
||||
let pub_key_cnt: Option<isize> = dc_sqlite3_query_row(
|
||||
context,
|
||||
&context.sql,
|
||||
"SELECT COUNT(*) FROM acpeerstates;",
|
||||
rusqlite::NO_PARAMS,
|
||||
0,
|
||||
);
|
||||
|
||||
let fingerprint_str = if let Some(key) = Key::from_self_public(context, &l2.addr, &context.sql)
|
||||
{
|
||||
key.fingerprint()
|
||||
} else {
|
||||
"<Not yet calculated>".into()
|
||||
};
|
||||
|
||||
let l_readable_str = dc_loginparam_get_readable(&l);
|
||||
let l2_readable_str = dc_loginparam_get_readable(&l2);
|
||||
let inbox_watch = dc_sqlite3_get_config_int(context, &context.sql, "inbox_watch", 1);
|
||||
let sentbox_watch = dc_sqlite3_get_config_int(context, &context.sql, "sentbox_watch", 1);
|
||||
let mvbox_watch = dc_sqlite3_get_config_int(context, &context.sql, "mvbox_watch", 1);
|
||||
let mvbox_move = dc_sqlite3_get_config_int(context, &context.sql, "mvbox_move", 1);
|
||||
let folders_configured =
|
||||
dc_sqlite3_get_config_int(context, &context.sql, "folders_configured", 0);
|
||||
let configured_sentbox_folder = dc_sqlite3_get_config(
|
||||
context,
|
||||
&context.sql,
|
||||
b"configured_sentbox_folder\x00" as *const u8 as *const libc::c_char,
|
||||
b"<unset>\x00" as *const u8 as *const libc::c_char,
|
||||
"configured_sentbox_folder",
|
||||
Some("<unset>"),
|
||||
);
|
||||
let configured_mvbox_folder = dc_sqlite3_get_config(
|
||||
context,
|
||||
&context.sql,
|
||||
b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char,
|
||||
b"<unset>\x00" as *const u8 as *const libc::c_char,
|
||||
"configured_mvbox_folder",
|
||||
Some("<unset>"),
|
||||
);
|
||||
|
||||
let res = format!(
|
||||
@@ -737,7 +624,7 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char {
|
||||
fingerprint={}\n\
|
||||
level=awesome\n",
|
||||
as_str(DC_VERSION_STR as *const u8 as *const _),
|
||||
as_str(libsqlite3_sys::SQLITE_VERSION as *const u8 as *const libc::c_char),
|
||||
rusqlite::version(),
|
||||
sqlite3_threadsafe(),
|
||||
// arch
|
||||
(::std::mem::size_of::<*mut libc::c_void>()).wrapping_mul(8),
|
||||
@@ -756,36 +643,24 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char {
|
||||
} else {
|
||||
unset
|
||||
},
|
||||
if !displayname.is_null() {
|
||||
as_str(displayname)
|
||||
} else {
|
||||
unset
|
||||
},
|
||||
displayname.unwrap_or_else(|| unset.into()),
|
||||
is_configured,
|
||||
as_str(l_readable_str),
|
||||
as_str(l2_readable_str),
|
||||
l_readable_str,
|
||||
l2_readable_str,
|
||||
inbox_watch,
|
||||
sentbox_watch,
|
||||
mvbox_watch,
|
||||
mvbox_move,
|
||||
folders_configured,
|
||||
as_str(configured_sentbox_folder),
|
||||
as_str(configured_mvbox_folder),
|
||||
configured_sentbox_folder.unwrap_or_default(),
|
||||
configured_mvbox_folder.unwrap_or_default(),
|
||||
mdns_enabled,
|
||||
e2ee_enabled,
|
||||
prv_key_cnt,
|
||||
pub_key_cnt,
|
||||
prv_key_cnt.unwrap_or_default(),
|
||||
pub_key_cnt.unwrap_or_default(),
|
||||
fingerprint_str,
|
||||
);
|
||||
|
||||
dc_loginparam_unref(l);
|
||||
dc_loginparam_unref(l2);
|
||||
free(displayname as *mut libc::c_void);
|
||||
free(l_readable_str as *mut libc::c_void);
|
||||
free(l2_readable_str as *mut libc::c_void);
|
||||
free(configured_sentbox_folder as *mut libc::c_void);
|
||||
free(configured_mvbox_folder as *mut libc::c_void);
|
||||
|
||||
strdup(to_cstring(res).as_ptr())
|
||||
}
|
||||
|
||||
@@ -793,155 +668,120 @@ pub unsafe fn dc_get_version_str() -> *mut libc::c_char {
|
||||
dc_strdup(DC_VERSION_STR as *const u8 as *const libc::c_char)
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_fresh_msgs(context: &Context) -> *mut dc_array_t {
|
||||
pub fn dc_get_fresh_msgs(context: &Context) -> *mut dc_array_t {
|
||||
let show_deaddrop = 0;
|
||||
let ret = dc_array_new(128 as size_t);
|
||||
let mut stmt = 0 as *mut sqlite3_stmt;
|
||||
let ret = unsafe { dc_array_new(128 as size_t) };
|
||||
if !ret.is_null() {
|
||||
stmt = dc_sqlite3_prepare(
|
||||
if let Some(ref mut stmt) = dc_sqlite3_prepare(
|
||||
context,
|
||||
&context.sql,
|
||||
b"SELECT m.id FROM msgs m LEFT JOIN contacts ct \
|
||||
ON m.from_id=ct.id LEFT JOIN chats c ON m.chat_id=c.id WHERE m.state=? \
|
||||
AND m.hidden=0 \
|
||||
AND m.chat_id>? \
|
||||
AND ct.blocked=0 \
|
||||
AND (c.blocked=0 OR c.blocked=?) ORDER BY m.timestamp DESC,m.id DESC;\x00"
|
||||
as *const u8 as *const libc::c_char,
|
||||
);
|
||||
sqlite3_bind_int(stmt, 1, 10);
|
||||
sqlite3_bind_int(stmt, 2, 9);
|
||||
sqlite3_bind_int(stmt, 3, if 0 != show_deaddrop { 2 } else { 0 });
|
||||
while sqlite3_step(stmt) == 100 {
|
||||
dc_array_add_id(ret, sqlite3_column_int(stmt, 0) as uint32_t);
|
||||
"SELECT m.id FROM msgs m LEFT JOIN contacts ct \
|
||||
ON m.from_id=ct.id LEFT JOIN chats c ON m.chat_id=c.id WHERE m.state=? \
|
||||
AND m.hidden=0 \
|
||||
AND m.chat_id>? \
|
||||
AND ct.blocked=0 \
|
||||
AND (c.blocked=0 OR c.blocked=?) ORDER BY m.timestamp DESC,m.id DESC;",
|
||||
) {
|
||||
match stmt.query_map(&[10, 9, if 0 != show_deaddrop { 2 } else { 0 }], |row| {
|
||||
row.get(0)
|
||||
}) {
|
||||
Ok(rows) => {
|
||||
for row in rows {
|
||||
if let Ok(id) = row {
|
||||
unsafe { dc_array_add_id(ret, id) };
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_err) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe fn dc_search_msgs(
|
||||
pub fn dc_search_msgs(
|
||||
context: &Context,
|
||||
chat_id: uint32_t,
|
||||
query: *const libc::c_char,
|
||||
) -> *mut dc_array_t {
|
||||
let mut success = 0;
|
||||
let ret = dc_array_new(100 as size_t);
|
||||
let mut strLikeInText = 0 as *mut libc::c_char;
|
||||
let mut strLikeBeg = 0 as *mut libc::c_char;
|
||||
let mut real_query = 0 as *mut libc::c_char;
|
||||
let mut stmt = 0 as *mut sqlite3_stmt;
|
||||
let mut success = false;
|
||||
let ret = unsafe { dc_array_new(100 as size_t) };
|
||||
|
||||
if !(ret.is_null() || query.is_null()) {
|
||||
real_query = dc_strdup(query);
|
||||
dc_trim(real_query);
|
||||
if *real_query.offset(0isize) as libc::c_int == 0 {
|
||||
success = 1
|
||||
let real_query = to_string(query).trim().to_string();
|
||||
if real_query.is_empty() {
|
||||
success = true;
|
||||
} else {
|
||||
strLikeInText = dc_mprintf(
|
||||
b"%%%s%%\x00" as *const u8 as *const libc::c_char,
|
||||
real_query,
|
||||
);
|
||||
strLikeBeg = dc_mprintf(b"%s%%\x00" as *const u8 as *const libc::c_char, real_query);
|
||||
if 0 != chat_id {
|
||||
stmt = dc_sqlite3_prepare(
|
||||
let strLikeInText = format!("%{}%", &real_query);
|
||||
let strLikeBeg = format!("{}%", &real_query);
|
||||
|
||||
let rows = if 0 != chat_id {
|
||||
dc_sqlite3_prepare(
|
||||
context,
|
||||
&context.sql,
|
||||
b"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.chat_id=? \
|
||||
"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.chat_id=? \
|
||||
AND m.hidden=0 \
|
||||
AND ct.blocked=0 AND (txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp,m.id;\x00"
|
||||
as *const u8 as *const libc::c_char
|
||||
);
|
||||
sqlite3_bind_int(stmt, 1, chat_id as libc::c_int);
|
||||
sqlite3_bind_text(stmt, 2, strLikeInText, -1, None);
|
||||
sqlite3_bind_text(stmt, 3, strLikeBeg, -1, None);
|
||||
AND ct.blocked=0 AND (txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp,m.id;"
|
||||
).and_then(|mut stmt| stmt.query_map(
|
||||
params![chat_id as libc::c_int, &strLikeInText, &strLikeBeg],
|
||||
|row| row.get::<_, i32>(0)
|
||||
).and_then(|res| res.collect::<rusqlite::Result<Vec<i32>>>()).ok())
|
||||
} else {
|
||||
let show_deaddrop = 0;
|
||||
stmt = dc_sqlite3_prepare(
|
||||
dc_sqlite3_prepare(
|
||||
context,
|
||||
&context.sql,
|
||||
b"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id \
|
||||
"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id \
|
||||
LEFT JOIN chats c ON m.chat_id=c.id WHERE m.chat_id>9 AND m.hidden=0 \
|
||||
AND (c.blocked=0 OR c.blocked=?) \
|
||||
AND ct.blocked=0 AND (m.txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp DESC,m.id DESC;\x00"
|
||||
as *const u8 as *const libc::c_char
|
||||
);
|
||||
sqlite3_bind_int(stmt, 1, if 0 != show_deaddrop { 2 } else { 0 });
|
||||
sqlite3_bind_text(stmt, 2, strLikeInText, -1, None);
|
||||
sqlite3_bind_text(stmt, 3, strLikeBeg, -1, None);
|
||||
AND ct.blocked=0 AND (m.txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp DESC,m.id DESC;"
|
||||
).and_then(|mut stmt|
|
||||
stmt.query_map(params![
|
||||
if 0 != show_deaddrop { 2 } else { 0 },
|
||||
strLikeInText, strLikeBeg,
|
||||
], |row| row.get::<_, i32>(0)).and_then(|res| res.collect::<rusqlite::Result<Vec<i32>>>()).ok()
|
||||
)
|
||||
};
|
||||
if let Some(ids) = rows {
|
||||
for id in ids {
|
||||
unsafe { dc_array_add_id(ret, id as u32) };
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
while sqlite3_step(stmt) == 100 {
|
||||
dc_array_add_id(ret, sqlite3_column_int(stmt, 0) as uint32_t);
|
||||
}
|
||||
success = 1
|
||||
}
|
||||
}
|
||||
|
||||
free(strLikeInText as *mut libc::c_void);
|
||||
free(strLikeBeg as *mut libc::c_void);
|
||||
free(real_query as *mut libc::c_void);
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
if 0 != success {
|
||||
if success {
|
||||
ret
|
||||
} else {
|
||||
if !ret.is_null() {
|
||||
dc_array_unref(ret);
|
||||
unsafe { dc_array_unref(ret) };
|
||||
}
|
||||
0 as *mut dc_array_t
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_is_inbox(_context: &Context, folder_name: *const libc::c_char) -> libc::c_int {
|
||||
let mut is_inbox = 0;
|
||||
if !folder_name.is_null() {
|
||||
is_inbox = if strcasecmp(
|
||||
b"INBOX\x00" as *const u8 as *const libc::c_char,
|
||||
folder_name,
|
||||
) == 0
|
||||
{
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
is_inbox
|
||||
pub fn dc_is_inbox(_context: &Context, folder_name: impl AsRef<str>) -> bool {
|
||||
folder_name.as_ref() == "INBOX"
|
||||
}
|
||||
|
||||
pub unsafe fn dc_is_sentbox(context: &Context, folder_name: *const libc::c_char) -> libc::c_int {
|
||||
let sentbox_name = dc_sqlite3_get_config(
|
||||
context,
|
||||
&context.sql,
|
||||
b"configured_sentbox_folder\x00" as *const u8 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
);
|
||||
let mut is_sentbox = 0;
|
||||
if !sentbox_name.is_null() && !folder_name.is_null() {
|
||||
is_sentbox = if strcasecmp(sentbox_name, folder_name) == 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
pub fn dc_is_sentbox(context: &Context, folder_name: impl AsRef<str>) -> bool {
|
||||
let sentbox_name =
|
||||
dc_sqlite3_get_config(context, &context.sql, "configured_sentbox_folder", None);
|
||||
if let Some(name) = sentbox_name {
|
||||
name == folder_name.as_ref()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
free(sentbox_name as *mut libc::c_void);
|
||||
is_sentbox
|
||||
}
|
||||
|
||||
pub unsafe fn dc_is_mvbox(context: &Context, folder_name: *const libc::c_char) -> libc::c_int {
|
||||
let mvbox_name = dc_sqlite3_get_config(
|
||||
context,
|
||||
&context.sql,
|
||||
b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
);
|
||||
let mut is_mvbox = 0;
|
||||
if !mvbox_name.is_null() && !folder_name.is_null() {
|
||||
is_mvbox = if strcasecmp(mvbox_name, folder_name) == 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
pub fn dc_is_mvbox(context: &Context, folder_name: impl AsRef<str>) -> bool {
|
||||
let mvbox_name = dc_sqlite3_get_config(context, &context.sql, "configured_mvbox_folder", None);
|
||||
|
||||
if let Some(name) = mvbox_name {
|
||||
name == folder_name.as_ref()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
free(mvbox_name as *mut libc::c_void);
|
||||
is_mvbox
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user