mirror of
https://github.com/chatmail/core.git
synced 2026-04-28 19:06:35 +03:00
Merge pull request #496 from KAction/safe
Make dc_msg_get_file return PathBuf, not char*
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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<Self> {
|
||||
if wanted_from.is_null() || header.is_null() {
|
||||
pub fn from_imffields(wanted_from: &str, header: *const mailimf_fields) -> Option<Self> {
|
||||
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 {
|
||||
|
||||
45
src/chat.rs
45
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<PathBuf> {
|
||||
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<String> = sql.query_row_col(
|
||||
let packed: Option<String> = 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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<isize> = context.sql.query_row_col(
|
||||
let prv_key_cnt: Option<isize> = context.sql.query_get_value(
|
||||
context,
|
||||
"SELECT COUNT(*) FROM keypairs;",
|
||||
rusqlite::NO_PARAMS,
|
||||
0,
|
||||
);
|
||||
|
||||
let pub_key_cnt: Option<isize> = context.sql.query_row_col(
|
||||
let pub_key_cnt: Option<isize> = 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=? \
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -991,11 +991,10 @@ unsafe fn calc_timestamps(
|
||||
}
|
||||
*sort_timestamp = message_timestamp;
|
||||
if 0 != is_fresh_msg {
|
||||
let last_msg_time: Option<i64> = context.sql.query_row_col(
|
||||
let last_msg_time: Option<i64> = 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 {
|
||||
|
||||
@@ -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<P: AsRef<std::path::Path>>(
|
||||
pub fn dc_get_abs_path<P: AsRef<std::path::Path>>(
|
||||
context: &Context,
|
||||
path: P,
|
||||
) -> std::path::PathBuf {
|
||||
@@ -808,33 +808,12 @@ pub fn dc_get_abs_path_safe<P: AsRef<std::path::Path>>(
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_abs_path(
|
||||
context: &Context,
|
||||
path_filename: impl AsRef<str>,
|
||||
) -> *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<std::path::Path>) -> 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<std::path::Path>) -> 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<std::path::Path>) ->
|
||||
}
|
||||
|
||||
pub fn dc_delete_file(context: &Context, path: impl AsRef<std::path::Path>) -> 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<std::path::Path>,
|
||||
dest: impl AsRef<std::path::Path>,
|
||||
) -> 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<std::path::Path>) -> 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<P: AsRef<std::path::Path>>(
|
||||
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<P: AsRef<std::path::Path>>(context: &Context, path: P) -> Option<Vec<u8>> {
|
||||
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) => {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
36
src/key.rs
36
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<Self> {
|
||||
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<u8>| Self::from_slice(&blob, KeyType::Public))
|
||||
}
|
||||
@@ -156,11 +156,10 @@ impl Key {
|
||||
self_addr: impl AsRef<str>,
|
||||
sql: &Sql,
|
||||
) -> Option<Self> {
|
||||
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<u8>| 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<Path>, 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 {
|
||||
|
||||
@@ -33,11 +33,10 @@ impl<'a> Keyring<'a> {
|
||||
self_addr: impl AsRef<str>,
|
||||
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<u8>| Key::from_slice(&blob, KeyType::Private))
|
||||
.map(|key| self.add_owned(key))
|
||||
|
||||
@@ -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<String> = context.sql.query_row_col(
|
||||
let rawtxt: Option<String> = 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<PathBuf> {
|
||||
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<Message, Error>
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_mime_headers(context: &Context, msg_id: u32) -> *mut libc::c_char {
|
||||
let headers: Option<String> = context.sql.query_row_col(
|
||||
let headers: Option<String> = 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<u32> = context.sql.query_row_col(
|
||||
let chat_id: Option<u32> = 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();
|
||||
/*
|
||||
|
||||
@@ -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<String> {
|
||||
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 {
|
||||
|
||||
13
src/sql.rs
13
src/sql.rs
@@ -155,19 +155,13 @@ impl Sql {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn query_row_col<P, T>(
|
||||
&self,
|
||||
context: &Context,
|
||||
query: &str,
|
||||
params: P,
|
||||
column: usize,
|
||||
) -> Option<T>
|
||||
pub fn query_get_value<P, T>(&self, context: &Context, query: &str, params: P) -> Option<T>
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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<String> {
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user