mirror of
https://github.com/chatmail/core.git
synced 2026-04-20 06:56:29 +03:00
refactor: remove x module and delete deadcode
This commit is contained in:
committed by
holger krekel
parent
b85f59798c
commit
05f9f454c3
505
src/dc_tools.rs
505
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<str> {
|
||||
pub(crate) fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Cow<str> {
|
||||
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<str>
|
||||
}
|
||||
|
||||
#[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<str>) -> u32 {
|
||||
pub(crate) fn dc_str_to_color(s: impl AsRef<str>) -> 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<str>) -> 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<u32>,
|
||||
@@ -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<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
|
||||
#[allow(non_snake_case)]
|
||||
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.
|
||||
/// 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,
|
||||
path: P,
|
||||
) -> 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()
|
||||
}
|
||||
|
||||
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);
|
||||
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<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);
|
||||
if !path_abs.is_file() {
|
||||
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,
|
||||
src: 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);
|
||||
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<std::path::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);
|
||||
if let Err(_err) = fs::write(&path_abs, buf) {
|
||||
warn!(
|
||||
@@ -800,42 +667,26 @@ pub fn dc_write_file(context: &Context, path: impl AsRef<Path>, buf: &[u8]) -> b
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe fn dc_read_file(
|
||||
pub fn dc_read_file<P: AsRef<std::path::Path>>(
|
||||
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<P: AsRef<std::path::Path>>(context: &Context, path: P) -> Option<Vec<u8>> {
|
||||
path: P,
|
||||
) -> Result<Vec<u8>, 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<Path>,
|
||||
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");
|
||||
}
|
||||
|
||||
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
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user