mirror of
https://github.com/chatmail/core.git
synced 2026-04-05 23:22:11 +03:00
440 lines
13 KiB
Rust
440 lines
13 KiB
Rust
use crate::dc_tools::*;
|
|
use crate::types::*;
|
|
use crate::x::*;
|
|
|
|
/// for msgs and jobs
|
|
pub const DC_PARAM_FILE: char = 'f'; // string
|
|
/// for msgs
|
|
pub const DC_PARAM_WIDTH: char = 'w'; // int
|
|
/// for msgs
|
|
pub const DC_PARAM_HEIGHT: char = 'h'; // int
|
|
/// for msgs
|
|
pub const DC_PARAM_DURATION: char = 'd'; // int
|
|
/// for msgs
|
|
pub const DC_PARAM_MIMETYPE: char = 'm'; // string
|
|
/// for msgs: incoming: message is encryoted, outgoing: guarantee E2EE or the message is not send
|
|
pub const DC_PARAM_GUARANTEE_E2EE: char = 'c'; // int (bool?)
|
|
/// for msgs: decrypted with validation errors or without mutual set, if neither 'c' nor 'e' are preset, the messages is only transport encrypted
|
|
pub const DC_PARAM_ERRONEOUS_E2EE: char = 'e'; // int
|
|
/// for msgs: force unencrypted message, either DC_FP_ADD_AUTOCRYPT_HEADER (1), DC_FP_NO_AUTOCRYPT_HEADER (2) or 0
|
|
pub const DC_PARAM_FORCE_PLAINTEXT: char = 'u'; // int (bool?)
|
|
/// for msgs: an incoming message which requests a MDN (aka read receipt)
|
|
pub const DC_PARAM_WANTS_MDN: char = 'r'; // int (bool?)
|
|
/// for msgs
|
|
pub const DC_PARAM_FORWARDED: char = 'a'; // int (bool?)
|
|
/// for msgs
|
|
pub const DC_PARAM_CMD: char = 'S'; // int
|
|
/// for msgs
|
|
pub const DC_PARAM_CMD_ARG: char = 'E'; // string
|
|
/// for msgs
|
|
pub const DC_PARAM_CMD_ARG2: char = 'F'; // string
|
|
/// for msgs
|
|
pub const DC_PARAM_CMD_ARG3: char = 'G'; // string
|
|
/// for msgs
|
|
pub const DC_PARAM_CMD_ARG4: char = 'H'; // string
|
|
/// for msgs
|
|
pub const DC_PARAM_ERROR: char = 'L'; // string
|
|
/// for msgs in PREPARING: space-separated list of message IDs of forwarded copies
|
|
pub const DC_PARAM_PREP_FORWARDS: char = 'P'; // string
|
|
/// for msgs
|
|
pub const DC_PARAM_SET_LATITUDE: char = 'l'; // float
|
|
/// for msgs
|
|
pub const DC_PARAM_SET_LONGITUDE: char = 'n'; // float
|
|
|
|
/// for jobs
|
|
pub const DC_PARAM_SERVER_FOLDER: char = 'Z'; // string
|
|
/// for jobs
|
|
pub const DC_PARAM_SERVER_UID: char = 'z'; // int
|
|
/// for jobs
|
|
pub const DC_PARAM_ALSO_MOVE: char = 'M'; // int (bool?)
|
|
/// for jobs: space-separated list of message recipients
|
|
pub const DC_PARAM_RECIPIENTS: char = 'R'; // stringap
|
|
/// for groups
|
|
pub const DC_PARAM_UNPROMOTED: char = 'U'; // int (bool?)
|
|
/// for groups and contacts
|
|
pub const DC_PARAM_PROFILE_IMAGE: char = 'i'; // string (bytes?)
|
|
/// for chats
|
|
pub const DC_PARAM_SELFTALK: char = 'K';
|
|
|
|
// missing: 's', 'x', 'g'
|
|
|
|
// values for DC_PARAM_FORCE_PLAINTEXT
|
|
pub const DC_FP_ADD_AUTOCRYPT_HEADER: u8 = 1;
|
|
pub const DC_FP_NO_AUTOCRYPT_HEADER: u8 = 2;
|
|
|
|
/// An object for handling key=value parameter lists; for the key, currently only
|
|
/// a single character is allowed.
|
|
///
|
|
/// The object is used eg. by Chat or dc_msg_t, for readable parameter names,
|
|
/// these classes define some DC_PARAM_* constantats.
|
|
///
|
|
/// Only for library-internal use.
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct dc_param_t {
|
|
pub packed: *mut libc::c_char,
|
|
}
|
|
|
|
// values for DC_PARAM_FORCE_PLAINTEXT
|
|
/* user functions */
|
|
pub unsafe fn dc_param_exists(param: *mut dc_param_t, key: libc::c_int) -> libc::c_int {
|
|
let mut p2: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
if param.is_null() || key == 0i32 {
|
|
return 0i32;
|
|
}
|
|
return if !find_param((*param).packed, key, &mut p2).is_null() {
|
|
1i32
|
|
} else {
|
|
0i32
|
|
};
|
|
}
|
|
|
|
unsafe extern "C" fn find_param(
|
|
haystack: *mut libc::c_char,
|
|
key: libc::c_int,
|
|
ret_p2: *mut *mut libc::c_char,
|
|
) -> *mut libc::c_char {
|
|
let mut p1: *mut libc::c_char;
|
|
let mut p2: *mut libc::c_char;
|
|
p1 = haystack;
|
|
loop {
|
|
if p1.is_null() || *p1 as libc::c_int == 0i32 {
|
|
return 0 as *mut libc::c_char;
|
|
} else {
|
|
if *p1 as libc::c_int == key && *p1.offset(1isize) as libc::c_int == '=' as i32 {
|
|
break;
|
|
}
|
|
p1 = strchr(p1, '\n' as i32);
|
|
if !p1.is_null() {
|
|
p1 = p1.offset(1isize)
|
|
}
|
|
}
|
|
}
|
|
p2 = strchr(p1, '\n' as i32);
|
|
if p2.is_null() {
|
|
p2 = &mut *p1.offset(strlen(p1) as isize) as *mut libc::c_char
|
|
}
|
|
*ret_p2 = p2;
|
|
|
|
p1
|
|
}
|
|
|
|
/* the value may be an empty string, "def" is returned only if the value unset. The result must be free()'d in any case. */
|
|
pub unsafe fn dc_param_get(
|
|
param: *const dc_param_t,
|
|
key: libc::c_int,
|
|
def: *const libc::c_char,
|
|
) -> *mut libc::c_char {
|
|
let mut p1: *mut libc::c_char;
|
|
let mut p2: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let bak: libc::c_char;
|
|
let ret: *mut libc::c_char;
|
|
if param.is_null() || key == 0i32 {
|
|
return if !def.is_null() {
|
|
dc_strdup(def)
|
|
} else {
|
|
0 as *mut libc::c_char
|
|
};
|
|
}
|
|
p1 = find_param((*param).packed, key, &mut p2);
|
|
if p1.is_null() {
|
|
return if !def.is_null() {
|
|
dc_strdup(def)
|
|
} else {
|
|
0 as *mut libc::c_char
|
|
};
|
|
}
|
|
p1 = p1.offset(2isize);
|
|
bak = *p2;
|
|
*p2 = 0i32 as libc::c_char;
|
|
ret = dc_strdup(p1);
|
|
dc_rtrim(ret);
|
|
*p2 = bak;
|
|
|
|
ret
|
|
}
|
|
|
|
pub unsafe fn dc_param_get_int(
|
|
param: *const dc_param_t,
|
|
key: libc::c_int,
|
|
def: int32_t,
|
|
) -> int32_t {
|
|
if param.is_null() || key == 0i32 {
|
|
return def;
|
|
}
|
|
let s = dc_param_get(param, key, 0 as *const libc::c_char);
|
|
if s.is_null() {
|
|
return def;
|
|
}
|
|
let ret = as_str(s).parse().unwrap_or_default();
|
|
free(s as *mut libc::c_void);
|
|
|
|
ret
|
|
}
|
|
|
|
/**
|
|
* Get value of a parameter.
|
|
*
|
|
* @memberof dc_param_t
|
|
* @param param Parameter object to query.
|
|
* @param key Key of the parameter to get, one of the DC_PARAM_* constants.
|
|
* @param def Value to return if the parameter is not set.
|
|
* @return The stored value or the default value.
|
|
*/
|
|
pub unsafe fn dc_param_get_float(
|
|
param: *const dc_param_t,
|
|
key: libc::c_int,
|
|
def: libc::c_double,
|
|
) -> libc::c_double {
|
|
if param.is_null() || key == 0 {
|
|
return def;
|
|
}
|
|
|
|
let str = dc_param_get(param, key, std::ptr::null());
|
|
if str.is_null() {
|
|
return def;
|
|
}
|
|
|
|
let ret = dc_atof(str) as libc::c_double;
|
|
free(str as *mut libc::c_void);
|
|
|
|
ret
|
|
}
|
|
|
|
pub unsafe fn dc_param_set(
|
|
mut param: *mut dc_param_t,
|
|
key: libc::c_int,
|
|
value: *const libc::c_char,
|
|
) {
|
|
let mut old1: *mut libc::c_char;
|
|
let mut old2: *mut libc::c_char;
|
|
let new1: *mut libc::c_char;
|
|
if param.is_null() || key == 0i32 {
|
|
return;
|
|
}
|
|
old1 = (*param).packed;
|
|
old2 = 0 as *mut libc::c_char;
|
|
if !old1.is_null() {
|
|
let p1: *mut libc::c_char;
|
|
let mut p2: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
p1 = find_param(old1, key, &mut p2);
|
|
if !p1.is_null() {
|
|
*p1 = 0i32 as libc::c_char;
|
|
old2 = p2
|
|
} else if value.is_null() {
|
|
return;
|
|
}
|
|
}
|
|
dc_rtrim(old1);
|
|
dc_ltrim(old2);
|
|
if !old1.is_null() && *old1.offset(0isize) as libc::c_int == 0i32 {
|
|
old1 = 0 as *mut libc::c_char
|
|
}
|
|
if !old2.is_null() && *old2.offset(0isize) as libc::c_int == 0i32 {
|
|
old2 = 0 as *mut libc::c_char
|
|
}
|
|
if !value.is_null() {
|
|
new1 = dc_mprintf(
|
|
b"%s%s%c=%s%s%s\x00" as *const u8 as *const libc::c_char,
|
|
if !old1.is_null() {
|
|
old1
|
|
} else {
|
|
b"\x00" as *const u8 as *const libc::c_char
|
|
},
|
|
if !old1.is_null() {
|
|
b"\n\x00" as *const u8 as *const libc::c_char
|
|
} else {
|
|
b"\x00" as *const u8 as *const libc::c_char
|
|
},
|
|
key,
|
|
value,
|
|
if !old2.is_null() {
|
|
b"\n\x00" as *const u8 as *const libc::c_char
|
|
} else {
|
|
b"\x00" as *const u8 as *const libc::c_char
|
|
},
|
|
if !old2.is_null() {
|
|
old2
|
|
} else {
|
|
b"\x00" as *const u8 as *const libc::c_char
|
|
},
|
|
)
|
|
} else {
|
|
new1 = dc_mprintf(
|
|
b"%s%s%s\x00" as *const u8 as *const libc::c_char,
|
|
if !old1.is_null() {
|
|
old1
|
|
} else {
|
|
b"\x00" as *const u8 as *const libc::c_char
|
|
},
|
|
if !old1.is_null() && !old2.is_null() {
|
|
b"\n\x00" as *const u8 as *const libc::c_char
|
|
} else {
|
|
b"\x00" as *const u8 as *const libc::c_char
|
|
},
|
|
if !old2.is_null() {
|
|
old2
|
|
} else {
|
|
b"\x00" as *const u8 as *const libc::c_char
|
|
},
|
|
)
|
|
}
|
|
free((*param).packed as *mut libc::c_void);
|
|
(*param).packed = new1;
|
|
}
|
|
|
|
pub unsafe fn dc_param_set_int(param: *mut dc_param_t, key: libc::c_int, value: int32_t) {
|
|
if param.is_null() || key == 0i32 {
|
|
return;
|
|
}
|
|
let value_str: *mut libc::c_char = dc_mprintf(
|
|
b"%i\x00" as *const u8 as *const libc::c_char,
|
|
value as libc::c_int,
|
|
);
|
|
if value_str.is_null() {
|
|
return;
|
|
}
|
|
dc_param_set(param, key, value_str);
|
|
free(value_str as *mut libc::c_void);
|
|
}
|
|
|
|
/* library-private */
|
|
pub unsafe fn dc_param_new() -> *mut dc_param_t {
|
|
let mut param: *mut dc_param_t;
|
|
param = calloc(1, ::std::mem::size_of::<dc_param_t>()) as *mut dc_param_t;
|
|
assert!(!param.is_null());
|
|
(*param).packed = calloc(1, 1) as *mut libc::c_char;
|
|
|
|
param
|
|
}
|
|
|
|
pub unsafe fn dc_param_empty(param: *mut dc_param_t) {
|
|
if param.is_null() {
|
|
return;
|
|
}
|
|
*(*param).packed.offset(0isize) = 0i32 as libc::c_char;
|
|
}
|
|
|
|
pub unsafe fn dc_param_unref(param: *mut dc_param_t) {
|
|
if param.is_null() {
|
|
return;
|
|
}
|
|
dc_param_empty(param);
|
|
free((*param).packed as *mut libc::c_void);
|
|
free(param as *mut libc::c_void);
|
|
}
|
|
|
|
pub unsafe fn dc_param_set_packed(mut param: *mut dc_param_t, packed: *const libc::c_char) {
|
|
if param.is_null() {
|
|
return;
|
|
}
|
|
dc_param_empty(param);
|
|
if !packed.is_null() {
|
|
free((*param).packed as *mut libc::c_void);
|
|
(*param).packed = dc_strdup(packed)
|
|
};
|
|
}
|
|
|
|
pub unsafe fn dc_param_set_urlencoded(mut param: *mut dc_param_t, urlencoded: *const libc::c_char) {
|
|
if param.is_null() {
|
|
return;
|
|
}
|
|
dc_param_empty(param);
|
|
if !urlencoded.is_null() {
|
|
free((*param).packed as *mut libc::c_void);
|
|
(*param).packed = dc_strdup(urlencoded);
|
|
dc_str_replace(
|
|
&mut (*param).packed,
|
|
b"&\x00" as *const u8 as *const libc::c_char,
|
|
b"\n\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Set parameter to a float.
|
|
*
|
|
* @memberof dc_param_t
|
|
* @param param Parameter object to modify.
|
|
* @param key Key of the parameter to modify, one of the DC_PARAM_* constants.
|
|
* @param value Value to store for key.
|
|
* @return None.
|
|
*/
|
|
pub unsafe fn dc_param_set_float(param: *mut dc_param_t, key: libc::c_int, value: libc::c_double) {
|
|
if param.is_null() || key == 0 {
|
|
return;
|
|
}
|
|
|
|
let value_str = dc_ftoa(value);
|
|
if value_str.is_null() {
|
|
return;
|
|
}
|
|
dc_param_set(param, key, value_str);
|
|
free(value_str as *mut libc::c_void);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use std::ffi::CStr;
|
|
|
|
#[test]
|
|
fn test_dc_param() {
|
|
unsafe {
|
|
let p1: *mut dc_param_t = dc_param_new();
|
|
dc_param_set_packed(
|
|
p1,
|
|
b"\r\n\r\na=1\nb=2\n\nc = 3 \x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
|
|
assert_eq!(dc_param_get_int(p1, 'a' as i32, 0), 1);
|
|
assert_eq!(dc_param_get_int(p1, 'b' as i32, 0), 2);
|
|
assert_eq!(dc_param_get_int(p1, 'c' as i32, 0), 0);
|
|
assert_eq!(dc_param_exists(p1, 'c' as i32), 0);
|
|
|
|
dc_param_set_int(p1, 'd' as i32, 4i32);
|
|
|
|
assert_eq!(dc_param_get_int(p1, 'd' as i32, 0), 4);
|
|
|
|
dc_param_empty(p1);
|
|
dc_param_set(
|
|
p1,
|
|
'a' as i32,
|
|
b"foo\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
dc_param_set_int(p1, 'b' as i32, 2i32);
|
|
dc_param_set(p1, 'c' as i32, 0 as *const libc::c_char);
|
|
dc_param_set_int(p1, 'd' as i32, 4i32);
|
|
|
|
assert_eq!(
|
|
CStr::from_ptr((*p1).packed as *const libc::c_char)
|
|
.to_str()
|
|
.unwrap(),
|
|
"a=foo\nb=2\nd=4"
|
|
);
|
|
|
|
dc_param_set(p1, 'b' as i32, 0 as *const libc::c_char);
|
|
|
|
assert_eq!(
|
|
CStr::from_ptr((*p1).packed as *const libc::c_char)
|
|
.to_str()
|
|
.unwrap(),
|
|
"a=foo\nd=4",
|
|
);
|
|
|
|
dc_param_set(p1, 'a' as i32, 0 as *const libc::c_char);
|
|
dc_param_set(p1, 'd' as i32, 0 as *const libc::c_char);
|
|
|
|
assert_eq!(
|
|
CStr::from_ptr((*p1).packed as *const libc::c_char)
|
|
.to_str()
|
|
.unwrap(),
|
|
"",
|
|
);
|
|
|
|
dc_param_unref(p1);
|
|
}
|
|
}
|
|
|
|
}
|