diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 0903b84d9..76491351e 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -24,7 +24,9 @@ use num_traits::{FromPrimitive, ToPrimitive}; use deltachat::contact::Contact; use deltachat::context::Context; -use deltachat::dc_tools::{as_path, as_str, dc_strdup, to_string, OsStrExt, StrExt}; +use deltachat::dc_tools::{ + as_path, as_str, dc_strdup, to_string, to_string_lossy, OsStrExt, StrExt, +}; use deltachat::*; // as C lacks a good and portable error handling, @@ -186,7 +188,7 @@ pub unsafe extern "C" fn dc_context_new( let os_name = if os_name.is_null() { String::from("DcFFI") } else { - dc_tools::to_string_lossy(os_name) + to_string_lossy(os_name) }; let ffi_ctx = ContextWrapper { cb, @@ -735,7 +737,7 @@ pub unsafe extern "C" fn dc_send_text_msg( return 0; } let ffi_context = &*context; - let text_to_send = dc_tools::to_string_lossy(text_to_send); + let text_to_send = to_string_lossy(text_to_send); ffi_context .with_inner(|ctx| { chat::send_text_msg(ctx, chat_id, text_to_send) @@ -2861,7 +2863,7 @@ fn as_opt_str<'a>(s: *const libc::c_char) -> Option<&'a str> { return None; } - Some(dc_tools::as_str(s)) + Some(as_str(s)) } pub mod providers; diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 5750efd2f..8824e36c2 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -1,4 +1,4 @@ -use std::ffi::CString; +use std::path::Path; use std::ptr; use std::str::FromStr; @@ -20,8 +20,8 @@ use deltachat::message::{self, Message, MessageState}; use deltachat::peerstate::*; use deltachat::qr::*; use deltachat::sql; -use deltachat::x::*; use deltachat::Event; +use libc::free; /// Reset database tables. This function is called from Core cmdline. /// Argument is a bitmask, executing single or multiple actions in one call. @@ -94,24 +94,20 @@ pub unsafe fn dc_reset_tables(context: &Context, bits: i32) -> i32 { 1 } -unsafe fn dc_poke_eml_file(context: &Context, filename: *const libc::c_char) -> libc::c_int { - /* mainly for testing, may be called by dc_import_spec() */ - let mut success: libc::c_int = 0i32; - let mut data: *mut libc::c_char = ptr::null_mut(); - let mut data_bytes = 0; - if !(dc_read_file( - context, - filename, - &mut data as *mut *mut libc::c_char as *mut *mut libc::c_void, - &mut data_bytes, - ) == 0i32) - { - dc_receive_imf(context, data, data_bytes, "import", 0, 0); - success = 1; - } - free(data as *mut libc::c_void); +fn dc_poke_eml_file(context: &Context, filename: impl AsRef) -> Result<(), Error> { + let data = dc_read_file(context, filename)?; - success + unsafe { + dc_receive_imf( + context, + data.as_ptr() as *const _, + data.len(), + "import", + 0, + 0, + ) + }; + Ok(()) } /// Import a file to the database. @@ -130,16 +126,16 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int let ok_to_continue; let mut success: libc::c_int = 0; - let real_spec: *mut libc::c_char; + let real_spec: String; let mut suffix: *mut libc::c_char = ptr::null_mut(); let mut read_cnt: libc::c_int = 0; /* if `spec` is given, remember it for later usage; if it is not given, try to use the last one */ if !spec.is_null() { - real_spec = dc_strdup(spec); + real_spec = to_string(spec); context .sql - .set_config(context, "import_spec", Some(as_str(real_spec))) + .set_config(context, "import_spec", Some(&real_spec)) .unwrap(); ok_to_continue = true; } else { @@ -150,27 +146,24 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int } else { ok_to_continue = true; } - real_spec = rs.unwrap_or_default().strdup(); + real_spec = rs.unwrap_or_default(); } if ok_to_continue { let ok_to_continue2; - suffix = dc_get_filesuffix_lc(as_str(real_spec)); - if !suffix.is_null() && strcmp(suffix, b"eml\x00" as *const u8 as *const libc::c_char) == 0 + suffix = dc_get_filesuffix_lc(&real_spec); + if !suffix.is_null() + && libc::strcmp(suffix, b"eml\x00" as *const u8 as *const libc::c_char) == 0 { - if 0 != dc_poke_eml_file(context, real_spec) { + if dc_poke_eml_file(context, &real_spec).is_ok() { read_cnt += 1 } ok_to_continue2 = true; } else { /* import a directory */ - let dir_name = std::path::Path::new(as_str(real_spec)); + let dir_name = std::path::Path::new(&real_spec); let dir = std::fs::read_dir(dir_name); if dir.is_err() { - error!( - context, - "Import: Cannot open directory \"{}\".", - as_str(real_spec), - ); + error!(context, "Import: Cannot open directory \"{}\".", &real_spec,); ok_to_continue2 = false; } else { let dir = dir.unwrap(); @@ -182,10 +175,9 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int let name_f = entry.file_name(); let name = name_f.to_string_lossy(); if name.ends_with(".eml") { - let path_plus_name = format!("{}/{}", as_str(real_spec), name); + let path_plus_name = format!("{}/{}", &real_spec, name); info!(context, "Import: {}", path_plus_name); - let path_plus_name_c = CString::yolo(path_plus_name); - if 0 != dc_poke_eml_file(context, path_plus_name_c.as_ptr()) { + if dc_poke_eml_file(context, path_plus_name).is_ok() { read_cnt += 1 } } @@ -196,9 +188,7 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int if ok_to_continue2 { info!( context, - "Import: {} items read from \"{}\".", - read_cnt, - as_str(real_spec) + "Import: {} items read from \"{}\".", read_cnt, &real_spec ); if read_cnt > 0 { context.call_cb(Event::MsgsChanged { @@ -210,7 +200,6 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int } } - free(real_spec as *mut libc::c_void); free(suffix as *mut libc::c_void); success } @@ -1017,7 +1006,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E "fileinfo" => { ensure!(!arg1.is_empty(), "Argument missing."); - if let Some(buf) = dc_read_file_safe(context, &arg1) { + if let Ok(buf) = dc_read_file(context, &arg1) { let (width, height) = dc_get_filemeta(&buf)?; println!("width={}, height={}", width, height); } else { diff --git a/examples/repl/main.rs b/examples/repl/main.rs index 6adbe567e..62839b321 100644 --- a/examples/repl/main.rs +++ b/examples/repl/main.rs @@ -23,11 +23,9 @@ use std::sync::{Arc, Mutex, RwLock}; use deltachat::config; use deltachat::configure::*; use deltachat::context::*; -use deltachat::dc_tools::*; use deltachat::job::*; use deltachat::oauth2::*; use deltachat::securejoin::*; -use deltachat::x::*; use deltachat::Event; use rustyline::completion::{Completer, FilenameCompleter, Pair}; use rustyline::config::OutputStreamType; @@ -441,11 +439,6 @@ unsafe fn handle_cmd(line: &str, ctx: Arc>) -> Result { @@ -521,8 +514,6 @@ unsafe fn handle_cmd(line: &str, ctx: Arc>) -> Result dc_cmdline(&ctx.read().unwrap(), line)?, } - free(arg1_c as *mut _); - Ok(ExitResult::Continue) } diff --git a/src/configure/auto_mozilla.rs b/src/configure/auto_mozilla.rs index fd2016682..005cc5fcb 100644 --- a/src/configure/auto_mozilla.rs +++ b/src/configure/auto_mozilla.rs @@ -1,3 +1,4 @@ +use libc::free; use quick_xml; use quick_xml::events::{BytesEnd, BytesStart, BytesText}; @@ -5,7 +6,6 @@ use crate::constants::*; use crate::context::Context; use crate::dc_tools::*; use crate::login_param::LoginParam; -use crate::x::*; use super::read_autoconf_file; /* ****************************************************************************** diff --git a/src/configure/auto_outlook.rs b/src/configure/auto_outlook.rs index b3fdbe9b5..05018bebf 100644 --- a/src/configure/auto_outlook.rs +++ b/src/configure/auto_outlook.rs @@ -1,3 +1,6 @@ +use std::ptr; + +use libc::free; use quick_xml; use quick_xml::events::{BytesEnd, BytesStart, BytesText}; @@ -5,8 +8,6 @@ use crate::constants::*; use crate::context::Context; use crate::dc_tools::*; use crate::login_param::LoginParam; -use crate::x::*; -use std::ptr; use super::read_autoconf_file; /* ****************************************************************************** @@ -46,7 +47,7 @@ pub unsafe fn outlk_autodiscover( ok_to_continue = true; break; } - memset( + libc::memset( &mut outlk_ad as *mut outlk_autodiscover_t as *mut libc::c_void, 0, ::std::mem::size_of::(), diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 33b196835..7902f44b7 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -2,6 +2,7 @@ use std::ffi::CString; use std::path::Path; use std::ptr; +use libc::{free, strcmp, strlen, strstr}; use mmime::mailmime_content::*; use mmime::mmapstring::*; use mmime::other::*; @@ -23,7 +24,6 @@ use crate::param::*; use crate::pgp::*; use crate::sql::{self, Sql}; use crate::stock::StockMessage; -use crate::x::*; // import/export and tools // param1 is a directory where the keys are written to @@ -276,7 +276,7 @@ pub unsafe fn dc_continue_key_transfer( } if let Some(filename) = msg.get_file(context) { - if let Some(buf) = dc_read_file_safe(context, filename) { + if let Ok(buf) = dc_read_file(context, filename) { norm_sc = dc_normalize_setup_code(context, setup_code); if norm_sc.is_null() { warn!(context, "Cannot normalize Setup Code.",); @@ -767,8 +767,8 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> bool { } else { info!(context, "EXPORTing filename={}", name); let curr_pathNfilename = context.get_blobdir().join(entry.file_name()); - if let Some(buf) = - dc_read_file_safe(context, &curr_pathNfilename) + if let Ok(buf) = + dc_read_file(context, &curr_pathNfilename) { if buf.is_empty() { continue; @@ -874,7 +874,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) -> free(buf.cast()); buf = ptr::null_mut(); - if let Some(buf_r) = dc_read_file_safe(context, &path_plus_name) { + if let Ok(buf_r) = dc_read_file(context, &path_plus_name) { buf = buf_r.as_ptr() as *mut _; std::mem::forget(buf_r); } else { diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs index a6a1af68e..9e82f8e3d 100644 --- a/src/dc_mimefactory.rs +++ b/src/dc_mimefactory.rs @@ -2,6 +2,7 @@ use std::path::Path; use std::ptr; use chrono::TimeZone; +use libc::{free, strcmp, strlen}; use mmime::clist::*; use mmime::mailimf_types::*; use mmime::mailimf_types_helper::*; @@ -25,7 +26,6 @@ use crate::location; use crate::message::{self, Message}; use crate::param::*; use crate::stock::StockMessage; -use crate::x::*; #[derive(Clone, Copy, Eq, PartialEq)] pub enum Loaded { diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index c91d1031a..31a8fa09c 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -4,6 +4,7 @@ use std::ptr; use charset::Charset; use deltachat_derive::{FromSql, ToSql}; +use libc::{strcmp, strlen, strncmp}; use mmime::clist::*; use mmime::mailimf::*; use mmime::mailimf_types::*; @@ -25,7 +26,6 @@ use crate::error::Error; use crate::location; use crate::param::*; use crate::stock::StockMessage; -use crate::x::*; #[derive(Debug)] pub struct MimeParser<'a> { diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 6d9476928..266a8d4cc 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2,6 +2,7 @@ use std::ffi::CString; use std::ptr; use itertools::join; +use libc::{free, strcmp, strlen}; use mmime::clist::*; use mmime::mailimf::*; use mmime::mailimf_types::*; @@ -28,7 +29,6 @@ use crate::peerstate::*; use crate::securejoin::handle_securejoin_handshake; use crate::sql; use crate::stock::StockMessage; -use crate::x::*; #[derive(Debug, PartialEq, Eq)] enum CreateEvent { diff --git a/src/dc_strencode.rs b/src/dc_strencode.rs index 05481481c..0ec5cd627 100644 --- a/src/dc_strencode.rs +++ b/src/dc_strencode.rs @@ -3,13 +3,13 @@ use std::ffi::CString; use std::ptr; use charset::Charset; +use libc::{free, strlen}; use mmime::mailmime_decode::*; use mmime::mmapstring::*; use mmime::other::*; use percent_encoding::{percent_decode, utf8_percent_encode, AsciiSet, CONTROLS}; use crate::dc_tools::*; -use crate::x::*; /** * Encode non-ascii-strings as `=?UTF-8?Q?Bj=c3=b6rn_Petersen?=`. @@ -336,6 +336,8 @@ unsafe fn print_hex(target: *mut libc::c_char, cur: *const libc::c_char) { #[cfg(test)] mod tests { use super::*; + + use libc::{strcmp, strncmp}; use std::ffi::CStr; #[test] diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 85de8d767..eb190c27e 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -9,16 +9,15 @@ use std::time::SystemTime; use std::{fmt, fs, ptr}; use chrono::{Local, TimeZone}; -use libc::uintptr_t; +use libc::{free, memcpy, strcpy, strlen, strstr, uintptr_t}; use mmime::clist::*; use mmime::mailimf_types::*; use rand::{thread_rng, Rng}; use crate::context::Context; use crate::error::Error; -use crate::x::*; -pub fn dc_exactly_one_bit_set(v: libc::c_int) -> bool { +pub(crate) fn dc_exactly_one_bit_set(v: libc::c_int) -> bool { 0 != v && 0 == v & (v - 1) } @@ -43,7 +42,7 @@ pub unsafe fn dc_strdup(s: *const libc::c_char) -> *mut libc::c_char { ret = strdup(s); assert!(!ret.is_null()); } else { - ret = calloc(1, 1) as *mut libc::c_char; + ret = libc::calloc(1, 1) as *mut libc::c_char; assert!(!ret.is_null()); } @@ -51,21 +50,7 @@ pub unsafe fn dc_strdup(s: *const libc::c_char) -> *mut libc::c_char { } /// Duplicates a string, returns null if given string is null -/// -/// # Examples -/// -/// ``` -/// use deltachat::dc_tools::{dc_strdup_keep_null, to_string}; -/// use std::ffi::{CStr}; -/// -/// unsafe { -/// let str_a = b"foobar\x00" as *const u8 as *const libc::c_char; -/// let str_a_copy = dc_strdup_keep_null(str_a); -/// assert_eq!(to_string(str_a_copy), "foobar"); -/// assert_ne!(str_a, str_a_copy); -/// } -/// ``` -pub unsafe fn dc_strdup_keep_null(s: *const libc::c_char) -> *mut libc::c_char { +pub(crate) unsafe fn dc_strdup_keep_null(s: *const libc::c_char) -> *mut libc::c_char { if !s.is_null() { dc_strdup(s) } else { @@ -73,7 +58,7 @@ pub unsafe fn dc_strdup_keep_null(s: *const libc::c_char) -> *mut libc::c_char { } } -pub unsafe fn dc_atoi_null_is_0(s: *const libc::c_char) -> libc::c_int { +pub(crate) fn dc_atoi_null_is_0(s: *const libc::c_char) -> libc::c_int { if !s.is_null() { as_str(s).parse().unwrap_or_default() } else { @@ -81,20 +66,6 @@ pub unsafe fn dc_atoi_null_is_0(s: *const libc::c_char) -> libc::c_int { } } -pub unsafe fn dc_str_replace( - haystack: *mut *mut libc::c_char, - needle: *const libc::c_char, - replacement: *const libc::c_char, -) { - let haystack_s = to_string(*haystack); - let needle_s = to_string(needle); - let replacement_s = to_string(replacement); - - free(*haystack as *mut libc::c_void); - - *haystack = haystack_s.replace(&needle_s, &replacement_s).strdup(); -} - unsafe fn dc_ltrim(buf: *mut libc::c_char) { let mut len: libc::size_t; let mut cur: *const libc::c_uchar; @@ -106,7 +77,7 @@ unsafe fn dc_ltrim(buf: *mut libc::c_char) { len = len.wrapping_sub(1) } if buf as *const libc::c_uchar != cur { - memmove( + libc::memmove( buf as *mut libc::c_void, cur as *const libc::c_void, len.wrapping_add(1), @@ -137,28 +108,13 @@ unsafe fn dc_rtrim(buf: *mut libc::c_char) { }; } -pub unsafe fn dc_trim(buf: *mut libc::c_char) { +pub(crate) unsafe fn dc_trim(buf: *mut libc::c_char) { dc_ltrim(buf); dc_rtrim(buf); } -/* the result must be free()'d */ -pub unsafe fn dc_null_terminate( - in_0: *const libc::c_char, - bytes: libc::c_int, -) -> *mut libc::c_char { - let out: *mut libc::c_char = malloc(bytes as usize + 1) as *mut libc::c_char; - assert!(!out.is_null()); - if !in_0.is_null() && bytes > 0 { - strncpy(out, in_0, bytes as usize); - } - *out.offset(bytes as isize) = 0 as libc::c_char; - - out -} - /* remove all \r characters from string */ -pub unsafe fn dc_remove_cr_chars(buf: *mut libc::c_char) { +pub(crate) unsafe fn dc_remove_cr_chars(buf: *mut libc::c_char) { /* search for first `\r` */ let mut p1: *const libc::c_char = buf; while 0 != *p1 { @@ -179,84 +135,9 @@ pub unsafe fn dc_remove_cr_chars(buf: *mut libc::c_char) { *p2 = 0 as libc::c_char; } -/* replace bad UTF-8 characters by sequences of `_` (to avoid problems in filenames, we do not use eg. `?`) the function is useful if strings are unexpectingly encoded eg. as ISO-8859-1 */ -#[allow(non_snake_case)] -pub unsafe fn dc_replace_bad_utf8_chars(buf: *mut libc::c_char) { - let mut OK_TO_CONTINUE = true; - if buf.is_null() { - return; - } - /* force unsigned - otherwise the `> ' '` comparison will fail */ - let mut p1: *mut libc::c_uchar = buf as *mut libc::c_uchar; - let p1len: libc::c_int = strlen(buf) as libc::c_int; - let mut c: libc::c_int; - let mut i: libc::c_int; - let ix: libc::c_int; - let mut n: libc::c_int; - let mut j: libc::c_int; - i = 0; - ix = p1len; - 's_36: loop { - if !(i < ix) { - break; - } - c = *p1.offset(i as isize) as libc::c_int; - if c > 0 && c <= 0x7f { - n = 0 - } else if c & 0xe0 == 0xc0 { - n = 1 - } else if c == 0xed - && i < ix - 1 - && *p1.offset((i + 1) as isize) as libc::c_int & 0xa0 == 0xa0 - { - /* U+d800 to U+dfff */ - OK_TO_CONTINUE = false; - break; - } else if c & 0xf0 == 0xe0 { - n = 2 - } else if c & 0xf8 == 0xf0 { - n = 3 - } else { - //else if ((c & 0xFC) == 0xF8) { n=4; } /* 111110bb - not valid in https://tools.ietf.org/html/rfc3629 */ - //else if ((c & 0xFE) == 0xFC) { n=5; } /* 1111110b - not valid in https://tools.ietf.org/html/rfc3629 */ - OK_TO_CONTINUE = false; - break; - } - j = 0; - while j < n && i < ix { - /* n bytes matching 10bbbbbb follow ? */ - i += 1; - if i == ix || *p1.offset(i as isize) as libc::c_int & 0xc0 != 0x80 { - OK_TO_CONTINUE = false; - break 's_36; - } - j += 1 - } - i += 1 - } - if OK_TO_CONTINUE == false { - while 0 != *p1 { - if *p1 as libc::c_int > 0x7f { - *p1 = '_' as i32 as libc::c_uchar - } - p1 = p1.offset(1isize) - } - return; - } -} - /// Shortens a string to a specified length and adds "..." or "[...]" to the end of /// the shortened string. -/// -/// # Examples -/// ``` -/// use deltachat::dc_tools::dc_truncate; -/// -/// let s = "this is a little test string"; -/// assert_eq!(dc_truncate(s, 16, false), "this is a [...]"); -/// assert_eq!(dc_truncate(s, 16, true), "this is a ..."); -/// ``` -pub fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Cow { +pub(crate) fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Cow { let ellipse = if do_unwrap { "..." } else { "[...]" }; let count = buf.chars().count(); @@ -278,7 +159,7 @@ pub fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Cow } #[allow(non_snake_case)] -pub unsafe fn dc_truncate_n_unwrap_str( +pub(crate) unsafe fn dc_truncate_n_unwrap_str( buf: *mut libc::c_char, approx_characters: libc::c_int, do_unwrap: libc::c_int, @@ -337,7 +218,7 @@ unsafe fn dc_utf8_strnlen(s: *const libc::c_char, n: libc::size_t) -> libc::size j } -pub unsafe fn dc_str_from_clist( +pub(crate) unsafe fn dc_str_from_clist( list: *const clist, delimiter: *const libc::c_char, ) -> *mut libc::c_char { @@ -369,7 +250,7 @@ pub unsafe fn dc_str_from_clist( res.strdup() } -pub unsafe fn dc_str_to_clist( +pub(crate) unsafe fn dc_str_to_clist( str: *const libc::c_char, delimiter: *const libc::c_char, ) -> *mut clist { @@ -408,7 +289,7 @@ const COLORS: [u32; 16] = [ 0x39b249, 0xbb243b, 0x964078, 0x66874f, 0x308ab9, 0x127ed0, 0xbe450c, ]; -pub fn dc_str_to_color(s: impl AsRef) -> u32 { +pub(crate) fn dc_str_to_color(s: impl AsRef) -> u32 { let str_lower = s.as_ref().to_lowercase(); let mut checksum = 0; let bytes = str_lower.as_bytes(); @@ -422,8 +303,9 @@ pub fn dc_str_to_color(s: impl AsRef) -> u32 { } /* clist tools */ + /* calls free() for each item content */ -pub unsafe fn clist_free_content(haystack: *const clist) { +pub(crate) unsafe fn clist_free_content(haystack: *const clist) { let mut iter = (*haystack).first; while !iter.is_null() { @@ -437,7 +319,7 @@ pub unsafe fn clist_free_content(haystack: *const clist) { } } -pub unsafe fn clist_search_string_nocase( +pub(crate) unsafe fn clist_search_string_nocase( haystack: *const clist, needle: *const libc::c_char, ) -> bool { @@ -448,7 +330,7 @@ pub unsafe fn clist_search_string_nocase( /* date/time tools */ /* the result is UTC or DC_INVALID_TIMESTAMP */ -pub unsafe fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 { +pub(crate) unsafe fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 { let sec = (*date_time).dt_sec; let min = (*date_time).dt_min; let hour = (*date_time).dt_hour; @@ -482,13 +364,13 @@ pub fn dc_timestamp_to_str(wanted: i64) -> String { ts.format("%Y.%m.%d %H:%M:%S").to_string() } -pub fn dc_gm2local_offset() -> i64 { +pub(crate) fn dc_gm2local_offset() -> i64 { let lt = Local::now(); ((lt.offset().local_minus_utc() / (60 * 60)) * 100) as i64 } /* timesmearing */ -pub fn dc_smeared_time(context: &Context) -> i64 { +pub(crate) fn dc_smeared_time(context: &Context) -> i64 { /* function returns a corrected time(NULL) */ let mut now = time(); let ts = *context.last_smeared_timestamp.clone().read().unwrap(); @@ -499,7 +381,7 @@ pub fn dc_smeared_time(context: &Context) -> i64 { now } -pub fn dc_create_smeared_timestamp(context: &Context) -> i64 { +pub(crate) fn dc_create_smeared_timestamp(context: &Context) -> i64 { let now = time(); let mut ret = now; @@ -514,7 +396,7 @@ pub fn dc_create_smeared_timestamp(context: &Context) -> i64 { ret } -pub fn dc_create_smeared_timestamps(context: &Context, count: usize) -> i64 { +pub(crate) fn dc_create_smeared_timestamps(context: &Context, count: usize) -> i64 { /* get a range to timestamps that can be used uniquely */ let now = time(); let start = now + (if count < 5 { count } else { 5 }) as i64 - count as i64; @@ -528,7 +410,7 @@ pub fn dc_create_smeared_timestamps(context: &Context, count: usize) -> i64 { } /* Message-ID tools */ -pub fn dc_create_id() -> String { +pub(crate) fn dc_create_id() -> String { /* generate an id. the generated ID should be as short and as unique as possible: - short, because it may also used as part of Message-ID headers or in QR codes - unique as two IDs generated on two devices should not be the same. However, collisions are not world-wide but only by the few contacts. @@ -568,7 +450,7 @@ fn encode_66bits_as_base64(v1: u32, v2: u32, fill: u32) -> String { String::from_utf8(wrapped_writer).unwrap() } -pub fn dc_create_incoming_rfc724_mid( +pub(crate) fn dc_create_incoming_rfc724_mid( message_timestamp: i64, contact_id_from: u32, contact_ids_to: &Vec, @@ -590,7 +472,7 @@ pub fn dc_create_incoming_rfc724_mid( /// - this function is called for all outgoing messages. /// - the message ID should be globally unique /// - do not add a counter or any private data as this leaks information unncessarily -pub fn dc_create_outgoing_rfc724_mid(grpid: Option<&str>, from_addr: &str) -> String { +pub(crate) fn dc_create_outgoing_rfc724_mid(grpid: Option<&str>, from_addr: &str) -> String { let hostname = from_addr .find('@') .map(|k| &from_addr[k..]) @@ -606,16 +488,7 @@ pub fn dc_create_outgoing_rfc724_mid(grpid: Option<&str>, from_addr: &str) -> St /// # Arguments /// /// * `mid` - A string that holds the message id -/// -/// # Examples -/// -/// ``` -/// use deltachat::dc_tools::dc_extract_grpid_from_rfc724_mid; -/// let mid = "Gr.12345678901.morerandom@domain.de"; -/// let grpid = dc_extract_grpid_from_rfc724_mid(mid); -/// assert_eq!(grpid, Some("12345678901")); -/// ``` -pub fn dc_extract_grpid_from_rfc724_mid(mid: &str) -> Option<&str> { +pub(crate) fn dc_extract_grpid_from_rfc724_mid(mid: &str) -> Option<&str> { if mid.len() < 9 || !mid.starts_with("Gr.") { return None; } @@ -632,7 +505,9 @@ pub fn dc_extract_grpid_from_rfc724_mid(mid: &str) -> Option<&str> { None } -pub unsafe fn dc_extract_grpid_from_rfc724_mid_list(list: *const clist) -> *mut libc::c_char { +pub(crate) unsafe fn dc_extract_grpid_from_rfc724_mid_list( + list: *const clist, +) -> *mut libc::c_char { if !list.is_null() { let mut cur: *mut clistiter = (*list).first; while !cur.is_null() { @@ -656,7 +531,7 @@ pub unsafe fn dc_extract_grpid_from_rfc724_mid_list(list: *const clist) -> *mut ptr::null_mut() } -pub fn dc_ensure_no_slash_safe(path: &str) -> &str { +pub(crate) fn dc_ensure_no_slash_safe(path: &str) -> &str { if path.ends_with('/') || path.ends_with('\\') { return &path[..path.len() - 1]; } @@ -671,14 +546,6 @@ fn validate_filename(filename: &str) -> String { .replace(':', "-") } -pub unsafe fn dc_get_filename(path_filename: impl AsRef) -> *mut libc::c_char { - if let Some(p) = Path::new(path_filename.as_ref()).file_name() { - p.to_string_lossy().strdup() - } else { - ptr::null_mut() - } -} - // the returned suffix is lower-case #[allow(non_snake_case)] pub unsafe fn dc_get_filesuffix_lc(path_filename: impl AsRef) -> *mut libc::c_char { @@ -700,7 +567,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>( +pub(crate) fn dc_get_abs_path>( context: &Context, path: P, ) -> std::path::PathBuf { @@ -712,11 +579,11 @@ pub fn dc_get_abs_path>( } } -pub fn dc_file_exist(context: &Context, path: impl AsRef) -> bool { +pub(crate) fn dc_file_exist(context: &Context, path: impl AsRef) -> bool { dc_get_abs_path(context, &path).exists() } -pub fn dc_get_filebytes(context: &Context, path: impl AsRef) -> u64 { +pub(crate) fn dc_get_filebytes(context: &Context, path: impl AsRef) -> u64 { let path_abs = dc_get_abs_path(context, &path); match fs::metadata(&path_abs) { Ok(meta) => meta.len() as u64, @@ -724,7 +591,7 @@ pub fn dc_get_filebytes(context: &Context, path: impl AsRef) -> } } -pub fn dc_delete_file(context: &Context, path: impl AsRef) -> bool { +pub(crate) fn dc_delete_file(context: &Context, path: impl AsRef) -> bool { let path_abs = dc_get_abs_path(context, &path); if !path_abs.is_file() { warn!( @@ -744,7 +611,7 @@ pub fn dc_delete_file(context: &Context, path: impl AsRef) -> b } } -pub fn dc_copy_file( +pub(crate) fn dc_copy_file( context: &Context, src: impl AsRef, dest: impl AsRef, @@ -765,7 +632,7 @@ pub fn dc_copy_file( } } -pub fn dc_create_folder(context: &Context, path: impl AsRef) -> bool { +pub(crate) fn dc_create_folder(context: &Context, path: impl AsRef) -> bool { let path_abs = dc_get_abs_path(context, &path); if !path_abs.exists() { match fs::create_dir_all(path_abs) { @@ -785,7 +652,7 @@ pub fn dc_create_folder(context: &Context, path: impl AsRef) -> } /// Write a the given content to provied file path. -pub fn dc_write_file(context: &Context, path: impl AsRef, buf: &[u8]) -> bool { +pub(crate) fn dc_write_file(context: &Context, path: impl AsRef, buf: &[u8]) -> bool { let path_abs = dc_get_abs_path(context, &path); if let Err(_err) = fs::write(&path_abs, buf) { warn!( @@ -800,42 +667,26 @@ pub fn dc_write_file(context: &Context, path: impl AsRef, buf: &[u8]) -> b } } -#[allow(non_snake_case)] -pub unsafe fn dc_read_file( +pub fn dc_read_file>( context: &Context, - pathNfilename: *const libc::c_char, - buf: *mut *mut libc::c_void, - buf_bytes: *mut libc::size_t, -) -> libc::c_int { - if pathNfilename.is_null() { - return 0; - } - if let Some(mut bytes) = dc_read_file_safe(context, as_str(pathNfilename)) { - *buf = &mut bytes[..] as *mut _ as *mut libc::c_void; - *buf_bytes = bytes.len(); - std::mem::forget(bytes); - 1 - } else { - 0 - } -} - -pub fn dc_read_file_safe>(context: &Context, path: P) -> Option> { + path: P, +) -> Result, Error> { let path_abs = dc_get_abs_path(context, &path); + match fs::read(&path_abs) { - Ok(bytes) => Some(bytes), - Err(_err) => { + Ok(bytes) => Ok(bytes), + Err(err) => { warn!( context, "Cannot read \"{}\" or file is empty.", path.as_ref().display() ); - None + Err(err.into()) } } } -pub fn dc_get_fine_path_filename( +pub(crate) fn dc_get_fine_path_filename( context: &Context, folder: impl AsRef, desired_filename_suffix: impl AsRef, @@ -880,7 +731,7 @@ pub fn dc_get_fine_path_filename( panic!("Something is really wrong, you need to clean up your disk"); } -pub fn dc_is_blobdir_path(context: &Context, path: impl AsRef) -> bool { +pub(crate) fn dc_is_blobdir_path(context: &Context, path: impl AsRef) -> bool { context .get_blobdir() .to_str() @@ -900,7 +751,7 @@ fn dc_make_rel_path(context: &Context, path: &mut String) { } } -pub fn dc_make_rel_and_copy(context: &Context, path: &mut String) -> bool { +pub(crate) fn dc_make_rel_and_copy(context: &Context, path: &mut String) -> bool { if dc_is_blobdir_path(context, &path) { dc_make_rel_path(context, path); return true; @@ -1148,7 +999,7 @@ fn as_path_unicode<'a>(s: *const libc::c_char) -> &'a std::path::Path { std::path::Path::new(as_str(s)) } -pub fn time() -> i64 { +pub(crate) fn time() -> i64 { SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() @@ -1220,36 +1071,64 @@ impl FromStr for EmailAddress { /// Utility to check if a in the binary represantion of listflags /// the bit at position bitindex is 1. -/// -/// -/// # Example -/// -/// ``` -/// use std::convert::TryInto; -/// use deltachat::dc_tools::listflags_has; -/// use deltachat::constants::{DC_GCL_ADD_SELF, DC_GCL_VERIFIED_ONLY}; -/// let listflags: u32 = 0x1101; -/// assert!(listflags_has(listflags, 0x1) == true); -/// assert!(listflags_has(listflags, 0x10) == false); -/// assert!(listflags_has(listflags, 0x100) == true); -/// assert!(listflags_has(listflags, 0x1000) == true); -/// let listflags: u32 = (DC_GCL_ADD_SELF | DC_GCL_VERIFIED_ONLY).try_into().unwrap(); -/// assert!(listflags_has(listflags, DC_GCL_VERIFIED_ONLY) == true); -/// assert!(listflags_has(listflags, DC_GCL_ADD_SELF) == true); -/// let listflags: u32 = DC_GCL_VERIFIED_ONLY.try_into().unwrap(); -/// assert!(listflags_has(listflags, DC_GCL_ADD_SELF) == false); -/// ``` -pub fn listflags_has(listflags: u32, bitindex: usize) -> bool { +pub(crate) fn listflags_has(listflags: u32, bitindex: usize) -> bool { let listflags = listflags as usize; (listflags & bitindex) == bitindex } +pub(crate) unsafe fn strdup(s: *const libc::c_char) -> *mut libc::c_char { + if s.is_null() { + return std::ptr::null_mut(); + } + + let slen = strlen(s); + let result = libc::malloc(slen + 1); + if result.is_null() { + return std::ptr::null_mut(); + } + + memcpy(result, s as *const _, slen + 1); + result as *mut _ +} + +pub(crate) fn strndup(s: *const libc::c_char, n: libc::c_ulong) -> *mut libc::c_char { + if s.is_null() { + return std::ptr::null_mut(); + } + + let end = std::cmp::min(n as usize, unsafe { strlen(s) }); + unsafe { + let result = libc::malloc(end + 1); + memcpy(result, s as *const _, end); + std::ptr::write_bytes(result.offset(end as isize), b'\x00', 1); + + result as *mut _ + } +} + +pub(crate) unsafe fn strcasecmp(s1: *const libc::c_char, s2: *const libc::c_char) -> libc::c_int { + let s1 = std::ffi::CStr::from_ptr(s1) + .to_string_lossy() + .to_lowercase(); + let s2 = std::ffi::CStr::from_ptr(s2) + .to_string_lossy() + .to_lowercase(); + if s1 == s2 { + 0 + } else { + 1 + } +} + #[cfg(test)] mod tests { use super::*; + use libc::strcmp; + use std::convert::TryInto; use std::ffi::CStr; + use crate::constants::*; use crate::test_utils::*; #[test] @@ -1348,23 +1227,6 @@ mod tests { assert_eq!("1.22", format!("{}", 1.22)); } - #[test] - fn test_dc_str_replace() { - unsafe { - let mut str: *mut libc::c_char = strdup(b"aaa\x00" as *const u8 as *const libc::c_char); - dc_str_replace( - &mut str, - b"a\x00" as *const u8 as *const libc::c_char, - b"ab\x00" as *const u8 as *const libc::c_char, - ); - assert_eq!( - CStr::from_ptr(str as *const libc::c_char).to_str().unwrap(), - "ababab" - ); - free(str as *mut libc::c_void); - } - } - #[test] fn test_dc_truncate_1() { let s = "this is a little test string"; @@ -1420,45 +1282,6 @@ mod tests { ); } - #[test] - fn test_dc_null_terminate_1() { - unsafe { - let str: *mut libc::c_char = - dc_null_terminate(b"abcxyz\x00" as *const u8 as *const libc::c_char, 3); - assert_eq!( - CStr::from_ptr(str as *const libc::c_char).to_str().unwrap(), - "abc" - ); - free(str as *mut libc::c_void); - } - } - - #[test] - fn test_dc_null_terminate_2() { - unsafe { - let str: *mut libc::c_char = - dc_null_terminate(b"abcxyz\x00" as *const u8 as *const libc::c_char, 0); - assert_eq!( - CStr::from_ptr(str as *const libc::c_char).to_str().unwrap(), - "" - ); - free(str as *mut libc::c_void); - } - } - - #[test] - fn test_dc_null_terminate_3() { - unsafe { - let str: *mut libc::c_char = - dc_null_terminate(0 as *const u8 as *const libc::c_char, 0); - assert_eq!( - CStr::from_ptr(str as *const libc::c_char).to_str().unwrap(), - "" - ); - free(str as *mut libc::c_void); - } - } - #[test] fn test_dc_str_to_clist_1() { unsafe { @@ -1517,63 +1340,6 @@ mod tests { } } - #[test] - fn test_dc_replace_bad_utf8_chars_1() { - unsafe { - let buf1 = strdup(b"ol\xc3\xa1 mundo <>\"\'& \xc3\xa4\xc3\x84\xc3\xb6\xc3\x96\xc3\xbc\xc3\x9c\xc3\x9f foo\xc3\x86\xc3\xa7\xc3\x87 \xe2\x99\xa6&noent;\x00" as *const u8 as *const libc::c_char); - let buf2 = strdup(buf1); - - dc_replace_bad_utf8_chars(buf2); - - assert_eq!(strcmp(buf1, buf2), 0); - - free(buf1 as *mut libc::c_void); - free(buf2 as *mut libc::c_void); - } - } - - #[test] - fn test_dc_replace_bad_utf8_chars_2() { - unsafe { - let buf1 = strdup(b"ISO-String with Ae: \xc4\x00" as *const u8 as *const libc::c_char); - let buf2 = strdup(buf1); - - dc_replace_bad_utf8_chars(buf2); - - assert_eq!( - CStr::from_ptr(buf2 as *const libc::c_char) - .to_str() - .unwrap(), - "ISO-String with Ae: _" - ); - - free(buf1 as *mut libc::c_void); - free(buf2 as *mut libc::c_void); - } - } - - #[test] - fn test_dc_replace_bad_utf8_chars_3() { - unsafe { - let buf1 = strdup(b"\x00" as *const u8 as *const libc::c_char); - let buf2 = strdup(buf1); - - dc_replace_bad_utf8_chars(buf2); - - assert_eq!(*buf2.offset(0), 0); - - free(buf1 as *mut libc::c_void); - free(buf2 as *mut libc::c_void); - } - } - - #[test] - fn test_dc_replace_bad_utf8_chars_4() { - unsafe { - dc_replace_bad_utf8_chars(ptr::null_mut()); - } - } - #[test] fn test_dc_create_id() { let buf = dc_create_id(); @@ -1809,4 +1575,85 @@ mod tests { dc_make_rel_path(&t.ctx, &mut foo); assert_eq!(foo, format!("$BLOBDIR{}foo", std::path::MAIN_SEPARATOR)); } + + #[test] + fn test_strndup() { + unsafe { + let res = strndup(b"helloworld\x00" as *const u8 as *const libc::c_char, 4); + assert_eq!( + to_string(res), + to_string(b"hell\x00" as *const u8 as *const libc::c_char) + ); + assert_eq!(strlen(res), 4); + free(res as *mut _); + } + } + + #[test] + fn test_file_handling() { + let t = dummy_context(); + let context = &t.ctx; + + if dc_file_exist(context, "$BLOBDIR/foobar") + || dc_file_exist(context, "$BLOBDIR/dada") + || dc_file_exist(context, "$BLOBDIR/foobar.dadada") + || dc_file_exist(context, "$BLOBDIR/foobar-folder") + { + dc_delete_file(context, "$BLOBDIR/foobar"); + dc_delete_file(context, "$BLOBDIR/dada"); + dc_delete_file(context, "$BLOBDIR/foobar.dadada"); + dc_delete_file(context, "$BLOBDIR/foobar-folder"); + } + assert!(dc_write_file(context, "$BLOBDIR/foobar", b"content")); + assert!(dc_file_exist(context, "$BLOBDIR/foobar",)); + assert!(!dc_file_exist(context, "$BLOBDIR/foobarx")); + assert_eq!(dc_get_filebytes(context, "$BLOBDIR/foobar"), 7); + + let abs_path = context + .get_blobdir() + .join("foobar") + .to_string_lossy() + .to_string(); + + assert!(dc_is_blobdir_path(context, &abs_path)); + assert!(dc_is_blobdir_path(context, "$BLOBDIR/fofo",)); + assert!(!dc_is_blobdir_path(context, "/BLOBDIR/fofo",)); + assert!(dc_file_exist(context, &abs_path)); + + assert!(dc_copy_file(context, "$BLOBDIR/foobar", "$BLOBDIR/dada",)); + assert_eq!(dc_get_filebytes(context, "$BLOBDIR/dada",), 7); + + let buf = dc_read_file(context, "$BLOBDIR/dada").unwrap(); + + assert_eq!(buf.len(), 7); + assert_eq!(&buf, b"content"); + + assert!(dc_delete_file(context, "$BLOBDIR/foobar")); + assert!(dc_delete_file(context, "$BLOBDIR/dada")); + assert!(dc_create_folder(context, "$BLOBDIR/foobar-folder")); + assert!(dc_file_exist(context, "$BLOBDIR/foobar-folder",)); + assert!(!dc_delete_file(context, "$BLOBDIR/foobar-folder")); + let fn0 = dc_get_fine_path_filename(context, "$BLOBDIR", "foobar.dadada"); + assert_eq!(fn0, PathBuf::from("$BLOBDIR/foobar.dadada")); + + assert!(dc_write_file(context, &fn0, b"content")); + let fn1 = dc_get_fine_path_filename(context, "$BLOBDIR", "foobar.dadada"); + assert_eq!(fn1, PathBuf::from("$BLOBDIR/foobar-1.dadada")); + + assert!(dc_delete_file(context, &fn0)); + } + + #[test] + fn test_listflags_has() { + let listflags: u32 = 0x1101; + assert!(listflags_has(listflags, 0x1) == true); + assert!(listflags_has(listflags, 0x10) == false); + assert!(listflags_has(listflags, 0x100) == true); + assert!(listflags_has(listflags, 0x1000) == true); + let listflags: u32 = (DC_GCL_ADD_SELF | DC_GCL_VERIFIED_ONLY).try_into().unwrap(); + assert!(listflags_has(listflags, DC_GCL_VERIFIED_ONLY) == true); + assert!(listflags_has(listflags, DC_GCL_ADD_SELF) == true); + let listflags: u32 = DC_GCL_VERIFIED_ONLY.try_into().unwrap(); + assert!(listflags_has(listflags, DC_GCL_ADD_SELF) == false); + } } diff --git a/src/e2ee.rs b/src/e2ee.rs index 55c6bc6ab..f47c97ecd 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -6,6 +6,7 @@ use std::ffi::CStr; use std::ptr; use std::str::FromStr; +use libc::{free, strcmp, strlen, strncmp}; use mmime::clist::*; use mmime::mailimf::*; use mmime::mailimf_types::*; @@ -30,7 +31,6 @@ use crate::keyring::*; use crate::peerstate::*; use crate::pgp::*; use crate::securejoin::handle_degrade_event; -use crate::x::*; #[derive(Debug, Default)] pub struct E2eeHelper { diff --git a/src/job.rs b/src/job.rs index 3d21537ba..59a637314 100644 --- a/src/job.rs +++ b/src/job.rs @@ -19,7 +19,6 @@ use crate::login_param::LoginParam; use crate::message::{self, Message, MessageState}; use crate::param::*; use crate::sql; -use crate::x::*; /// Thread IDs #[derive(Debug, Display, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive, FromSql, ToSql)] @@ -140,7 +139,7 @@ impl Job { } if let Some(filename) = self.param.get(Param::File) { - if let Some(body) = dc_read_file_safe(context, filename) { + if let Ok(body) = dc_read_file(context, filename) { if let Some(recipients) = self.param.get(Param::Recipients) { let recipients_list = recipients .split("\x1e") @@ -670,7 +669,7 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: u32) -> libc::c_int { mimefactory.msg.param.set_int(Param::Width, 0); mimefactory.msg.param.set_int(Param::Height, 0); - if let Some(buf) = dc_read_file_safe(context, pathNfilename) { + if let Ok(buf) = dc_read_file(context, pathNfilename) { if let Ok((width, height)) = dc_get_filemeta(&buf) { mimefactory.msg.param.set_int(Param::Width, width as i32); mimefactory.msg.param.set_int(Param::Height, height as i32); @@ -1047,7 +1046,7 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &MimeFactory) -> success = 1; } unsafe { - free(recipients.cast()); + libc::free(recipients.cast()); } success } diff --git a/src/lib.rs b/src/lib.rs index 20954f241..87cf915be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,7 +54,6 @@ pub mod qr; mod smtp; pub mod sql; mod stock; -pub mod x; pub mod dc_array; mod dc_dehtml; diff --git a/src/message.rs b/src/message.rs index fc7619406..edf54655b 100644 --- a/src/message.rs +++ b/src/message.rs @@ -2,6 +2,7 @@ use std::path::{Path, PathBuf}; use std::ptr; use deltachat_derive::{FromSql, ToSql}; +use libc::{free, strcmp}; use phf::phf_map; use crate::chat::{self, Chat}; @@ -18,7 +19,6 @@ use crate::param::*; use crate::pgp::*; use crate::sql; use crate::stock::StockMessage; -use crate::x::*; /// In practice, the user additionally cuts the string himself pixel-accurate. const SUMMARY_CHARACTERS: usize = 160; @@ -351,7 +351,7 @@ impl Message { } if let Some(filename) = self.get_file(context) { - if let Some(mut buf) = dc_read_file_safe(context, filename) { + if let Ok(mut buf) = dc_read_file(context, filename) { unsafe { // just a pointer inside buf, MUST NOT be free()'d let mut buf_headerline = ptr::null(); diff --git a/src/pgp.rs b/src/pgp.rs index 84c300ce6..96b144700 100644 --- a/src/pgp.rs +++ b/src/pgp.rs @@ -3,6 +3,7 @@ use std::convert::TryInto; use std::io::Cursor; use std::ptr; +use libc::{strchr, strlen, strncmp, strspn, strstr}; use pgp::composed::{ Deserializable, KeyType as PgpKeyType, Message, SecretKeyParamsBuilder, SignedPublicKey, SignedSecretKey, SubkeyParamsBuilder, @@ -15,7 +16,6 @@ use crate::dc_tools::*; use crate::error::Error; use crate::key::*; use crate::keyring::*; -use crate::x::*; pub unsafe fn dc_split_armored_data( buf: *mut libc::c_char, diff --git a/src/stock.rs b/src/stock.rs index 28481d5c5..e92b08d2c 100644 --- a/src/stock.rs +++ b/src/stock.rs @@ -7,7 +7,6 @@ use crate::contact::*; use crate::context::Context; use crate::dc_tools::*; use crate::events::Event; -use libc::free; /// Stock strings /// @@ -133,7 +132,7 @@ impl Context { Cow::Borrowed(id.fallback()) } else { let ret = to_string(ptr); - unsafe { free(ptr as *mut libc::c_void) }; + unsafe { libc::free(ptr as *mut libc::c_void) }; Cow::Owned(ret) } } diff --git a/src/top_evil_rs.py b/src/top_evil_rs.py index 2976b0de1..633017a6b 100755 --- a/src/top_evil_rs.py +++ b/src/top_evil_rs.py @@ -15,19 +15,21 @@ if __name__ == "__main__": unsafe = s.count("unsafe") free = s.count("free(") gotoblocks = s.count("ok_to_continue") + s.count('OK_TO_CONTINUE') - filestats.append((fn, unsafe, free, gotoblocks)) + chars = s.count("c_char") + s.count("CStr") + filestats.append((fn, unsafe, free, gotoblocks, chars)) - sum_unsafe, sum_free, sum_gotoblocks = 0, 0, 0 + sum_unsafe, sum_free, sum_gotoblocks, sum_chars = 0, 0, 0, 0 - for fn, unsafe, free, gotoblocks in reversed(sorted(filestats, key=lambda x: sum(x[1:]))): - print("{0: <30} unsafe: {1: >3} free: {2: >3} ok_to_continue: {3: >3}".format(str(fn), unsafe, free, gotoblocks)) + for fn, unsafe, free, gotoblocks, chars in reversed(sorted(filestats, key=lambda x: sum(x[1:]))): + print("{0: <25} unsafe: {1: >3} free: {2: >3} ok_to_cont: {3: >3} chars: {4: >3}".format(str(fn), unsafe, free, gotoblocks, chars)) sum_unsafe += unsafe sum_free += free sum_gotoblocks += gotoblocks + sum_chars += chars print() print("total unsafe:", sum_unsafe) print("total free:", sum_free) print("total ok_to_continue:", sum_gotoblocks) - + print("total c_chars:", sum_chars) diff --git a/src/x.rs b/src/x.rs deleted file mode 100644 index 481f837ca..000000000 --- a/src/x.rs +++ /dev/null @@ -1,67 +0,0 @@ -pub use libc::{ - calloc, exit, free, malloc, memcmp, memcpy, memmove, memset, realloc, strcat, strchr, strcmp, - strcpy, strcspn, strlen, strncmp, strncpy, strrchr, strspn, strstr, strtol, system, -}; - -pub unsafe fn strdup(s: *const libc::c_char) -> *mut libc::c_char { - if s.is_null() { - return std::ptr::null_mut(); - } - - let slen = strlen(s); - let result = malloc(slen + 1); - if result.is_null() { - return std::ptr::null_mut(); - } - - memcpy(result, s as *const _, slen + 1); - result as *mut _ -} - -pub fn strndup(s: *const libc::c_char, n: libc::c_ulong) -> *mut libc::c_char { - if s.is_null() { - return std::ptr::null_mut(); - } - - let end = std::cmp::min(n as usize, unsafe { strlen(s) }); - unsafe { - let result = malloc(end + 1); - memcpy(result, s as *const _, end); - std::ptr::write_bytes(result.offset(end as isize), b'\x00', 1); - - result as *mut _ - } -} - -pub(crate) unsafe fn strcasecmp(s1: *const libc::c_char, s2: *const libc::c_char) -> libc::c_int { - let s1 = std::ffi::CStr::from_ptr(s1) - .to_string_lossy() - .to_lowercase(); - let s2 = std::ffi::CStr::from_ptr(s2) - .to_string_lossy() - .to_lowercase(); - if s1 == s2 { - 0 - } else { - 1 - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::dc_tools::to_string; - - #[test] - fn test_strndup() { - unsafe { - let res = strndup(b"helloworld\x00" as *const u8 as *const libc::c_char, 4); - assert_eq!( - to_string(res), - to_string(b"hell\x00" as *const u8 as *const libc::c_char) - ); - assert_eq!(strlen(res), 4); - free(res as *mut _); - } - } -} diff --git a/tests/stress.rs b/tests/stress.rs index bb71e89e4..91d700ea9 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -1,11 +1,8 @@ //! Stress some functions for testing; if used as a lib, this file is obsolete. use std::collections::HashSet; -use std::path::PathBuf; use std::ptr; -use tempfile::{tempdir, TempDir}; - use deltachat::chat::{self, Chat}; use deltachat::config; use deltachat::contact::*; @@ -15,9 +12,9 @@ use deltachat::dc_tools::*; use deltachat::keyring::*; use deltachat::oauth2::*; use deltachat::pgp::*; -use deltachat::x::*; use deltachat::Event; -use libc; +use libc::{free, strcmp, strdup, strlen, strncmp}; +use tempfile::{tempdir, TempDir}; /* some data used for testing ******************************************************************************/ @@ -30,68 +27,6 @@ static mut S_EM_SETUPFILE: *const libc::c_char = as *const u8 as *const libc::c_char; unsafe fn stress_functions(context: &Context) { - if dc_file_exist(context, "$BLOBDIR/foobar") - || dc_file_exist(context, "$BLOBDIR/dada") - || dc_file_exist(context, "$BLOBDIR/foobar.dadada") - || dc_file_exist(context, "$BLOBDIR/foobar-folder") - { - dc_delete_file(context, "$BLOBDIR/foobar"); - dc_delete_file(context, "$BLOBDIR/dada"); - dc_delete_file(context, "$BLOBDIR/foobar.dadada"); - dc_delete_file(context, "$BLOBDIR/foobar-folder"); - } - assert!(dc_write_file(context, "$BLOBDIR/foobar", b"content")); - assert!(dc_file_exist(context, "$BLOBDIR/foobar",)); - assert!(!dc_file_exist(context, "$BLOBDIR/foobarx")); - assert_eq!(dc_get_filebytes(context, "$BLOBDIR/foobar"), 7); - - let abs_path = context - .get_blobdir() - .join("foobar") - .to_string_lossy() - .to_string(); - - assert!(dc_is_blobdir_path(context, &abs_path)); - assert!(dc_is_blobdir_path(context, "$BLOBDIR/fofo",)); - assert!(!dc_is_blobdir_path(context, "/BLOBDIR/fofo",)); - assert!(dc_file_exist(context, &abs_path)); - - assert!(dc_copy_file(context, "$BLOBDIR/foobar", "$BLOBDIR/dada",)); - assert_eq!(dc_get_filebytes(context, "$BLOBDIR/dada",), 7); - - let mut buf: *mut libc::c_void = ptr::null_mut(); - let mut buf_bytes: libc::size_t = 0; - - assert_eq!( - dc_read_file( - context, - b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char, - &mut buf, - &mut buf_bytes, - ), - 1 - ); - assert_eq!(buf_bytes, 7); - assert_eq!( - std::str::from_utf8(std::slice::from_raw_parts(buf as *const u8, buf_bytes)).unwrap(), - "content" - ); - - free(buf as *mut _); - assert!(dc_delete_file(context, "$BLOBDIR/foobar")); - assert!(dc_delete_file(context, "$BLOBDIR/dada")); - assert!(dc_create_folder(context, "$BLOBDIR/foobar-folder")); - assert!(dc_file_exist(context, "$BLOBDIR/foobar-folder",)); - assert!(!dc_delete_file(context, "$BLOBDIR/foobar-folder")); - let fn0 = dc_get_fine_path_filename(context, "$BLOBDIR", "foobar.dadada"); - assert_eq!(fn0, PathBuf::from("$BLOBDIR/foobar.dadada")); - - assert!(dc_write_file(context, &fn0, b"content")); - let fn1 = dc_get_fine_path_filename(context, "$BLOBDIR", "foobar.dadada"); - assert_eq!(fn1, PathBuf::from("$BLOBDIR/foobar-1.dadada")); - - assert!(dc_delete_file(context, &fn0)); - let res = context.get_config(config::Config::SysConfigKeys).unwrap(); assert!(!res.contains(" probably_never_a_key "));