refactor: remove x module and delete deadcode

This commit is contained in:
dignifiedquire
2019-09-21 16:22:58 +02:00
committed by holger krekel
parent b85f59798c
commit 05f9f454c3
20 changed files with 244 additions and 545 deletions

View File

@@ -24,7 +24,9 @@ use num_traits::{FromPrimitive, ToPrimitive};
use deltachat::contact::Contact; use deltachat::contact::Contact;
use deltachat::context::Context; 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::*; use deltachat::*;
// as C lacks a good and portable error handling, // 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() { let os_name = if os_name.is_null() {
String::from("DcFFI") String::from("DcFFI")
} else { } else {
dc_tools::to_string_lossy(os_name) to_string_lossy(os_name)
}; };
let ffi_ctx = ContextWrapper { let ffi_ctx = ContextWrapper {
cb, cb,
@@ -735,7 +737,7 @@ pub unsafe extern "C" fn dc_send_text_msg(
return 0; return 0;
} }
let ffi_context = &*context; 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 ffi_context
.with_inner(|ctx| { .with_inner(|ctx| {
chat::send_text_msg(ctx, chat_id, text_to_send) 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; return None;
} }
Some(dc_tools::as_str(s)) Some(as_str(s))
} }
pub mod providers; pub mod providers;

View File

@@ -1,4 +1,4 @@
use std::ffi::CString; use std::path::Path;
use std::ptr; use std::ptr;
use std::str::FromStr; use std::str::FromStr;
@@ -20,8 +20,8 @@ use deltachat::message::{self, Message, MessageState};
use deltachat::peerstate::*; use deltachat::peerstate::*;
use deltachat::qr::*; use deltachat::qr::*;
use deltachat::sql; use deltachat::sql;
use deltachat::x::*;
use deltachat::Event; use deltachat::Event;
use libc::free;
/// Reset database tables. This function is called from Core cmdline. /// Reset database tables. This function is called from Core cmdline.
/// Argument is a bitmask, executing single or multiple actions in one call. /// 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 1
} }
unsafe fn dc_poke_eml_file(context: &Context, filename: *const libc::c_char) -> libc::c_int { fn dc_poke_eml_file(context: &Context, filename: impl AsRef<Path>) -> Result<(), Error> {
/* mainly for testing, may be called by dc_import_spec() */ let data = dc_read_file(context, filename)?;
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);
success unsafe {
dc_receive_imf(
context,
data.as_ptr() as *const _,
data.len(),
"import",
0,
0,
)
};
Ok(())
} }
/// Import a file to the database. /// 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 ok_to_continue;
let mut success: libc::c_int = 0; 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 suffix: *mut libc::c_char = ptr::null_mut();
let mut read_cnt: libc::c_int = 0; 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 given, remember it for later usage; if it is not given, try to use the last one */
if !spec.is_null() { if !spec.is_null() {
real_spec = dc_strdup(spec); real_spec = to_string(spec);
context context
.sql .sql
.set_config(context, "import_spec", Some(as_str(real_spec))) .set_config(context, "import_spec", Some(&real_spec))
.unwrap(); .unwrap();
ok_to_continue = true; ok_to_continue = true;
} else { } else {
@@ -150,27 +146,24 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
} else { } else {
ok_to_continue = true; ok_to_continue = true;
} }
real_spec = rs.unwrap_or_default().strdup(); real_spec = rs.unwrap_or_default();
} }
if ok_to_continue { if ok_to_continue {
let ok_to_continue2; let ok_to_continue2;
suffix = dc_get_filesuffix_lc(as_str(real_spec)); suffix = dc_get_filesuffix_lc(&real_spec);
if !suffix.is_null() && strcmp(suffix, b"eml\x00" as *const u8 as *const libc::c_char) == 0 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 read_cnt += 1
} }
ok_to_continue2 = true; ok_to_continue2 = true;
} else { } else {
/* import a directory */ /* 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); let dir = std::fs::read_dir(dir_name);
if dir.is_err() { if dir.is_err() {
error!( error!(context, "Import: Cannot open directory \"{}\".", &real_spec,);
context,
"Import: Cannot open directory \"{}\".",
as_str(real_spec),
);
ok_to_continue2 = false; ok_to_continue2 = false;
} else { } else {
let dir = dir.unwrap(); 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_f = entry.file_name();
let name = name_f.to_string_lossy(); let name = name_f.to_string_lossy();
if name.ends_with(".eml") { 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); info!(context, "Import: {}", path_plus_name);
let path_plus_name_c = CString::yolo(path_plus_name); if dc_poke_eml_file(context, path_plus_name).is_ok() {
if 0 != dc_poke_eml_file(context, path_plus_name_c.as_ptr()) {
read_cnt += 1 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 { if ok_to_continue2 {
info!( info!(
context, context,
"Import: {} items read from \"{}\".", "Import: {} items read from \"{}\".", read_cnt, &real_spec
read_cnt,
as_str(real_spec)
); );
if read_cnt > 0 { if read_cnt > 0 {
context.call_cb(Event::MsgsChanged { 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); free(suffix as *mut libc::c_void);
success success
} }
@@ -1017,7 +1006,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
"fileinfo" => { "fileinfo" => {
ensure!(!arg1.is_empty(), "Argument <file> missing."); ensure!(!arg1.is_empty(), "Argument <file> 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)?; let (width, height) = dc_get_filemeta(&buf)?;
println!("width={}, height={}", width, height); println!("width={}, height={}", width, height);
} else { } else {

View File

@@ -23,11 +23,9 @@ use std::sync::{Arc, Mutex, RwLock};
use deltachat::config; use deltachat::config;
use deltachat::configure::*; use deltachat::configure::*;
use deltachat::context::*; use deltachat::context::*;
use deltachat::dc_tools::*;
use deltachat::job::*; use deltachat::job::*;
use deltachat::oauth2::*; use deltachat::oauth2::*;
use deltachat::securejoin::*; use deltachat::securejoin::*;
use deltachat::x::*;
use deltachat::Event; use deltachat::Event;
use rustyline::completion::{Completer, FilenameCompleter, Pair}; use rustyline::completion::{Completer, FilenameCompleter, Pair};
use rustyline::config::OutputStreamType; use rustyline::config::OutputStreamType;
@@ -441,11 +439,6 @@ unsafe fn handle_cmd(line: &str, ctx: Arc<RwLock<Context>>) -> Result<ExitResult
let mut args = line.splitn(2, ' '); let mut args = line.splitn(2, ' ');
let arg0 = args.next().unwrap_or_default(); let arg0 = args.next().unwrap_or_default();
let arg1 = args.next().unwrap_or_default(); let arg1 = args.next().unwrap_or_default();
let arg1_c = if arg1.is_empty() {
std::ptr::null()
} else {
arg1.strdup()
};
match arg0 { match arg0 {
"connect" => { "connect" => {
@@ -521,8 +514,6 @@ unsafe fn handle_cmd(line: &str, ctx: Arc<RwLock<Context>>) -> Result<ExitResult
_ => dc_cmdline(&ctx.read().unwrap(), line)?, _ => dc_cmdline(&ctx.read().unwrap(), line)?,
} }
free(arg1_c as *mut _);
Ok(ExitResult::Continue) Ok(ExitResult::Continue)
} }

View File

@@ -1,3 +1,4 @@
use libc::free;
use quick_xml; use quick_xml;
use quick_xml::events::{BytesEnd, BytesStart, BytesText}; use quick_xml::events::{BytesEnd, BytesStart, BytesText};
@@ -5,7 +6,6 @@ use crate::constants::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::login_param::LoginParam; use crate::login_param::LoginParam;
use crate::x::*;
use super::read_autoconf_file; use super::read_autoconf_file;
/* ****************************************************************************** /* ******************************************************************************

View File

@@ -1,3 +1,6 @@
use std::ptr;
use libc::free;
use quick_xml; use quick_xml;
use quick_xml::events::{BytesEnd, BytesStart, BytesText}; use quick_xml::events::{BytesEnd, BytesStart, BytesText};
@@ -5,8 +8,6 @@ use crate::constants::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::login_param::LoginParam; use crate::login_param::LoginParam;
use crate::x::*;
use std::ptr;
use super::read_autoconf_file; use super::read_autoconf_file;
/* ****************************************************************************** /* ******************************************************************************
@@ -46,7 +47,7 @@ pub unsafe fn outlk_autodiscover(
ok_to_continue = true; ok_to_continue = true;
break; break;
} }
memset( libc::memset(
&mut outlk_ad as *mut outlk_autodiscover_t as *mut libc::c_void, &mut outlk_ad as *mut outlk_autodiscover_t as *mut libc::c_void,
0, 0,
::std::mem::size_of::<outlk_autodiscover_t>(), ::std::mem::size_of::<outlk_autodiscover_t>(),

View File

@@ -2,6 +2,7 @@ use std::ffi::CString;
use std::path::Path; use std::path::Path;
use std::ptr; use std::ptr;
use libc::{free, strcmp, strlen, strstr};
use mmime::mailmime_content::*; use mmime::mailmime_content::*;
use mmime::mmapstring::*; use mmime::mmapstring::*;
use mmime::other::*; use mmime::other::*;
@@ -23,7 +24,6 @@ use crate::param::*;
use crate::pgp::*; use crate::pgp::*;
use crate::sql::{self, Sql}; use crate::sql::{self, Sql};
use crate::stock::StockMessage; use crate::stock::StockMessage;
use crate::x::*;
// import/export and tools // import/export and tools
// param1 is a directory where the keys are written to // 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(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); norm_sc = dc_normalize_setup_code(context, setup_code);
if norm_sc.is_null() { if norm_sc.is_null() {
warn!(context, "Cannot normalize Setup Code.",); warn!(context, "Cannot normalize Setup Code.",);
@@ -767,8 +767,8 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> bool {
} else { } else {
info!(context, "EXPORTing filename={}", name); info!(context, "EXPORTing filename={}", name);
let curr_pathNfilename = context.get_blobdir().join(entry.file_name()); let curr_pathNfilename = context.get_blobdir().join(entry.file_name());
if let Some(buf) = if let Ok(buf) =
dc_read_file_safe(context, &curr_pathNfilename) dc_read_file(context, &curr_pathNfilename)
{ {
if buf.is_empty() { if buf.is_empty() {
continue; continue;
@@ -874,7 +874,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
free(buf.cast()); free(buf.cast());
buf = ptr::null_mut(); 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 _; buf = buf_r.as_ptr() as *mut _;
std::mem::forget(buf_r); std::mem::forget(buf_r);
} else { } else {

View File

@@ -2,6 +2,7 @@ use std::path::Path;
use std::ptr; use std::ptr;
use chrono::TimeZone; use chrono::TimeZone;
use libc::{free, strcmp, strlen};
use mmime::clist::*; use mmime::clist::*;
use mmime::mailimf_types::*; use mmime::mailimf_types::*;
use mmime::mailimf_types_helper::*; use mmime::mailimf_types_helper::*;
@@ -25,7 +26,6 @@ use crate::location;
use crate::message::{self, Message}; use crate::message::{self, Message};
use crate::param::*; use crate::param::*;
use crate::stock::StockMessage; use crate::stock::StockMessage;
use crate::x::*;
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
pub enum Loaded { pub enum Loaded {

View File

@@ -4,6 +4,7 @@ use std::ptr;
use charset::Charset; use charset::Charset;
use deltachat_derive::{FromSql, ToSql}; use deltachat_derive::{FromSql, ToSql};
use libc::{strcmp, strlen, strncmp};
use mmime::clist::*; use mmime::clist::*;
use mmime::mailimf::*; use mmime::mailimf::*;
use mmime::mailimf_types::*; use mmime::mailimf_types::*;
@@ -25,7 +26,6 @@ use crate::error::Error;
use crate::location; use crate::location;
use crate::param::*; use crate::param::*;
use crate::stock::StockMessage; use crate::stock::StockMessage;
use crate::x::*;
#[derive(Debug)] #[derive(Debug)]
pub struct MimeParser<'a> { pub struct MimeParser<'a> {

View File

@@ -2,6 +2,7 @@ use std::ffi::CString;
use std::ptr; use std::ptr;
use itertools::join; use itertools::join;
use libc::{free, strcmp, strlen};
use mmime::clist::*; use mmime::clist::*;
use mmime::mailimf::*; use mmime::mailimf::*;
use mmime::mailimf_types::*; use mmime::mailimf_types::*;
@@ -28,7 +29,6 @@ use crate::peerstate::*;
use crate::securejoin::handle_securejoin_handshake; use crate::securejoin::handle_securejoin_handshake;
use crate::sql; use crate::sql;
use crate::stock::StockMessage; use crate::stock::StockMessage;
use crate::x::*;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
enum CreateEvent { enum CreateEvent {

View File

@@ -3,13 +3,13 @@ use std::ffi::CString;
use std::ptr; use std::ptr;
use charset::Charset; use charset::Charset;
use libc::{free, strlen};
use mmime::mailmime_decode::*; use mmime::mailmime_decode::*;
use mmime::mmapstring::*; use mmime::mmapstring::*;
use mmime::other::*; use mmime::other::*;
use percent_encoding::{percent_decode, utf8_percent_encode, AsciiSet, CONTROLS}; use percent_encoding::{percent_decode, utf8_percent_encode, AsciiSet, CONTROLS};
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::x::*;
/** /**
* Encode non-ascii-strings as `=?UTF-8?Q?Bj=c3=b6rn_Petersen?=`. * 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use libc::{strcmp, strncmp};
use std::ffi::CStr; use std::ffi::CStr;
#[test] #[test]

View File

@@ -9,16 +9,15 @@ use std::time::SystemTime;
use std::{fmt, fs, ptr}; use std::{fmt, fs, ptr};
use chrono::{Local, TimeZone}; use chrono::{Local, TimeZone};
use libc::uintptr_t; use libc::{free, memcpy, strcpy, strlen, strstr, uintptr_t};
use mmime::clist::*; use mmime::clist::*;
use mmime::mailimf_types::*; use mmime::mailimf_types::*;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use crate::context::Context; use crate::context::Context;
use crate::error::Error; 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) 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); ret = strdup(s);
assert!(!ret.is_null()); assert!(!ret.is_null());
} else { } else {
ret = calloc(1, 1) as *mut libc::c_char; ret = libc::calloc(1, 1) as *mut libc::c_char;
assert!(!ret.is_null()); 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 /// Duplicates a string, returns null if given string is null
/// pub(crate) unsafe fn dc_strdup_keep_null(s: *const libc::c_char) -> *mut libc::c_char {
/// # 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 {
if !s.is_null() { if !s.is_null() {
dc_strdup(s) dc_strdup(s)
} else { } 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() { if !s.is_null() {
as_str(s).parse().unwrap_or_default() as_str(s).parse().unwrap_or_default()
} else { } 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) { unsafe fn dc_ltrim(buf: *mut libc::c_char) {
let mut len: libc::size_t; let mut len: libc::size_t;
let mut cur: *const libc::c_uchar; 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) len = len.wrapping_sub(1)
} }
if buf as *const libc::c_uchar != cur { if buf as *const libc::c_uchar != cur {
memmove( libc::memmove(
buf as *mut libc::c_void, buf as *mut libc::c_void,
cur as *const libc::c_void, cur as *const libc::c_void,
len.wrapping_add(1), 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_ltrim(buf);
dc_rtrim(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 */ /* 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` */ /* search for first `\r` */
let mut p1: *const libc::c_char = buf; let mut p1: *const libc::c_char = buf;
while 0 != *p1 { 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; *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 /// Shortens a string to a specified length and adds "..." or "[...]" to the end of
/// the shortened string. /// the shortened string.
/// pub(crate) fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Cow<str> {
/// # 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<str> {
let ellipse = if do_unwrap { "..." } else { "[...]" }; let ellipse = if do_unwrap { "..." } else { "[...]" };
let count = buf.chars().count(); let count = buf.chars().count();
@@ -278,7 +159,7 @@ pub fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Cow<str>
} }
#[allow(non_snake_case)] #[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, buf: *mut libc::c_char,
approx_characters: libc::c_int, approx_characters: libc::c_int,
do_unwrap: 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 j
} }
pub unsafe fn dc_str_from_clist( pub(crate) unsafe fn dc_str_from_clist(
list: *const clist, list: *const clist,
delimiter: *const libc::c_char, delimiter: *const libc::c_char,
) -> *mut libc::c_char { ) -> *mut libc::c_char {
@@ -369,7 +250,7 @@ pub unsafe fn dc_str_from_clist(
res.strdup() res.strdup()
} }
pub unsafe fn dc_str_to_clist( pub(crate) unsafe fn dc_str_to_clist(
str: *const libc::c_char, str: *const libc::c_char,
delimiter: *const libc::c_char, delimiter: *const libc::c_char,
) -> *mut clist { ) -> *mut clist {
@@ -408,7 +289,7 @@ const COLORS: [u32; 16] = [
0x39b249, 0xbb243b, 0x964078, 0x66874f, 0x308ab9, 0x127ed0, 0xbe450c, 0x39b249, 0xbb243b, 0x964078, 0x66874f, 0x308ab9, 0x127ed0, 0xbe450c,
]; ];
pub fn dc_str_to_color(s: impl AsRef<str>) -> u32 { pub(crate) fn dc_str_to_color(s: impl AsRef<str>) -> u32 {
let str_lower = s.as_ref().to_lowercase(); let str_lower = s.as_ref().to_lowercase();
let mut checksum = 0; let mut checksum = 0;
let bytes = str_lower.as_bytes(); let bytes = str_lower.as_bytes();
@@ -422,8 +303,9 @@ pub fn dc_str_to_color(s: impl AsRef<str>) -> u32 {
} }
/* clist tools */ /* clist tools */
/* calls free() for each item content */ /* 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; let mut iter = (*haystack).first;
while !iter.is_null() { 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, haystack: *const clist,
needle: *const libc::c_char, needle: *const libc::c_char,
) -> bool { ) -> bool {
@@ -448,7 +330,7 @@ pub unsafe fn clist_search_string_nocase(
/* date/time tools */ /* date/time tools */
/* the result is UTC or DC_INVALID_TIMESTAMP */ /* 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 sec = (*date_time).dt_sec;
let min = (*date_time).dt_min; let min = (*date_time).dt_min;
let hour = (*date_time).dt_hour; 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() 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(); let lt = Local::now();
((lt.offset().local_minus_utc() / (60 * 60)) * 100) as i64 ((lt.offset().local_minus_utc() / (60 * 60)) * 100) as i64
} }
/* timesmearing */ /* timesmearing */
pub fn dc_smeared_time(context: &Context) -> i64 { pub(crate) fn dc_smeared_time(context: &Context) -> i64 {
/* function returns a corrected time(NULL) */ /* function returns a corrected time(NULL) */
let mut now = time(); let mut now = time();
let ts = *context.last_smeared_timestamp.clone().read().unwrap(); let ts = *context.last_smeared_timestamp.clone().read().unwrap();
@@ -499,7 +381,7 @@ pub fn dc_smeared_time(context: &Context) -> i64 {
now now
} }
pub fn dc_create_smeared_timestamp(context: &Context) -> i64 { pub(crate) fn dc_create_smeared_timestamp(context: &Context) -> i64 {
let now = time(); let now = time();
let mut ret = now; let mut ret = now;
@@ -514,7 +396,7 @@ pub fn dc_create_smeared_timestamp(context: &Context) -> i64 {
ret 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 */ /* get a range to timestamps that can be used uniquely */
let now = time(); let now = time();
let start = now + (if count < 5 { count } else { 5 }) as i64 - count as i64; 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 */ /* 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: /* 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 - 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. - 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() String::from_utf8(wrapped_writer).unwrap()
} }
pub fn dc_create_incoming_rfc724_mid( pub(crate) fn dc_create_incoming_rfc724_mid(
message_timestamp: i64, message_timestamp: i64,
contact_id_from: u32, contact_id_from: u32,
contact_ids_to: &Vec<u32>, contact_ids_to: &Vec<u32>,
@@ -590,7 +472,7 @@ pub fn dc_create_incoming_rfc724_mid(
/// - this function is called for all outgoing messages. /// - this function is called for all outgoing messages.
/// - the message ID should be globally unique /// - the message ID should be globally unique
/// - do not add a counter or any private data as this leaks information unncessarily /// - 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 let hostname = from_addr
.find('@') .find('@')
.map(|k| &from_addr[k..]) .map(|k| &from_addr[k..])
@@ -606,16 +488,7 @@ pub fn dc_create_outgoing_rfc724_mid(grpid: Option<&str>, from_addr: &str) -> St
/// # Arguments /// # Arguments
/// ///
/// * `mid` - A string that holds the message id /// * `mid` - A string that holds the message id
/// pub(crate) fn dc_extract_grpid_from_rfc724_mid(mid: &str) -> Option<&str> {
/// # 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> {
if mid.len() < 9 || !mid.starts_with("Gr.") { if mid.len() < 9 || !mid.starts_with("Gr.") {
return None; return None;
} }
@@ -632,7 +505,9 @@ pub fn dc_extract_grpid_from_rfc724_mid(mid: &str) -> Option<&str> {
None 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() { if !list.is_null() {
let mut cur: *mut clistiter = (*list).first; let mut cur: *mut clistiter = (*list).first;
while !cur.is_null() { 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() 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('\\') { if path.ends_with('/') || path.ends_with('\\') {
return &path[..path.len() - 1]; return &path[..path.len() - 1];
} }
@@ -671,14 +546,6 @@ fn validate_filename(filename: &str) -> String {
.replace(':', "-") .replace(':', "-")
} }
pub unsafe fn dc_get_filename(path_filename: impl AsRef<str>) -> *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 // the returned suffix is lower-case
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub unsafe fn dc_get_filesuffix_lc(path_filename: impl AsRef<str>) -> *mut libc::c_char { pub unsafe fn dc_get_filesuffix_lc(path_filename: impl AsRef<str>) -> *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. /// If `path` starts with "$BLOBDIR", replaces it with the blobdir path.
/// Otherwise, returns path as is. /// Otherwise, returns path as is.
pub fn dc_get_abs_path<P: AsRef<std::path::Path>>( pub(crate) fn dc_get_abs_path<P: AsRef<std::path::Path>>(
context: &Context, context: &Context,
path: P, path: P,
) -> std::path::PathBuf { ) -> std::path::PathBuf {
@@ -712,11 +579,11 @@ pub fn dc_get_abs_path<P: AsRef<std::path::Path>>(
} }
} }
pub fn dc_file_exist(context: &Context, path: impl AsRef<std::path::Path>) -> bool { pub(crate) fn dc_file_exist(context: &Context, path: impl AsRef<std::path::Path>) -> bool {
dc_get_abs_path(context, &path).exists() dc_get_abs_path(context, &path).exists()
} }
pub fn dc_get_filebytes(context: &Context, path: impl AsRef<std::path::Path>) -> u64 { pub(crate) fn dc_get_filebytes(context: &Context, path: impl AsRef<std::path::Path>) -> u64 {
let path_abs = dc_get_abs_path(context, &path); let path_abs = dc_get_abs_path(context, &path);
match fs::metadata(&path_abs) { match fs::metadata(&path_abs) {
Ok(meta) => meta.len() as u64, Ok(meta) => meta.len() as u64,
@@ -724,7 +591,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 { pub(crate) fn dc_delete_file(context: &Context, path: impl AsRef<std::path::Path>) -> bool {
let path_abs = dc_get_abs_path(context, &path); let path_abs = dc_get_abs_path(context, &path);
if !path_abs.is_file() { if !path_abs.is_file() {
warn!( warn!(
@@ -744,7 +611,7 @@ pub fn dc_delete_file(context: &Context, path: impl AsRef<std::path::Path>) -> b
} }
} }
pub fn dc_copy_file( pub(crate) fn dc_copy_file(
context: &Context, context: &Context,
src: impl AsRef<std::path::Path>, src: impl AsRef<std::path::Path>,
dest: impl AsRef<std::path::Path>, dest: impl AsRef<std::path::Path>,
@@ -765,7 +632,7 @@ pub fn dc_copy_file(
} }
} }
pub fn dc_create_folder(context: &Context, path: impl AsRef<std::path::Path>) -> bool { pub(crate) fn dc_create_folder(context: &Context, path: impl AsRef<std::path::Path>) -> bool {
let path_abs = dc_get_abs_path(context, &path); let path_abs = dc_get_abs_path(context, &path);
if !path_abs.exists() { if !path_abs.exists() {
match fs::create_dir_all(path_abs) { match fs::create_dir_all(path_abs) {
@@ -785,7 +652,7 @@ pub fn dc_create_folder(context: &Context, path: impl AsRef<std::path::Path>) ->
} }
/// Write a the given content to provied file path. /// Write a the given content to provied file path.
pub fn dc_write_file(context: &Context, path: impl AsRef<Path>, buf: &[u8]) -> bool { pub(crate) fn dc_write_file(context: &Context, path: impl AsRef<Path>, buf: &[u8]) -> bool {
let path_abs = dc_get_abs_path(context, &path); let path_abs = dc_get_abs_path(context, &path);
if let Err(_err) = fs::write(&path_abs, buf) { if let Err(_err) = fs::write(&path_abs, buf) {
warn!( warn!(
@@ -800,42 +667,26 @@ pub fn dc_write_file(context: &Context, path: impl AsRef<Path>, buf: &[u8]) -> b
} }
} }
#[allow(non_snake_case)] pub fn dc_read_file<P: AsRef<std::path::Path>>(
pub unsafe fn dc_read_file(
context: &Context, context: &Context,
pathNfilename: *const libc::c_char, path: P,
buf: *mut *mut libc::c_void, ) -> Result<Vec<u8>, Error> {
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<P: AsRef<std::path::Path>>(context: &Context, path: P) -> Option<Vec<u8>> {
let path_abs = dc_get_abs_path(context, &path); let path_abs = dc_get_abs_path(context, &path);
match fs::read(&path_abs) { match fs::read(&path_abs) {
Ok(bytes) => Some(bytes), Ok(bytes) => Ok(bytes),
Err(_err) => { Err(err) => {
warn!( warn!(
context, context,
"Cannot read \"{}\" or file is empty.", "Cannot read \"{}\" or file is empty.",
path.as_ref().display() 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, context: &Context,
folder: impl AsRef<Path>, folder: impl AsRef<Path>,
desired_filename_suffix: impl AsRef<str>, desired_filename_suffix: impl AsRef<str>,
@@ -880,7 +731,7 @@ pub fn dc_get_fine_path_filename(
panic!("Something is really wrong, you need to clean up your disk"); panic!("Something is really wrong, you need to clean up your disk");
} }
pub fn dc_is_blobdir_path(context: &Context, path: impl AsRef<str>) -> bool { pub(crate) fn dc_is_blobdir_path(context: &Context, path: impl AsRef<str>) -> bool {
context context
.get_blobdir() .get_blobdir()
.to_str() .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) { if dc_is_blobdir_path(context, &path) {
dc_make_rel_path(context, path); dc_make_rel_path(context, path);
return true; 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)) std::path::Path::new(as_str(s))
} }
pub fn time() -> i64 { pub(crate) fn time() -> i64 {
SystemTime::now() SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH) .duration_since(SystemTime::UNIX_EPOCH)
.unwrap() .unwrap()
@@ -1220,36 +1071,64 @@ impl FromStr for EmailAddress {
/// Utility to check if a in the binary represantion of listflags /// Utility to check if a in the binary represantion of listflags
/// the bit at position bitindex is 1. /// the bit at position bitindex is 1.
/// pub(crate) fn listflags_has(listflags: u32, bitindex: usize) -> bool {
///
/// # 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 {
let listflags = listflags as usize; let listflags = listflags as usize;
(listflags & bitindex) == bitindex (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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use libc::strcmp;
use std::convert::TryInto;
use std::ffi::CStr; use std::ffi::CStr;
use crate::constants::*;
use crate::test_utils::*; use crate::test_utils::*;
#[test] #[test]
@@ -1348,23 +1227,6 @@ mod tests {
assert_eq!("1.22", format!("{}", 1.22)); 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] #[test]
fn test_dc_truncate_1() { fn test_dc_truncate_1() {
let s = "this is a little test string"; 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] #[test]
fn test_dc_str_to_clist_1() { fn test_dc_str_to_clist_1() {
unsafe { 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] #[test]
fn test_dc_create_id() { fn test_dc_create_id() {
let buf = dc_create_id(); let buf = dc_create_id();
@@ -1809,4 +1575,85 @@ mod tests {
dc_make_rel_path(&t.ctx, &mut foo); dc_make_rel_path(&t.ctx, &mut foo);
assert_eq!(foo, format!("$BLOBDIR{}foo", std::path::MAIN_SEPARATOR)); 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);
}
} }

View File

@@ -6,6 +6,7 @@ use std::ffi::CStr;
use std::ptr; use std::ptr;
use std::str::FromStr; use std::str::FromStr;
use libc::{free, strcmp, strlen, strncmp};
use mmime::clist::*; use mmime::clist::*;
use mmime::mailimf::*; use mmime::mailimf::*;
use mmime::mailimf_types::*; use mmime::mailimf_types::*;
@@ -30,7 +31,6 @@ use crate::keyring::*;
use crate::peerstate::*; use crate::peerstate::*;
use crate::pgp::*; use crate::pgp::*;
use crate::securejoin::handle_degrade_event; use crate::securejoin::handle_degrade_event;
use crate::x::*;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct E2eeHelper { pub struct E2eeHelper {

View File

@@ -19,7 +19,6 @@ use crate::login_param::LoginParam;
use crate::message::{self, Message, MessageState}; use crate::message::{self, Message, MessageState};
use crate::param::*; use crate::param::*;
use crate::sql; use crate::sql;
use crate::x::*;
/// Thread IDs /// Thread IDs
#[derive(Debug, Display, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive, FromSql, ToSql)] #[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(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) { if let Some(recipients) = self.param.get(Param::Recipients) {
let recipients_list = recipients let recipients_list = recipients
.split("\x1e") .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::Width, 0);
mimefactory.msg.param.set_int(Param::Height, 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) { 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::Width, width as i32);
mimefactory.msg.param.set_int(Param::Height, height 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; success = 1;
} }
unsafe { unsafe {
free(recipients.cast()); libc::free(recipients.cast());
} }
success success
} }

View File

@@ -54,7 +54,6 @@ pub mod qr;
mod smtp; mod smtp;
pub mod sql; pub mod sql;
mod stock; mod stock;
pub mod x;
pub mod dc_array; pub mod dc_array;
mod dc_dehtml; mod dc_dehtml;

View File

@@ -2,6 +2,7 @@ use std::path::{Path, PathBuf};
use std::ptr; use std::ptr;
use deltachat_derive::{FromSql, ToSql}; use deltachat_derive::{FromSql, ToSql};
use libc::{free, strcmp};
use phf::phf_map; use phf::phf_map;
use crate::chat::{self, Chat}; use crate::chat::{self, Chat};
@@ -18,7 +19,6 @@ use crate::param::*;
use crate::pgp::*; use crate::pgp::*;
use crate::sql; use crate::sql;
use crate::stock::StockMessage; use crate::stock::StockMessage;
use crate::x::*;
/// In practice, the user additionally cuts the string himself pixel-accurate. /// In practice, the user additionally cuts the string himself pixel-accurate.
const SUMMARY_CHARACTERS: usize = 160; const SUMMARY_CHARACTERS: usize = 160;
@@ -351,7 +351,7 @@ impl Message {
} }
if let Some(filename) = self.get_file(context) { 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 { unsafe {
// just a pointer inside buf, MUST NOT be free()'d // just a pointer inside buf, MUST NOT be free()'d
let mut buf_headerline = ptr::null(); let mut buf_headerline = ptr::null();

View File

@@ -3,6 +3,7 @@ use std::convert::TryInto;
use std::io::Cursor; use std::io::Cursor;
use std::ptr; use std::ptr;
use libc::{strchr, strlen, strncmp, strspn, strstr};
use pgp::composed::{ use pgp::composed::{
Deserializable, KeyType as PgpKeyType, Message, SecretKeyParamsBuilder, SignedPublicKey, Deserializable, KeyType as PgpKeyType, Message, SecretKeyParamsBuilder, SignedPublicKey,
SignedSecretKey, SubkeyParamsBuilder, SignedSecretKey, SubkeyParamsBuilder,
@@ -15,7 +16,6 @@ use crate::dc_tools::*;
use crate::error::Error; use crate::error::Error;
use crate::key::*; use crate::key::*;
use crate::keyring::*; use crate::keyring::*;
use crate::x::*;
pub unsafe fn dc_split_armored_data( pub unsafe fn dc_split_armored_data(
buf: *mut libc::c_char, buf: *mut libc::c_char,

View File

@@ -7,7 +7,6 @@ use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::events::Event; use crate::events::Event;
use libc::free;
/// Stock strings /// Stock strings
/// ///
@@ -133,7 +132,7 @@ impl Context {
Cow::Borrowed(id.fallback()) Cow::Borrowed(id.fallback())
} else { } else {
let ret = to_string(ptr); 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) Cow::Owned(ret)
} }
} }

View File

@@ -15,19 +15,21 @@ if __name__ == "__main__":
unsafe = s.count("unsafe") unsafe = s.count("unsafe")
free = s.count("free(") free = s.count("free(")
gotoblocks = s.count("ok_to_continue") + s.count('OK_TO_CONTINUE') 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:]))): for fn, unsafe, free, gotoblocks, chars 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)) 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_unsafe += unsafe
sum_free += free sum_free += free
sum_gotoblocks += gotoblocks sum_gotoblocks += gotoblocks
sum_chars += chars
print() print()
print("total unsafe:", sum_unsafe) print("total unsafe:", sum_unsafe)
print("total free:", sum_free) print("total free:", sum_free)
print("total ok_to_continue:", sum_gotoblocks) print("total ok_to_continue:", sum_gotoblocks)
print("total c_chars:", sum_chars)

View File

@@ -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 _);
}
}
}

View File

@@ -1,11 +1,8 @@
//! Stress some functions for testing; if used as a lib, this file is obsolete. //! Stress some functions for testing; if used as a lib, this file is obsolete.
use std::collections::HashSet; use std::collections::HashSet;
use std::path::PathBuf;
use std::ptr; use std::ptr;
use tempfile::{tempdir, TempDir};
use deltachat::chat::{self, Chat}; use deltachat::chat::{self, Chat};
use deltachat::config; use deltachat::config;
use deltachat::contact::*; use deltachat::contact::*;
@@ -15,9 +12,9 @@ use deltachat::dc_tools::*;
use deltachat::keyring::*; use deltachat::keyring::*;
use deltachat::oauth2::*; use deltachat::oauth2::*;
use deltachat::pgp::*; use deltachat::pgp::*;
use deltachat::x::*;
use deltachat::Event; use deltachat::Event;
use libc; use libc::{free, strcmp, strdup, strlen, strncmp};
use tempfile::{tempdir, TempDir};
/* some data used for testing /* 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; as *const u8 as *const libc::c_char;
unsafe fn stress_functions(context: &Context) { 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(); let res = context.get_config(config::Config::SysConfigKeys).unwrap();
assert!(!res.contains(" probably_never_a_key ")); assert!(!res.contains(" probably_never_a_key "));