mirror of
https://github.com/chatmail/core.git
synced 2026-04-02 05:22:14 +03:00
Compare commits
9 Commits
v1.133.2
...
cleanup/mi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
829a7b5c72 | ||
|
|
1e80cfc72f | ||
|
|
695ba44a6c | ||
|
|
aa5cab9ae7 | ||
|
|
cea931dcc7 | ||
|
|
cace6fee85 | ||
|
|
d3dfe02ef1 | ||
|
|
a134ace787 | ||
|
|
1812b55b20 |
@@ -118,17 +118,14 @@ fn dc_poke_eml_file(context: &Context, filename: impl AsRef<Path>) -> Result<(),
|
||||
/// @param context The context as created by dc_context_new().
|
||||
/// @param spec The file or directory to import. NULL for the last command.
|
||||
/// @return 1=success, 0=error.
|
||||
unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int {
|
||||
fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int {
|
||||
if !context.sql.is_open() {
|
||||
error!(context, "Import: Database not opened.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
let ok_to_continue;
|
||||
let mut success: libc::c_int = 0;
|
||||
let real_spec: String;
|
||||
let mut suffix: *mut libc::c_char = ptr::null_mut();
|
||||
let mut read_cnt: libc::c_int = 0;
|
||||
let mut read_cnt = 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() {
|
||||
@@ -137,71 +134,57 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
|
||||
.sql
|
||||
.set_config(context, "import_spec", Some(&real_spec))
|
||||
.unwrap();
|
||||
ok_to_continue = true;
|
||||
} else {
|
||||
let rs = context.sql.get_config(context, "import_spec");
|
||||
if rs.is_none() {
|
||||
error!(context, "Import: No file or folder given.");
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
return 0;
|
||||
}
|
||||
real_spec = rs.unwrap_or_default();
|
||||
real_spec = rs.unwrap();
|
||||
}
|
||||
if ok_to_continue {
|
||||
let ok_to_continue2;
|
||||
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 let Some(suffix) = dc_get_filesuffix_lc(&real_spec) {
|
||||
if suffix == "eml" {
|
||||
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(&real_spec);
|
||||
let dir = std::fs::read_dir(dir_name);
|
||||
if dir.is_err() {
|
||||
error!(context, "Import: Cannot open directory \"{}\".", &real_spec,);
|
||||
return 0;
|
||||
} else {
|
||||
/* import a directory */
|
||||
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 \"{}\".", &real_spec,);
|
||||
ok_to_continue2 = false;
|
||||
} else {
|
||||
let dir = dir.unwrap();
|
||||
for entry in dir {
|
||||
if entry.is_err() {
|
||||
break;
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
let name_f = entry.file_name();
|
||||
let name = name_f.to_string_lossy();
|
||||
if name.ends_with(".eml") {
|
||||
let path_plus_name = format!("{}/{}", &real_spec, name);
|
||||
info!(context, "Import: {}", path_plus_name);
|
||||
if dc_poke_eml_file(context, path_plus_name).is_ok() {
|
||||
read_cnt += 1
|
||||
}
|
||||
let dir = dir.unwrap();
|
||||
for entry in dir {
|
||||
if entry.is_err() {
|
||||
break;
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
let name_f = entry.file_name();
|
||||
let name = name_f.to_string_lossy();
|
||||
if name.ends_with(".eml") {
|
||||
let path_plus_name = format!("{}/{}", &real_spec, name);
|
||||
info!(context, "Import: {}", path_plus_name);
|
||||
if dc_poke_eml_file(context, path_plus_name).is_ok() {
|
||||
read_cnt += 1
|
||||
}
|
||||
}
|
||||
ok_to_continue2 = true;
|
||||
}
|
||||
}
|
||||
if ok_to_continue2 {
|
||||
info!(
|
||||
context,
|
||||
"Import: {} items read from \"{}\".", read_cnt, &real_spec
|
||||
);
|
||||
if read_cnt > 0 {
|
||||
context.call_cb(Event::MsgsChanged {
|
||||
chat_id: 0,
|
||||
msg_id: 0,
|
||||
});
|
||||
}
|
||||
success = 1
|
||||
}
|
||||
}
|
||||
|
||||
free(suffix as *mut libc::c_void);
|
||||
success
|
||||
info!(
|
||||
context,
|
||||
"Import: {} items read from \"{}\".", read_cnt, &real_spec
|
||||
);
|
||||
if read_cnt > 0 {
|
||||
context.call_cb(Event::MsgsChanged {
|
||||
chat_id: 0,
|
||||
msg_id: 0,
|
||||
});
|
||||
}
|
||||
1
|
||||
}
|
||||
|
||||
unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: &Message) {
|
||||
|
||||
@@ -784,7 +784,7 @@ pub fn send_msg(context: &Context, chat_id: u32, msg: &mut Message) -> Result<u3
|
||||
}
|
||||
|
||||
ensure!(
|
||||
unsafe { job_send_msg(context, msg.id) } != 0,
|
||||
job_send_msg(context, msg.id) != 0,
|
||||
"Failed to initiate send job"
|
||||
);
|
||||
|
||||
@@ -1787,7 +1787,7 @@ pub fn forward_msgs(context: &Context, msg_ids: &[u32], chat_id: u32) {
|
||||
new_msg_id = chat
|
||||
.prepare_msg_raw(context, &mut msg, fresh10)
|
||||
.unwrap_or_default();
|
||||
unsafe { job_send_msg(context, new_msg_id) };
|
||||
job_send_msg(context, new_msg_id);
|
||||
}
|
||||
created_db_entries.push(chat_id);
|
||||
created_db_entries.push(new_msg_id);
|
||||
|
||||
@@ -60,6 +60,10 @@ const DC_GCM_ADDDAYMARKER: usize = 0x01;
|
||||
pub const DC_GCL_VERIFIED_ONLY: usize = 0x01;
|
||||
pub const DC_GCL_ADD_SELF: usize = 0x02;
|
||||
|
||||
// values for DC_PARAM_FORCE_PLAINTEXT
|
||||
pub(crate) const DC_FP_NO_AUTOCRYPT_HEADER: i32 = 2;
|
||||
pub(crate) const DC_FP_ADD_AUTOCRYPT_HEADER: i32 = 1;
|
||||
|
||||
/// param1 is a directory where the keys are written to
|
||||
const DC_IMEX_EXPORT_SELF_KEYS: usize = 1;
|
||||
/// param1 is a directory where the keys are searched in and read from
|
||||
|
||||
@@ -135,7 +135,8 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
msg.param
|
||||
.set(Param::MimeType, "application/autocrypt-setup");
|
||||
msg.param.set_int(Param::Cmd, 6);
|
||||
msg.param.set_int(Param::ForcePlaintext, 2);
|
||||
msg.param
|
||||
.set_int(Param::ForcePlaintext, DC_FP_NO_AUTOCRYPT_HEADER);
|
||||
|
||||
if !context
|
||||
.running_state
|
||||
@@ -843,7 +844,6 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
Maybe we should make the "default" key handlong also a little bit smarter
|
||||
(currently, the last imported key is the standard key unless it contains the string "legacy" in its name) */
|
||||
let mut imported_cnt: libc::c_int = 0;
|
||||
let mut suffix: *mut libc::c_char = ptr::null_mut();
|
||||
let mut set_default: libc::c_int;
|
||||
let mut buf: *mut libc::c_char = ptr::null_mut();
|
||||
// a pointer inside buf, MUST NOT be free()'d
|
||||
@@ -858,17 +858,20 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
if entry.is_err() {
|
||||
break;
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
free(suffix as *mut libc::c_void);
|
||||
let name_f = entry.file_name();
|
||||
let name_c = name_f.to_c_string().unwrap();
|
||||
suffix = dc_get_filesuffix_lc(name_f.to_string_lossy());
|
||||
if suffix.is_null()
|
||||
|| strcmp(suffix, b"asc\x00" as *const u8 as *const libc::c_char) != 0
|
||||
{
|
||||
continue;
|
||||
let entry_fn = entry.unwrap().file_name();
|
||||
let name_f = entry_fn.to_string_lossy();
|
||||
|
||||
match dc_get_filesuffix_lc(&name_f) {
|
||||
Some(suffix) => {
|
||||
if suffix != ".asc" {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let path_plus_name = dir.join(entry.file_name());
|
||||
let path_plus_name = dir.join(&entry_fn);
|
||||
info!(context, "Checking: {}", path_plus_name.display());
|
||||
|
||||
free(buf.cast());
|
||||
@@ -906,12 +909,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
}
|
||||
}
|
||||
set_default = 1;
|
||||
if !strstr(
|
||||
name_c.as_ptr(),
|
||||
b"legacy\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
.is_null()
|
||||
{
|
||||
if name_f.contains("legacy") {
|
||||
info!(
|
||||
context,
|
||||
"Treating \"{}\" as a legacy private key.",
|
||||
@@ -940,7 +938,6 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
}
|
||||
}
|
||||
|
||||
free(suffix as *mut libc::c_void);
|
||||
free(buf as *mut libc::c_void);
|
||||
free(buf2 as *mut libc::c_void);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@ use crate::dc_tools::*;
|
||||
* @return Returns the encoded string which must be free()'d when no longed needed.
|
||||
* On errors, NULL is returned.
|
||||
*/
|
||||
pub unsafe fn dc_encode_header_words(to_encode_r: impl AsRef<str>) -> *mut libc::c_char {
|
||||
pub unsafe fn dc_encode_header_words(to_encode_r: impl AsRef<str>) -> String {
|
||||
let to_encode =
|
||||
CString::new(to_encode_r.as_ref().as_bytes()).expect("invalid cstring to_encode");
|
||||
|
||||
@@ -117,7 +117,9 @@ pub unsafe fn dc_encode_header_words(to_encode_r: impl AsRef<str>) -> *mut libc:
|
||||
}
|
||||
}
|
||||
|
||||
ret_str
|
||||
let s = to_string(ret_str);
|
||||
free(ret_str.cast());
|
||||
s
|
||||
}
|
||||
|
||||
unsafe fn quote_word(
|
||||
@@ -337,7 +339,7 @@ unsafe fn print_hex(target: *mut libc::c_char, cur: *const libc::c_char) {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use libc::{strcmp, strncmp};
|
||||
use libc::strcmp;
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[test]
|
||||
@@ -360,19 +362,15 @@ mod tests {
|
||||
assert_eq!(CStr::from_ptr(buf1).to_str().unwrap(), "just ascii test");
|
||||
free(buf1 as *mut libc::c_void);
|
||||
|
||||
buf1 = dc_encode_header_words("abcdef");
|
||||
assert_eq!(CStr::from_ptr(buf1).to_str().unwrap(), "abcdef");
|
||||
free(buf1 as *mut libc::c_void);
|
||||
assert_eq!(dc_encode_header_words("abcdef"), "abcdef");
|
||||
|
||||
buf1 = dc_encode_header_words(
|
||||
let r = dc_encode_header_words(
|
||||
std::string::String::from_utf8(b"test\xc3\xa4\xc3\xb6\xc3\xbc.txt".to_vec())
|
||||
.unwrap(),
|
||||
);
|
||||
assert_eq!(
|
||||
strncmp(buf1, b"=?utf-8\x00" as *const u8 as *const libc::c_char, 7),
|
||||
0
|
||||
);
|
||||
assert!(r.starts_with("=?utf-8"));
|
||||
|
||||
buf1 = r.strdup();
|
||||
let buf2: *mut libc::c_char = dc_decode_header_words(buf1);
|
||||
assert_eq!(
|
||||
strcmp(
|
||||
@@ -381,7 +379,6 @@ mod tests {
|
||||
),
|
||||
0
|
||||
);
|
||||
free(buf1 as *mut libc::c_void);
|
||||
free(buf2 as *mut libc::c_void);
|
||||
|
||||
buf1 = dc_decode_header_words(
|
||||
@@ -395,7 +392,6 @@ mod tests {
|
||||
),
|
||||
0
|
||||
);
|
||||
free(buf1 as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
195
src/dc_tools.rs
195
src/dc_tools.rs
@@ -9,7 +9,7 @@ use std::time::SystemTime;
|
||||
use std::{fmt, fs, ptr};
|
||||
|
||||
use chrono::{Local, TimeZone};
|
||||
use libc::{free, memcpy, strcpy, strlen, strstr, uintptr_t};
|
||||
use libc::{memcpy, strcpy, strlen, uintptr_t};
|
||||
use mmime::clist::*;
|
||||
use mmime::mailimf_types::*;
|
||||
use rand::{thread_rng, Rng};
|
||||
@@ -49,15 +49,6 @@ pub unsafe fn dc_strdup(s: *const libc::c_char) -> *mut libc::c_char {
|
||||
ret
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
if !s.is_null() {
|
||||
dc_strdup(s)
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
@@ -250,32 +241,14 @@ pub(crate) unsafe fn dc_str_from_clist(
|
||||
res.strdup()
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn dc_str_to_clist(
|
||||
str: *const libc::c_char,
|
||||
delimiter: *const libc::c_char,
|
||||
) -> *mut clist {
|
||||
let list: *mut clist = clist_new();
|
||||
assert!(!list.is_null());
|
||||
|
||||
if !str.is_null() && !delimiter.is_null() && strlen(delimiter) >= 1 {
|
||||
let mut p1: *const libc::c_char = str;
|
||||
loop {
|
||||
let p2: *const libc::c_char = strstr(p1, delimiter);
|
||||
if p2.is_null() {
|
||||
clist_insert_after(list, (*list).last, strdup(p1) as *mut libc::c_void);
|
||||
break;
|
||||
} else {
|
||||
clist_insert_after(
|
||||
list,
|
||||
(*list).last,
|
||||
strndup(p1, p2.wrapping_offset_from(p1) as libc::c_ulong) as *mut libc::c_void,
|
||||
);
|
||||
p1 = p2.add(strlen(delimiter))
|
||||
}
|
||||
pub(crate) fn dc_str_to_clist(str: &str, delimiter: &str) -> *mut clist {
|
||||
unsafe {
|
||||
let list: *mut clist = clist_new();
|
||||
for cur in str.split(&delimiter) {
|
||||
clist_insert_after(list, (*list).last, cur.strdup().cast());
|
||||
}
|
||||
list
|
||||
}
|
||||
|
||||
list
|
||||
}
|
||||
|
||||
/* the colors must fulfill some criterions as:
|
||||
@@ -302,32 +275,6 @@ pub(crate) fn dc_str_to_color(s: impl AsRef<str>) -> u32 {
|
||||
COLORS[color_index]
|
||||
}
|
||||
|
||||
/* clist tools */
|
||||
|
||||
/* calls free() for each item content */
|
||||
pub(crate) unsafe fn clist_free_content(haystack: *const clist) {
|
||||
let mut iter = (*haystack).first;
|
||||
|
||||
while !iter.is_null() {
|
||||
free((*iter).data);
|
||||
(*iter).data = ptr::null_mut();
|
||||
iter = if !iter.is_null() {
|
||||
(*iter).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn clist_search_string_nocase(
|
||||
haystack: *const clist,
|
||||
needle: *const libc::c_char,
|
||||
) -> bool {
|
||||
(&*haystack)
|
||||
.into_iter()
|
||||
.any(|data| strcasecmp(data.cast(), needle) == 0)
|
||||
}
|
||||
|
||||
/* date/time tools */
|
||||
/* the result is UTC or DC_INVALID_TIMESTAMP */
|
||||
pub(crate) unsafe fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 {
|
||||
@@ -505,25 +452,15 @@ pub(crate) fn dc_extract_grpid_from_rfc724_mid(mid: &str) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn dc_extract_grpid_from_rfc724_mid_list(
|
||||
list: *const clist,
|
||||
) -> *mut libc::c_char {
|
||||
pub(crate) 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() {
|
||||
let mid = if !cur.is_null() {
|
||||
as_str((*cur).data as *const libc::c_char)
|
||||
} else {
|
||||
""
|
||||
};
|
||||
unsafe {
|
||||
for cur in (*list).into_iter() {
|
||||
let mid = as_str(cur as *const libc::c_char);
|
||||
|
||||
if let Some(grpid) = dc_extract_grpid_from_rfc724_mid(mid) {
|
||||
return grpid.strdup();
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
if let Some(grpid) = dc_extract_grpid_from_rfc724_mid(mid) {
|
||||
return grpid.strdup();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -548,11 +485,11 @@ fn validate_filename(filename: &str) -> String {
|
||||
|
||||
// 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 {
|
||||
pub fn dc_get_filesuffix_lc(path_filename: impl AsRef<str>) -> Option<String> {
|
||||
if let Some(p) = Path::new(path_filename.as_ref()).extension() {
|
||||
p.to_string_lossy().to_lowercase().strdup()
|
||||
Some(p.to_string_lossy().to_lowercase())
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1091,21 +1028,6 @@ pub(crate) unsafe fn strdup(s: *const libc::c_char) -> *mut libc::c_char {
|
||||
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()
|
||||
@@ -1124,7 +1046,7 @@ pub(crate) unsafe fn strcasecmp(s1: *const libc::c_char, s2: *const libc::c_char
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use libc::strcmp;
|
||||
use libc::{free, strcmp};
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::CStr;
|
||||
|
||||
@@ -1156,24 +1078,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_strdup_keep_null() {
|
||||
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!(
|
||||
CStr::from_ptr(str_a_copy),
|
||||
CString::new("foobar").unwrap().as_c_str()
|
||||
);
|
||||
assert_ne!(str_a, str_a_copy);
|
||||
|
||||
let str_a = ptr::null();
|
||||
let str_a_copy = dc_strdup_keep_null(str_a);
|
||||
assert_eq!(str_a.is_null(), true);
|
||||
assert_eq!(str_a_copy.is_null(), true);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_ltrim() {
|
||||
unsafe {
|
||||
@@ -1282,49 +1186,50 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/* calls free() for each item content */
|
||||
unsafe fn clist_free_content(haystack: *const clist) {
|
||||
let mut iter = (*haystack).first;
|
||||
|
||||
while !iter.is_null() {
|
||||
free((*iter).data);
|
||||
(*iter).data = ptr::null_mut();
|
||||
iter = if !iter.is_null() {
|
||||
(*iter).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 _
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_str_to_clist_1() {
|
||||
unsafe {
|
||||
let list = dc_str_to_clist(ptr::null(), b" \x00" as *const u8 as *const libc::c_char);
|
||||
assert_eq!((*list).count, 0);
|
||||
clist_free_content(list);
|
||||
clist_free(list);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_str_to_clist_2() {
|
||||
unsafe {
|
||||
let list: *mut clist = dc_str_to_clist(
|
||||
b"\x00" as *const u8 as *const libc::c_char,
|
||||
b" \x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
let list = dc_str_to_clist("", " ");
|
||||
assert_eq!((*list).count, 1);
|
||||
clist_free_content(list);
|
||||
clist_free(list);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_str_to_clist_3() {
|
||||
unsafe {
|
||||
let list: *mut clist = dc_str_to_clist(
|
||||
b" \x00" as *const u8 as *const libc::c_char,
|
||||
b" \x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
assert_eq!((*list).count, 2);
|
||||
clist_free_content(list);
|
||||
clist_free(list);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_str_to_clist_4() {
|
||||
unsafe {
|
||||
let list: *mut clist = dc_str_to_clist(
|
||||
b"foo bar test\x00" as *const u8 as *const libc::c_char,
|
||||
b" \x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
let list: *mut clist = dc_str_to_clist("foo bar test", " ");
|
||||
assert_eq!((*list).count, 3);
|
||||
let str: *mut libc::c_char =
|
||||
dc_str_from_clist(list, b" \x00" as *const u8 as *const libc::c_char);
|
||||
|
||||
177
src/e2ee.rs
177
src/e2ee.rs
@@ -53,11 +53,11 @@ impl E2eeHelper {
|
||||
pub unsafe fn encrypt(
|
||||
&mut self,
|
||||
context: &Context,
|
||||
recipients_addr: *const clist,
|
||||
force_unencrypted: libc::c_int,
|
||||
e2ee_guaranteed: libc::c_int,
|
||||
recipients_addr: &Vec<String>,
|
||||
force_unencrypted: bool,
|
||||
e2ee_guaranteed: bool,
|
||||
min_verified: libc::c_int,
|
||||
do_gossip: libc::c_int,
|
||||
do_gossip: bool,
|
||||
mut in_out_message: *mut mailmime,
|
||||
) {
|
||||
let mut ok_to_continue = true;
|
||||
@@ -69,10 +69,7 @@ impl E2eeHelper {
|
||||
let plain: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
||||
let mut peerstates: Vec<Peerstate> = Vec::new();
|
||||
|
||||
if !(recipients_addr.is_null()
|
||||
|| in_out_message.is_null()
|
||||
|| !(*in_out_message).mm_parent.is_null()
|
||||
|| plain.is_null())
|
||||
if !(in_out_message.is_null() || !(*in_out_message).mm_parent.is_null() || plain.is_null())
|
||||
{
|
||||
/* libEtPan's pgp_encrypt_mime() takes the parent as the new root. We just expect the root as being given to this function. */
|
||||
let prefer_encrypt = if 0
|
||||
@@ -95,19 +92,16 @@ impl E2eeHelper {
|
||||
});
|
||||
if let Ok(public_key) = pubkey_ret {
|
||||
/*only for random-seed*/
|
||||
if prefer_encrypt == EncryptPreference::Mutual || 0 != e2ee_guaranteed {
|
||||
if prefer_encrypt == EncryptPreference::Mutual || e2ee_guaranteed {
|
||||
do_encrypt = 1i32;
|
||||
let mut iter1: *mut clistiter;
|
||||
iter1 = (*recipients_addr).first;
|
||||
while !iter1.is_null() {
|
||||
let recipient_addr = to_string((*iter1).data as *const libc::c_char);
|
||||
if recipient_addr != addr {
|
||||
for recipient_addr in recipients_addr.iter() {
|
||||
if *recipient_addr != addr {
|
||||
let peerstate =
|
||||
Peerstate::from_addr(context, &context.sql, &recipient_addr);
|
||||
if peerstate.is_some()
|
||||
&& (peerstate.as_ref().unwrap().prefer_encrypt
|
||||
== EncryptPreference::Mutual
|
||||
|| 0 != e2ee_guaranteed)
|
||||
|| e2ee_guaranteed)
|
||||
{
|
||||
let peerstate = peerstate.unwrap();
|
||||
info!(
|
||||
@@ -130,11 +124,6 @@ impl E2eeHelper {
|
||||
break;
|
||||
}
|
||||
}
|
||||
iter1 = if !iter1.is_null() {
|
||||
(*iter1).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
let sign_key = if 0 != do_encrypt {
|
||||
@@ -148,7 +137,7 @@ impl E2eeHelper {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if 0 != force_unencrypted {
|
||||
if force_unencrypted {
|
||||
do_encrypt = 0i32
|
||||
}
|
||||
imffields_unprotected = mailmime_find_mailimf_fields(in_out_message);
|
||||
@@ -175,7 +164,7 @@ impl E2eeHelper {
|
||||
imffields_encrypted,
|
||||
part_to_encrypt,
|
||||
);
|
||||
if 0 != do_gossip {
|
||||
if do_gossip {
|
||||
let i_cnt = peerstates.len() as libc::c_int;
|
||||
if i_cnt > 1 {
|
||||
let mut i = 0;
|
||||
@@ -197,63 +186,39 @@ impl E2eeHelper {
|
||||
}
|
||||
}
|
||||
/* memoryhole headers */
|
||||
// XXX we can't use clist's into_iter()
|
||||
// because the loop body also removes items
|
||||
let mut cur: *mut clistiter =
|
||||
(*(*imffields_unprotected).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut move_to_encrypted: libc::c_int = 0i32;
|
||||
let field: *mut mailimf_field = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
})
|
||||
as *mut mailimf_field;
|
||||
let field: *mut mailimf_field = (*cur).data as *mut mailimf_field;
|
||||
let mut move_to_encrypted = false;
|
||||
if !field.is_null() {
|
||||
if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int {
|
||||
move_to_encrypted = 1i32
|
||||
move_to_encrypted = true;
|
||||
} else if (*field).fld_type
|
||||
== MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int
|
||||
{
|
||||
let opt_field: *mut mailimf_optional_field =
|
||||
(*field).fld_data.fld_optional_field;
|
||||
let opt_field = (*field).fld_data.fld_optional_field;
|
||||
if !opt_field.is_null() && !(*opt_field).fld_name.is_null()
|
||||
{
|
||||
if strncmp(
|
||||
(*opt_field).fld_name,
|
||||
b"Secure-Join\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
11,
|
||||
) == 0
|
||||
|| strncmp(
|
||||
(*opt_field).fld_name,
|
||||
b"Chat-\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
5,
|
||||
) == 0
|
||||
&& strcmp(
|
||||
(*opt_field).fld_name,
|
||||
b"Chat-Version\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
) != 0
|
||||
let fld_name = to_string_lossy((*opt_field).fld_name);
|
||||
if fld_name.starts_with("Secure-Join")
|
||||
|| fld_name.starts_with("Chat-")
|
||||
{
|
||||
move_to_encrypted = 1
|
||||
move_to_encrypted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if 0 != move_to_encrypted {
|
||||
if move_to_encrypted {
|
||||
mailimf_fields_add(imffields_encrypted, field);
|
||||
cur = clist_delete((*imffields_unprotected).fld_list, cur)
|
||||
cur = clist_delete((*imffields_unprotected).fld_list, cur);
|
||||
} else {
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
cur = (*cur).next;
|
||||
}
|
||||
}
|
||||
let subject: *mut mailimf_subject = mailimf_subject_new(dc_strdup(
|
||||
b"...\x00" as *const u8 as *const libc::c_char,
|
||||
));
|
||||
let subject: *mut mailimf_subject = mailimf_subject_new("...".strdup());
|
||||
mailimf_fields_add(
|
||||
imffields_unprotected,
|
||||
mailimf_field_new(
|
||||
@@ -645,19 +610,13 @@ unsafe fn update_gossip_peerstates(
|
||||
imffields: *mut mailimf_fields,
|
||||
gossip_headers: *const mailimf_fields,
|
||||
) -> HashSet<String> {
|
||||
let mut cur1: *mut clistiter;
|
||||
let mut recipients: Option<HashSet<String>> = None;
|
||||
let mut gossipped_addr: HashSet<String> = Default::default();
|
||||
cur1 = (*(*gossip_headers).fld_list).first;
|
||||
while !cur1.is_null() {
|
||||
let field: *mut mailimf_field = (if !cur1.is_null() {
|
||||
(*cur1).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut mailimf_field;
|
||||
|
||||
for cur_data in (*(*gossip_headers).fld_list).into_iter() {
|
||||
let field: *mut mailimf_field = cur_data as *mut _;
|
||||
if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
|
||||
let optional_field: *const mailimf_optional_field =
|
||||
(*field).fld_data.fld_optional_field;
|
||||
let optional_field = (*field).fld_data.fld_optional_field;
|
||||
if !optional_field.is_null()
|
||||
&& !(*optional_field).fld_name.is_null()
|
||||
&& strcasecmp(
|
||||
@@ -701,11 +660,6 @@ unsafe fn update_gossip_peerstates(
|
||||
}
|
||||
}
|
||||
}
|
||||
cur1 = if !cur1.is_null() {
|
||||
(*cur1).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
gossipped_addr
|
||||
@@ -722,7 +676,6 @@ unsafe fn decrypt_recursive(
|
||||
) -> Result<()> {
|
||||
ensure!(!mime.is_null(), "Invalid mime reference");
|
||||
let ct: *mut mailmime_content;
|
||||
let mut cur: *mut clistiter;
|
||||
|
||||
if (*mime).mm_type == MAILMIME_MULTIPLE as libc::c_int {
|
||||
ct = (*mime).mm_content_type;
|
||||
@@ -733,23 +686,18 @@ unsafe fn decrypt_recursive(
|
||||
b"encrypted\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0i32
|
||||
{
|
||||
cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
|
||||
while !cur.is_null() {
|
||||
for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() {
|
||||
let mut decrypted_mime: *mut mailmime = ptr::null_mut();
|
||||
if decrypt_part(
|
||||
context,
|
||||
(if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut mailmime,
|
||||
cur_data as *mut mailmime,
|
||||
private_keyring,
|
||||
public_keyring_for_validate,
|
||||
ret_valid_signatures,
|
||||
&mut decrypted_mime,
|
||||
) {
|
||||
if (*ret_gossip_headers).is_null() && ret_valid_signatures.len() > 0 {
|
||||
let mut dummy: libc::size_t = 0i32 as libc::size_t;
|
||||
let mut dummy: libc::size_t = 0;
|
||||
let mut test: *mut mailimf_fields = ptr::null_mut();
|
||||
if mailimf_envelope_and_optional_fields_parse(
|
||||
(*decrypted_mime).mm_mime_start,
|
||||
@@ -766,23 +714,13 @@ unsafe fn decrypt_recursive(
|
||||
mailmime_free(mime);
|
||||
return Ok(());
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
*ret_has_unencrypted_parts = 1i32
|
||||
} else {
|
||||
cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
|
||||
while !cur.is_null() {
|
||||
for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() {
|
||||
if decrypt_recursive(
|
||||
context,
|
||||
(if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut mailmime,
|
||||
cur_data as *mut mailmime,
|
||||
private_keyring,
|
||||
public_keyring_for_validate,
|
||||
ret_valid_signatures,
|
||||
@@ -793,11 +731,6 @@ unsafe fn decrypt_recursive(
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (*mime).mm_type == MAILMIME_MESSAGE as libc::c_int {
|
||||
@@ -847,25 +780,12 @@ unsafe fn decrypt_part(
|
||||
|| (*mime_data).dt_data.dt_text.dt_length <= 0)
|
||||
{
|
||||
if !(*mime).mm_mime_fields.is_null() {
|
||||
let mut cur: *mut clistiter;
|
||||
cur = (*(*(*mime).mm_mime_fields).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let field: *mut mailmime_field = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut mailmime_field;
|
||||
if !field.is_null() {
|
||||
if (*field).fld_type == MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int
|
||||
&& !(*field).fld_data.fld_encoding.is_null()
|
||||
{
|
||||
mime_transfer_encoding = (*(*field).fld_data.fld_encoding).enc_type
|
||||
}
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
for cur_data in (*(*(*mime).mm_mime_fields).fld_list).into_iter() {
|
||||
let field: *mut mailmime_field = cur_data as *mut _;
|
||||
if (*field).fld_type == MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int
|
||||
&& !(*field).fld_data.fld_encoding.is_null()
|
||||
{
|
||||
mime_transfer_encoding = (*(*field).fld_data.fld_encoding).enc_type
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -992,23 +912,10 @@ unsafe fn contains_report(mime: *mut mailmime) -> bool {
|
||||
{
|
||||
return true;
|
||||
}
|
||||
let mut cur: *mut clistiter;
|
||||
cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
|
||||
while !cur.is_null() {
|
||||
if contains_report(
|
||||
(if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut mailmime,
|
||||
) {
|
||||
for cur_data in (*(*(*mime).mm_mime_fields).fld_list).into_iter() {
|
||||
if contains_report(cur_data as *mut mailmime) {
|
||||
return true;
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
} else if (*mime).mm_type == MAILMIME_MESSAGE as libc::c_int {
|
||||
if contains_report((*mime).mm_data.mm_message.mm_msg_mime) {
|
||||
|
||||
46
src/job.rs
46
src/job.rs
@@ -1,8 +1,6 @@
|
||||
use std::ptr;
|
||||
use std::time::Duration;
|
||||
|
||||
use deltachat_derive::{FromSql, ToSql};
|
||||
use mmime::clist::*;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::chat;
|
||||
@@ -642,12 +640,12 @@ pub fn job_action_exists(context: &Context, action: Action) -> bool {
|
||||
|
||||
/* special case for DC_JOB_SEND_MSG_TO_SMTP */
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe fn job_send_msg(context: &Context, msg_id: u32) -> libc::c_int {
|
||||
pub fn job_send_msg(context: &Context, msg_id: u32) -> libc::c_int {
|
||||
let mut success = 0;
|
||||
|
||||
/* load message data */
|
||||
let mimefactory = dc_mimefactory_load_msg(context, msg_id);
|
||||
if mimefactory.is_err() || mimefactory.as_ref().unwrap().from_addr.is_null() {
|
||||
if mimefactory.is_err() {
|
||||
warn!(
|
||||
context,
|
||||
"Cannot load data to send, maybe the message is deleted in between.",
|
||||
@@ -680,8 +678,9 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: u32) -> libc::c_int {
|
||||
}
|
||||
}
|
||||
/* create message */
|
||||
if !dc_mimefactory_render(context, &mut mimefactory) {
|
||||
message::set_msg_failed(context, msg_id, as_opt_str(mimefactory.error));
|
||||
if let Err(msg) = unsafe { dc_mimefactory_render(context, &mut mimefactory) } {
|
||||
let e = msg.to_string();
|
||||
message::set_msg_failed(context, msg_id, Some(e));
|
||||
} else if 0
|
||||
!= mimefactory
|
||||
.msg
|
||||
@@ -690,6 +689,7 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: u32) -> libc::c_int {
|
||||
.unwrap_or_default()
|
||||
&& !mimefactory.out_encrypted
|
||||
{
|
||||
/* unrecoverable */
|
||||
warn!(
|
||||
context,
|
||||
"e2e encryption unavailable {} - {:?}",
|
||||
@@ -702,18 +702,11 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: u32) -> libc::c_int {
|
||||
Some("End-to-end-encryption unavailable unexpectedly."),
|
||||
);
|
||||
} else {
|
||||
/* unrecoverable */
|
||||
if !clist_search_string_nocase(mimefactory.recipients_addr, mimefactory.from_addr) {
|
||||
clist_insert_after(
|
||||
mimefactory.recipients_names,
|
||||
(*mimefactory.recipients_names).last,
|
||||
ptr::null_mut(),
|
||||
);
|
||||
clist_insert_after(
|
||||
mimefactory.recipients_addr,
|
||||
(*mimefactory.recipients_addr).last,
|
||||
dc_strdup(mimefactory.from_addr) as *mut libc::c_void,
|
||||
);
|
||||
if !vec_contains_lowercase(&mimefactory.recipients_addr, &mimefactory.from_addr) {
|
||||
mimefactory.recipients_names.push("".to_string());
|
||||
mimefactory
|
||||
.recipients_addr
|
||||
.push(mimefactory.from_addr.to_string());
|
||||
}
|
||||
if mimefactory.out_gossiped {
|
||||
chat::set_gossiped_timestamp(context, mimefactory.msg.chat_id, time());
|
||||
@@ -997,8 +990,8 @@ fn connect_to_inbox(context: &Context, inbox: &Imap) -> libc::c_int {
|
||||
}
|
||||
|
||||
fn send_mdn(context: &Context, msg_id: u32) {
|
||||
if let Ok(mut mimefactory) = unsafe { dc_mimefactory_load_mdn(context, msg_id) } {
|
||||
if unsafe { dc_mimefactory_render(context, &mut mimefactory) } {
|
||||
if let Ok(mut mimefactory) = dc_mimefactory_load_mdn(context, msg_id) {
|
||||
if unsafe { dc_mimefactory_render(context, &mut mimefactory) }.is_ok() {
|
||||
add_smtp_job(context, Action::SendMdn, &mut mimefactory);
|
||||
}
|
||||
}
|
||||
@@ -1007,7 +1000,6 @@ fn send_mdn(context: &Context, msg_id: u32) {
|
||||
#[allow(non_snake_case)]
|
||||
fn add_smtp_job(context: &Context, action: Action, mimefactory: &MimeFactory) -> libc::c_int {
|
||||
let mut success: libc::c_int = 0i32;
|
||||
let mut recipients: *mut libc::c_char = ptr::null_mut();
|
||||
let mut param = Params::new();
|
||||
let path_filename = dc_get_fine_path_filename(context, "$BLOBDIR", &mimefactory.rfc724_mid);
|
||||
let bytes = unsafe {
|
||||
@@ -1024,14 +1016,9 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &MimeFactory) ->
|
||||
path_filename.display(),
|
||||
);
|
||||
} else {
|
||||
recipients = unsafe {
|
||||
dc_str_from_clist(
|
||||
mimefactory.recipients_addr,
|
||||
b"\x1e\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
};
|
||||
let recipients = mimefactory.recipients_addr.join("\x1e");
|
||||
param.set(Param::File, path_filename.to_string_lossy());
|
||||
param.set(Param::Recipients, as_str(recipients));
|
||||
param.set(Param::Recipients, &recipients);
|
||||
job_add(
|
||||
context,
|
||||
action,
|
||||
@@ -1045,9 +1032,6 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &MimeFactory) ->
|
||||
);
|
||||
success = 1;
|
||||
}
|
||||
unsafe {
|
||||
libc::free(recipients.cast());
|
||||
}
|
||||
success
|
||||
}
|
||||
|
||||
|
||||
@@ -680,6 +680,7 @@ pub fn guess_msgtype_from_suffix(path: &Path) -> Option<(Viewtype, &str)> {
|
||||
"mp4" => (Viewtype::Video, "video/mp4"),
|
||||
"jpg" => (Viewtype::Image, "image/jpeg"),
|
||||
"jpeg" => (Viewtype::Image, "image/jpeg"),
|
||||
"jpe" => (Viewtype::Image, "image/jpeg"),
|
||||
"png" => (Viewtype::Image, "image/png"),
|
||||
"webp" => (Viewtype::Image, "image/webp"),
|
||||
"gif" => (Viewtype::Gif, "image/gif"),
|
||||
|
||||
Reference in New Issue
Block a user