mirror of
https://github.com/chatmail/core.git
synced 2026-05-09 01:46:30 +03:00
refactor(tools): no more dc_mprintf
This commit is contained in:
@@ -101,7 +101,6 @@ pub unsafe fn dc_imex_has_backup(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||||
let mut setup_file_name: *mut libc::c_char = ptr::null_mut();
|
|
||||||
let mut msg: Message;
|
let mut msg: Message;
|
||||||
if !dc_alloc_ongoing(context) {
|
if !dc_alloc_ongoing(context) {
|
||||||
return std::ptr::null_mut();
|
return std::ptr::null_mut();
|
||||||
@@ -115,8 +114,7 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.shall_stop_ongoing
|
.shall_stop_ongoing
|
||||||
{
|
{
|
||||||
if let Ok(setup_file_content) = dc_render_setup_file(context, &setup_code) {
|
if let Ok(ref setup_file_content) = dc_render_setup_file(context, &setup_code) {
|
||||||
let setup_file_content_c = CString::yolo(setup_file_content.as_str());
|
|
||||||
/* encrypting may also take a while ... */
|
/* encrypting may also take a while ... */
|
||||||
if !context
|
if !context
|
||||||
.running_state
|
.running_state
|
||||||
@@ -125,23 +123,14 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.shall_stop_ongoing
|
.shall_stop_ongoing
|
||||||
{
|
{
|
||||||
setup_file_name = dc_get_fine_pathNfilename(
|
let setup_file_name =
|
||||||
context,
|
dc_get_fine_path_filename(context, "$BLOBDIR", "autocrypt-setup-message.html");
|
||||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
if dc_write_file(context, &setup_file_name, setup_file_content.as_bytes()) {
|
||||||
b"autocrypt-setup-message.html\x00" as *const u8 as *const libc::c_char,
|
|
||||||
);
|
|
||||||
if !(setup_file_name.is_null()
|
|
||||||
|| 0 == dc_write_file(
|
|
||||||
context,
|
|
||||||
setup_file_name,
|
|
||||||
setup_file_content_c.as_ptr() as *const libc::c_void,
|
|
||||||
setup_file_content_c.as_bytes().len(),
|
|
||||||
))
|
|
||||||
{
|
|
||||||
if let Ok(chat_id) = chat::create_by_contact_id(context, 1) {
|
if let Ok(chat_id) = chat::create_by_contact_id(context, 1) {
|
||||||
msg = dc_msg_new_untyped();
|
msg = dc_msg_new_untyped();
|
||||||
msg.type_0 = Viewtype::File;
|
msg.type_0 = Viewtype::File;
|
||||||
msg.param.set(Param::File, as_str(setup_file_name));
|
msg.param
|
||||||
|
.set(Param::File, setup_file_name.to_string_lossy());
|
||||||
|
|
||||||
msg.param
|
msg.param
|
||||||
.set(Param::MimeType, "application/autocrypt-setup");
|
.set(Param::MimeType, "application/autocrypt-setup");
|
||||||
@@ -182,7 +171,6 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(setup_file_name as *mut libc::c_void);
|
|
||||||
dc_free_ongoing(context);
|
dc_free_ongoing(context);
|
||||||
|
|
||||||
setup_code.strdup()
|
setup_code.strdup()
|
||||||
@@ -640,7 +628,7 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
|
|||||||
}
|
}
|
||||||
|
|
||||||
let pathNfilename = context.get_blobdir().join(file_name);
|
let pathNfilename = context.get_blobdir().join(file_name);
|
||||||
if dc_write_file_safe(context, &pathNfilename, &file_blob) {
|
if dc_write_file(context, &pathNfilename, &file_blob) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
error!(
|
error!(
|
||||||
@@ -687,13 +675,8 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> bool {
|
|||||||
let res = chrono::NaiveDateTime::from_timestamp(now as i64, 0)
|
let res = chrono::NaiveDateTime::from_timestamp(now as i64, 0)
|
||||||
.format("delta-chat-%Y-%m-%d.bak")
|
.format("delta-chat-%Y-%m-%d.bak")
|
||||||
.to_string();
|
.to_string();
|
||||||
let buffer = CString::yolo(res);
|
|
||||||
let dest_pathNfilename = dc_get_fine_pathNfilename(context, dir, buffer.as_ptr());
|
|
||||||
if dest_pathNfilename.is_null() {
|
|
||||||
error!(context, "Cannot get backup file name.",);
|
|
||||||
|
|
||||||
return success;
|
let dest_path_filename = dc_get_fine_path_filename(context, as_path(dir), res);
|
||||||
}
|
|
||||||
|
|
||||||
sql::housekeeping(context);
|
sql::housekeeping(context);
|
||||||
|
|
||||||
@@ -704,15 +687,15 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> bool {
|
|||||||
context,
|
context,
|
||||||
"Backup \"{}\" to \"{}\".",
|
"Backup \"{}\" to \"{}\".",
|
||||||
context.get_dbfile().display(),
|
context.get_dbfile().display(),
|
||||||
as_str(dest_pathNfilename),
|
dest_path_filename.display(),
|
||||||
);
|
);
|
||||||
if dc_copy_file(context, context.get_dbfile(), as_path(dest_pathNfilename)) {
|
if dc_copy_file(context, context.get_dbfile(), &dest_path_filename) {
|
||||||
context.sql.open(&context, &context.get_dbfile(), 0);
|
context.sql.open(&context, &context.get_dbfile(), 0);
|
||||||
closed = false;
|
closed = false;
|
||||||
/* add all files as blobs to the database copy (this does not require the source to be locked, neigher the destination as it is used only here) */
|
/* add all files as blobs to the database copy (this does not require the source to be locked, neigher the destination as it is used only here) */
|
||||||
/*for logging only*/
|
/*for logging only*/
|
||||||
let sql = Sql::new();
|
let sql = Sql::new();
|
||||||
if sql.open(context, as_path(dest_pathNfilename), 0) {
|
if sql.open(context, &dest_path_filename, 0) {
|
||||||
if !sql.table_exists("backup_blobs") {
|
if !sql.table_exists("backup_blobs") {
|
||||||
if sql::execute(
|
if sql::execute(
|
||||||
context,
|
context,
|
||||||
@@ -821,9 +804,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> bool {
|
|||||||
.set_config_int(context, "backup_time", now as i32)
|
.set_config_int(context, "backup_time", now as i32)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
context.call_cb(Event::ImexFileWritten(
|
context.call_cb(Event::ImexFileWritten(&dest_path_filename));
|
||||||
as_path(dest_pathNfilename).to_path_buf(),
|
|
||||||
));
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -841,9 +822,8 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> bool {
|
|||||||
context.sql.open(&context, &context.get_dbfile(), 0);
|
context.sql.open(&context, &context.get_dbfile(), 0);
|
||||||
}
|
}
|
||||||
if 0 != delete_dest_file {
|
if 0 != delete_dest_file {
|
||||||
dc_delete_file(context, as_path(dest_pathNfilename));
|
dc_delete_file(context, &dest_path_filename);
|
||||||
}
|
}
|
||||||
free(dest_pathNfilename as *mut libc::c_void);
|
|
||||||
|
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1301,34 +1301,22 @@ unsafe fn do_add_single_file_part(
|
|||||||
decoded_data_bytes: libc::size_t,
|
decoded_data_bytes: libc::size_t,
|
||||||
desired_filename: *const libc::c_char,
|
desired_filename: *const libc::c_char,
|
||||||
) {
|
) {
|
||||||
let pathNfilename: *mut libc::c_char;
|
let path_filename =
|
||||||
/* create a free file name to use */
|
dc_get_fine_path_filename((*parser).context, "$BLOBDIR", as_str(desired_filename));
|
||||||
pathNfilename = dc_get_fine_pathNfilename(
|
let bytes = std::slice::from_raw_parts(decoded_data as *const u8, decoded_data_bytes);
|
||||||
(*parser).context,
|
|
||||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
|
||||||
desired_filename,
|
|
||||||
);
|
|
||||||
if !pathNfilename.is_null() {
|
|
||||||
/* copy data to file */
|
/* copy data to file */
|
||||||
if !(dc_write_file(
|
if dc_write_file((*parser).context, &path_filename, bytes) {
|
||||||
(*parser).context,
|
|
||||||
pathNfilename,
|
|
||||||
decoded_data as *const libc::c_void,
|
|
||||||
decoded_data_bytes,
|
|
||||||
) == 0i32)
|
|
||||||
{
|
|
||||||
let mut part = dc_mimepart_new();
|
let mut part = dc_mimepart_new();
|
||||||
part.type_0 = msg_type;
|
part.type_0 = msg_type;
|
||||||
part.int_mimetype = mime_type;
|
part.int_mimetype = mime_type;
|
||||||
part.bytes = decoded_data_bytes as libc::c_int;
|
part.bytes = decoded_data_bytes as libc::c_int;
|
||||||
part.param.set(Param::File, as_str(pathNfilename));
|
part.param.set(Param::File, path_filename.to_string_lossy());
|
||||||
part.param.set(Param::MimeType, raw_mime);
|
part.param.set(Param::MimeType, raw_mime);
|
||||||
if mime_type == 80 {
|
if mime_type == 80 {
|
||||||
assert!(!decoded_data.is_null(), "invalid image data");
|
assert!(!decoded_data.is_null(), "invalid image data");
|
||||||
let data = std::slice::from_raw_parts(
|
let data =
|
||||||
decoded_data as *const u8,
|
std::slice::from_raw_parts(decoded_data as *const u8, decoded_data_bytes as usize);
|
||||||
decoded_data_bytes as usize,
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Ok((width, height)) = dc_get_filemeta(data) {
|
if let Ok((width, height)) = dc_get_filemeta(data) {
|
||||||
part.param.set_int(Param::Width, width as i32);
|
part.param.set_int(Param::Width, width as i32);
|
||||||
@@ -1338,8 +1326,6 @@ unsafe fn do_add_single_file_part(
|
|||||||
do_add_single_part(parser, part);
|
do_add_single_part(parser, part);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(pathNfilename as *mut libc::c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn do_add_single_part(parser: &mut dc_mimeparser_t, mut part: dc_mimepart_t) {
|
unsafe fn do_add_single_part(parser: &mut dc_mimeparser_t, mut part: dc_mimepart_t) {
|
||||||
if (*parser).e2ee_helper.encrypted && (*parser).e2ee_helper.signatures.len() > 0 {
|
if (*parser).e2ee_helper.encrypted && (*parser).e2ee_helper.signatures.len() > 0 {
|
||||||
|
|||||||
276
src/dc_tools.rs
276
src/dc_tools.rs
@@ -1,12 +1,14 @@
|
|||||||
|
//! Some tools and enhancements to the used libraries, there should be
|
||||||
|
//! no references to Context and other "larger" entities here.
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString, OsString};
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use std::{fmt, fs, ptr};
|
use std::{fmt, fs, ptr};
|
||||||
|
|
||||||
use chrono::{Local, TimeZone};
|
use chrono::{Local, TimeZone};
|
||||||
use itertools::max;
|
|
||||||
use libc::uintptr_t;
|
use libc::uintptr_t;
|
||||||
use mmime::clist::*;
|
use mmime::clist::*;
|
||||||
use mmime::mailimf_types::*;
|
use mmime::mailimf_types::*;
|
||||||
@@ -16,10 +18,6 @@ use crate::context::Context;
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::x::*;
|
use crate::x::*;
|
||||||
|
|
||||||
/* Some tools and enhancements to the used libraries, there should be
|
|
||||||
no references to Context and other "larger" classes here. */
|
|
||||||
/* ** library-private **********************************************************/
|
|
||||||
/* math tools */
|
|
||||||
pub fn dc_exactly_one_bit_set(v: libc::c_int) -> bool {
|
pub fn dc_exactly_one_bit_set(v: libc::c_int) -> bool {
|
||||||
0 != v && 0 == v & (v - 1)
|
0 != v && 0 == v & (v - 1)
|
||||||
}
|
}
|
||||||
@@ -570,7 +568,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 unsafe fn dc_create_incoming_rfc724_mid(
|
pub 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>,
|
||||||
@@ -579,51 +577,36 @@ pub unsafe fn dc_create_incoming_rfc724_mid(
|
|||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
}
|
}
|
||||||
/* find out the largest receiver ID (we could also take the smallest, but it should be unique) */
|
/* find out the largest receiver ID (we could also take the smallest, but it should be unique) */
|
||||||
let largest_id_to = max(contact_ids_to.iter());
|
let largest_id_to = contact_ids_to.iter().max().copied().unwrap_or_default();
|
||||||
|
|
||||||
dc_mprintf(
|
let result = format!(
|
||||||
b"%lu-%lu-%lu@stub\x00" as *const u8 as *const libc::c_char,
|
"{}-{}-{}@stub",
|
||||||
message_timestamp as libc::c_ulong,
|
message_timestamp, contact_id_from, largest_id_to
|
||||||
contact_id_from as libc::c_ulong,
|
);
|
||||||
*largest_id_to.unwrap() as libc::c_ulong,
|
|
||||||
)
|
unsafe { result.strdup() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Function generates a Message-ID that can be used for a new outgoing message.
|
||||||
|
/// - 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 as this may give unneeded information to the receiver
|
||||||
pub unsafe fn dc_create_outgoing_rfc724_mid(
|
pub unsafe fn dc_create_outgoing_rfc724_mid(
|
||||||
grpid: *const libc::c_char,
|
grpid: *const libc::c_char,
|
||||||
from_addr: *const libc::c_char,
|
from_addr: *const libc::c_char,
|
||||||
) -> *mut libc::c_char {
|
) -> *mut libc::c_char {
|
||||||
/* Function generates a Message-ID that can be used for a new outgoing message.
|
let rand2 = dc_create_id();
|
||||||
- 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 as this may give unneeded information to the receiver */
|
|
||||||
let mut rand1: *mut libc::c_char = ptr::null_mut();
|
|
||||||
let rand2: *mut libc::c_char = dc_create_id().strdup();
|
|
||||||
let ret: *mut libc::c_char;
|
|
||||||
let mut at_hostname: *const libc::c_char = strchr(from_addr, '@' as i32);
|
|
||||||
if at_hostname.is_null() {
|
|
||||||
at_hostname = b"@nohost\x00" as *const u8 as *const libc::c_char
|
|
||||||
}
|
|
||||||
if !grpid.is_null() {
|
|
||||||
ret = dc_mprintf(
|
|
||||||
b"Gr.%s.%s%s\x00" as *const u8 as *const libc::c_char,
|
|
||||||
grpid,
|
|
||||||
rand2,
|
|
||||||
at_hostname,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
rand1 = dc_create_id().strdup();
|
|
||||||
ret = dc_mprintf(
|
|
||||||
b"Mr.%s.%s%s\x00" as *const u8 as *const libc::c_char,
|
|
||||||
rand1,
|
|
||||||
rand2,
|
|
||||||
at_hostname,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
free(rand1 as *mut libc::c_void);
|
|
||||||
free(rand2 as *mut libc::c_void);
|
|
||||||
|
|
||||||
ret
|
let at_hostname = as_opt_str(strchr(from_addr, '@' as i32)).unwrap_or_else(|| "@nohost");
|
||||||
|
|
||||||
|
let ret = if !grpid.is_null() {
|
||||||
|
format!("Gr.{}.{}{}", as_str(grpid), rand2, at_hostname,)
|
||||||
|
} else {
|
||||||
|
let rand1 = dc_create_id();
|
||||||
|
format!("Mr.{}.{}{}", rand1, rand2, at_hostname)
|
||||||
|
};
|
||||||
|
|
||||||
|
ret.strdup()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate globally-unique message-id for a new outgoing message.
|
/// Generate globally-unique message-id for a new outgoing message.
|
||||||
@@ -696,16 +679,6 @@ pub unsafe fn dc_extract_grpid_from_rfc724_mid_list(list: *const clist) -> *mut
|
|||||||
ptr::null_mut()
|
ptr::null_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
unsafe fn dc_ensure_no_slash(pathNfilename: *mut libc::c_char) {
|
|
||||||
let path_len = strlen(pathNfilename);
|
|
||||||
if path_len > 0 && *pathNfilename.add(path_len - 1) as libc::c_int == '/' as i32
|
|
||||||
|| *pathNfilename.add(path_len - 1) as libc::c_int == '\\' as i32
|
|
||||||
{
|
|
||||||
*pathNfilename.add(path_len - 1) = 0 as libc::c_char;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dc_ensure_no_slash_safe(path: &str) -> &str {
|
pub 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];
|
||||||
@@ -713,18 +686,12 @@ pub fn dc_ensure_no_slash_safe(path: &str) -> &str {
|
|||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn dc_validate_filename(filename: *mut libc::c_char) {
|
/// Function modifies the given buffer and replaces all characters not valid in filenames by a "-".
|
||||||
/* function modifies the given buffer and replaces all characters not valid in filenames by a "-" */
|
fn validate_filename(filename: &str) -> String {
|
||||||
let mut p1: *mut libc::c_char = filename;
|
filename
|
||||||
while 0 != *p1 {
|
.replace('/', "-")
|
||||||
if *p1 as libc::c_int == '/' as i32
|
.replace('\\', "-")
|
||||||
|| *p1 as libc::c_int == '\\' as i32
|
.replace(':', "-")
|
||||||
|| *p1 as libc::c_int == ':' as i32
|
|
||||||
{
|
|
||||||
*p1 = '-' as i32 as libc::c_char
|
|
||||||
}
|
|
||||||
p1 = p1.offset(1isize)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_get_filename(path_filename: impl AsRef<str>) -> *mut libc::c_char {
|
pub unsafe fn dc_get_filename(path_filename: impl AsRef<str>) -> *mut libc::c_char {
|
||||||
@@ -735,42 +702,6 @@ pub unsafe fn dc_get_filename(path_filename: impl AsRef<str>) -> *mut libc::c_ch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the case of the suffix is preserved
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
unsafe fn dc_split_filename(
|
|
||||||
pathNfilename: *const libc::c_char,
|
|
||||||
ret_basename: *mut *mut libc::c_char,
|
|
||||||
ret_all_suffixes_incl_dot: *mut *mut libc::c_char,
|
|
||||||
) {
|
|
||||||
if pathNfilename.is_null() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* splits a filename into basename and all suffixes, eg. "/path/foo.tar.gz" is split into "foo.tar" and ".gz",
|
|
||||||
(we use the _last_ dot which allows the usage inside the filename which are very usual;
|
|
||||||
maybe the detection could be more intelligent, however, for the moment, it is just file)
|
|
||||||
- if there is no suffix, the returned suffix string is empty, eg. "/path/foobar" is split into "foobar" and ""
|
|
||||||
- the case of the returned suffix is preserved; this is to allow reconstruction of (similar) names */
|
|
||||||
let basename: *mut libc::c_char = dc_get_filename(as_str(pathNfilename));
|
|
||||||
let suffix: *mut libc::c_char;
|
|
||||||
let p1: *mut libc::c_char = strrchr(basename, '.' as i32);
|
|
||||||
if !p1.is_null() {
|
|
||||||
suffix = dc_strdup(p1);
|
|
||||||
*p1 = 0 as libc::c_char
|
|
||||||
} else {
|
|
||||||
suffix = dc_strdup(ptr::null())
|
|
||||||
}
|
|
||||||
if !ret_basename.is_null() {
|
|
||||||
*ret_basename = basename
|
|
||||||
} else {
|
|
||||||
free(basename as *mut libc::c_void);
|
|
||||||
}
|
|
||||||
if !ret_all_suffixes_incl_dot.is_null() {
|
|
||||||
*ret_all_suffixes_incl_dot = suffix
|
|
||||||
} else {
|
|
||||||
free(suffix as *mut libc::c_void);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
||||||
@@ -876,23 +807,8 @@ pub fn dc_create_folder(context: &Context, path: impl AsRef<std::path::Path>) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
/// Write a the given content to provied file path.
|
||||||
pub unsafe fn dc_write_file(
|
pub fn dc_write_file(context: &Context, path: impl AsRef<Path>, buf: &[u8]) -> bool {
|
||||||
context: &Context,
|
|
||||||
pathNfilename: *const libc::c_char,
|
|
||||||
buf: *const libc::c_void,
|
|
||||||
buf_bytes: libc::size_t,
|
|
||||||
) -> libc::c_int {
|
|
||||||
let bytes = std::slice::from_raw_parts(buf as *const u8, buf_bytes);
|
|
||||||
|
|
||||||
dc_write_file_safe(context, as_str(pathNfilename), bytes) as libc::c_int
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dc_write_file_safe<P: AsRef<std::path::Path>>(
|
|
||||||
context: &Context,
|
|
||||||
path: P,
|
|
||||||
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!(
|
||||||
@@ -942,58 +858,48 @@ pub fn dc_read_file_safe<P: AsRef<std::path::Path>>(context: &Context, path: P)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
pub fn dc_get_fine_path_filename(
|
||||||
pub unsafe fn dc_get_fine_pathNfilename(
|
|
||||||
context: &Context,
|
context: &Context,
|
||||||
pathNfolder: *const libc::c_char,
|
folder: impl AsRef<Path>,
|
||||||
desired_filenameNsuffix__: *const libc::c_char,
|
desired_filename_suffix: impl AsRef<str>,
|
||||||
) -> *mut libc::c_char {
|
) -> PathBuf {
|
||||||
let mut ret: *mut libc::c_char = ptr::null_mut();
|
|
||||||
let pathNfolder_wo_slash: *mut libc::c_char;
|
|
||||||
let filenameNsuffix: *mut libc::c_char;
|
|
||||||
let mut basename: *mut libc::c_char = ptr::null_mut();
|
|
||||||
let mut dotNSuffix: *mut libc::c_char = ptr::null_mut();
|
|
||||||
let now = time();
|
let now = time();
|
||||||
|
|
||||||
pathNfolder_wo_slash = dc_strdup(pathNfolder);
|
let folder = PathBuf::from(folder.as_ref());
|
||||||
dc_ensure_no_slash(pathNfolder_wo_slash);
|
let suffix = validate_filename(desired_filename_suffix.as_ref());
|
||||||
filenameNsuffix = dc_strdup(desired_filenameNsuffix__);
|
|
||||||
dc_validate_filename(filenameNsuffix);
|
|
||||||
dc_split_filename(filenameNsuffix, &mut basename, &mut dotNSuffix);
|
|
||||||
|
|
||||||
for i in 0..1000i64 {
|
let file_name = PathBuf::from(suffix);
|
||||||
/*no deadlocks, please*/
|
let extension = file_name.extension().map(|c| c.clone());
|
||||||
if 0 != i {
|
|
||||||
let idx = if i < 100 { i } else { now + i };
|
for i in 0..100_000 {
|
||||||
ret = dc_mprintf(
|
let ret = if i == 0 {
|
||||||
b"%s/%s-%lu%s\x00" as *const u8 as *const libc::c_char,
|
let mut folder = folder.clone();
|
||||||
pathNfolder_wo_slash,
|
folder.push(&file_name);
|
||||||
basename,
|
folder
|
||||||
idx as libc::c_ulong,
|
|
||||||
dotNSuffix,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
ret = dc_mprintf(
|
let idx = if i < 100 { i } else { now + i };
|
||||||
b"%s/%s%s\x00" as *const u8 as *const libc::c_char,
|
let file_name = if let Some(stem) = file_name.file_stem() {
|
||||||
pathNfolder_wo_slash,
|
let mut stem = stem.to_os_string();
|
||||||
basename,
|
stem.push(format!("-{}", idx));
|
||||||
dotNSuffix,
|
stem
|
||||||
)
|
} else {
|
||||||
|
OsString::from(idx.to_string())
|
||||||
|
};
|
||||||
|
let mut folder = folder.clone();
|
||||||
|
folder.push(file_name);
|
||||||
|
if let Some(ext) = extension {
|
||||||
|
folder.set_extension(&ext);
|
||||||
}
|
}
|
||||||
if !dc_file_exist(context, as_path(ret)) {
|
folder
|
||||||
/* fine filename found */
|
};
|
||||||
break;
|
|
||||||
|
if !dc_file_exist(context, &ret) {
|
||||||
|
// fine filename found
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
free(ret as *mut libc::c_void);
|
|
||||||
ret = ptr::null_mut();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(filenameNsuffix as *mut libc::c_void);
|
panic!("Something is really wrong, you need to clean up your disk");
|
||||||
free(basename as *mut libc::c_void);
|
|
||||||
free(dotNSuffix as *mut libc::c_void);
|
|
||||||
free(pathNfolder_wo_slash as *mut libc::c_void);
|
|
||||||
|
|
||||||
ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dc_is_blobdir_path(context: &Context, path: impl AsRef<str>) -> bool {
|
pub fn dc_is_blobdir_path(context: &Context, path: impl AsRef<str>) -> bool {
|
||||||
@@ -1017,38 +923,18 @@ fn dc_make_rel_path(context: &Context, path: &mut String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn dc_make_rel_and_copy(context: &Context, path: &mut String) -> bool {
|
pub fn dc_make_rel_and_copy(context: &Context, path: &mut String) -> bool {
|
||||||
let mut success = false;
|
|
||||||
let mut filename = ptr::null_mut();
|
|
||||||
let mut blobdir_path = ptr::null_mut();
|
|
||||||
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);
|
||||||
success = true;
|
return true;
|
||||||
} else {
|
|
||||||
filename = unsafe { dc_get_filename(&path) };
|
|
||||||
if !(filename.is_null()
|
|
||||||
|| {
|
|
||||||
blobdir_path = unsafe {
|
|
||||||
dc_get_fine_pathNfilename(
|
|
||||||
context,
|
|
||||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
|
||||||
filename,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
blobdir_path.is_null()
|
|
||||||
}
|
}
|
||||||
|| !dc_copy_file(context, &path, as_path(blobdir_path)))
|
let blobdir_path = dc_get_fine_path_filename(context, "$BLOBDIR", &path);
|
||||||
{
|
if dc_copy_file(context, &path, &blobdir_path) {
|
||||||
*path = to_string(blobdir_path);
|
*path = blobdir_path.to_string_lossy().to_string();
|
||||||
blobdir_path = ptr::null_mut();
|
|
||||||
dc_make_rel_path(context, path);
|
dc_make_rel_path(context, path);
|
||||||
success = true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
unsafe {
|
false
|
||||||
free(blobdir_path.cast());
|
|
||||||
free(filename.cast());
|
|
||||||
}
|
|
||||||
success
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error type for the [OsStrExt] trait
|
/// Error type for the [OsStrExt] trait
|
||||||
@@ -1923,4 +1809,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dc_create_incoming_rfc724_mid() {
|
||||||
|
let res = dc_create_incoming_rfc724_mid(123, 45, &vec![6, 7]);
|
||||||
|
assert_eq!(as_str(res), "123-45-7@stub");
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
free(res.cast());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/job.rs
34
src/job.rs
@@ -998,38 +998,23 @@ fn send_mdn(context: &Context, msg_id: u32) {
|
|||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_t) -> libc::c_int {
|
fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_t) -> libc::c_int {
|
||||||
let pathNfilename: *mut libc::c_char;
|
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0i32;
|
||||||
let mut recipients: *mut libc::c_char = ptr::null_mut();
|
let mut recipients: *mut libc::c_char = ptr::null_mut();
|
||||||
let mut param = Params::new();
|
let mut param = Params::new();
|
||||||
pathNfilename = unsafe {
|
let path_filename =
|
||||||
dc_get_fine_pathNfilename(
|
dc_get_fine_path_filename(context, "$BLOBDIR", as_str(mimefactory.rfc724_mid));
|
||||||
context,
|
let bytes = unsafe {
|
||||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
std::slice::from_raw_parts(
|
||||||
mimefactory.rfc724_mid,
|
(*mimefactory.out).str_0 as *const u8,
|
||||||
)
|
|
||||||
};
|
|
||||||
if pathNfilename.is_null() {
|
|
||||||
error!(
|
|
||||||
context,
|
|
||||||
"Could not find free file name for message with ID <{}>.",
|
|
||||||
to_string(mimefactory.rfc724_mid),
|
|
||||||
);
|
|
||||||
} else if 0
|
|
||||||
== unsafe {
|
|
||||||
dc_write_file(
|
|
||||||
context,
|
|
||||||
pathNfilename,
|
|
||||||
(*mimefactory.out).str_0 as *const libc::c_void,
|
|
||||||
(*mimefactory.out).len,
|
(*mimefactory.out).len,
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
{
|
if !dc_write_file(context, &path_filename, bytes) {
|
||||||
error!(
|
error!(
|
||||||
context,
|
context,
|
||||||
"Could not write message <{}> to \"{}\".",
|
"Could not write message <{}> to \"{}\".",
|
||||||
to_string(mimefactory.rfc724_mid),
|
to_string(mimefactory.rfc724_mid),
|
||||||
as_str(pathNfilename),
|
path_filename.display(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
recipients = unsafe {
|
recipients = unsafe {
|
||||||
@@ -1038,7 +1023,7 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_
|
|||||||
b"\x1e\x00" as *const u8 as *const libc::c_char,
|
b"\x1e\x00" as *const u8 as *const libc::c_char,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
param.set(Param::File, as_str(pathNfilename));
|
param.set(Param::File, path_filename.to_string_lossy());
|
||||||
param.set(Param::Recipients, as_str(recipients));
|
param.set(Param::Recipients, as_str(recipients));
|
||||||
job_add(
|
job_add(
|
||||||
context,
|
context,
|
||||||
@@ -1057,7 +1042,6 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_
|
|||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
free(recipients.cast());
|
free(recipients.cast());
|
||||||
free(pathNfilename.cast());
|
|
||||||
}
|
}
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ impl Key {
|
|||||||
pub fn write_asc_to_file(&self, file: impl AsRef<Path>, context: &Context) -> bool {
|
pub fn write_asc_to_file(&self, file: impl AsRef<Path>, context: &Context) -> bool {
|
||||||
let file_content = self.to_asc(None).into_bytes();
|
let file_content = self.to_asc(None).into_bytes();
|
||||||
|
|
||||||
if dc_write_file_safe(context, &file, &file_content) {
|
if dc_write_file(context, &file, &file_content) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
error!(context, "Cannot write key to {}", file.as_ref().display());
|
error!(context, "Cannot write key to {}", file.as_ref().display());
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
//! 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 tempfile::{tempdir, TempDir};
|
||||||
@@ -39,15 +40,10 @@ unsafe fn stress_functions(context: &Context) {
|
|||||||
dc_delete_file(context, "$BLOBDIR/foobar.dadada");
|
dc_delete_file(context, "$BLOBDIR/foobar.dadada");
|
||||||
dc_delete_file(context, "$BLOBDIR/foobar-folder");
|
dc_delete_file(context, "$BLOBDIR/foobar-folder");
|
||||||
}
|
}
|
||||||
dc_write_file(
|
assert!(dc_write_file(context, "$BLOBDIR/foobar", b"content"));
|
||||||
context,
|
|
||||||
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
|
|
||||||
b"content\x00" as *const u8 as *const libc::c_char as *const libc::c_void,
|
|
||||||
7,
|
|
||||||
);
|
|
||||||
assert!(dc_file_exist(context, "$BLOBDIR/foobar",));
|
assert!(dc_file_exist(context, "$BLOBDIR/foobar",));
|
||||||
assert!(!dc_file_exist(context, "$BLOBDIR/foobarx"));
|
assert!(!dc_file_exist(context, "$BLOBDIR/foobarx"));
|
||||||
assert_eq!(dc_get_filebytes(context, "$BLOBDIR/foobar",), 7);
|
assert_eq!(dc_get_filebytes(context, "$BLOBDIR/foobar"), 7);
|
||||||
|
|
||||||
let abs_path = context
|
let abs_path = context
|
||||||
.get_blobdir()
|
.get_blobdir()
|
||||||
@@ -87,41 +83,14 @@ unsafe fn stress_functions(context: &Context) {
|
|||||||
assert!(dc_create_folder(context, "$BLOBDIR/foobar-folder"));
|
assert!(dc_create_folder(context, "$BLOBDIR/foobar-folder"));
|
||||||
assert!(dc_file_exist(context, "$BLOBDIR/foobar-folder",));
|
assert!(dc_file_exist(context, "$BLOBDIR/foobar-folder",));
|
||||||
assert!(!dc_delete_file(context, "$BLOBDIR/foobar-folder"));
|
assert!(!dc_delete_file(context, "$BLOBDIR/foobar-folder"));
|
||||||
let fn0: *mut libc::c_char = dc_get_fine_pathNfilename(
|
let fn0 = dc_get_fine_path_filename(context, "$BLOBDIR", "foobar.dadada");
|
||||||
context,
|
assert_eq!(fn0, PathBuf::from("$BLOBDIR/foobar.dadada"));
|
||||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
|
||||||
b"foobar.dadada\x00" as *const u8 as *const libc::c_char,
|
assert!(dc_write_file(context, &fn0, b"content"));
|
||||||
);
|
let fn1 = dc_get_fine_path_filename(context, "$BLOBDIR", "foobar.dadada");
|
||||||
assert!(!fn0.is_null());
|
assert_eq!(fn1, PathBuf::from("$BLOBDIR/foobar-1.dadada"));
|
||||||
assert_eq!(
|
|
||||||
strcmp(
|
assert!(dc_delete_file(context, &fn0));
|
||||||
fn0,
|
|
||||||
b"$BLOBDIR/foobar.dadada\x00" as *const u8 as *const libc::c_char,
|
|
||||||
),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
dc_write_file(
|
|
||||||
context,
|
|
||||||
fn0,
|
|
||||||
b"content\x00" as *const u8 as *const libc::c_char as *const libc::c_void,
|
|
||||||
7,
|
|
||||||
);
|
|
||||||
let fn1: *mut libc::c_char = dc_get_fine_pathNfilename(
|
|
||||||
context,
|
|
||||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
|
||||||
b"foobar.dadada\x00" as *const u8 as *const libc::c_char,
|
|
||||||
);
|
|
||||||
assert!(!fn1.is_null());
|
|
||||||
assert_eq!(
|
|
||||||
strcmp(
|
|
||||||
fn1,
|
|
||||||
b"$BLOBDIR/foobar-1.dadada\x00" as *const u8 as *const libc::c_char,
|
|
||||||
),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
assert!(dc_delete_file(context, as_path(fn0)));
|
|
||||||
free(fn0 as *mut libc::c_void);
|
|
||||||
free(fn1 as *mut libc::c_void);
|
|
||||||
|
|
||||||
let res = context.get_config(config::Config::SysConfigKeys).unwrap();
|
let res = context.get_config(config::Config::SysConfigKeys).unwrap();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user