diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 7b8786861..5d0f08366 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -17,7 +17,7 @@ use std::ptr; use std::str::FromStr; use deltachat::contact::Contact; -use deltachat::dc_tools::{as_str, dc_strdup, StrExt}; +use deltachat::dc_tools::{as_str, dc_strdup, OsStrExt, StrExt}; use deltachat::*; // as C lacks a good and portable error handling, @@ -2013,6 +2013,9 @@ pub unsafe extern "C" fn dc_msg_get_file(msg: *mut dc_msg_t) -> *mut libc::c_cha } let ffi_msg = &*msg; message::dc_msg_get_file(&*ffi_msg.context, &ffi_msg.message) + .and_then(|p| p.to_c_string().ok()) + .map(|cs| dc_strdup(cs.as_ptr())) + .unwrap_or_else(|| dc_strdup(ptr::null())) } #[no_mangle] diff --git a/src/aheader.rs b/src/aheader.rs index 20a2daa2c..eb77331de 100644 --- a/src/aheader.rs +++ b/src/aheader.rs @@ -7,7 +7,6 @@ use mmime::mailimf_types::*; use crate::constants::*; use crate::contact::*; -use crate::dc_tools::as_str; use crate::key::*; /// Possible values for encryption preference @@ -64,11 +63,8 @@ impl Aheader { } } - pub fn from_imffields( - wanted_from: *const libc::c_char, - header: *const mailimf_fields, - ) -> Option { - if wanted_from.is_null() || header.is_null() { + pub fn from_imffields(wanted_from: &str, header: *const mailimf_fields) -> Option { + if header.is_null() { return None; } @@ -94,7 +90,7 @@ impl Aheader { match Self::from_str(value) { Ok(test) => { - if addr_cmp(&test.addr, as_str(wanted_from)) { + if addr_cmp(&test.addr, wanted_from) { if fine_header.is_none() { fine_header = Some(test); } else { diff --git a/src/chat.rs b/src/chat.rs index 6aa74d6fe..662cd8584 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2,6 +2,7 @@ use std::ffi::CString; use std::path::{Path, PathBuf}; use crate::chatlist::*; +use crate::config::*; use crate::constants::*; use crate::contact::*; use crate::context::Context; @@ -59,15 +60,13 @@ impl Chat { match res { Err(err @ crate::error::Error::Sql(rusqlite::Error::QueryReturnedNoRows)) => Err(err), - Err(err) => match err { - _ => { - error!( - context, - "chat: failed to load from db {}: {:?}", chat_id, err - ); - Err(err) - } - }, + Err(err) => { + error!( + context, + "chat: failed to load from db {}: {:?}", chat_id, err + ); + Err(err) + } Ok(mut chat) => { match chat.id { DC_CHAT_ID_DEADDROP => { @@ -140,13 +139,12 @@ impl Chat { if self.typ == Chattype::Single { return context .sql - .query_row_col( + .query_get_value( context, "SELECT c.addr FROM chats_contacts cc \ LEFT JOIN contacts c ON c.id=cc.contact_id \ WHERE cc.chat_id=?;", params![self.id as i32], - 0, ) .unwrap_or_else(|| "Err".into()); } @@ -183,7 +181,7 @@ impl Chat { pub fn get_profile_image(&self, context: &Context) -> Option { if let Some(image_rel) = self.param.get(Param::ProfileImage) { if !image_rel.is_empty() { - return Some(dc_get_abs_path_safe(context, image_rel)); + return Some(dc_get_abs_path(context, image_rel)); } } else if self.typ == Chattype::Single { let contacts = get_chat_contacts(context, self.id); @@ -269,7 +267,7 @@ impl Chat { return Ok(0); } - if let Some(from) = context.sql.get_config(context, "configured_addr") { + if let Some(from) = context.get_config(Config::ConfiguredAddr) { let new_rfc724_mid = { let grpid = match self.typ { Chattype::Group | Chattype::VerifiedGroup => Some(self.grpid.as_str()), @@ -279,11 +277,10 @@ impl Chat { }; if self.typ == Chattype::Single { - if let Some(id) = context.sql.query_row_col( + if let Some(id) = context.sql.query_get_value( context, "SELECT contact_id FROM chats_contacts WHERE chat_id=?;", params![self.id as i32], - 0, ) { to_id = id; } else { @@ -724,13 +721,12 @@ fn prepare_msg_common(context: &Context, chat_id: u32, msg: &mut Message) -> Res } fn last_msg_in_chat_encrypted(context: &Context, sql: &Sql, chat_id: u32) -> bool { - let packed: Option = sql.query_row_col( + let packed: Option = sql.query_get_value( context, "SELECT param \ FROM msgs WHERE timestamp=(SELECT MAX(timestamp) FROM msgs WHERE chat_id=?) \ ORDER BY id DESC;", params![chat_id as i32], - 0, ); if let Some(ref packed) = packed { @@ -912,11 +908,10 @@ unsafe fn set_draft_raw(context: &Context, chat_id: u32, mut msg: Option<&mut Me fn get_draft_msg_id(context: &Context, chat_id: u32) -> u32 { context .sql - .query_row_col::<_, i32>( + .query_get_value::<_, i32>( context, "SELECT id FROM msgs WHERE chat_id=? AND state=?;", params![chat_id as i32, MessageState::OutDraft], - 0, ) .unwrap_or_default() as u32 } @@ -1007,11 +1002,10 @@ pub fn get_chat_msgs(context: &Context, chat_id: u32, flags: u32, marker1before: pub fn get_msg_cnt(context: &Context, chat_id: u32) -> usize { context .sql - .query_row_col::<_, i32>( + .query_get_value::<_, i32>( context, "SELECT COUNT(*) FROM msgs WHERE chat_id=?;", params![chat_id as i32], - 0, ) .unwrap_or_default() as usize } @@ -1019,14 +1013,13 @@ pub fn get_msg_cnt(context: &Context, chat_id: u32) -> usize { pub fn get_fresh_msg_cnt(context: &Context, chat_id: u32) -> usize { context .sql - .query_row_col::<_, i32>( + .query_get_value::<_, i32>( context, "SELECT COUNT(*) FROM msgs \ WHERE state=10 \ AND hidden=0 \ AND chat_id=?;", params![chat_id as i32], - 0, ) .unwrap_or_default() as usize } @@ -1791,11 +1784,10 @@ pub unsafe fn forward_msgs( pub fn get_chat_contact_cnt(context: &Context, chat_id: u32) -> libc::c_int { context .sql - .query_row_col( + .query_get_value( context, "SELECT COUNT(*) FROM chats_contacts WHERE chat_id=?;", params![chat_id as i32], - 0, ) .unwrap_or_default() } @@ -1805,11 +1797,10 @@ pub fn get_chat_cnt(context: &Context) -> usize { /* no database, no chats - this is no error (needed eg. for information) */ context .sql - .query_row_col::<_, isize>( + .query_get_value::<_, isize>( context, "SELECT COUNT(*) FROM chats WHERE id>9 AND blocked=0;", params![], - 0, ) .unwrap_or_default() as usize } else { diff --git a/src/chatlist.rs b/src/chatlist.rs index 03165d65c..1a29b05e4 100644 --- a/src/chatlist.rs +++ b/src/chatlist.rs @@ -301,11 +301,10 @@ impl Chatlist { pub fn dc_get_archived_cnt(context: &Context) -> u32 { context .sql - .query_row_col( + .query_get_value( context, "SELECT COUNT(*) FROM chats WHERE blocked=0 AND archived=1;", params![], - 0, ) .unwrap_or_default() } @@ -315,7 +314,7 @@ fn get_last_deaddrop_fresh_msg(context: &Context) -> u32 { // only few fresh messages. context .sql - .query_row_col( + .query_get_value( context, "SELECT m.id FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id \ WHERE m.state=10 \ @@ -323,7 +322,6 @@ fn get_last_deaddrop_fresh_msg(context: &Context) -> u32 { AND c.blocked=2 \ ORDER BY m.timestamp DESC, m.id DESC;", params![], - 0, ) .unwrap_or_default() } diff --git a/src/config.rs b/src/config.rs index de85f96bd..e64ca11bb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -73,7 +73,7 @@ impl Context { let value = match key { Config::Selfavatar => { let rel_path = self.sql.get_config(self, key); - rel_path.map(|p| dc_get_abs_path_safe(self, &p).to_str().unwrap().to_string()) + rel_path.map(|p| dc_get_abs_path(self, &p).to_str().unwrap().to_string()) } Config::SysVersion => Some((&*DC_VERSION_STR).clone()), Config::SysMsgsizeMaxRecommended => Some(format!("{}", 24 * 1024 * 1024 / 4 * 3)), diff --git a/src/contact.rs b/src/contact.rs index c67a46a2f..434358d19 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -264,7 +264,7 @@ impl Contact { return 1; } - context.sql.query_row_col( + context.sql.query_get_value( context, "SELECT id FROM contacts WHERE addr=?1 COLLATE NOCASE AND id>?2 AND origin>=?3 AND blocked=0;", params![ @@ -272,7 +272,6 @@ impl Contact { DC_CONTACT_ID_LAST_SPECIAL as i32, DC_ORIGIN_MIN_CONTACT_LIST, ], - 0 ).unwrap_or_default() } @@ -538,11 +537,10 @@ impl Contact { pub fn get_blocked_cnt(context: &Context) -> usize { context .sql - .query_row_col::<_, isize>( + .query_get_value::<_, isize>( context, "SELECT COUNT(*) FROM contacts WHERE id>? AND blocked!=0", params![DC_CONTACT_ID_LAST_SPECIAL as i32], - 0, ) .unwrap_or_default() as usize } @@ -645,22 +643,20 @@ impl Contact { let count_contacts: i32 = context .sql - .query_row_col( + .query_get_value( context, "SELECT COUNT(*) FROM chats_contacts WHERE contact_id=?;", params![contact_id as i32], - 0, ) .unwrap_or_default(); let count_msgs: i32 = if count_contacts > 0 { context .sql - .query_row_col( + .query_get_value( context, "SELECT COUNT(*) FROM msgs WHERE from_id=? OR to_id=?;", params![contact_id as i32, contact_id as i32], - 0, ) .unwrap_or_default() } else { @@ -844,11 +840,10 @@ impl Contact { context .sql - .query_row_col::<_, isize>( + .query_get_value::<_, isize>( context, "SELECT COUNT(*) FROM contacts WHERE id>?;", params![DC_CONTACT_ID_LAST_SPECIAL as i32], - 0, ) .unwrap_or_default() as usize } diff --git a/src/context.rs b/src/context.rs index 255282f95..6502a9356 100644 --- a/src/context.rs +++ b/src/context.rs @@ -349,18 +349,16 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char { .get_config_int(context, "mdns_enabled") .unwrap_or_else(|| 1); - let prv_key_cnt: Option = context.sql.query_row_col( + let prv_key_cnt: Option = context.sql.query_get_value( context, "SELECT COUNT(*) FROM keypairs;", rusqlite::NO_PARAMS, - 0, ); - let pub_key_cnt: Option = context.sql.query_row_col( + let pub_key_cnt: Option = context.sql.query_get_value( context, "SELECT COUNT(*) FROM acpeerstates;", rusqlite::NO_PARAMS, - 0, ); let fingerprint_str = if let Some(key) = Key::from_self_public(context, &l2.addr, &context.sql) @@ -508,12 +506,12 @@ pub fn dc_search_msgs( return Vec::new(); } - let real_query = to_string(query).trim().to_string(); + let real_query = as_str(query).trim(); if real_query.is_empty() { return Vec::new(); } - let strLikeInText = format!("%{}%", &real_query); - let strLikeBeg = format!("{}%", &real_query); + let strLikeInText = format!("%{}%", real_query); + let strLikeBeg = format!("{}%", real_query); let query = if 0 != chat_id { "SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.chat_id=? \ diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 21bc72125..54d6161ab 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -269,54 +269,48 @@ pub unsafe fn dc_continue_key_transfer( setup_code: *const libc::c_char, ) -> bool { let mut success = false; - let mut filename: *mut libc::c_char = ptr::null_mut(); - let mut filecontent: *mut libc::c_char = ptr::null_mut(); - let mut filebytes: size_t = 0i32 as size_t; let mut armored_key: *mut libc::c_char = ptr::null_mut(); - let mut norm_sc: *mut libc::c_char = ptr::null_mut(); + let norm_sc; if msg_id <= 9i32 as libc::c_uint || setup_code.is_null() { return false; } + let msg = dc_get_msg(context, msg_id); - if msg.is_err() - || !dc_msg_is_setupmessage(msg.as_ref().unwrap()) - || { - filename = dc_msg_get_file(context, msg.as_ref().unwrap()); - filename.is_null() - } - || *filename.offset(0isize) as libc::c_int == 0i32 - { - error!(context, "Message is no Autocrypt Setup Message.",); - } else if 0 - == dc_read_file( - context, - filename, - &mut filecontent as *mut *mut libc::c_char as *mut *mut libc::c_void, - &mut filebytes, - ) - || filecontent.is_null() - || filebytes <= 0 - { - error!(context, "Cannot read Autocrypt Setup Message file.",); - } else { - norm_sc = dc_normalize_setup_code(context, setup_code); - if norm_sc.is_null() { - warn!(context, "Cannot normalize Setup Code.",); - } else { - armored_key = dc_decrypt_setup_file(context, norm_sc, filecontent); - if armored_key.is_null() { - warn!(context, "Cannot decrypt Autocrypt Setup Message.",); - } else if set_self_key(context, armored_key, 1) { - /*set default*/ - /* error already logged */ - success = true + if msg.is_err() { + error!(context, "Message is no Autocrypt Setup Message."); + return false; + } + let msg = msg.unwrap(); + if !dc_msg_is_setupmessage(&msg) { + error!(context, "Message is no Autocrypt Setup Message."); + return false; + } + + if let Some(filename) = dc_msg_get_file(context, &msg) { + if let Some(buf) = dc_read_file_safe(context, filename) { + norm_sc = dc_normalize_setup_code(context, setup_code); + if norm_sc.is_null() { + warn!(context, "Cannot normalize Setup Code.",); + } else { + armored_key = dc_decrypt_setup_file(context, norm_sc, buf.as_ptr().cast()); + if armored_key.is_null() { + warn!(context, "Cannot decrypt Autocrypt Setup Message.",); + } else if set_self_key(context, armored_key, 1) { + /*set default*/ + /* error already logged */ + success = true + } } + } else { + error!(context, "Cannot read Autocrypt Setup Message file.",); + return false; } + } else { + error!(context, "Message is no Autocrypt Setup Message."); + return false; } free(armored_key as *mut libc::c_void); - free(filecontent as *mut libc::c_void); - free(filename as *mut libc::c_void); free(norm_sc as *mut libc::c_void); success @@ -368,7 +362,7 @@ fn set_self_key( error!(context, "File does not contain a private key.",); } - let self_addr = context.sql.get_config(context, "configured_addr"); + let self_addr = context.get_config(Config::ConfiguredAddr); if self_addr.is_none() { error!(context, "Missing self addr"); @@ -612,7 +606,7 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char let total_files_cnt = context .sql - .query_row_col::<_, isize>(context, "SELECT COUNT(*) FROM backup_blobs;", params![], 0) + .query_get_value::<_, isize>(context, "SELECT COUNT(*) FROM backup_blobs;", params![]) .unwrap_or_default() as usize; info!( context, @@ -1099,7 +1093,7 @@ unsafe fn export_key_to_asc_file( } info!(context, "Exporting key {}", as_str(file_name),); dc_delete_file(context, as_path(file_name)); - if !key.write_asc_to_file(file_name, context) { + if !key.write_asc_to_file(as_path(file_name), context) { error!(context, "Cannot write key to {}", as_str(file_name),); } else { context.call_cb( diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs index 0c745f65c..371c55b33 100644 --- a/src/dc_mimefactory.rs +++ b/src/dc_mimefactory.rs @@ -1289,7 +1289,10 @@ unsafe fn build_body_file( ) as *mut libc::c_void, ); mime_sub = mailmime_new_empty(content, mime_fields); - mailmime_set_body_file(mime_sub, dc_get_abs_path(context, path_filename)); + let abs_path = dc_get_abs_path(context, path_filename) + .to_c_string() + .unwrap(); + mailmime_set_body_file(mime_sub, dc_strdup(abs_path.as_ptr())); if !ret_file_name_as_sent.is_null() { *ret_file_name_as_sent = dc_strdup(filename_to_send) } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 4740245c7..45263d723 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -991,11 +991,10 @@ unsafe fn calc_timestamps( } *sort_timestamp = message_timestamp; if 0 != is_fresh_msg { - let last_msg_time: Option = context.sql.query_row_col( + let last_msg_time: Option = context.sql.query_get_value( context, "SELECT MAX(timestamp) FROM msgs WHERE chat_id=? and from_id!=? AND timestamp>=?", params![chat_id as i32, from_id as i32, *sort_timestamp], - 0, ); if let Some(last_msg_time) = last_msg_time { if last_msg_time > 0 { diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 225c32cbe..bf2009318 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -792,7 +792,7 @@ pub fn dc_get_filemeta(buf: &[u8]) -> Result<(u32, u32), Error> { /// /// If `path` starts with "$BLOBDIR", replaces it with the blobdir path. /// Otherwise, returns path as is. -pub fn dc_get_abs_path_safe>( +pub fn dc_get_abs_path>( context: &Context, path: P, ) -> std::path::PathBuf { @@ -808,33 +808,12 @@ pub fn dc_get_abs_path_safe>( } } -pub unsafe fn dc_get_abs_path( - context: &Context, - path_filename: impl AsRef, -) -> *mut libc::c_char { - let starts = path_filename.as_ref().starts_with("$BLOBDIR"); - - if starts && !context.has_blobdir() { - return ptr::null_mut(); - } - - let mut path_filename_abs = path_filename.as_ref().strdup(); - if starts && context.has_blobdir() { - dc_str_replace( - &mut path_filename_abs, - b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, - context.get_blobdir(), - ); - } - path_filename_abs -} - pub fn dc_file_exist(context: &Context, path: impl AsRef) -> bool { - dc_get_abs_path_safe(context, &path).exists() + dc_get_abs_path(context, &path).exists() } pub fn dc_get_filebytes(context: &Context, path: impl AsRef) -> uint64_t { - let path_abs = dc_get_abs_path_safe(context, &path); + let path_abs = dc_get_abs_path(context, &path); match fs::metadata(&path_abs) { Ok(meta) => meta.len() as uint64_t, Err(_err) => 0, @@ -842,7 +821,7 @@ pub fn dc_get_filebytes(context: &Context, path: impl AsRef) -> } pub fn dc_delete_file(context: &Context, path: impl AsRef) -> bool { - let path_abs = dc_get_abs_path_safe(context, &path); + let path_abs = dc_get_abs_path(context, &path); if !path_abs.is_file() { warn!( context, @@ -866,8 +845,8 @@ pub fn dc_copy_file( src: impl AsRef, dest: impl AsRef, ) -> bool { - let src_abs = dc_get_abs_path_safe(context, &src); - let dest_abs = dc_get_abs_path_safe(context, &dest); + let src_abs = dc_get_abs_path(context, &src); + let dest_abs = dc_get_abs_path(context, &dest); match fs::copy(&src_abs, &dest_abs) { Ok(_) => true, Err(_) => { @@ -883,7 +862,7 @@ pub fn dc_copy_file( } pub fn dc_create_folder(context: &Context, path: impl AsRef) -> bool { - let path_abs = dc_get_abs_path_safe(context, &path); + let path_abs = dc_get_abs_path(context, &path); if !path_abs.exists() { match fs::create_dir_all(path_abs) { Ok(_) => true, @@ -918,7 +897,7 @@ pub fn dc_write_file_safe>( path: P, buf: &[u8], ) -> bool { - let path_abs = dc_get_abs_path_safe(context, &path); + let path_abs = dc_get_abs_path(context, &path); if let Err(_err) = fs::write(&path_abs, buf) { warn!( context, @@ -953,7 +932,7 @@ pub unsafe fn dc_read_file( } pub fn dc_read_file_safe>(context: &Context, path: P) -> Option> { - let path_abs = dc_get_abs_path_safe(context, &path); + let path_abs = dc_get_abs_path(context, &path); match fs::read(&path_abs) { Ok(bytes) => Some(bytes), Err(_err) => { diff --git a/src/e2ee.rs b/src/e2ee.rs index d752ed78f..8622957c1 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -87,7 +87,7 @@ impl E2eeHelper { EncryptPreference::NoPreference }; - let addr = context.sql.get_config(context, "configured_addr"); + let addr = context.get_config(Config::ConfiguredAddr); if let Some(addr) = addr { let pubkey_ret = load_or_generate_self_public_key(context, &addr).map_err(|err| { @@ -408,7 +408,8 @@ impl E2eeHelper { } } let mut peerstate = None; - let autocryptheader = Aheader::from_imffields(from, imffields); + let autocryptheader = + as_opt_str(from).and_then(|from| Aheader::from_imffields(from, imffields)); if message_time > 0 && !from.is_null() { peerstate = Peerstate::from_addr(context, &context.sql, as_str(from)); @@ -429,7 +430,7 @@ impl E2eeHelper { } } /* load private key for decryption */ - let self_addr = context.sql.get_config(context, "configured_addr"); + let self_addr = context.get_config(Config::ConfiguredAddr); if let Some(self_addr) = self_addr { if private_keyring.load_self_private_for_decrypting( context, diff --git a/src/job.rs b/src/job.rs index f4c0ac4b5..24904ef9d 100644 --- a/src/job.rs +++ b/src/job.rs @@ -182,11 +182,10 @@ impl Job { ); let chat_id: i32 = context .sql - .query_row_col( + .query_get_value( context, "SELECT chat_id FROM msgs WHERE id=?", params![self.foreign_id as i32], - 0, ) .unwrap_or_default(); context.call_cb( @@ -599,11 +598,10 @@ pub fn perform_smtp_idle(context: &Context) { fn get_next_wakeup_time(context: &Context, thread: Thread) -> Duration { let t: i64 = context .sql - .query_row_col( + .query_get_value( context, "SELECT MIN(desired_timestamp) FROM jobs WHERE thread=?;", params![thread], - 0, ) .unwrap_or_default(); diff --git a/src/key.rs b/src/key.rs index 3ccddc8e5..0262750c2 100644 --- a/src/key.rs +++ b/src/key.rs @@ -1,6 +1,7 @@ use std::collections::BTreeMap; use std::ffi::{CStr, CString}; use std::io::Cursor; +use std::path::Path; use libc; use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey}; @@ -142,11 +143,10 @@ impl Key { ) -> Option { let addr = self_addr.as_ref(); - sql.query_row_col( + sql.query_get_value( context, "SELECT public_key FROM keypairs WHERE addr=? AND is_default=1;", &[addr], - 0, ) .and_then(|blob: Vec| Self::from_slice(&blob, KeyType::Public)) } @@ -156,11 +156,10 @@ impl Key { self_addr: impl AsRef, sql: &Sql, ) -> Option { - sql.query_row_col( + sql.query_get_value( context, "SELECT private_key FROM keypairs WHERE addr=? AND is_default=1;", &[self_addr.as_ref()], - 0, ) .and_then(|blob: Vec| Self::from_slice(&blob, KeyType::Private)) } @@ -218,30 +217,15 @@ impl Key { .expect("failed to serialize key") } - pub fn write_asc_to_file(&self, file: *const libc::c_char, context: &Context) -> bool { - if file.is_null() { + pub fn write_asc_to_file(&self, file: impl AsRef, context: &Context) -> bool { + let file_content = self.to_asc(None).into_bytes(); + + if dc_write_file_safe(context, &file, &file_content) { + return true; + } else { + error!(context, "Cannot write key to {}", file.as_ref().display()); return false; } - - let file_content = self.to_asc(None); - let file_content_c = CString::new(file_content).unwrap(); - - let success = if 0 - == unsafe { - dc_write_file( - context, - file, - file_content_c.as_ptr() as *const libc::c_void, - file_content_c.as_bytes().len(), - ) - } { - error!(context, "Cannot write key to {}", to_string(file)); - false - } else { - true - }; - - success } pub fn fingerprint(&self) -> String { diff --git a/src/keyring.rs b/src/keyring.rs index b47928b56..f07a9ee16 100644 --- a/src/keyring.rs +++ b/src/keyring.rs @@ -33,11 +33,10 @@ impl<'a> Keyring<'a> { self_addr: impl AsRef, sql: &Sql, ) -> bool { - sql.query_row_col( + sql.query_get_value( context, "SELECT private_key FROM keypairs ORDER BY addr=? DESC, is_default DESC;", &[self_addr.as_ref()], - 0, ) .and_then(|blob: Vec| Key::from_slice(&blob, KeyType::Private)) .map(|key| self.add_owned(key)) diff --git a/src/message.rs b/src/message.rs index a4432407c..df18da1e2 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,5 +1,5 @@ use std::ffi::CString; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::ptr; use deltachat_derive::{FromSql, ToSql}; @@ -173,11 +173,10 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch let msg = msg.unwrap(); - let rawtxt: Option = context.sql.query_row_col( + let rawtxt: Option = context.sql.query_get_value( context, "SELECT txt_raw FROM msgs WHERE id=?;", params![msg_id as i32], - 0, ); if rawtxt.is_none() { @@ -269,15 +268,10 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch _ => {} } - let p = dc_msg_get_file(context, &msg); - if !p.is_null() && 0 != *p.offset(0isize) as libc::c_int { - ret += &format!( - "\nFile: {}, {}, bytes\n", - as_str(p), - dc_get_filebytes(context, as_path(p)) as libc::c_int, - ); + if let Some(path) = dc_msg_get_file(context, &msg) { + let bytes = dc_get_filebytes(context, &path); + ret += &format!("\nFile: {}, {}, bytes\n", path.display(), bytes); } - free(p as *mut libc::c_void); if msg.type_0 != Viewtype::Text { ret += "Type: "; @@ -378,17 +372,10 @@ pub fn dc_msg_guess_msgtype_from_suffix(path: &Path) -> Option<(Viewtype, &str)> KNOWN.get(extension).map(|x| *x) } -pub unsafe fn dc_msg_get_file(context: &Context, msg: &Message) -> *mut libc::c_char { - let mut file_abs = ptr::null_mut(); - - if let Some(file_rel) = msg.param.get(Param::File) { - file_abs = dc_get_abs_path(context, file_rel); - } - if !file_abs.is_null() { - file_abs - } else { - dc_strdup(0 as *const libc::c_char) - } +pub unsafe fn dc_msg_get_file(context: &Context, msg: &Message) -> Option { + msg.param + .get(Param::File) + .map(|f| dc_get_abs_path(context, f)) } /** @@ -503,11 +490,10 @@ pub fn dc_msg_load_from_db(context: &Context, id: u32) -> Result } pub unsafe fn dc_get_mime_headers(context: &Context, msg_id: u32) -> *mut libc::c_char { - let headers: Option = context.sql.query_row_col( + let headers: Option = context.sql.query_get_value( context, "SELECT mime_headers FROM msgs WHERE id=?;", params![msg_id as i32], - 0, ); if let Some(headers) = headers { @@ -896,29 +882,16 @@ pub fn dc_msg_is_setupmessage(msg: &Message) -> bool { } pub unsafe fn dc_msg_get_setupcodebegin(context: &Context, msg: &Message) -> *mut libc::c_char { - let mut filename: *mut libc::c_char = ptr::null_mut(); - let mut buf: *mut libc::c_char = ptr::null_mut(); - let mut buf_bytes: size_t = 0i32 as size_t; // just a pointer inside buf, MUST NOT be free()'d let mut buf_headerline: *const libc::c_char = ptr::null(); // just a pointer inside buf, MUST NOT be free()'d let mut buf_setupcodebegin: *const libc::c_char = ptr::null(); let mut ret: *mut libc::c_char = ptr::null_mut(); if dc_msg_is_setupmessage(msg) { - filename = dc_msg_get_file(context, msg); - if !(filename.is_null() || *filename.offset(0isize) as libc::c_int == 0i32) { - if !(0 - == dc_read_file( - context, - filename, - &mut buf as *mut *mut libc::c_char as *mut *mut libc::c_void, - &mut buf_bytes, - ) - || buf.is_null() - || buf_bytes <= 0) - { + if let Some(filename) = dc_msg_get_file(context, msg) { + if let Some(mut buf) = dc_read_file_safe(context, filename) { if dc_split_armored_data( - buf, + buf.as_mut_ptr().cast(), &mut buf_headerline, &mut buf_setupcodebegin, ptr::null_mut(), @@ -934,8 +907,6 @@ pub unsafe fn dc_msg_get_setupcodebegin(context: &Context, msg: &Message) -> *mu } } } - free(filename as *mut libc::c_void); - free(buf as *mut libc::c_void); if !ret.is_null() { ret } else { @@ -1035,11 +1006,10 @@ pub fn dc_msg_exists(context: &Context, msg_id: u32) -> bool { return false; } - let chat_id: Option = context.sql.query_row_col( + let chat_id: Option = context.sql.query_get_value( context, "SELECT chat_id FROM msgs WHERE id=?;", params![msg_id], - 0, ); if let Some(chat_id) = chat_id { @@ -1158,11 +1128,10 @@ pub unsafe fn dc_mdn_from_ext( /* send event about new state */ let ist_cnt: i32 = context .sql - .query_row_col( + .query_get_value( context, "SELECT COUNT(*) FROM msgs_mdns WHERE msg_id=?;", params![*ret_msg_id as i32], - 0, ) .unwrap_or_default(); /* diff --git a/src/securejoin.rs b/src/securejoin.rs index 1ce0a0268..5ab3948d1 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -4,6 +4,7 @@ use std::ptr; use crate::aheader::EncryptPreference; use crate::chat::{self, Chat}; +use crate::config::*; use crate::configure::*; use crate::constants::*; use crate::contact::*; @@ -82,7 +83,7 @@ pub fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -> Optio ensure_secret_key_exists(context).ok(); let invitenumber = token::lookup_or_new(context, token::Namespace::InviteNumber, group_chat_id); let auth = token::lookup_or_new(context, token::Namespace::Auth, group_chat_id); - let self_addr = match context.sql.get_config(context, "configured_addr") { + let self_addr = match context.get_config(Config::ConfiguredAddr) { Some(addr) => addr, None => { error!(context, "Not configured, cannot generate QR code.",); @@ -139,7 +140,7 @@ pub fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -> Optio } fn get_self_fingerprint(context: &Context) -> Option { - if let Some(self_addr) = context.sql.get_config(context, "configured_addr") { + if let Some(self_addr) = context.get_config(Config::ConfiguredAddr) { if let Some(key) = Key::from_self_public(context, self_addr, &context.sql) { return Some(key.fingerprint()); } @@ -753,11 +754,10 @@ pub fn handle_degrade_event(context: &Context, peerstate: &Peerstate) { if Some(DegradeEvent::FingerprintChanged) == peerstate.degrade_event { let contact_id: i32 = context .sql - .query_row_col( + .query_get_value( context, "SELECT id FROM contacts WHERE addr=?;", params![&peerstate.addr], - 0, ) .unwrap_or_default(); if contact_id > 0 { diff --git a/src/sql.rs b/src/sql.rs index 29e8d5e07..c4b90854d 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -155,19 +155,13 @@ impl Sql { .unwrap_or_default() } - pub fn query_row_col( - &self, - context: &Context, - query: &str, - params: P, - column: usize, - ) -> Option + pub fn query_get_value(&self, context: &Context, query: &str, params: P) -> Option where P: IntoIterator, P::Item: rusqlite::ToSql, T: rusqlite::types::FromSql, { - match self.query_row(query, params, |row| row.get::<_, T>(column)) { + match self.query_row(query, params, |row| row.get::<_, T>(0)) { Ok(res) => Some(res), Err(Error::Sql(rusqlite::Error::QueryReturnedNoRows)) => None, Err(Error::Sql(rusqlite::Error::InvalidColumnType( @@ -238,11 +232,10 @@ impl Sql { if !self.is_open() || key.as_ref().is_empty() { return None; } - self.query_row_col( + self.query_get_value( context, "SELECT value FROM config WHERE keyname=?;", params![key.as_ref()], - 0, ) } diff --git a/src/token.rs b/src/token.rs index e08f8686d..0ffbe035f 100644 --- a/src/token.rs +++ b/src/token.rs @@ -35,11 +35,10 @@ pub fn save(context: &Context, namespace: Namespace, foreign_id: u32) -> String } pub fn lookup(context: &Context, namespace: Namespace, foreign_id: u32) -> Option { - context.sql.query_row_col::<_, String>( + context.sql.query_get_value::<_, String>( context, "SELECT token FROM tokens WHERE namespc=? AND foreign_id=?;", params![namespace, foreign_id as i32], - 0, ) }