refactor: safe sql access

This commit is contained in:
dignifiedquire
2019-06-08 16:42:29 +02:00
parent 205493f89d
commit ab41679855
34 changed files with 6550 additions and 8249 deletions

View File

@@ -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
}