mirror of
https://github.com/chatmail/core.git
synced 2026-05-02 12:56:30 +03:00
Merge branch 'refactor/remove-mprintf'
This commit is contained in:
448
Cargo.lock
generated
448
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -5,10 +5,6 @@ authors = ["dignifiedquire <dignifiedquire@gmail.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MPL"
|
license = "MPL"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
cc = "1.0.35"
|
|
||||||
pkg-config = "0.3"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deltachat_derive = { path = "./deltachat_derive" }
|
deltachat_derive = { path = "./deltachat_derive" }
|
||||||
libc = "0.2.51"
|
libc = "0.2.51"
|
||||||
|
|||||||
38
build.rs
38
build.rs
@@ -1,38 +0,0 @@
|
|||||||
extern crate cc;
|
|
||||||
|
|
||||||
fn link_static(lib: &str) {
|
|
||||||
println!("cargo:rustc-link-lib=static={}", lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn link_framework(fw: &str) {
|
|
||||||
println!("cargo:rustc-link-lib=framework={}", fw);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_search_path(p: &str) {
|
|
||||||
println!("cargo:rustc-link-search={}", p);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_tools() {
|
|
||||||
let mut config = cc::Build::new();
|
|
||||||
config.file("misc.c").compile("libtools.a");
|
|
||||||
|
|
||||||
println!("rerun-if-changed=build.rs");
|
|
||||||
println!("rerun-if-changed=misc.h");
|
|
||||||
println!("rerun-if-changed=misc.c");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
build_tools();
|
|
||||||
|
|
||||||
add_search_path("/usr/local/lib");
|
|
||||||
|
|
||||||
let target = std::env::var("TARGET").unwrap();
|
|
||||||
if target.contains("-apple") || target.contains("-darwin") {
|
|
||||||
link_framework("CoreFoundation");
|
|
||||||
link_framework("CoreServices");
|
|
||||||
link_framework("Security");
|
|
||||||
}
|
|
||||||
|
|
||||||
// local tools
|
|
||||||
link_static("tools");
|
|
||||||
}
|
|
||||||
@@ -510,18 +510,14 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
|||||||
}
|
}
|
||||||
"export-setup" => {
|
"export-setup" => {
|
||||||
let setup_code = dc_create_setup_code(context);
|
let setup_code = dc_create_setup_code(context);
|
||||||
let file_name: *mut libc::c_char = dc_mprintf(
|
let file_name = context.get_blobdir().join("autocrypt-setup-message.html");
|
||||||
b"%s/autocrypt-setup-message.html\x00" as *const u8 as *const libc::c_char,
|
|
||||||
context.get_blobdir(),
|
|
||||||
);
|
|
||||||
let file_content = dc_render_setup_file(context, &setup_code)?;
|
let file_content = dc_render_setup_file(context, &setup_code)?;
|
||||||
std::fs::write(as_str(file_name), file_content)?;
|
std::fs::write(&file_name, file_content)?;
|
||||||
println!(
|
println!(
|
||||||
"Setup message written to: {}\nSetup code: {}",
|
"Setup message written to: {}\nSetup code: {}",
|
||||||
as_str(file_name),
|
file_name.display(),
|
||||||
&setup_code,
|
&setup_code,
|
||||||
);
|
);
|
||||||
free(file_name as *mut libc::c_void);
|
|
||||||
}
|
}
|
||||||
"poke" => {
|
"poke" => {
|
||||||
ensure!(0 != poke_spec(context, arg1_c), "Poke failed");
|
ensure!(0 != poke_spec(context, arg1_c), "Poke failed");
|
||||||
|
|||||||
52
misc.c
52
misc.c
@@ -1,52 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "misc.h"
|
|
||||||
|
|
||||||
|
|
||||||
static char* internal_dc_strdup(const char* s) /* strdup(NULL) is undefined, save_strdup(NULL) returns an empty string in this case */
|
|
||||||
{
|
|
||||||
char* ret = NULL;
|
|
||||||
if (s) {
|
|
||||||
if ((ret=strdup(s))==NULL) {
|
|
||||||
exit(16); /* cannot allocate (little) memory, unrecoverable error */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ((ret=(char*)calloc(1, 1))==NULL) {
|
|
||||||
exit(17); /* cannot allocate little memory, unrecoverable error */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* dc_mprintf(const char* format, ...)
|
|
||||||
{
|
|
||||||
char testbuf[1];
|
|
||||||
char* buf = NULL;
|
|
||||||
int char_cnt_without_zero = 0;
|
|
||||||
|
|
||||||
va_list argp;
|
|
||||||
va_list argp_copy;
|
|
||||||
va_start(argp, format);
|
|
||||||
va_copy(argp_copy, argp);
|
|
||||||
|
|
||||||
char_cnt_without_zero = vsnprintf(testbuf, 0, format, argp);
|
|
||||||
va_end(argp);
|
|
||||||
if (char_cnt_without_zero < 0) {
|
|
||||||
va_end(argp_copy);
|
|
||||||
return internal_dc_strdup("ErrFmt");
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = malloc(char_cnt_without_zero+2 /* +1 would be enough, however, protect against off-by-one-errors */);
|
|
||||||
if (buf==NULL) {
|
|
||||||
va_end(argp_copy);
|
|
||||||
return internal_dc_strdup("ErrMem");
|
|
||||||
}
|
|
||||||
|
|
||||||
vsnprintf(buf, char_cnt_without_zero+1, format, argp_copy);
|
|
||||||
va_end(argp_copy);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
1
misc.h
1
misc.h
@@ -1 +0,0 @@
|
|||||||
char* dc_mprintf (const char* format, ...); /* The result must be free()'d. */
|
|
||||||
128
src/dc_imex.rs
128
src/dc_imex.rs
@@ -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()
|
||||||
@@ -639,7 +627,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!(
|
||||||
@@ -686,13 +674,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);
|
||||||
|
|
||||||
@@ -703,15 +686,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,
|
||||||
@@ -820,9 +803,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.clone()));
|
||||||
as_path(dest_pathNfilename).to_path_buf(),
|
|
||||||
));
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -840,9 +821,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
|
||||||
}
|
}
|
||||||
@@ -859,10 +839,8 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
|||||||
(currently, the last imported key is the standard key unless it contains the string "legacy" in its name) */
|
(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 imported_cnt: libc::c_int = 0;
|
||||||
let mut suffix: *mut libc::c_char = ptr::null_mut();
|
let mut suffix: *mut libc::c_char = ptr::null_mut();
|
||||||
let mut path_plus_name: *mut libc::c_char = ptr::null_mut();
|
|
||||||
let mut set_default: libc::c_int;
|
let mut set_default: libc::c_int;
|
||||||
let mut buf: *mut libc::c_char = ptr::null_mut();
|
let mut buf: *mut libc::c_char = ptr::null_mut();
|
||||||
let mut buf_bytes: libc::size_t = 0;
|
|
||||||
// a pointer inside buf, MUST NOT be free()'d
|
// a pointer inside buf, MUST NOT be free()'d
|
||||||
let mut private_key: *const libc::c_char;
|
let mut private_key: *const libc::c_char;
|
||||||
let mut buf2: *mut libc::c_char = ptr::null_mut();
|
let mut buf2: *mut libc::c_char = ptr::null_mut();
|
||||||
@@ -885,25 +863,21 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
free(path_plus_name as *mut libc::c_void);
|
let path_plus_name = dir.join(entry.file_name());
|
||||||
path_plus_name = dc_mprintf(
|
info!(context, "Checking: {}", path_plus_name.display());
|
||||||
b"%s/%s\x00" as *const u8 as *const libc::c_char,
|
|
||||||
dir_name,
|
free(buf.cast());
|
||||||
name_c.as_ptr(),
|
|
||||||
);
|
|
||||||
info!(context, "Checking: {}", as_str(path_plus_name));
|
|
||||||
free(buf as *mut libc::c_void);
|
|
||||||
buf = ptr::null_mut();
|
buf = ptr::null_mut();
|
||||||
if 0 == dc_read_file(
|
|
||||||
context,
|
if let Some(buf_r) = dc_read_file_safe(context, &path_plus_name) {
|
||||||
path_plus_name,
|
buf = buf_r.as_ptr() as *mut _;
|
||||||
&mut buf as *mut *mut libc::c_char as *mut *mut libc::c_void,
|
std::mem::forget(buf_r);
|
||||||
&mut buf_bytes,
|
} else {
|
||||||
) || buf_bytes < 50
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
};
|
||||||
|
|
||||||
private_key = buf;
|
private_key = buf;
|
||||||
|
|
||||||
free(buf2 as *mut libc::c_void);
|
free(buf2 as *mut libc::c_void);
|
||||||
buf2 = dc_strdup(buf);
|
buf2 = dc_strdup(buf);
|
||||||
if dc_split_armored_data(
|
if dc_split_armored_data(
|
||||||
@@ -936,7 +910,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
|||||||
info!(
|
info!(
|
||||||
context,
|
context,
|
||||||
"Treating \"{}\" as a legacy private key.",
|
"Treating \"{}\" as a legacy private key.",
|
||||||
as_str(path_plus_name),
|
path_plus_name.display(),
|
||||||
);
|
);
|
||||||
set_default = 0i32
|
set_default = 0i32
|
||||||
}
|
}
|
||||||
@@ -962,7 +936,6 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(suffix as *mut libc::c_void);
|
free(suffix as *mut libc::c_void);
|
||||||
free(path_plus_name as *mut libc::c_void);
|
|
||||||
free(buf as *mut libc::c_void);
|
free(buf as *mut libc::c_void);
|
||||||
free(buf2 as *mut libc::c_void);
|
free(buf2 as *mut libc::c_void);
|
||||||
|
|
||||||
@@ -1025,38 +998,31 @@ unsafe fn export_key_to_asc_file(
|
|||||||
is_default: libc::c_int,
|
is_default: libc::c_int,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut success = false;
|
let mut success = false;
|
||||||
let file_name;
|
let dir = as_path(dir);
|
||||||
if 0 != is_default {
|
|
||||||
file_name = dc_mprintf(
|
let file_name = if 0 != is_default {
|
||||||
b"%s/%s-key-default.asc\x00" as *const u8 as *const libc::c_char,
|
let name = format!(
|
||||||
dir,
|
"{}-key-default.asc",
|
||||||
if key.is_public() {
|
if key.is_public() { "public" } else { "private" },
|
||||||
b"public\x00" as *const u8 as *const libc::c_char
|
);
|
||||||
} else {
|
dir.join(name)
|
||||||
b"private\x00" as *const u8 as *const libc::c_char
|
|
||||||
},
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
file_name = dc_mprintf(
|
let name = format!(
|
||||||
b"%s/%s-key-%i.asc\x00" as *const u8 as *const libc::c_char,
|
"{}-key-{}.asc",
|
||||||
dir,
|
if key.is_public() { "public" } else { "private" },
|
||||||
if key.is_public() {
|
id
|
||||||
b"public\x00" as *const u8 as *const libc::c_char
|
);
|
||||||
} else {
|
dir.join(name)
|
||||||
b"private\x00" as *const u8 as *const libc::c_char
|
};
|
||||||
},
|
info!(context, "Exporting key {}", file_name.display());
|
||||||
id,
|
dc_delete_file(context, &file_name);
|
||||||
)
|
|
||||||
}
|
if !key.write_asc_to_file(&file_name, context) {
|
||||||
info!(context, "Exporting key {}", as_str(file_name),);
|
error!(context, "Cannot write key to {}", file_name.display());
|
||||||
dc_delete_file(context, as_path(file_name));
|
|
||||||
if !key.write_asc_to_file(as_path(file_name), context) {
|
|
||||||
error!(context, "Cannot write key to {}", as_str(file_name),);
|
|
||||||
} else {
|
} else {
|
||||||
context.call_cb(Event::ImexFileWritten(as_path(file_name).to_path_buf()));
|
context.call_cb(Event::ImexFileWritten(file_name.clone()));
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
free(file_name as *mut libc::c_void);
|
|
||||||
|
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::ffi::CString;
|
use std::path::Path;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use chrono::TimeZone;
|
use chrono::TimeZone;
|
||||||
@@ -32,7 +32,7 @@ use crate::x::*;
|
|||||||
pub struct dc_mimefactory_t<'a> {
|
pub struct dc_mimefactory_t<'a> {
|
||||||
pub from_addr: *mut libc::c_char,
|
pub from_addr: *mut libc::c_char,
|
||||||
pub from_displayname: *mut libc::c_char,
|
pub from_displayname: *mut libc::c_char,
|
||||||
pub selfstatus: *mut libc::c_char,
|
pub selfstatus: Option<String>,
|
||||||
pub recipients_names: *mut clist,
|
pub recipients_names: *mut clist,
|
||||||
pub recipients_addr: *mut clist,
|
pub recipients_addr: *mut clist,
|
||||||
pub timestamp: i64,
|
pub timestamp: i64,
|
||||||
@@ -57,7 +57,6 @@ impl<'a> Drop for dc_mimefactory_t<'a> {
|
|||||||
unsafe {
|
unsafe {
|
||||||
free(self.from_addr as *mut libc::c_void);
|
free(self.from_addr as *mut libc::c_void);
|
||||||
free(self.from_displayname as *mut libc::c_void);
|
free(self.from_displayname as *mut libc::c_void);
|
||||||
free(self.selfstatus as *mut libc::c_void);
|
|
||||||
free(self.rfc724_mid as *mut libc::c_void);
|
free(self.rfc724_mid as *mut libc::c_void);
|
||||||
if !self.recipients_names.is_null() {
|
if !self.recipients_names.is_null() {
|
||||||
clist_free_content(self.recipients_names);
|
clist_free_content(self.recipients_names);
|
||||||
@@ -95,7 +94,7 @@ pub unsafe fn dc_mimefactory_load_msg(
|
|||||||
let mut factory = dc_mimefactory_t {
|
let mut factory = dc_mimefactory_t {
|
||||||
from_addr: ptr::null_mut(),
|
from_addr: ptr::null_mut(),
|
||||||
from_displayname: ptr::null_mut(),
|
from_displayname: ptr::null_mut(),
|
||||||
selfstatus: ptr::null_mut(),
|
selfstatus: None,
|
||||||
recipients_names: clist_new(),
|
recipients_names: clist_new(),
|
||||||
recipients_addr: clist_new(),
|
recipients_addr: clist_new(),
|
||||||
timestamp: 0,
|
timestamp: 0,
|
||||||
@@ -253,14 +252,16 @@ unsafe fn load_from(factory: &mut dc_mimefactory_t) {
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.strdup();
|
.strdup();
|
||||||
|
|
||||||
factory.selfstatus = context
|
factory.selfstatus = context.sql.get_config(context, "selfstatus");
|
||||||
.sql
|
|
||||||
.get_config(context, "selfstatus")
|
if factory.selfstatus.is_none() {
|
||||||
.unwrap_or_default()
|
factory.selfstatus = Some(
|
||||||
.strdup();
|
factory
|
||||||
if factory.selfstatus.is_null() {
|
.context
|
||||||
factory.selfstatus = factory.context.stock_str(StockMessage::StatusLine).strdup();
|
.stock_str(StockMessage::StatusLine)
|
||||||
};
|
.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_mimefactory_load_mdn<'a>(
|
pub unsafe fn dc_mimefactory_load_mdn<'a>(
|
||||||
@@ -283,7 +284,7 @@ pub unsafe fn dc_mimefactory_load_mdn<'a>(
|
|||||||
let mut factory = dc_mimefactory_t {
|
let mut factory = dc_mimefactory_t {
|
||||||
from_addr: ptr::null_mut(),
|
from_addr: ptr::null_mut(),
|
||||||
from_displayname: ptr::null_mut(),
|
from_displayname: ptr::null_mut(),
|
||||||
selfstatus: ptr::null_mut(),
|
selfstatus: None,
|
||||||
recipients_names: clist_new(),
|
recipients_names: clist_new(),
|
||||||
recipients_addr: clist_new(),
|
recipients_addr: clist_new(),
|
||||||
timestamp: 0,
|
timestamp: 0,
|
||||||
@@ -342,7 +343,6 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
let mut message: *mut mailmime = ptr::null_mut();
|
let mut message: *mut mailmime = ptr::null_mut();
|
||||||
let mut message_text: *mut libc::c_char = ptr::null_mut();
|
let mut message_text: *mut libc::c_char = ptr::null_mut();
|
||||||
let mut message_text2: *mut libc::c_char = ptr::null_mut();
|
let mut message_text2: *mut libc::c_char = ptr::null_mut();
|
||||||
let mut subject_str: *mut libc::c_char = ptr::null_mut();
|
|
||||||
let mut afwd_email: libc::c_int = 0;
|
let mut afwd_email: libc::c_int = 0;
|
||||||
let mut col: libc::c_int = 0;
|
let mut col: libc::c_int = 0;
|
||||||
let mut success = false;
|
let mut success = false;
|
||||||
@@ -369,7 +369,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
from,
|
from,
|
||||||
mailimf_mailbox_new(
|
mailimf_mailbox_new(
|
||||||
if !factory.from_displayname.is_null() {
|
if !factory.from_displayname.is_null() {
|
||||||
dc_encode_header_words(factory.from_displayname)
|
dc_encode_header_words(as_str(factory.from_displayname))
|
||||||
} else {
|
} else {
|
||||||
ptr::null_mut()
|
ptr::null_mut()
|
||||||
},
|
},
|
||||||
@@ -403,7 +403,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
MAILIMF_ADDRESS_MAILBOX as libc::c_int,
|
MAILIMF_ADDRESS_MAILBOX as libc::c_int,
|
||||||
mailimf_mailbox_new(
|
mailimf_mailbox_new(
|
||||||
if !name.is_null() {
|
if !name.is_null() {
|
||||||
dc_encode_header_words(name)
|
dc_encode_header_words(as_str(name))
|
||||||
} else {
|
} else {
|
||||||
ptr::null_mut()
|
ptr::null_mut()
|
||||||
},
|
},
|
||||||
@@ -458,17 +458,12 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| format!("/{}", s))
|
.map(|s| format!("/{}", s))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let os_part = CString::new(os_part).expect("String -> CString conversion failed");
|
let version = get_version_str();
|
||||||
let version = CString::yolo(get_version_str());
|
|
||||||
mailimf_fields_add(
|
mailimf_fields_add(
|
||||||
imf_fields,
|
imf_fields,
|
||||||
mailimf_field_new_custom(
|
mailimf_field_new_custom(
|
||||||
strdup(b"X-Mailer\x00" as *const u8 as *const libc::c_char),
|
strdup(b"X-Mailer\x00" as *const u8 as *const libc::c_char),
|
||||||
dc_mprintf(
|
format!("Delta Chat Core {}{}", version, os_part).strdup(),
|
||||||
b"Delta Chat Core %s%s\x00" as *const u8 as *const libc::c_char,
|
|
||||||
version.as_ptr(),
|
|
||||||
os_part.as_ptr(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -497,7 +492,8 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
let chat = factory.chat.as_ref().unwrap();
|
let chat = factory.chat.as_ref().unwrap();
|
||||||
let mut meta_part: *mut mailmime = ptr::null_mut();
|
let mut meta_part: *mut mailmime = ptr::null_mut();
|
||||||
let mut placeholdertext: *mut libc::c_char = ptr::null_mut();
|
let mut placeholdertext = None;
|
||||||
|
|
||||||
if chat.typ == Chattype::VerifiedGroup {
|
if chat.typ == Chattype::VerifiedGroup {
|
||||||
mailimf_fields_add(
|
mailimf_fields_add(
|
||||||
imf_fields,
|
imf_fields,
|
||||||
@@ -539,12 +535,11 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
chat.grpid.strdup(),
|
chat.grpid.strdup(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
let name = CString::yolo(chat.name.as_bytes());
|
|
||||||
mailimf_fields_add(
|
mailimf_fields_add(
|
||||||
imf_fields,
|
imf_fields,
|
||||||
mailimf_field_new_custom(
|
mailimf_field_new_custom(
|
||||||
strdup(b"Chat-Group-Name\x00" as *const u8 as *const libc::c_char),
|
strdup(b"Chat-Group-Name\x00" as *const u8 as *const libc::c_char),
|
||||||
dc_encode_header_words(name.as_ptr()),
|
dc_encode_header_words(&chat.name),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -645,10 +640,12 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
strdup(b"v1\x00" as *const u8 as *const libc::c_char),
|
strdup(b"v1\x00" as *const u8 as *const libc::c_char),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
placeholdertext = factory
|
placeholdertext = Some(
|
||||||
.context
|
factory
|
||||||
.stock_str(StockMessage::AcSetupMsgBody)
|
.context
|
||||||
.strdup();
|
.stock_str(StockMessage::AcSetupMsgBody)
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if command == SystemMessage::SecurejoinMessage {
|
if command == SystemMessage::SecurejoinMessage {
|
||||||
let msg = &factory.msg;
|
let msg = &factory.msg;
|
||||||
@@ -772,78 +769,68 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
imf_fields,
|
imf_fields,
|
||||||
mailimf_field_new_custom(
|
mailimf_field_new_custom(
|
||||||
strdup(b"Chat-Duration\x00" as *const u8 as *const libc::c_char),
|
strdup(b"Chat-Duration\x00" as *const u8 as *const libc::c_char),
|
||||||
dc_mprintf(
|
duration_ms.to_string().strdup(),
|
||||||
b"%i\x00" as *const u8 as *const libc::c_char,
|
|
||||||
duration_ms as libc::c_int,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
afwd_email = factory.msg.param.exists(Param::Forwarded) as libc::c_int;
|
afwd_email = factory.msg.param.exists(Param::Forwarded) as libc::c_int;
|
||||||
let mut fwdhint = ptr::null_mut();
|
let fwdhint = if 0 != afwd_email {
|
||||||
if 0 != afwd_email {
|
Some(
|
||||||
fwdhint = dc_strdup(
|
"---------- Forwarded message ----------\r\nFrom: Delta Chat\r\n\r\n"
|
||||||
b"---------- Forwarded message ----------\r\nFrom: Delta Chat\r\n\r\n\x00"
|
.to_string(),
|
||||||
as *const u8 as *const libc::c_char,
|
|
||||||
)
|
)
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let final_text = {
|
let final_text = {
|
||||||
if !placeholdertext.is_null() {
|
if let Some(ref text) = placeholdertext {
|
||||||
to_string(placeholdertext)
|
text
|
||||||
} else if let Some(ref text) = factory.msg.text {
|
} else if let Some(ref text) = factory.msg.text {
|
||||||
text.clone()
|
text
|
||||||
} else {
|
} else {
|
||||||
"".into()
|
""
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let final_text = CString::yolo(final_text);
|
|
||||||
|
|
||||||
let footer: *mut libc::c_char = factory.selfstatus;
|
let footer = factory.selfstatus.as_ref();
|
||||||
message_text = dc_mprintf(
|
|
||||||
b"%s%s%s%s%s\x00" as *const u8 as *const libc::c_char,
|
message_text = format!(
|
||||||
if !fwdhint.is_null() {
|
"{}{}{}{}{}",
|
||||||
fwdhint
|
if let Some(ref hint) = fwdhint {
|
||||||
|
hint
|
||||||
} else {
|
} else {
|
||||||
b"\x00" as *const u8 as *const libc::c_char
|
""
|
||||||
},
|
},
|
||||||
final_text.as_ptr(),
|
&final_text,
|
||||||
if final_text != CString::yolo("")
|
if !final_text.is_empty() && footer.is_some() {
|
||||||
&& !footer.is_null()
|
"\r\n\r\n"
|
||||||
&& 0 != *footer.offset(0isize) as libc::c_int
|
|
||||||
{
|
|
||||||
b"\r\n\r\n\x00" as *const u8 as *const libc::c_char
|
|
||||||
} else {
|
} else {
|
||||||
b"\x00" as *const u8 as *const libc::c_char
|
""
|
||||||
},
|
},
|
||||||
if !footer.is_null() && 0 != *footer.offset(0isize) as libc::c_int {
|
if footer.is_some() { "-- \r\n" } else { "" },
|
||||||
b"-- \r\n\x00" as *const u8 as *const libc::c_char
|
if let Some(footer) = footer {
|
||||||
} else {
|
|
||||||
b"\x00" as *const u8 as *const libc::c_char
|
|
||||||
},
|
|
||||||
if !footer.is_null() && 0 != *footer.offset(0isize) as libc::c_int {
|
|
||||||
footer
|
footer
|
||||||
} else {
|
} else {
|
||||||
b"\x00" as *const u8 as *const libc::c_char
|
""
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
.strdup();
|
||||||
let text_part: *mut mailmime = build_body_text(message_text);
|
let text_part: *mut mailmime = build_body_text(message_text);
|
||||||
mailmime_smart_add_part(message, text_part);
|
mailmime_smart_add_part(message, text_part);
|
||||||
parts += 1;
|
parts += 1;
|
||||||
free(fwdhint as *mut libc::c_void);
|
|
||||||
free(placeholdertext as *mut libc::c_void);
|
|
||||||
|
|
||||||
/* add attachment part */
|
/* add attachment part */
|
||||||
if chat::msgtype_has_file(factory.msg.type_0) {
|
if chat::msgtype_has_file(factory.msg.type_0) {
|
||||||
if !is_file_size_okay(context, &factory.msg) {
|
if !is_file_size_okay(context, &factory.msg) {
|
||||||
let error: *mut libc::c_char = dc_mprintf(
|
let error = format!(
|
||||||
b"Message exceeds the recommended %i MB.\x00" as *const u8
|
"Message exceeds the recommended {} MB.",
|
||||||
as *const libc::c_char,
|
|
||||||
24 * 1024 * 1024 / 4 * 3 / 1000 / 1000,
|
24 * 1024 * 1024 / 4 * 3 / 1000 / 1000,
|
||||||
);
|
)
|
||||||
|
.strdup();
|
||||||
set_error(factory, error);
|
set_error(factory, error);
|
||||||
free(error as *mut libc::c_void);
|
free(error.cast());
|
||||||
ok_to_continue = false;
|
ok_to_continue = false;
|
||||||
} else {
|
} else {
|
||||||
let file_part: *mut mailmime =
|
let file_part: *mut mailmime =
|
||||||
@@ -958,15 +945,14 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
message_text = format!("{}\r\n", p2).strdup();
|
message_text = format!("{}\r\n", p2).strdup();
|
||||||
let human_mime_part: *mut mailmime = build_body_text(message_text);
|
let human_mime_part: *mut mailmime = build_body_text(message_text);
|
||||||
mailmime_add_part(multipart, human_mime_part);
|
mailmime_add_part(multipart, human_mime_part);
|
||||||
let version = CString::yolo(get_version_str());
|
let version = get_version_str();
|
||||||
message_text2 =
|
message_text2 = format!(
|
||||||
dc_mprintf(
|
"Reporting-UA: Delta Chat {}\r\nOriginal-Recipient: rfc822;{}\r\nFinal-Recipient: rfc822;{}\r\nOriginal-Message-ID: <{}>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n",
|
||||||
b"Reporting-UA: Delta Chat %s\r\nOriginal-Recipient: rfc822;%s\r\nFinal-Recipient: rfc822;%s\r\nOriginal-Message-ID: <%s>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n\x00"
|
version,
|
||||||
as *const u8 as *const libc::c_char,
|
as_str(factory.from_addr),
|
||||||
version.as_ptr(),
|
as_str(factory.from_addr),
|
||||||
factory.from_addr, factory.from_addr,
|
as_str(factory.msg.rfc724_mid)
|
||||||
factory.msg.rfc724_mid
|
).strdup();
|
||||||
);
|
|
||||||
|
|
||||||
let content_type_0: *mut mailmime_content = mailmime_content_new_with_str(
|
let content_type_0: *mut mailmime_content = mailmime_content_new_with_str(
|
||||||
b"message/disposition-notification\x00" as *const u8 as *const libc::c_char,
|
b"message/disposition-notification\x00" as *const u8 as *const libc::c_char,
|
||||||
@@ -986,17 +972,19 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ok_to_continue {
|
if ok_to_continue {
|
||||||
if factory.loaded as libc::c_uint == DC_MF_MDN_LOADED as libc::c_int as libc::c_uint {
|
let subject_str = if factory.loaded as libc::c_uint == DC_MF_MDN_LOADED as libc::c_uint
|
||||||
let e = CString::new(factory.context.stock_str(StockMessage::ReadRcpt).as_ref())
|
{
|
||||||
.unwrap();
|
let e = factory.context.stock_str(StockMessage::ReadRcpt);
|
||||||
subject_str = dc_mprintf(
|
format!("Chat: {}", e)
|
||||||
b"Chat: %s\x00" as *const u8 as *const libc::c_char,
|
|
||||||
e.as_ptr(),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
subject_str =
|
to_string(get_subject(
|
||||||
get_subject(context, factory.chat.as_ref(), &mut factory.msg, afwd_email)
|
context,
|
||||||
}
|
factory.chat.as_ref(),
|
||||||
|
&mut factory.msg,
|
||||||
|
afwd_email,
|
||||||
|
))
|
||||||
|
};
|
||||||
|
|
||||||
subject = mailimf_subject_new(dc_encode_header_words(subject_str));
|
subject = mailimf_subject_new(dc_encode_header_words(subject_str));
|
||||||
mailimf_fields_add(
|
mailimf_fields_add(
|
||||||
imf_fields,
|
imf_fields,
|
||||||
@@ -1055,7 +1043,6 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
|
|||||||
e2ee_helper.thanks();
|
e2ee_helper.thanks();
|
||||||
free(message_text as *mut libc::c_void);
|
free(message_text as *mut libc::c_void);
|
||||||
free(message_text2 as *mut libc::c_void);
|
free(message_text2 as *mut libc::c_void);
|
||||||
free(subject_str as *mut libc::c_void);
|
|
||||||
|
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
@@ -1073,34 +1060,17 @@ unsafe fn get_subject(
|
|||||||
let chat = chat.unwrap();
|
let chat = chat.unwrap();
|
||||||
let ret: *mut libc::c_char;
|
let ret: *mut libc::c_char;
|
||||||
|
|
||||||
let raw_subject = {
|
let raw_subject =
|
||||||
dc_msg_get_summarytext_by_raw(msg.type_0, msg.text.as_ref(), &mut msg.param, 32, context)
|
dc_msg_get_summarytext_by_raw(msg.type_0, msg.text.as_ref(), &mut msg.param, 32, context);
|
||||||
.strdup()
|
|
||||||
};
|
|
||||||
|
|
||||||
let fwd = if 0 != afwd_email {
|
let fwd = if 0 != afwd_email { "Fwd: " } else { "" };
|
||||||
b"Fwd: \x00" as *const u8 as *const libc::c_char
|
|
||||||
} else {
|
|
||||||
b"\x00" as *const u8 as *const libc::c_char
|
|
||||||
};
|
|
||||||
if msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage {
|
if msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage {
|
||||||
ret = context.stock_str(StockMessage::AcSetupMsgSubject).strdup()
|
ret = context.stock_str(StockMessage::AcSetupMsgSubject).strdup()
|
||||||
} else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
|
} else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
|
||||||
ret = format!(
|
ret = format!("Chat: {}: {}{}", chat.name, fwd, raw_subject,).strdup();
|
||||||
"Chat: {}: {}{}",
|
|
||||||
chat.name,
|
|
||||||
to_string(fwd),
|
|
||||||
to_string(raw_subject),
|
|
||||||
)
|
|
||||||
.strdup()
|
|
||||||
} else {
|
} else {
|
||||||
ret = dc_mprintf(
|
ret = format!("Chat: {}{}", fwd, raw_subject).strdup();
|
||||||
b"Chat: %s%s\x00" as *const u8 as *const libc::c_char,
|
|
||||||
fwd,
|
|
||||||
raw_subject,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
free(raw_subject as *mut libc::c_void);
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
@@ -1152,13 +1122,12 @@ unsafe fn build_body_file(
|
|||||||
.map(|s| s.strdup())
|
.map(|s| s.strdup())
|
||||||
.unwrap_or_else(|| std::ptr::null_mut());
|
.unwrap_or_else(|| std::ptr::null_mut());
|
||||||
|
|
||||||
let mut filename_to_send = ptr::null_mut();
|
|
||||||
let mut filename_encoded = ptr::null_mut();
|
let mut filename_encoded = ptr::null_mut();
|
||||||
|
|
||||||
if let Some(ref path_filename) = path_filename {
|
if let Some(ref path_filename) = path_filename {
|
||||||
let suffix = dc_get_filesuffix_lc(path_filename);
|
let suffix = dc_get_filesuffix_lc(path_filename);
|
||||||
|
|
||||||
if msg.type_0 == Viewtype::Voice {
|
let filename_to_send = if msg.type_0 == Viewtype::Voice {
|
||||||
let ts = chrono::Utc.timestamp(msg.timestamp_sort as i64, 0);
|
let ts = chrono::Utc.timestamp(msg.timestamp_sort as i64, 0);
|
||||||
|
|
||||||
let suffix = if !suffix.is_null() {
|
let suffix = if !suffix.is_null() {
|
||||||
@@ -1166,37 +1135,42 @@ unsafe fn build_body_file(
|
|||||||
} else {
|
} else {
|
||||||
"dat".into()
|
"dat".into()
|
||||||
};
|
};
|
||||||
let res = ts
|
ts.format(&format!("voice-message_%Y-%m-%d_%H-%M-%S.{}", suffix))
|
||||||
.format(&format!("voice-message_%Y-%m-%d_%H-%M-%S.{}", suffix))
|
.to_string()
|
||||||
.to_string();
|
|
||||||
filename_to_send = res.strdup();
|
|
||||||
} else if msg.type_0 == Viewtype::Audio {
|
} else if msg.type_0 == Viewtype::Audio {
|
||||||
filename_to_send = dc_get_filename(path_filename)
|
Path::new(path_filename)
|
||||||
|
.file_name()
|
||||||
|
.map(|c| c.to_string_lossy().to_string())
|
||||||
|
.unwrap_or_default()
|
||||||
} else if msg.type_0 == Viewtype::Image || msg.type_0 == Viewtype::Gif {
|
} else if msg.type_0 == Viewtype::Image || msg.type_0 == Viewtype::Gif {
|
||||||
if base_name.is_null() {
|
if base_name.is_null() {
|
||||||
base_name = b"image\x00" as *const u8 as *const libc::c_char
|
base_name = b"image\x00" as *const u8 as *const libc::c_char
|
||||||
}
|
}
|
||||||
filename_to_send = dc_mprintf(
|
format!(
|
||||||
b"%s.%s\x00" as *const u8 as *const libc::c_char,
|
"{}.{}",
|
||||||
base_name,
|
as_str(base_name),
|
||||||
if !suffix.is_null() {
|
if !suffix.is_null() {
|
||||||
suffix
|
as_str(suffix)
|
||||||
} else {
|
} else {
|
||||||
b"dat\x00" as *const u8 as *const libc::c_char
|
"dat"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else if msg.type_0 == Viewtype::Video {
|
} else if msg.type_0 == Viewtype::Video {
|
||||||
filename_to_send = dc_mprintf(
|
format!(
|
||||||
b"video.%s\x00" as *const u8 as *const libc::c_char,
|
"video.{}",
|
||||||
if !suffix.is_null() {
|
if !suffix.is_null() {
|
||||||
suffix
|
as_str(suffix)
|
||||||
} else {
|
} else {
|
||||||
b"dat\x00" as *const u8 as *const libc::c_char
|
"dat"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
filename_to_send = dc_get_filename(path_filename)
|
Path::new(path_filename)
|
||||||
}
|
.file_name()
|
||||||
|
.map(|c| c.to_string_lossy().to_string())
|
||||||
|
.unwrap_or_default()
|
||||||
|
};
|
||||||
|
|
||||||
if mimetype.is_null() {
|
if mimetype.is_null() {
|
||||||
if suffix.is_null() {
|
if suffix.is_null() {
|
||||||
mimetype =
|
mimetype =
|
||||||
@@ -1219,13 +1193,13 @@ unsafe fn build_body_file(
|
|||||||
/* create mime part, for Content-Disposition, see RFC 2183.
|
/* create mime part, for Content-Disposition, see RFC 2183.
|
||||||
`Content-Disposition: attachment` seems not to make a difference to `Content-Disposition: inline` at least on tested Thunderbird and Gma'l in 2017.
|
`Content-Disposition: attachment` seems not to make a difference to `Content-Disposition: inline` at least on tested Thunderbird and Gma'l in 2017.
|
||||||
But I've heard about problems with inline and outl'k, so we just use the attachment-type until we run into other problems ... */
|
But I've heard about problems with inline and outl'k, so we just use the attachment-type until we run into other problems ... */
|
||||||
needs_ext = dc_needs_ext_header(as_str(filename_to_send));
|
needs_ext = dc_needs_ext_header(&filename_to_send);
|
||||||
mime_fields = mailmime_fields_new_filename(
|
mime_fields = mailmime_fields_new_filename(
|
||||||
MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int,
|
MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int,
|
||||||
if needs_ext {
|
if needs_ext {
|
||||||
ptr::null_mut()
|
ptr::null_mut()
|
||||||
} else {
|
} else {
|
||||||
dc_strdup(filename_to_send)
|
filename_to_send.strdup()
|
||||||
},
|
},
|
||||||
MAILMIME_MECHANISM_BASE64 as libc::c_int,
|
MAILMIME_MECHANISM_BASE64 as libc::c_int,
|
||||||
);
|
);
|
||||||
@@ -1256,7 +1230,7 @@ unsafe fn build_body_file(
|
|||||||
strdup(
|
strdup(
|
||||||
b"filename*\x00" as *const u8 as *const libc::c_char,
|
b"filename*\x00" as *const u8 as *const libc::c_char,
|
||||||
),
|
),
|
||||||
dc_encode_ext_header(as_str(filename_to_send)).strdup(),
|
dc_encode_ext_header(&filename_to_send).strdup(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if !parm.is_null() {
|
if !parm.is_null() {
|
||||||
@@ -1278,7 +1252,7 @@ unsafe fn build_body_file(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
content = mailmime_content_new_with_str(mimetype);
|
content = mailmime_content_new_with_str(mimetype);
|
||||||
filename_encoded = dc_encode_header_words(filename_to_send);
|
filename_encoded = dc_encode_header_words(&filename_to_send);
|
||||||
clist_insert_after(
|
clist_insert_after(
|
||||||
(*content).ct_parameters,
|
(*content).ct_parameters,
|
||||||
(*(*content).ct_parameters).last,
|
(*(*content).ct_parameters).last,
|
||||||
@@ -1293,13 +1267,12 @@ unsafe fn build_body_file(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
mailmime_set_body_file(mime_sub, dc_strdup(abs_path.as_ptr()));
|
mailmime_set_body_file(mime_sub, dc_strdup(abs_path.as_ptr()));
|
||||||
if !ret_file_name_as_sent.is_null() {
|
if !ret_file_name_as_sent.is_null() {
|
||||||
*ret_file_name_as_sent = dc_strdup(filename_to_send)
|
*ret_file_name_as_sent = filename_to_send.strdup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(mimetype as *mut libc::c_void);
|
free(mimetype as *mut libc::c_void);
|
||||||
free(filename_to_send as *mut libc::c_void);
|
|
||||||
free(filename_encoded as *mut libc::c_void);
|
free(filename_encoded as *mut libc::c_void);
|
||||||
|
|
||||||
mime_sub
|
mime_sub
|
||||||
|
|||||||
@@ -207,18 +207,14 @@ impl<'a> MimeParser<'a> {
|
|||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
if !subj.is_empty() {
|
if !subj.is_empty() {
|
||||||
let subj_c = CString::yolo(subj);
|
|
||||||
for part in self.parts.iter_mut() {
|
for part in self.parts.iter_mut() {
|
||||||
if part.typ == Viewtype::Text {
|
if part.typ == Viewtype::Text {
|
||||||
let msg_c = part.msg.as_ref().unwrap().strdup();
|
let new_txt = format!(
|
||||||
let new_txt: *mut libc::c_char = dc_mprintf(
|
"{} – {}",
|
||||||
b"%s \xe2\x80\x93 %s\x00" as *const u8 as *const libc::c_char,
|
subj,
|
||||||
subj_c.as_ptr(),
|
part.msg.as_ref().expect("missing msg part")
|
||||||
msg_c,
|
|
||||||
);
|
);
|
||||||
free(msg_c.cast());
|
part.msg = Some(new_txt);
|
||||||
part.msg = Some(to_string_lossy(new_txt));
|
|
||||||
free(new_txt.cast());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,7 +307,7 @@ impl<'a> MimeParser<'a> {
|
|||||||
self.parts.iter_mut().rev().find(|part| !part.is_meta)
|
self.parts.iter_mut().rev().find(|part| !part.is_meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the following functions can be used only after a call to dc_mimeparser_parse() */
|
/* the following functions can be used only after a call to parse() */
|
||||||
|
|
||||||
pub fn lookup_field(&self, field_name: &str) -> Option<*mut mailimf_field> {
|
pub fn lookup_field(&self, field_name: &str) -> Option<*mut mailimf_field> {
|
||||||
match self.header.get(field_name) {
|
match self.header.get(field_name) {
|
||||||
@@ -805,10 +801,11 @@ impl<'a> MimeParser<'a> {
|
|||||||
if !(*mime).mm_content_type.is_null()
|
if !(*mime).mm_content_type.is_null()
|
||||||
&& !(*(*mime).mm_content_type).ct_subtype.is_null()
|
&& !(*(*mime).mm_content_type).ct_subtype.is_null()
|
||||||
{
|
{
|
||||||
desired_filename = dc_mprintf(
|
desired_filename = format!(
|
||||||
b"file.%s\x00" as *const u8 as *const libc::c_char,
|
"file.{}",
|
||||||
(*(*mime).mm_content_type).ct_subtype,
|
as_str((*(*mime).mm_content_type).ct_subtype)
|
||||||
);
|
)
|
||||||
|
.strdup();
|
||||||
} else {
|
} else {
|
||||||
ok_to_continue = false;
|
ok_to_continue = false;
|
||||||
}
|
}
|
||||||
@@ -896,44 +893,32 @@ impl<'a> MimeParser<'a> {
|
|||||||
desired_filename: *const libc::c_char,
|
desired_filename: *const libc::c_char,
|
||||||
) {
|
) {
|
||||||
/* create a free file name to use */
|
/* create a free file name to use */
|
||||||
let path_n_filename = dc_get_fine_pathNfilename(
|
let path_filename =
|
||||||
self.context,
|
dc_get_fine_path_filename(self.context, "$BLOBDIR", as_str(desired_filename));
|
||||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
let bytes = std::slice::from_raw_parts(decoded_data as *const u8, decoded_data_bytes);
|
||||||
desired_filename,
|
|
||||||
);
|
|
||||||
if !path_n_filename.is_null() {
|
|
||||||
/* copy data to file */
|
|
||||||
if dc_write_file(
|
|
||||||
self.context,
|
|
||||||
path_n_filename,
|
|
||||||
decoded_data as *const libc::c_void,
|
|
||||||
decoded_data_bytes,
|
|
||||||
) != 0
|
|
||||||
{
|
|
||||||
let mut part = Part::default();
|
|
||||||
part.typ = msg_type;
|
|
||||||
part.mimetype = mime_type;
|
|
||||||
part.bytes = decoded_data_bytes as libc::c_int;
|
|
||||||
part.param.set(Param::File, as_str(path_n_filename));
|
|
||||||
part.param.set(Param::MimeType, raw_mime);
|
|
||||||
|
|
||||||
if mime_type == 80 {
|
/* copy data to file */
|
||||||
assert!(!decoded_data.is_null(), "invalid image data");
|
if dc_write_file(self.context, &path_filename, bytes) {
|
||||||
let data = std::slice::from_raw_parts(
|
let mut part = Part::default();
|
||||||
decoded_data as *const u8,
|
part.typ = msg_type;
|
||||||
decoded_data_bytes as usize,
|
part.mimetype = mime_type;
|
||||||
);
|
part.bytes = decoded_data_bytes as libc::c_int;
|
||||||
|
part.param.set(Param::File, path_filename.to_string_lossy());
|
||||||
|
part.param.set(Param::MimeType, raw_mime);
|
||||||
|
if mime_type == 80 {
|
||||||
|
assert!(!decoded_data.is_null(), "invalid image data");
|
||||||
|
let data = std::slice::from_raw_parts(
|
||||||
|
decoded_data as *const u8,
|
||||||
|
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);
|
||||||
part.param.set_int(Param::Height, height as i32);
|
part.param.set_int(Param::Height, height as i32);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.do_add_single_part(part);
|
|
||||||
}
|
}
|
||||||
|
self.do_add_single_part(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(path_n_filename as *mut libc::c_void);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_add_single_part(&mut self, mut part: Part) {
|
fn do_add_single_part(&mut self, mut part: Part) {
|
||||||
|
|||||||
@@ -308,14 +308,10 @@ unsafe fn add_parts(
|
|||||||
let mut rcvd_timestamp = 0;
|
let mut rcvd_timestamp = 0;
|
||||||
let mut mime_in_reply_to = std::ptr::null_mut();
|
let mut mime_in_reply_to = std::ptr::null_mut();
|
||||||
let mut mime_references = std::ptr::null_mut();
|
let mut mime_references = std::ptr::null_mut();
|
||||||
let mut txt_raw = std::ptr::null_mut();
|
|
||||||
|
|
||||||
let cleanup = |mime_in_reply_to: *mut libc::c_char,
|
let cleanup = |mime_in_reply_to: *mut libc::c_char, mime_references: *mut libc::c_char| {
|
||||||
mime_references: *mut libc::c_char,
|
|
||||||
txt_raw: *mut libc::c_char| {
|
|
||||||
free(mime_in_reply_to.cast());
|
free(mime_in_reply_to.cast());
|
||||||
free(mime_references.cast());
|
free(mime_references.cast());
|
||||||
free(txt_raw.cast());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// collect the rest information, CC: is added to the to-list, BCC: is ignored
|
// collect the rest information, CC: is added to the to-list, BCC: is ignored
|
||||||
@@ -354,7 +350,7 @@ unsafe fn add_parts(
|
|||||||
if rfc724_mid.is_null() {
|
if rfc724_mid.is_null() {
|
||||||
rfc724_mid = dc_create_incoming_rfc724_mid(*sent_timestamp, *from_id, to_ids);
|
rfc724_mid = dc_create_incoming_rfc724_mid(*sent_timestamp, *from_id, to_ids);
|
||||||
if rfc724_mid.is_null() {
|
if rfc724_mid.is_null() {
|
||||||
cleanup(mime_in_reply_to, mime_references, txt_raw);
|
cleanup(mime_in_reply_to, mime_references);
|
||||||
bail!("Cannot create Message-ID");
|
bail!("Cannot create Message-ID");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,7 +372,7 @@ unsafe fn add_parts(
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(old_server_folder.cast());
|
free(old_server_folder.cast());
|
||||||
cleanup(mime_in_reply_to, mime_references, txt_raw);
|
cleanup(mime_in_reply_to, mime_references);
|
||||||
bail!("Message already in DB");
|
bail!("Message already in DB");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,6 +627,8 @@ unsafe fn add_parts(
|
|||||||
// into only one message; mails sent by other clients may result in several messages
|
// into only one message; mails sent by other clients may result in several messages
|
||||||
// (eg. one per attachment))
|
// (eg. one per attachment))
|
||||||
let icnt = mime_parser.parts.len();
|
let icnt = mime_parser.parts.len();
|
||||||
|
let mut txt_raw = None;
|
||||||
|
|
||||||
let is_ok = context
|
let is_ok = context
|
||||||
.sql
|
.sql
|
||||||
.prepare(
|
.prepare(
|
||||||
@@ -658,20 +656,13 @@ unsafe fn add_parts(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if part.typ == Viewtype::Text {
|
if part.typ == Viewtype::Text {
|
||||||
let msg_raw =
|
let msg_raw = part.msg_raw.as_ref().cloned().unwrap_or_default();
|
||||||
CString::yolo(part.msg_raw.as_ref().cloned().unwrap_or_default());
|
let subject = mime_parser
|
||||||
let subject_c = CString::yolo(
|
.subject
|
||||||
mime_parser
|
.as_ref()
|
||||||
.subject
|
.map(|s| s.to_string())
|
||||||
.as_ref()
|
.unwrap_or("".into());
|
||||||
.map(|s| s.to_string())
|
txt_raw = Some(format!("{}\n\n{}", subject, msg_raw));
|
||||||
.unwrap_or("".into()),
|
|
||||||
);
|
|
||||||
txt_raw = dc_mprintf(
|
|
||||||
b"%s\n\n%s\x00" as *const u8 as *const libc::c_char,
|
|
||||||
subject_c.as_ptr(),
|
|
||||||
msg_raw.as_ptr(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if mime_parser.is_system_message != SystemMessage::Unknown {
|
if mime_parser.is_system_message != SystemMessage::Unknown {
|
||||||
part.param
|
part.param
|
||||||
@@ -693,11 +684,7 @@ unsafe fn add_parts(
|
|||||||
msgrmsg,
|
msgrmsg,
|
||||||
part.msg.as_ref().map_or("", String::as_str),
|
part.msg.as_ref().map_or("", String::as_str),
|
||||||
// txt_raw might contain invalid utf8
|
// txt_raw might contain invalid utf8
|
||||||
if !txt_raw.is_null() {
|
txt_raw.unwrap_or_default(),
|
||||||
to_string_lossy(txt_raw)
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
},
|
|
||||||
part.param.to_string(),
|
part.param.to_string(),
|
||||||
part.bytes,
|
part.bytes,
|
||||||
*hidden,
|
*hidden,
|
||||||
@@ -716,8 +703,7 @@ unsafe fn add_parts(
|
|||||||
to_string(mime_references),
|
to_string(mime_references),
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
free(txt_raw as *mut libc::c_void);
|
txt_raw = None;
|
||||||
txt_raw = ptr::null_mut();
|
|
||||||
*insert_msg_id = sql::get_rowid_with_conn(
|
*insert_msg_id = sql::get_rowid_with_conn(
|
||||||
context,
|
context,
|
||||||
conn,
|
conn,
|
||||||
@@ -734,7 +720,7 @@ unsafe fn add_parts(
|
|||||||
|
|
||||||
if !is_ok {
|
if !is_ok {
|
||||||
// i/o error - there is nothing more we can do - in other cases, we try to write at least an empty record
|
// i/o error - there is nothing more we can do - in other cases, we try to write at least an empty record
|
||||||
cleanup(mime_in_reply_to, mime_references, txt_raw);
|
cleanup(mime_in_reply_to, mime_references);
|
||||||
bail!("Cannot write DB.");
|
bail!("Cannot write DB.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -757,7 +743,7 @@ unsafe fn add_parts(
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.do_heuristics_moves(server_folder.as_ref(), *insert_msg_id);
|
context.do_heuristics_moves(server_folder.as_ref(), *insert_msg_id);
|
||||||
cleanup(mime_in_reply_to, mime_references, txt_raw);
|
cleanup(mime_in_reply_to, mime_references);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,15 @@ use crate::x::*;
|
|||||||
* @return Returns the encoded string which must be free()'d when no longed needed.
|
* @return Returns the encoded string which must be free()'d when no longed needed.
|
||||||
* On errors, NULL is returned.
|
* On errors, NULL is returned.
|
||||||
*/
|
*/
|
||||||
pub unsafe fn dc_encode_header_words(to_encode: *const libc::c_char) -> *mut libc::c_char {
|
pub unsafe fn dc_encode_header_words(to_encode_r: impl AsRef<str>) -> *mut libc::c_char {
|
||||||
|
let to_encode =
|
||||||
|
CString::new(to_encode_r.as_ref().as_bytes()).expect("invalid cstring to_encode");
|
||||||
|
|
||||||
let mut ok_to_continue = true;
|
let mut ok_to_continue = true;
|
||||||
let mut ret_str: *mut libc::c_char = ptr::null_mut();
|
let mut ret_str: *mut libc::c_char = ptr::null_mut();
|
||||||
let mut cur: *const libc::c_char = to_encode;
|
let mut cur: *const libc::c_char = to_encode.as_ptr();
|
||||||
let mmapstr: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
let mmapstr: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
||||||
if to_encode.is_null() || mmapstr.is_null() {
|
if mmapstr.is_null() {
|
||||||
ok_to_continue = false;
|
ok_to_continue = false;
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
@@ -355,12 +358,13 @@ mod tests {
|
|||||||
assert_eq!(CStr::from_ptr(buf1).to_str().unwrap(), "just ascii test");
|
assert_eq!(CStr::from_ptr(buf1).to_str().unwrap(), "just ascii test");
|
||||||
free(buf1 as *mut libc::c_void);
|
free(buf1 as *mut libc::c_void);
|
||||||
|
|
||||||
buf1 = dc_encode_header_words(b"abcdef\x00" as *const u8 as *const libc::c_char);
|
buf1 = dc_encode_header_words("abcdef");
|
||||||
assert_eq!(CStr::from_ptr(buf1).to_str().unwrap(), "abcdef");
|
assert_eq!(CStr::from_ptr(buf1).to_str().unwrap(), "abcdef");
|
||||||
free(buf1 as *mut libc::c_void);
|
free(buf1 as *mut libc::c_void);
|
||||||
|
|
||||||
buf1 = dc_encode_header_words(
|
buf1 = dc_encode_header_words(
|
||||||
b"test\xc3\xa4\xc3\xb6\xc3\xbc.txt\x00" as *const u8 as *const libc::c_char,
|
std::string::String::from_utf8(b"test\xc3\xa4\xc3\xb6\xc3\xbc.txt".to_vec())
|
||||||
|
.unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
strncmp(buf1, b"=?utf-8\x00" as *const u8 as *const libc::c_char, 7),
|
strncmp(buf1, b"=?utf-8\x00" as *const u8 as *const libc::c_char, 7),
|
||||||
|
|||||||
280
src/dc_tools.rs
280
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);
|
||||||
|
}
|
||||||
|
folder
|
||||||
|
};
|
||||||
|
|
||||||
|
if !dc_file_exist(context, &ret) {
|
||||||
|
// fine filename found
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
if !dc_file_exist(context, as_path(ret)) {
|
|
||||||
/* fine filename found */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
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)))
|
|
||||||
{
|
|
||||||
*path = to_string(blobdir_path);
|
|
||||||
blobdir_path = ptr::null_mut();
|
|
||||||
dc_make_rel_path(context, path);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unsafe {
|
let blobdir_path = dc_get_fine_path_filename(context, "$BLOBDIR", &path);
|
||||||
free(blobdir_path.cast());
|
if dc_copy_file(context, &path, &blobdir_path) {
|
||||||
free(filename.cast());
|
*path = blobdir_path.to_string_lossy().to_string();
|
||||||
|
dc_make_rel_path(context, path);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
success
|
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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,
|
||||||
|
(*mimefactory.out).len,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
if pathNfilename.is_null() {
|
if !dc_write_file(context, &path_filename, bytes) {
|
||||||
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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
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());
|
||||||
|
|||||||
7
src/x.rs
7
src/x.rs
@@ -33,13 +33,6 @@ pub fn strndup(s: *const libc::c_char, n: libc::c_ulong) -> *mut libc::c_char {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
pub fn clock() -> libc::clock_t;
|
|
||||||
|
|
||||||
// -- DC Methods
|
|
||||||
pub fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) unsafe fn strcasecmp(s1: *const libc::c_char, s2: *const libc::c_char) -> libc::c_int {
|
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)
|
let s1 = std::ffi::CStr::from_ptr(s1)
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
|
|||||||
@@ -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