mirror of
https://github.com/chatmail/core.git
synced 2026-05-02 12:56:30 +03:00
Make stock strings rusty
This converts the stock strings API to be more safe-rust style. The API is kept roughly the same for now but moved to methods on the context.
This commit is contained in:
committed by
Floris Bruynooghe
parent
44b8629811
commit
4902310138
@@ -4,9 +4,9 @@ use strum_macros::{AsRefStr, Display, EnumIter, EnumProperty, EnumString};
|
||||
use crate::constants::DC_VERSION_STR;
|
||||
use crate::context::Context;
|
||||
use crate::dc_job::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::Error;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::x::*;
|
||||
|
||||
/// The available configuration keys.
|
||||
@@ -94,12 +94,7 @@ impl Context {
|
||||
|
||||
// Default values
|
||||
match key {
|
||||
Config::Selfstatus => {
|
||||
let s = unsafe { dc_stock_str(self, 13) };
|
||||
let res = to_string(s);
|
||||
unsafe { free(s as *mut _) };
|
||||
Some(res)
|
||||
}
|
||||
Config::Selfstatus => Some(self.stock_str(StockMessage::StatusLine).into_owned()),
|
||||
_ => key.get_str("default").map(|s| s.to_string()),
|
||||
}
|
||||
}
|
||||
@@ -129,15 +124,14 @@ impl Context {
|
||||
ret
|
||||
}
|
||||
Config::Selfstatus => {
|
||||
let def = unsafe { dc_stock_str(self, 13) };
|
||||
let val = if value.is_none() || value.unwrap() == as_str(def) {
|
||||
let def = self.stock_str(StockMessage::StatusLine);
|
||||
let val = if value.is_none() || value.unwrap() == def {
|
||||
None
|
||||
} else {
|
||||
value
|
||||
};
|
||||
|
||||
let ret = self.sql.set_config(self, key, val);
|
||||
unsafe { free(def as *mut libc::c_void) };
|
||||
ret
|
||||
}
|
||||
_ => self.sql.set_config(self, key, value),
|
||||
|
||||
111
src/dc_chat.rs
111
src/dc_chat.rs
@@ -1,3 +1,5 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_array::*;
|
||||
@@ -6,9 +8,9 @@ use crate::dc_contact::*;
|
||||
use crate::dc_job::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_param::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::sql::{self, Sql};
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -167,27 +169,24 @@ pub fn dc_chat_load_from_db(chat: *mut Chat, chat_id: u32) -> bool {
|
||||
match c.id {
|
||||
1 => unsafe {
|
||||
free((*chat).name as *mut libc::c_void);
|
||||
(*chat).name = dc_stock_str((*chat).context, 8);
|
||||
(*chat).name = to_cstring((*chat).context.stock_str(StockMessage::DeadDrop));
|
||||
},
|
||||
6 => unsafe {
|
||||
free((*chat).name as *mut libc::c_void);
|
||||
let tempname: *mut libc::c_char = dc_stock_str((*chat).context, 40);
|
||||
(*chat).name = dc_mprintf(
|
||||
b"%s (%i)\x00" as *const u8 as *const libc::c_char,
|
||||
tempname,
|
||||
dc_get_archived_cnt((*chat).context),
|
||||
);
|
||||
free(tempname as *mut libc::c_void);
|
||||
let tempname = (*chat).context.stock_str(StockMessage::ArchivedChats);
|
||||
let cnt = dc_get_archived_cnt((*chat).context);
|
||||
(*chat).name = to_cstring(format!("{} ({})", tempname, cnt));
|
||||
},
|
||||
5 => unsafe {
|
||||
free((*chat).name as *mut libc::c_void);
|
||||
(*chat).name = dc_stock_str((*chat).context, 41);
|
||||
(*chat).name = to_cstring((*chat).context.stock_str(StockMessage::StarredMsgs));
|
||||
},
|
||||
_ => {
|
||||
if 0 != unsafe { dc_param_exists((*chat).param, DC_PARAM_SELFTALK as i32) } {
|
||||
unsafe {
|
||||
free((*chat).name as *mut libc::c_void);
|
||||
(*chat).name = dc_stock_str((*chat).context, 2);
|
||||
(*chat).name =
|
||||
to_cstring((*chat).context.stock_str(StockMessage::SelfMsg));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1498,10 +1497,10 @@ pub unsafe fn dc_create_group_chat(
|
||||
if chat_name.is_null() || *chat_name.offset(0) as libc::c_int == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let draft_txt = dc_stock_str_repl_string(context, 14, chat_name);
|
||||
let draft_txt =
|
||||
CString::new(context.stock_string_repl_str(StockMessage::NewGroupDraft, as_str(chat_name)))
|
||||
.unwrap();
|
||||
let grpid = as_str(dc_create_id());
|
||||
|
||||
if sql::execute(
|
||||
context,
|
||||
&context.sql,
|
||||
@@ -1518,15 +1517,12 @@ pub unsafe fn dc_create_group_chat(
|
||||
if chat_id != 0 {
|
||||
if 0 != dc_add_to_chat_contacts_table(context, chat_id, 1) {
|
||||
let draft_msg = dc_msg_new(context, 10);
|
||||
dc_msg_set_text(draft_msg, draft_txt);
|
||||
dc_msg_set_text(draft_msg, draft_txt.as_ptr());
|
||||
set_draft_raw(context, chat_id, draft_msg);
|
||||
dc_msg_unref(draft_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(draft_txt as *mut libc::c_void);
|
||||
|
||||
if 0 != chat_id {
|
||||
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
|
||||
}
|
||||
@@ -1633,13 +1629,12 @@ pub unsafe fn dc_add_contact_to_chat_ex(
|
||||
if OK_TO_CONTINUE {
|
||||
if dc_param_get_int((*chat).param, DC_PARAM_UNPROMOTED as i32, 0) == 0 {
|
||||
(*msg).type_0 = DC_MSG_TEXT;
|
||||
(*msg).text = dc_stock_system_msg(
|
||||
context,
|
||||
17,
|
||||
(*contact).addr,
|
||||
0 as *const libc::c_char,
|
||||
1 as uint32_t,
|
||||
);
|
||||
(*msg).text = to_cstring(context.stock_system_msg(
|
||||
StockMessage::MsgAddMember,
|
||||
as_str((*contact).addr),
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as uint32_t,
|
||||
));
|
||||
dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 4);
|
||||
dc_param_set((*msg).param, DC_PARAM_CMD_ARG as i32, (*contact).addr);
|
||||
dc_param_set_int((*msg).param, DC_PARAM_CMD_ARG2 as i32, flags);
|
||||
@@ -1745,21 +1740,19 @@ pub unsafe fn dc_remove_contact_from_chat(
|
||||
(*msg).type_0 = DC_MSG_TEXT;
|
||||
if (*contact).id == 1 as libc::c_uint {
|
||||
dc_set_group_explicitly_left(context, (*chat).grpid);
|
||||
(*msg).text = dc_stock_system_msg(
|
||||
context,
|
||||
19,
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
1 as uint32_t,
|
||||
)
|
||||
(*msg).text = to_cstring(context.stock_system_msg(
|
||||
StockMessage::MsgGroupLeft,
|
||||
"",
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
} else {
|
||||
(*msg).text = dc_stock_system_msg(
|
||||
context,
|
||||
18,
|
||||
(*contact).addr,
|
||||
0 as *const libc::c_char,
|
||||
1 as uint32_t,
|
||||
)
|
||||
(*msg).text = to_cstring(context.stock_system_msg(
|
||||
StockMessage::MsgDelMember,
|
||||
as_str((*contact).addr),
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
}
|
||||
dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 5);
|
||||
dc_param_set((*msg).param, DC_PARAM_CMD_ARG as i32, (*contact).addr);
|
||||
@@ -1858,14 +1851,13 @@ pub unsafe fn dc_set_chat_name(
|
||||
{
|
||||
if dc_param_get_int((*chat).param, DC_PARAM_UNPROMOTED as i32, 0i32) == 0i32 {
|
||||
(*msg).type_0 = DC_MSG_TEXT;
|
||||
(*msg).text = dc_stock_system_msg(
|
||||
context,
|
||||
15i32,
|
||||
(*chat).name,
|
||||
new_name,
|
||||
1i32 as uint32_t,
|
||||
);
|
||||
dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 2i32);
|
||||
(*msg).text = to_cstring(context.stock_system_msg(
|
||||
StockMessage::MsgGrpName,
|
||||
as_str((*chat).name),
|
||||
as_str(new_name),
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 2);
|
||||
dc_param_set((*msg).param, DC_PARAM_CMD_ARG as i32, (*chat).name);
|
||||
(*msg).id = dc_send_msg(context, chat_id, msg);
|
||||
context.call_cb(
|
||||
@@ -1927,17 +1919,16 @@ pub unsafe fn dc_set_chat_profile_image(
|
||||
dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 3i32);
|
||||
dc_param_set((*msg).param, DC_PARAM_CMD_ARG as i32, new_image_rel);
|
||||
(*msg).type_0 = DC_MSG_TEXT;
|
||||
(*msg).text = dc_stock_system_msg(
|
||||
context,
|
||||
(*msg).text = to_cstring(context.stock_system_msg(
|
||||
if !new_image_rel.is_null() {
|
||||
16i32
|
||||
StockMessage::MsgGrpImgChanged
|
||||
} else {
|
||||
33i32
|
||||
StockMessage::MsgGrpImgDeleted
|
||||
},
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
1i32 as uint32_t,
|
||||
);
|
||||
"",
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as uint32_t,
|
||||
));
|
||||
(*msg).id = dc_send_msg(context, chat_id, msg);
|
||||
context.call_cb(
|
||||
Event::MSGS_CHANGED,
|
||||
@@ -2116,7 +2107,7 @@ pub unsafe fn dc_chat_get_subtitle(chat: *const Chat) -> *mut libc::c_char {
|
||||
|
||||
let mut ret: *mut libc::c_char = std::ptr::null_mut();
|
||||
if (*chat).type_0 == 100 && 0 != dc_param_exists((*chat).param, DC_PARAM_SELFTALK as i32) {
|
||||
ret = dc_stock_str((*chat).context, 50)
|
||||
ret = to_cstring((*chat).context.stock_str(StockMessage::SelfTalkSubTitle));
|
||||
} else if (*chat).type_0 == 100 {
|
||||
let ret_raw: String = (*chat)
|
||||
.context
|
||||
@@ -2133,10 +2124,14 @@ pub unsafe fn dc_chat_get_subtitle(chat: *const Chat) -> *mut libc::c_char {
|
||||
ret = to_cstring(ret_raw);
|
||||
} else if (*chat).type_0 == 120 || (*chat).type_0 == 130 {
|
||||
if (*chat).id == 1 {
|
||||
ret = dc_stock_str((*chat).context, 8)
|
||||
ret = to_cstring((*chat).context.stock_str(StockMessage::DeadDrop));
|
||||
} else {
|
||||
let cnt = dc_get_chat_contact_cnt((*chat).context, (*chat).id);
|
||||
ret = dc_stock_str_repl_int((*chat).context, 4, cnt)
|
||||
ret = to_cstring(
|
||||
(*chat)
|
||||
.context
|
||||
.stock_string_repl_int(StockMessage::Member, cnt),
|
||||
);
|
||||
}
|
||||
}
|
||||
return if !ret.is_null() {
|
||||
|
||||
@@ -4,8 +4,8 @@ use crate::dc_chat::*;
|
||||
use crate::dc_contact::*;
|
||||
use crate::dc_lot::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -375,7 +375,8 @@ pub unsafe fn dc_chatlist_get_summary<'a>(
|
||||
if (*chat).id == 6i32 as libc::c_uint {
|
||||
(*ret).text2 = dc_strdup(0 as *const libc::c_char)
|
||||
} else if lastmsg.is_null() || (*lastmsg).from_id == 0i32 as libc::c_uint {
|
||||
(*ret).text2 = dc_stock_str((*chatlist).context, 1i32)
|
||||
(*ret).text2 =
|
||||
to_cstring((*chatlist).context.stock_str(StockMessage::NoMessages));
|
||||
} else {
|
||||
dc_lot_fill(ret, lastmsg, chat, lastcontact, (*chatlist).context);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use crate::aheader::EncryptPreference;
|
||||
use crate::config;
|
||||
use crate::constants::*;
|
||||
@@ -5,11 +7,11 @@ use crate::context::Context;
|
||||
use crate::dc_array::*;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_loginparam::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::key::*;
|
||||
use crate::peerstate::*;
|
||||
use crate::sql::{self, Sql};
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -276,7 +278,7 @@ pub unsafe fn dc_contact_load_from_db(
|
||||
|
||||
if contact_id == 1 as libc::c_uint {
|
||||
(*contact).id = contact_id;
|
||||
(*contact).name = dc_stock_str((*contact).context, 2);
|
||||
(*contact).name = to_cstring((*contact).context.stock_str(StockMessage::SelfMsg));
|
||||
(*contact).addr = to_cstring(
|
||||
(*contact)
|
||||
.context
|
||||
@@ -575,16 +577,15 @@ pub fn dc_get_contacts(
|
||||
.get_config(context, "displayname")
|
||||
.unwrap_or_default();
|
||||
|
||||
let self_name2 = unsafe { dc_stock_str(context, 2) };
|
||||
let self_name2 = CString::new(context.stock_str(StockMessage::SelfMsg).as_ref()).unwrap();
|
||||
|
||||
if query.is_null()
|
||||
|| self_addr.contains(as_str(query))
|
||||
|| self_name.contains(as_str(query))
|
||||
|| 0 != unsafe { dc_str_contains(self_name2, query) }
|
||||
|| 0 != unsafe { dc_str_contains(self_name2.as_ptr(), query) }
|
||||
{
|
||||
add_self = true;
|
||||
}
|
||||
unsafe { free(self_name2 as *mut _) };
|
||||
} else {
|
||||
add_self = true;
|
||||
|
||||
@@ -650,7 +651,6 @@ pub unsafe fn dc_get_contact_encrinfo(
|
||||
let mut fingerprint_self = 0 as *mut libc::c_char;
|
||||
let mut fingerprint_other_verified = 0 as *mut libc::c_char;
|
||||
let mut fingerprint_other_unverified = 0 as *mut libc::c_char;
|
||||
let mut p: *mut libc::c_char;
|
||||
|
||||
if !(!dc_contact_load_from_db(contact, &context.sql, contact_id)) {
|
||||
let peerstate = Peerstate::from_addr(context, &context.sql, as_str((*contact).addr));
|
||||
@@ -660,23 +660,18 @@ pub unsafe fn dc_get_contact_encrinfo(
|
||||
|
||||
if peerstate.is_some() && peerstate.as_ref().and_then(|p| p.peek_key(0)).is_some() {
|
||||
let peerstate = peerstate.as_ref().unwrap();
|
||||
p = dc_stock_str(
|
||||
context,
|
||||
if peerstate.prefer_encrypt == EncryptPreference::Mutual {
|
||||
34i32
|
||||
} else {
|
||||
25i32
|
||||
},
|
||||
);
|
||||
ret += as_str(p);
|
||||
free(p as *mut libc::c_void);
|
||||
let p = context.stock_str(if peerstate.prefer_encrypt == EncryptPreference::Mutual {
|
||||
StockMessage::E2ePreferred
|
||||
} else {
|
||||
StockMessage::E2eAvailable
|
||||
});
|
||||
ret += &p;
|
||||
if self_key.is_none() {
|
||||
dc_ensure_secret_key_exists(context);
|
||||
self_key = Key::from_self_public(context, &loginparam.addr, &context.sql);
|
||||
}
|
||||
p = dc_stock_str(context, 30i32);
|
||||
ret += &format!(" {}:", as_str(p));
|
||||
free(p as *mut libc::c_void);
|
||||
let p = context.stock_str(StockMessage::FingerPrints);
|
||||
ret += &format!(" {}:", p);
|
||||
|
||||
fingerprint_self = self_key
|
||||
.map(|k| k.formatted_fingerprint_c())
|
||||
@@ -717,13 +712,9 @@ pub unsafe fn dc_get_contact_encrinfo(
|
||||
);
|
||||
}
|
||||
} else if 0 == loginparam.server_flags & 0x400 && 0 == loginparam.server_flags & 0x40000 {
|
||||
p = dc_stock_str(context, 27);
|
||||
ret += as_str(p);
|
||||
free(p as *mut libc::c_void);
|
||||
ret += &context.stock_str(StockMessage::EncrTransp);
|
||||
} else {
|
||||
p = dc_stock_str(context, 28);
|
||||
ret += as_str(p);
|
||||
free(p as *mut libc::c_void);
|
||||
ret += &context.stock_str(StockMessage::EncrNone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@ use crate::dc_e2ee::*;
|
||||
use crate::dc_job::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_param::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::key::*;
|
||||
use crate::pgp::*;
|
||||
use crate::sql::{self, Sql};
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -260,25 +260,19 @@ pub unsafe extern "C" fn dc_render_setup_file(
|
||||
replacement,
|
||||
);
|
||||
free(replacement as *mut libc::c_void);
|
||||
let setup_message_title: *mut libc::c_char = dc_stock_str(context, 42i32);
|
||||
let mut setup_message_body: *mut libc::c_char = dc_stock_str(context, 43i32);
|
||||
dc_str_replace(
|
||||
&mut setup_message_body,
|
||||
b"\r\x00" as *const u8 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
);
|
||||
dc_str_replace(
|
||||
&mut setup_message_body,
|
||||
b"\n\x00" as *const u8 as *const libc::c_char,
|
||||
b"<br>\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
let setup_message_title =
|
||||
CString::new(context.stock_str(StockMessage::AcSetupMsgSubject).as_ref())
|
||||
.unwrap();
|
||||
let setup_message_body = context.stock_str(StockMessage::AcSetupMsgBody);
|
||||
let msg_body_head: &str = setup_message_body.split('\r').next().unwrap();
|
||||
let msg_body_html = CString::new(msg_body_head.replace("\n", "<br>")).unwrap();
|
||||
ret_setupfilecontent =
|
||||
dc_mprintf(b"<!DOCTYPE html>\r\n<html>\r\n<head>\r\n<title>%s</title>\r\n</head>\r\n<body>\r\n<h1>%s</h1>\r\n<p>%s</p>\r\n<pre>\r\n%s\r\n</pre>\r\n</body>\r\n</html>\r\n\x00"
|
||||
as *const u8 as *const libc::c_char,
|
||||
setup_message_title, setup_message_title,
|
||||
setup_message_body, encr_string);
|
||||
free(setup_message_title as *mut libc::c_void);
|
||||
free(setup_message_body as *mut libc::c_void);
|
||||
as *const u8 as *const libc::c_char,
|
||||
setup_message_title.as_ptr(),
|
||||
setup_message_title.as_ptr(),
|
||||
msg_body_html.as_ptr(),
|
||||
encr_string);
|
||||
free(encr_string as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use crate::constants::Event;
|
||||
use crate::context::*;
|
||||
use crate::dc_array::*;
|
||||
@@ -6,9 +8,9 @@ use crate::dc_job::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_param::*;
|
||||
use crate::dc_saxparser::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::sql;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -71,7 +73,6 @@ pub unsafe fn dc_send_locations_to_chat(
|
||||
) {
|
||||
let now = time();
|
||||
let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t;
|
||||
let mut stock_str: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let is_sending_locations_before: bool;
|
||||
if !(seconds < 0i32 || chat_id <= 9i32 as libc::c_uint) {
|
||||
is_sending_locations_before = dc_is_sending_locations_to_chat(context, chat_id);
|
||||
@@ -96,24 +97,23 @@ pub unsafe fn dc_send_locations_to_chat(
|
||||
{
|
||||
if 0 != seconds && !is_sending_locations_before {
|
||||
msg = dc_msg_new(context, 10i32);
|
||||
(*msg).text = dc_stock_system_msg(
|
||||
context,
|
||||
64,
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
(*msg).text = to_cstring(context.stock_system_msg(
|
||||
StockMessage::MsgLocationEnabled,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
);
|
||||
));
|
||||
dc_param_set_int((*msg).param, DC_PARAM_CMD as i32, 8);
|
||||
dc_send_msg(context, chat_id, msg);
|
||||
} else if 0 == seconds && is_sending_locations_before {
|
||||
stock_str = dc_stock_system_msg(
|
||||
context,
|
||||
65i32,
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
0i32 as uint32_t,
|
||||
);
|
||||
dc_add_device_msg(context, chat_id, stock_str);
|
||||
let stock_str = CString::new(context.stock_system_msg(
|
||||
StockMessage::MsgLocationDisabled,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
))
|
||||
.unwrap();
|
||||
dc_add_device_msg(context, chat_id, stock_str.as_ptr());
|
||||
}
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
@@ -132,7 +132,6 @@ pub unsafe fn dc_send_locations_to_chat(
|
||||
}
|
||||
}
|
||||
}
|
||||
free(stock_str as *mut libc::c_void);
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
|
||||
@@ -736,7 +735,6 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context: &Context, job: &mut
|
||||
// if so, a device-message is added if not yet done.
|
||||
|
||||
let chat_id = (*job).foreign_id;
|
||||
let mut stock_str = 0 as *mut libc::c_char;
|
||||
|
||||
if let Ok((send_begin, send_until)) = context.sql.query_row(
|
||||
"SELECT locations_send_begin, locations_send_until FROM chats WHERE id=?",
|
||||
@@ -753,14 +751,8 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context: &Context, job: &mut
|
||||
"UPDATE chats SET locations_send_begin=0, locations_send_until=0 WHERE id=?",
|
||||
params![chat_id as i32],
|
||||
).is_ok() {
|
||||
stock_str = dc_stock_system_msg(
|
||||
context,
|
||||
65,
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
0,
|
||||
);
|
||||
dc_add_device_msg(context, chat_id, stock_str);
|
||||
let stock_str = CString::new(context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0)).unwrap();
|
||||
dc_add_device_msg(context, chat_id, stock_str.as_ptr());
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
chat_id as usize,
|
||||
@@ -770,5 +762,4 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context: &Context, job: &mut
|
||||
}
|
||||
}
|
||||
}
|
||||
free(stock_str as *mut libc::c_void);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ use crate::context::Context;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_contact::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -134,14 +134,14 @@ pub unsafe fn dc_lot_fill(
|
||||
return;
|
||||
}
|
||||
if (*msg).state == 19i32 {
|
||||
(*lot).text1 = dc_stock_str(context, 3i32);
|
||||
(*lot).text1 = to_cstring(context.stock_str(StockMessage::Draft));
|
||||
(*lot).text1_meaning = 1i32
|
||||
} else if (*msg).from_id == 1i32 as libc::c_uint {
|
||||
if 0 != dc_msg_is_info(msg) || 0 != dc_chat_is_self_talk(chat) {
|
||||
(*lot).text1 = 0 as *mut libc::c_char;
|
||||
(*lot).text1_meaning = 0i32
|
||||
} else {
|
||||
(*lot).text1 = dc_stock_str(context, 2i32);
|
||||
(*lot).text1 = to_cstring(context.stock_str(StockMessage::SelfMsg));
|
||||
(*lot).text1_meaning = 3i32
|
||||
}
|
||||
} else if chat.is_null() {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use chrono::TimeZone;
|
||||
use mmime::mailimf_types::*;
|
||||
use mmime::mailimf_types_helper::*;
|
||||
@@ -16,9 +18,9 @@ use crate::dc_e2ee::*;
|
||||
use crate::dc_location::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_param::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_strencode::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -282,7 +284,7 @@ unsafe fn load_from(mut factory: *mut dc_mimefactory_t) {
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
if (*factory).selfstatus.is_null() {
|
||||
(*factory).selfstatus = dc_stock_str((*factory).context, 13)
|
||||
(*factory).selfstatus = to_cstring((*factory).context.stock_str(StockMessage::StatusLine));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -677,7 +679,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
strdup(b"v1\x00" as *const u8 as *const libc::c_char),
|
||||
),
|
||||
);
|
||||
placeholdertext = dc_stock_str((*factory).context, 43)
|
||||
placeholdertext =
|
||||
to_cstring((*factory).context.stock_str(StockMessage::AcSetupMsgBody));
|
||||
}
|
||||
if command == 7 {
|
||||
let step: *mut libc::c_char = dc_param_get(
|
||||
@@ -992,14 +995,18 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
let p1: *mut libc::c_char;
|
||||
let p2: *mut libc::c_char;
|
||||
if 0 != dc_param_get_int((*(*factory).msg).param, DC_PARAM_GUARANTEE_E2EE as i32, 0) {
|
||||
p1 = dc_stock_str((*factory).context, 24)
|
||||
p1 = to_cstring((*factory).context.stock_str(StockMessage::EncryptedMsg));
|
||||
} else {
|
||||
p1 = dc_msg_get_summarytext((*factory).msg, 32)
|
||||
}
|
||||
p2 = dc_stock_str_repl_string((*factory).context, 32, p1);
|
||||
p2 = to_cstring(
|
||||
(*factory)
|
||||
.context
|
||||
.stock_string_repl_str(StockMessage::ReadRcptMailBody, as_str(p1)),
|
||||
);
|
||||
message_text = dc_mprintf(b"%s\r\n\x00" as *const u8 as *const libc::c_char, p2);
|
||||
free(p2 as *mut libc::c_void);
|
||||
free(p1 as *mut libc::c_void);
|
||||
free(p2 as *mut libc::c_void);
|
||||
let human_mime_part: *mut mailmime = build_body_text(message_text);
|
||||
mailmime_add_part(multipart, human_mime_part);
|
||||
message_text2 =
|
||||
@@ -1031,10 +1038,17 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
if (*factory).loaded as libc::c_uint
|
||||
== DC_MF_MDN_LOADED as libc::c_int as libc::c_uint
|
||||
{
|
||||
let e: *mut libc::c_char = dc_stock_str((*factory).context, 31);
|
||||
subject_str =
|
||||
dc_mprintf(b"Chat: %s\x00" as *const u8 as *const libc::c_char, e);
|
||||
free(e as *mut libc::c_void);
|
||||
let e = CString::new(
|
||||
(*factory)
|
||||
.context
|
||||
.stock_str(StockMessage::ReadRcpt)
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
subject_str = dc_mprintf(
|
||||
b"Chat: %s\x00" as *const u8 as *const libc::c_char,
|
||||
e.as_ptr(),
|
||||
);
|
||||
} else {
|
||||
subject_str = get_subject((*factory).chat, (*factory).msg, afwd_email)
|
||||
}
|
||||
@@ -1118,7 +1132,7 @@ unsafe fn get_subject(
|
||||
b"\x00" as *const u8 as *const libc::c_char
|
||||
};
|
||||
if dc_param_get_int((*msg).param, DC_PARAM_CMD as i32, 0) == 6 {
|
||||
ret = dc_stock_str(context, 42)
|
||||
ret = to_cstring(context.stock_str(StockMessage::AcSetupMsgSubject))
|
||||
} else if (*chat).type_0 == DC_CHAT_TYPE_GROUP as libc::c_int
|
||||
|| (*chat).type_0 == DC_CHAT_TYPE_VERIFIED_GROUP as libc::c_int
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use charset::Charset;
|
||||
use mmime::mailimf::*;
|
||||
@@ -17,9 +17,9 @@ use crate::dc_e2ee::*;
|
||||
use crate::dc_location::*;
|
||||
use crate::dc_param::*;
|
||||
use crate::dc_simplify::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_strencode::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -667,11 +667,18 @@ unsafe fn dc_mimeparser_parse_mime_recursive(
|
||||
40 => {
|
||||
let mut part: *mut dc_mimepart_t = dc_mimepart_new();
|
||||
(*part).type_0 = 10i32;
|
||||
let msg_body: *mut libc::c_char = dc_stock_str((*mimeparser).context, 29i32);
|
||||
(*part).msg =
|
||||
dc_mprintf(b"[%s]\x00" as *const u8 as *const libc::c_char, msg_body);
|
||||
let msg_body = CString::new(
|
||||
(*mimeparser)
|
||||
.context
|
||||
.stock_str(StockMessage::CantDecryptMsgBody)
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
(*part).msg = dc_mprintf(
|
||||
b"[%s]\x00" as *const u8 as *const libc::c_char,
|
||||
msg_body.as_ptr(),
|
||||
);
|
||||
(*part).msg_raw = dc_strdup((*part).msg);
|
||||
free(msg_body as *mut libc::c_void);
|
||||
carray_add(
|
||||
(*mimeparser).parts,
|
||||
part as *mut libc::c_void,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::context::*;
|
||||
use crate::dc_chat::*;
|
||||
@@ -6,10 +8,10 @@ use crate::dc_job::*;
|
||||
use crate::dc_lot::dc_lot_t;
|
||||
use crate::dc_lot::*;
|
||||
use crate::dc_param::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::pgp::*;
|
||||
use crate::sql;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -840,17 +842,16 @@ pub unsafe fn dc_msg_get_summarytext_by_raw(
|
||||
let mut ret;
|
||||
let mut prefix: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut label: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut value: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut append_text: libc::c_int = 1i32;
|
||||
match type_0 {
|
||||
20 => prefix = dc_stock_str(context, 9i32),
|
||||
21 => prefix = dc_stock_str(context, 23i32),
|
||||
50 => prefix = dc_stock_str(context, 10i32),
|
||||
41 => prefix = dc_stock_str(context, 7i32),
|
||||
20 => prefix = to_cstring(context.stock_str(StockMessage::Image)),
|
||||
21 => prefix = to_cstring(context.stock_str(StockMessage::Gif)),
|
||||
50 => prefix = to_cstring(context.stock_str(StockMessage::Video)),
|
||||
41 => prefix = to_cstring(context.stock_str(StockMessage::VoiceMessage)),
|
||||
40 | 60 => {
|
||||
if dc_param_get_int(param, DC_PARAM_CMD as i32, 0) == 6i32 {
|
||||
prefix = dc_stock_str(context, 42i32);
|
||||
if dc_param_get_int(param, DC_PARAM_CMD as i32, 0) == 6 {
|
||||
prefix = to_cstring(context.stock_str(StockMessage::AcSetupMsgSubject));
|
||||
append_text = 0i32
|
||||
} else {
|
||||
pathNfilename = dc_param_get(
|
||||
@@ -859,24 +860,26 @@ pub unsafe fn dc_msg_get_summarytext_by_raw(
|
||||
b"ErrFilename\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
value = dc_get_filename(pathNfilename);
|
||||
label = dc_stock_str(
|
||||
context,
|
||||
if type_0 == DC_MSG_AUDIO as libc::c_int {
|
||||
11i32
|
||||
} else {
|
||||
12i32
|
||||
},
|
||||
);
|
||||
let label = CString::new(
|
||||
context
|
||||
.stock_str(if type_0 == DC_MSG_AUDIO {
|
||||
StockMessage::Audio
|
||||
} else {
|
||||
StockMessage::File
|
||||
})
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
prefix = dc_mprintf(
|
||||
b"%s \xe2\x80\x93 %s\x00" as *const u8 as *const libc::c_char,
|
||||
label,
|
||||
label.as_ptr(),
|
||||
value,
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if dc_param_get_int(param, DC_PARAM_CMD as i32, 0) == 9i32 {
|
||||
prefix = dc_stock_str(context, 66i32);
|
||||
prefix = to_cstring(context.stock_str(StockMessage::Location));
|
||||
append_text = 0i32
|
||||
}
|
||||
}
|
||||
@@ -901,7 +904,6 @@ pub unsafe fn dc_msg_get_summarytext_by_raw(
|
||||
}
|
||||
free(prefix as *mut libc::c_void);
|
||||
free(pathNfilename as *mut libc::c_void);
|
||||
free(label as *mut libc::c_void);
|
||||
free(value as *mut libc::c_void);
|
||||
if ret.is_null() {
|
||||
ret = dc_strdup(0 as *const libc::c_char)
|
||||
|
||||
@@ -19,11 +19,11 @@ use crate::dc_move::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_param::*;
|
||||
use crate::dc_securejoin::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_strencode::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::peerstate::*;
|
||||
use crate::sql;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -944,18 +944,13 @@ unsafe fn create_or_lookup_group(
|
||||
let mut X_MrAddToGrp: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut X_MrGrpNameChanged: libc::c_int = 0;
|
||||
let mut X_MrGrpImageChanged: *const libc::c_char = 0 as *const libc::c_char;
|
||||
let mut better_msg: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut better_msg: String = From::from("");
|
||||
let mut failure_reason: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
if mime_parser.is_system_message == 8 {
|
||||
better_msg = dc_stock_system_msg(
|
||||
context,
|
||||
64,
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
from_id as uint32_t,
|
||||
)
|
||||
if mime_parser.is_system_message == 8i32 {
|
||||
better_msg =
|
||||
context.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", from_id as u32)
|
||||
}
|
||||
set_better_msg(mime_parser, &mut better_msg);
|
||||
set_better_msg(mime_parser, &better_msg);
|
||||
/* search the grpid in the header */
|
||||
let mut field: *mut mailimf_field;
|
||||
let mut optional_field: *mut mailimf_optional_field;
|
||||
@@ -1034,12 +1029,15 @@ unsafe fn create_or_lookup_group(
|
||||
let left_group: libc::c_int =
|
||||
(dc_lookup_contact_id_by_addr(context, X_MrRemoveFromGrp)
|
||||
== from_id as libc::c_uint) as libc::c_int;
|
||||
better_msg = dc_stock_system_msg(
|
||||
context,
|
||||
if 0 != left_group { 19 } else { 18 },
|
||||
X_MrRemoveFromGrp,
|
||||
0 as *const libc::c_char,
|
||||
from_id as uint32_t,
|
||||
better_msg = context.stock_system_msg(
|
||||
if 0 != left_group {
|
||||
StockMessage::MsgGroupLeft
|
||||
} else {
|
||||
StockMessage::MsgDelMember
|
||||
},
|
||||
as_str(X_MrRemoveFromGrp),
|
||||
"",
|
||||
from_id as u32,
|
||||
)
|
||||
} else {
|
||||
optional_field = dc_mimeparser_lookup_optional_field(
|
||||
@@ -1056,12 +1054,11 @@ unsafe fn create_or_lookup_group(
|
||||
if !optional_field.is_null() {
|
||||
X_MrGrpImageChanged = (*optional_field).fld_value
|
||||
}
|
||||
better_msg = dc_stock_system_msg(
|
||||
context,
|
||||
17,
|
||||
X_MrAddToGrp,
|
||||
0 as *const libc::c_char,
|
||||
from_id as uint32_t,
|
||||
better_msg = context.stock_system_msg(
|
||||
StockMessage::MsgAddMember,
|
||||
as_str(X_MrAddToGrp),
|
||||
"",
|
||||
from_id as u32,
|
||||
)
|
||||
} else {
|
||||
optional_field = dc_mimeparser_lookup_optional_field(
|
||||
@@ -1069,14 +1066,13 @@ unsafe fn create_or_lookup_group(
|
||||
b"Chat-Group-Name-Changed\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
if !optional_field.is_null() {
|
||||
X_MrGrpNameChanged = 1;
|
||||
mime_parser.is_system_message = 2;
|
||||
better_msg = dc_stock_system_msg(
|
||||
context,
|
||||
15,
|
||||
(*optional_field).fld_value,
|
||||
grpname,
|
||||
from_id as uint32_t,
|
||||
X_MrGrpNameChanged = 1i32;
|
||||
mime_parser.is_system_message = 2i32;
|
||||
better_msg = context.stock_system_msg(
|
||||
StockMessage::MsgGrpName,
|
||||
as_str((*optional_field).fld_value),
|
||||
as_str(grpname),
|
||||
from_id as u32,
|
||||
)
|
||||
} else {
|
||||
optional_field = dc_mimeparser_lookup_optional_field(
|
||||
@@ -1086,26 +1082,25 @@ unsafe fn create_or_lookup_group(
|
||||
if !optional_field.is_null() {
|
||||
X_MrGrpImageChanged = (*optional_field).fld_value;
|
||||
mime_parser.is_system_message = 3;
|
||||
better_msg = dc_stock_system_msg(
|
||||
context,
|
||||
better_msg = context.stock_system_msg(
|
||||
if strcmp(
|
||||
X_MrGrpImageChanged,
|
||||
b"0\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
{
|
||||
33
|
||||
StockMessage::MsgGrpImgDeleted
|
||||
} else {
|
||||
16
|
||||
StockMessage::MsgGrpImgChanged
|
||||
},
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
from_id as uint32_t,
|
||||
"",
|
||||
"",
|
||||
from_id as u32,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
set_better_msg(mime_parser, &mut better_msg);
|
||||
set_better_msg(mime_parser, &better_msg);
|
||||
chat_id = dc_get_chat_id_by_grpid(
|
||||
context,
|
||||
grpid,
|
||||
@@ -1345,8 +1340,6 @@ unsafe fn create_or_lookup_group(
|
||||
}
|
||||
free(grpid as *mut libc::c_void);
|
||||
free(grpname as *mut libc::c_void);
|
||||
|
||||
free(better_msg as *mut libc::c_void);
|
||||
free(failure_reason as *mut libc::c_void);
|
||||
if !ret_chat_id.is_null() {
|
||||
*ret_chat_id = chat_id
|
||||
@@ -1432,11 +1425,10 @@ unsafe fn create_or_lookup_adhoc_group(
|
||||
{
|
||||
grpname = dc_strdup(mime_parser.subject)
|
||||
} else {
|
||||
grpname = dc_stock_str_repl_int(
|
||||
context,
|
||||
4,
|
||||
grpname = to_cstring(context.stock_string_repl_int(
|
||||
StockMessage::Member,
|
||||
dc_array_get_cnt(member_ids) as libc::c_int,
|
||||
)
|
||||
));
|
||||
}
|
||||
chat_id =
|
||||
create_group_record(context, grpid, grpname, create_blocked, 0);
|
||||
@@ -1732,14 +1724,14 @@ unsafe fn check_verified_properties(
|
||||
1
|
||||
}
|
||||
|
||||
unsafe fn set_better_msg(mime_parser: &dc_mimeparser_t, better_msg: *mut *mut libc::c_char) {
|
||||
if !(*better_msg).is_null() && carray_count((*mime_parser).parts) > 0 as libc::c_uint {
|
||||
unsafe fn set_better_msg<T: AsRef<str>>(mime_parser: &dc_mimeparser_t, better_msg: T) {
|
||||
let msg = better_msg.as_ref();
|
||||
if !(msg.len() > 0) && carray_count((*mime_parser).parts) > 0 {
|
||||
let mut part: *mut dc_mimepart_t =
|
||||
carray_get(mime_parser.parts, 0 as libc::c_uint) as *mut dc_mimepart_t;
|
||||
if (*part).type_0 == 10 {
|
||||
free((*part).msg as *mut libc::c_void);
|
||||
(*part).msg = *better_msg;
|
||||
*better_msg = 0 as *mut libc::c_char
|
||||
(*part).msg = to_cstring(msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use mmime::mailimf_types::*;
|
||||
use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
|
||||
|
||||
@@ -14,12 +16,12 @@ use crate::dc_mimeparser::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_param::*;
|
||||
use crate::dc_qr::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_strencode::*;
|
||||
use crate::dc_token::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::key::*;
|
||||
use crate::peerstate::*;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
@@ -797,22 +799,21 @@ unsafe fn end_bobs_joining(context: &Context, status: libc::c_int) {
|
||||
unsafe fn secure_connection_established(context: &Context, contact_chat_id: uint32_t) {
|
||||
let contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id);
|
||||
let contact: *mut dc_contact_t = dc_get_contact(context, contact_id);
|
||||
let msg: *mut libc::c_char = dc_stock_str_repl_string(
|
||||
context,
|
||||
35i32,
|
||||
let msg = CString::new(context.stock_string_repl_str(
|
||||
StockMessage::ContactVerified,
|
||||
if !contact.is_null() {
|
||||
(*contact).addr
|
||||
as_str((*contact).addr)
|
||||
} else {
|
||||
b"?\x00" as *const u8 as *const libc::c_char
|
||||
"?"
|
||||
},
|
||||
);
|
||||
dc_add_device_msg(context, contact_chat_id, msg);
|
||||
))
|
||||
.unwrap();
|
||||
dc_add_device_msg(context, contact_chat_id, msg.as_ptr());
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
contact_chat_id as uintptr_t,
|
||||
0i32 as uintptr_t,
|
||||
);
|
||||
free(msg as *mut libc::c_void);
|
||||
dc_contact_unref(contact);
|
||||
}
|
||||
|
||||
@@ -840,18 +841,17 @@ unsafe fn could_not_establish_secure_connection(
|
||||
) {
|
||||
let contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id);
|
||||
let contact = dc_get_contact(context, contact_id);
|
||||
let msg: *mut libc::c_char = dc_stock_str_repl_string(
|
||||
context,
|
||||
36i32,
|
||||
let msg = context.stock_string_repl_str(
|
||||
StockMessage::ContactNotVerified,
|
||||
if !contact.is_null() {
|
||||
(*contact).addr
|
||||
as_str((*contact).addr)
|
||||
} else {
|
||||
b"?\x00" as *const u8 as *const libc::c_char
|
||||
"?"
|
||||
},
|
||||
);
|
||||
dc_add_device_msg(context, contact_chat_id, msg);
|
||||
error!(context, 0, "{} ({})", as_str(msg), to_string(details),);
|
||||
free(msg as *mut libc::c_void);
|
||||
let msg_c = CString::new(msg.as_str()).unwrap();
|
||||
dc_add_device_msg(context, contact_chat_id, msg_c.as_ptr());
|
||||
error!(context, 0, "{} ({})", msg, as_str(details));
|
||||
dc_contact_unref(contact);
|
||||
}
|
||||
|
||||
@@ -939,15 +939,15 @@ pub unsafe fn dc_handle_degrade_event(context: &Context, peerstate: &Peerstate)
|
||||
&mut contact_chat_id,
|
||||
0 as *mut libc::c_int,
|
||||
);
|
||||
let c_addr_ptr = if let Some(ref addr) = peerstate.addr {
|
||||
to_cstring(addr)
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
let peeraddr: &str = match peerstate.addr {
|
||||
Some(ref addr) => &addr,
|
||||
None => "",
|
||||
};
|
||||
let msg = dc_stock_str_repl_string(context, 37, c_addr_ptr);
|
||||
dc_add_device_msg(context, contact_chat_id, msg);
|
||||
free(msg as *mut libc::c_void);
|
||||
free(c_addr_ptr as *mut _);
|
||||
let msg = CString::new(
|
||||
context.stock_string_repl_str(StockMessage::ContactSetupChanged, peeraddr),
|
||||
)
|
||||
.unwrap();
|
||||
dc_add_device_msg(context, contact_chat_id, msg.as_ptr());
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
contact_chat_id as uintptr_t,
|
||||
|
||||
338
src/dc_stock.rs
338
src/dc_stock.rs
@@ -1,338 +0,0 @@
|
||||
use crate::constants::Event;
|
||||
use crate::context::Context;
|
||||
use crate::dc_contact::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
/* Return the string with the given ID by calling DC_EVENT_GET_STRING.
|
||||
The result must be free()'d! */
|
||||
pub unsafe fn dc_stock_str(context: &Context, id: libc::c_int) -> *mut libc::c_char {
|
||||
return get_string(context, id, 0i32);
|
||||
}
|
||||
|
||||
unsafe fn get_string(context: &Context, id: libc::c_int, qty: libc::c_int) -> *mut libc::c_char {
|
||||
let mut ret: *mut libc::c_char;
|
||||
|
||||
ret =
|
||||
context.call_cb(Event::GET_STRING, id as uintptr_t, qty as uintptr_t) as *mut libc::c_char;
|
||||
|
||||
if ret.is_null() {
|
||||
ret = default_string(id)
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
/* Add translated strings that are used by the messager backend.
|
||||
As the logging functions may use these strings, do not log any
|
||||
errors from here. */
|
||||
unsafe fn default_string(id: libc::c_int) -> *mut libc::c_char {
|
||||
// TODO match on enum values /rtn
|
||||
match id {
|
||||
1 => {
|
||||
return dc_strdup(b"No messages.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
2 => {
|
||||
return dc_strdup(b"Me\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
3 => {
|
||||
return dc_strdup(b"Draft\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
4 => {
|
||||
return dc_strdup(b"%1$s member(s)\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
6 => {
|
||||
return dc_strdup(b"%1$s contact(s)\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
7 => {
|
||||
return dc_strdup(b"Voice message\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
8 => {
|
||||
return dc_strdup(b"Contact requests\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
9 => {
|
||||
return dc_strdup(b"Image\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
23 => {
|
||||
return dc_strdup(b"GIF\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
10 => {
|
||||
return dc_strdup(b"Video\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
11 => {
|
||||
return dc_strdup(b"Audio\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
12 => {
|
||||
return dc_strdup(b"File\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
66 => {
|
||||
return dc_strdup(b"Location\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
24 => {
|
||||
return dc_strdup(b"Encrypted message\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
13 => {
|
||||
return dc_strdup(b"Sent with my Delta Chat Messenger: https://delta.chat\x00"
|
||||
as *const u8 as *const libc::c_char)
|
||||
}
|
||||
14 => {
|
||||
return dc_strdup(b"Hello, I\'ve just created the group \"%1$s\" for us.\x00"
|
||||
as *const u8 as *const libc::c_char)
|
||||
}
|
||||
15 => {
|
||||
return dc_strdup(b"Group name changed from \"%1$s\" to \"%2$s\".\x00"
|
||||
as *const u8 as *const libc::c_char)
|
||||
}
|
||||
16 => {
|
||||
return dc_strdup(b"Group image changed.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
17 => {
|
||||
return dc_strdup(b"Member %1$s added.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
18 => {
|
||||
return dc_strdup(b"Member %1$s removed.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
19 => {
|
||||
return dc_strdup(b"Group left.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
64 => {
|
||||
return dc_strdup(b"Location streaming enabled.\x00" as *const u8
|
||||
as *const libc::c_char)
|
||||
}
|
||||
65 => {
|
||||
return dc_strdup(b"Location streaming disabled.\x00" as *const u8
|
||||
as *const libc::c_char)
|
||||
}
|
||||
62 => {
|
||||
return dc_strdup(b"%1$s by %2$s.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
63 => {
|
||||
return dc_strdup(b"%1$s by me.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
25 => {
|
||||
return dc_strdup(b"End-to-end encryption available.\x00" as
|
||||
*const u8 as *const libc::c_char)
|
||||
}
|
||||
27 => {
|
||||
return dc_strdup(b"Transport-encryption.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
28 => {
|
||||
return dc_strdup(b"No encryption.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
30 => {
|
||||
return dc_strdup(b"Fingerprints\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
31 => {
|
||||
return dc_strdup(b"Return receipt\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
32 => {
|
||||
return dc_strdup(b"This is a return receipt for the message \"%1$s\".\x00"
|
||||
as *const u8 as *const libc::c_char)
|
||||
}
|
||||
33 => {
|
||||
return dc_strdup(b"Group image deleted.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
34 => {
|
||||
return dc_strdup(b"End-to-end encryption preferred.\x00" as
|
||||
*const u8 as *const libc::c_char)
|
||||
}
|
||||
35 => {
|
||||
return dc_strdup(b"%1$s verified.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
36 => {
|
||||
return dc_strdup(b"Cannot verifiy %1$s\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
37 => {
|
||||
return dc_strdup(b"Changed setup for %1$s\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
40 => {
|
||||
return dc_strdup(b"Archived chats\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
41 => {
|
||||
return dc_strdup(b"Starred messages\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
42 => {
|
||||
return dc_strdup(b"Autocrypt Setup Message\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
43 => {
|
||||
return dc_strdup(b"This is the Autocrypt Setup Message used to transfer your key between clients.\n\nTo decrypt and use your key, open the message in an Autocrypt-compliant client and enter the setup code presented on the generating device.\x00"
|
||||
as *const u8 as *const libc::c_char)
|
||||
}
|
||||
50 => {
|
||||
return dc_strdup(b"Messages I sent to myself\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
29 => {
|
||||
return dc_strdup(b"This message was encrypted for another setup.\x00"
|
||||
as *const u8 as *const libc::c_char)
|
||||
}
|
||||
60 => {
|
||||
return dc_strdup(b"Cannot login as %1$s.\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
61 => {
|
||||
return dc_strdup(b"Response from %1$s: %2$s\x00" as *const u8 as
|
||||
*const libc::c_char)
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
|
||||
dc_strdup(b"ErrStr\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
|
||||
/* Replaces the first `%1$s` in the given String-ID by the given value.
|
||||
The result must be free()'d! */
|
||||
pub unsafe fn dc_stock_str_repl_string(
|
||||
context: &Context,
|
||||
id: libc::c_int,
|
||||
to_insert: *const libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
let mut ret: *mut libc::c_char = get_string(context, id, 0i32);
|
||||
dc_str_replace(
|
||||
&mut ret,
|
||||
b"%1$s\x00" as *const u8 as *const libc::c_char,
|
||||
to_insert,
|
||||
);
|
||||
dc_str_replace(
|
||||
&mut ret,
|
||||
b"%1$d\x00" as *const u8 as *const libc::c_char,
|
||||
to_insert,
|
||||
);
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe fn dc_stock_str_repl_int(
|
||||
context: &Context,
|
||||
id: libc::c_int,
|
||||
to_insert_int: libc::c_int,
|
||||
) -> *mut libc::c_char {
|
||||
let mut ret: *mut libc::c_char = get_string(context, id, to_insert_int);
|
||||
let to_insert_str: *mut libc::c_char = dc_mprintf(
|
||||
b"%i\x00" as *const u8 as *const libc::c_char,
|
||||
to_insert_int as libc::c_int,
|
||||
);
|
||||
dc_str_replace(
|
||||
&mut ret,
|
||||
b"%1$s\x00" as *const u8 as *const libc::c_char,
|
||||
to_insert_str,
|
||||
);
|
||||
dc_str_replace(
|
||||
&mut ret,
|
||||
b"%1$d\x00" as *const u8 as *const libc::c_char,
|
||||
to_insert_str,
|
||||
);
|
||||
free(to_insert_str as *mut libc::c_void);
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
/* Replaces the first `%1$s` and `%2$s` in the given String-ID by the two given strings.
|
||||
The result must be free()'d! */
|
||||
pub unsafe fn dc_stock_str_repl_string2(
|
||||
context: &Context,
|
||||
id: libc::c_int,
|
||||
to_insert: *const libc::c_char,
|
||||
to_insert2: *const libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
let mut ret: *mut libc::c_char = get_string(context, id, 0i32);
|
||||
dc_str_replace(
|
||||
&mut ret,
|
||||
b"%1$s\x00" as *const u8 as *const libc::c_char,
|
||||
to_insert,
|
||||
);
|
||||
dc_str_replace(
|
||||
&mut ret,
|
||||
b"%1$d\x00" as *const u8 as *const libc::c_char,
|
||||
to_insert,
|
||||
);
|
||||
dc_str_replace(
|
||||
&mut ret,
|
||||
b"%2$s\x00" as *const u8 as *const libc::c_char,
|
||||
to_insert2,
|
||||
);
|
||||
dc_str_replace(
|
||||
&mut ret,
|
||||
b"%2$d\x00" as *const u8 as *const libc::c_char,
|
||||
to_insert2,
|
||||
);
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
/* Misc. */
|
||||
pub unsafe fn dc_stock_system_msg(
|
||||
context: &Context,
|
||||
str_id: libc::c_int,
|
||||
mut param1: *const libc::c_char,
|
||||
param2: *const libc::c_char,
|
||||
from_id: uint32_t,
|
||||
) -> *mut libc::c_char {
|
||||
let ret: *mut libc::c_char;
|
||||
let mut mod_contact: *mut dc_contact_t = 0 as *mut dc_contact_t;
|
||||
let mut mod_displayname: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut from_contact: *mut dc_contact_t = 0 as *mut dc_contact_t;
|
||||
let mut from_displayname: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
if str_id == 17i32 || str_id == 18i32 {
|
||||
let mod_contact_id: uint32_t = dc_lookup_contact_id_by_addr(context, param1);
|
||||
if mod_contact_id != 0i32 as libc::c_uint {
|
||||
mod_contact = dc_get_contact(context, mod_contact_id);
|
||||
mod_displayname = dc_contact_get_name_n_addr(mod_contact);
|
||||
param1 = mod_displayname
|
||||
}
|
||||
}
|
||||
let action: *mut libc::c_char = dc_stock_str_repl_string2(context, str_id, param1, param2);
|
||||
if 0 != from_id {
|
||||
if 0 != strlen(action)
|
||||
&& *action.offset(strlen(action).wrapping_sub(1) as isize) as libc::c_int == '.' as i32
|
||||
{
|
||||
*action.offset(strlen(action).wrapping_sub(1) as isize) = 0i32 as libc::c_char
|
||||
}
|
||||
from_contact = dc_get_contact(context, from_id);
|
||||
from_displayname = dc_contact_get_display_name(from_contact);
|
||||
ret = dc_stock_str_repl_string2(
|
||||
context,
|
||||
if from_id == 1i32 as libc::c_uint {
|
||||
63i32
|
||||
} else {
|
||||
62i32
|
||||
},
|
||||
action,
|
||||
from_displayname,
|
||||
)
|
||||
} else {
|
||||
ret = dc_strdup(action)
|
||||
}
|
||||
free(action as *mut libc::c_void);
|
||||
free(from_displayname as *mut libc::c_void);
|
||||
free(mod_displayname as *mut libc::c_void);
|
||||
dc_contact_unref(from_contact);
|
||||
dc_contact_unref(mod_contact);
|
||||
|
||||
ret
|
||||
}
|
||||
@@ -34,6 +34,7 @@ pub mod peerstate;
|
||||
pub mod pgp;
|
||||
pub mod smtp;
|
||||
pub mod sql;
|
||||
pub mod stock;
|
||||
pub mod types;
|
||||
pub mod x;
|
||||
|
||||
@@ -60,9 +61,11 @@ pub mod dc_receive_imf;
|
||||
pub mod dc_saxparser;
|
||||
pub mod dc_securejoin;
|
||||
pub mod dc_simplify;
|
||||
pub mod dc_stock;
|
||||
pub mod dc_strencode;
|
||||
pub mod dc_token;
|
||||
pub mod dc_tools;
|
||||
|
||||
pub use self::constants::*;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_utils;
|
||||
|
||||
423
src/stock.rs
Normal file
423
src/stock.rs
Normal file
@@ -0,0 +1,423 @@
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CString;
|
||||
|
||||
use strum::EnumProperty;
|
||||
use strum_macros::EnumProperty;
|
||||
|
||||
use crate::constants::Event;
|
||||
use crate::context::Context;
|
||||
use crate::dc_contact::*;
|
||||
use crate::dc_tools::*;
|
||||
use libc::free;
|
||||
|
||||
/// Stock strings
|
||||
///
|
||||
/// These identify the string to return in [Context.stock_str]. The
|
||||
/// numbers must stay in sync with `deltachat.h` `DC_STR_*` constants.
|
||||
///
|
||||
/// See the `stock_*` methods on [Context] to use these.
|
||||
///
|
||||
/// [Context]: crate::context::Context
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, EnumProperty)]
|
||||
#[repr(u32)]
|
||||
pub enum StockMessage {
|
||||
#[strum(props(fallback = "No messages."))]
|
||||
NoMessages = 1,
|
||||
#[strum(props(fallback = "Me"))]
|
||||
SelfMsg = 2,
|
||||
#[strum(props(fallback = "Draft"))]
|
||||
Draft = 3,
|
||||
#[strum(props(fallback = "%1$s member(s)"))]
|
||||
Member = 4,
|
||||
#[strum(props(fallback = "%1$s contact(s)"))]
|
||||
Contact = 6,
|
||||
#[strum(props(fallback = "Voice message"))]
|
||||
VoiceMessage = 7,
|
||||
#[strum(props(fallback = "Contact requests"))]
|
||||
DeadDrop = 8,
|
||||
#[strum(props(fallback = "Image"))]
|
||||
Image = 9,
|
||||
#[strum(props(fallback = "Video"))]
|
||||
Video = 10,
|
||||
#[strum(props(fallback = "Audio"))]
|
||||
Audio = 11,
|
||||
#[strum(props(fallback = "File"))]
|
||||
File = 12,
|
||||
#[strum(props(fallback = "Sent with my Delta Chat Messenger: https://delta.chat"))]
|
||||
StatusLine = 13,
|
||||
#[strum(props(fallback = "Hello, I\'ve just created the group \"%1$s\" for us."))]
|
||||
NewGroupDraft = 14,
|
||||
#[strum(props(fallback = "Group name changed from \"%1$s\" to \"%2$s\"."))]
|
||||
MsgGrpName = 15,
|
||||
#[strum(props(fallback = "Group image changed."))]
|
||||
MsgGrpImgChanged = 16,
|
||||
#[strum(props(fallback = "Member %1$s added."))]
|
||||
MsgAddMember = 17,
|
||||
#[strum(props(fallback = "Member %1$s removed."))]
|
||||
MsgDelMember = 18,
|
||||
#[strum(props(fallback = "Group left."))]
|
||||
MsgGroupLeft = 19,
|
||||
#[strum(props(fallback = "GIF"))]
|
||||
Gif = 23,
|
||||
#[strum(props(fallback = "Encrypted message"))]
|
||||
EncryptedMsg = 24,
|
||||
#[strum(props(fallback = "End-to-end encryption available."))]
|
||||
E2eAvailable = 25,
|
||||
#[strum(props(fallback = "Transport-encryption."))]
|
||||
EncrTransp = 27,
|
||||
#[strum(props(fallback = "No encryption."))]
|
||||
EncrNone = 28,
|
||||
#[strum(props(fallback = "This message was encrypted for another setup."))]
|
||||
CantDecryptMsgBody = 29,
|
||||
#[strum(props(fallback = "Fingerprints"))]
|
||||
FingerPrints = 30,
|
||||
#[strum(props(fallback = "Return receipt"))]
|
||||
ReadRcpt = 31,
|
||||
#[strum(props(fallback = "This is a return receipt for the message \"%1$s\"."))]
|
||||
ReadRcptMailBody = 32,
|
||||
#[strum(props(fallback = "Group image deleted."))]
|
||||
MsgGrpImgDeleted = 33,
|
||||
#[strum(props(fallback = "End-to-end encryption preferred."))]
|
||||
E2ePreferred = 34,
|
||||
#[strum(props(fallback = "%1$s verified."))]
|
||||
ContactVerified = 35,
|
||||
#[strum(props(fallback = "Cannot verify %1$s"))]
|
||||
ContactNotVerified = 36,
|
||||
#[strum(props(fallback = "Changed setup for %1$s"))]
|
||||
ContactSetupChanged = 37,
|
||||
#[strum(props(fallback = "Archived chats"))]
|
||||
ArchivedChats = 40,
|
||||
#[strum(props(fallback = "Starred messages"))]
|
||||
StarredMsgs = 41,
|
||||
#[strum(props(fallback = "Autocrypt Setup Message"))]
|
||||
AcSetupMsgSubject = 42,
|
||||
#[strum(props(
|
||||
fallback = "This is the Autocrypt Setup Message used to transfer your key between clients.\n\nTo decrypt and use your key, open the message in an Autocrypt-compliant client and enter the setup code presented on the generating device."
|
||||
))]
|
||||
AcSetupMsgBody = 43,
|
||||
#[strum(props(fallback = "Messages I sent to myself"))]
|
||||
SelfTalkSubTitle = 50,
|
||||
#[strum(props(fallback = "Cannot login as %1$s."))]
|
||||
CannotLogin = 60,
|
||||
#[strum(props(fallback = "Response from %1$s: %2$s"))]
|
||||
ServerResponse = 61,
|
||||
#[strum(props(fallback = "%1$s by %2$s."))]
|
||||
MsgActionByUser = 62,
|
||||
#[strum(props(fallback = "%1$s by me."))]
|
||||
MsgActionByMe = 63,
|
||||
#[strum(props(fallback = "Location streaming enabled."))]
|
||||
MsgLocationEnabled = 64,
|
||||
#[strum(props(fallback = "Location streaming disabled."))]
|
||||
MsgLocationDisabled = 65,
|
||||
#[strum(props(fallback = "Location"))]
|
||||
Location = 66,
|
||||
}
|
||||
|
||||
impl StockMessage {
|
||||
/// Default untranslated strings for stock messages.
|
||||
///
|
||||
/// These could be used in logging calls, so no logging here.
|
||||
fn fallback(&self) -> &'static str {
|
||||
self.get_str("fallback").unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Return the stock string for the [StockMessage].
|
||||
///
|
||||
/// If the context callback responds with a string to use, e.g. a
|
||||
/// translation, then this string will be returned. Otherwise a
|
||||
/// default (English) string is returned.
|
||||
pub fn stock_str(&self, id: StockMessage) -> Cow<str> {
|
||||
let ptr = self.call_cb(Event::GET_STRING, id as usize, 0) as *mut libc::c_char;
|
||||
if ptr.is_null() {
|
||||
Cow::Borrowed(id.fallback())
|
||||
} else {
|
||||
let ret = to_string(ptr);
|
||||
unsafe { free(ptr as *mut libc::c_void) };
|
||||
Cow::Owned(ret)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return stock string, replacing placeholders with provided string.
|
||||
///
|
||||
/// This replaces both the *first* `%1$s` **and** `%1$d`
|
||||
/// placeholders with the provided string.
|
||||
pub fn stock_string_repl_str(&self, id: StockMessage, insert: impl AsRef<str>) -> String {
|
||||
self.stock_str(id)
|
||||
.replacen("%1$s", insert.as_ref(), 1)
|
||||
.replacen("%1$d", insert.as_ref(), 1)
|
||||
}
|
||||
|
||||
/// Return stock string, replacing placeholders with provided int.
|
||||
///
|
||||
/// Like [Context::stock_string_repl_str] but substitute the placeholders
|
||||
/// with an integer.
|
||||
pub fn stock_string_repl_int(&self, id: StockMessage, insert: i32) -> String {
|
||||
self.stock_string_repl_str(id, format!("{}", insert).as_str())
|
||||
}
|
||||
|
||||
/// Return stock string, replacing 2 placeholders with provided string.
|
||||
///
|
||||
/// This replaces both the *first* `%1$s` **and** `%1$d`
|
||||
/// placeholders with the string in `insert` and does the same for
|
||||
/// `%2$s` and `%2$d` for `insert2`.
|
||||
fn stock_string_repl_str2(
|
||||
&self,
|
||||
id: StockMessage,
|
||||
insert: impl AsRef<str>,
|
||||
insert2: impl AsRef<str>,
|
||||
) -> String {
|
||||
self.stock_str(id)
|
||||
.replacen("%1$s", insert.as_ref(), 1)
|
||||
.replacen("%1$d", insert.as_ref(), 1)
|
||||
.replacen("%2$s", insert2.as_ref(), 1)
|
||||
.replacen("%2$d", insert2.as_ref(), 1)
|
||||
}
|
||||
|
||||
/// Return some kind of stock message
|
||||
///
|
||||
/// If the `id` is [StockMessage::MsgAddMember] or
|
||||
/// [StockMessage::MsgDelMember] then `param1` is considered to be the
|
||||
/// contact address and will be replaced by that contact's display
|
||||
/// name.
|
||||
///
|
||||
/// If `from_id` is not `0`, any trailing dot is removed from the
|
||||
/// first stock string created so far. If the `from_id` contact is
|
||||
/// the user itself, i.e. `DC_CONTACT_ID_SELF` the string is used
|
||||
/// itself as param to the [StockMessage::MsgActionByMe] stock string
|
||||
/// resulting in a string like "Member Alice added by me." (for
|
||||
/// [StockMessage::MsgAddMember] as `id`). If the `from_id` contact
|
||||
/// is any other user than the contact's display name is looked up and
|
||||
/// used as the second parameter to [StockMessage::MsgActionByUser] with
|
||||
/// again the original stock string being used as the first parameter,
|
||||
/// resulting in a string like "Member Alice added by Bob.".
|
||||
pub fn stock_system_msg(
|
||||
&self,
|
||||
id: StockMessage,
|
||||
param1: impl AsRef<str>,
|
||||
param2: impl AsRef<str>,
|
||||
from_id: u32,
|
||||
) -> String {
|
||||
let insert1 = if id == StockMessage::MsgAddMember || id == StockMessage::MsgDelMember {
|
||||
unsafe {
|
||||
let param1_c = CString::new(param1.as_ref()).unwrap();
|
||||
let contact_id = dc_lookup_contact_id_by_addr(self, param1_c.as_ptr());
|
||||
if contact_id != 0 {
|
||||
let contact = dc_get_contact(self, contact_id);
|
||||
let displayname = dc_contact_get_name_n_addr(contact);
|
||||
let ret = to_string(displayname);
|
||||
free(contact as *mut libc::c_void);
|
||||
free(displayname as *mut libc::c_void);
|
||||
ret
|
||||
} else {
|
||||
param1.as_ref().to_string()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
param1.as_ref().to_string()
|
||||
};
|
||||
let action = self.stock_string_repl_str2(id, insert1, param2.as_ref().to_string());
|
||||
let action1 = action.trim_end_matches('.');
|
||||
match from_id {
|
||||
0 => action,
|
||||
1 => self.stock_string_repl_str(StockMessage::MsgActionByMe, action1), // DC_CONTACT_ID_SELF
|
||||
_ => unsafe {
|
||||
let contact = dc_get_contact(self, from_id);
|
||||
let displayname = dc_contact_get_display_name(contact);
|
||||
let ret = self.stock_string_repl_str2(
|
||||
StockMessage::MsgActionByUser,
|
||||
action1,
|
||||
as_str(displayname),
|
||||
);
|
||||
free(contact as *mut libc::c_void);
|
||||
free(displayname as *mut libc::c_void);
|
||||
ret
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test_utils::*;
|
||||
|
||||
use std::ffi::CString;
|
||||
|
||||
use crate::constants::DC_CONTACT_ID_SELF;
|
||||
use crate::context::dc_context_new;
|
||||
use crate::types::uintptr_t;
|
||||
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
#[test]
|
||||
fn test_enum_mapping() {
|
||||
assert_eq!(StockMessage::NoMessages.to_usize().unwrap(), 1);
|
||||
assert_eq!(StockMessage::SelfMsg.to_usize().unwrap(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fallback() {
|
||||
assert_eq!(StockMessage::NoMessages.fallback(), "No messages.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_str() {
|
||||
let ctx = dc_context_new(None, std::ptr::null_mut(), std::ptr::null_mut());
|
||||
assert_eq!(ctx.stock_str(StockMessage::NoMessages), "No messages.");
|
||||
}
|
||||
|
||||
unsafe extern "C" fn test_stock_str_no_fallback_cb(
|
||||
_ctx: &Context,
|
||||
evt: Event,
|
||||
d1: uintptr_t,
|
||||
_d2: uintptr_t,
|
||||
) -> uintptr_t {
|
||||
if evt == Event::GET_STRING && d1 == StockMessage::NoMessages.to_usize().unwrap() {
|
||||
let tmp = CString::new("Hello there").unwrap();
|
||||
dc_strdup(tmp.as_ptr()) as usize
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_str_no_fallback() {
|
||||
let t = test_context(Some(test_stock_str_no_fallback_cb));
|
||||
assert_eq!(t.ctx.stock_str(StockMessage::NoMessages), "Hello there");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_string_repl_str() {
|
||||
let ctx = dc_context_new(None, std::ptr::null_mut(), std::ptr::null_mut());
|
||||
// uses %1$s substitution
|
||||
assert_eq!(
|
||||
ctx.stock_string_repl_str(StockMessage::Member, "42"),
|
||||
"42 member(s)"
|
||||
);
|
||||
// We have no string using %1$d to test...
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_string_repl_int() {
|
||||
let ctx = dc_context_new(None, std::ptr::null_mut(), std::ptr::null_mut());
|
||||
assert_eq!(
|
||||
ctx.stock_string_repl_int(StockMessage::Member, 42),
|
||||
"42 member(s)"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_string_repl_str2() {
|
||||
let ctx = dc_context_new(None, std::ptr::null_mut(), std::ptr::null_mut());
|
||||
assert_eq!(
|
||||
ctx.stock_string_repl_str2(StockMessage::ServerResponse, "foo", "bar"),
|
||||
"Response from foo: bar"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_system_msg_simple() {
|
||||
let ctx = dc_context_new(None, std::ptr::null_mut(), std::ptr::null_mut());
|
||||
assert_eq!(
|
||||
ctx.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", 0),
|
||||
"Location streaming enabled."
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_system_msg_add_member_by_me() {
|
||||
let ctx = dc_context_new(None, std::ptr::null_mut(), std::ptr::null_mut());
|
||||
assert_eq!(
|
||||
ctx.stock_system_msg(
|
||||
StockMessage::MsgAddMember,
|
||||
"alice@example.com",
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32
|
||||
),
|
||||
"Member alice@example.com added by me."
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_system_msg_add_member_by_me_with_displayname() {
|
||||
let t = dummy_context();
|
||||
unsafe {
|
||||
let name = CString::new("Alice").unwrap();
|
||||
let addr = CString::new("alice@example.com").unwrap();
|
||||
assert!(dc_create_contact(&t.ctx, name.as_ptr(), addr.as_ptr()) > 0);
|
||||
}
|
||||
assert_eq!(
|
||||
t.ctx.stock_system_msg(
|
||||
StockMessage::MsgAddMember,
|
||||
"alice@example.com",
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32
|
||||
),
|
||||
"Member Alice (alice@example.com) added by me."
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_system_msg_add_member_by_other_with_displayname() {
|
||||
let t = dummy_context();
|
||||
let contact_id = unsafe {
|
||||
let name = CString::new("Alice").unwrap();
|
||||
let addr = CString::new("alice@example.com").unwrap();
|
||||
assert!(
|
||||
dc_create_contact(&t.ctx, name.as_ptr(), addr.as_ptr()) > 0,
|
||||
"Failed to create contact Alice"
|
||||
);
|
||||
let name = CString::new("Bob").unwrap();
|
||||
let addr = CString::new("bob@example.com").unwrap();
|
||||
let id = dc_create_contact(&t.ctx, name.as_ptr(), addr.as_ptr());
|
||||
assert!(id > 0, "Failed to create contact Bob");
|
||||
id
|
||||
};
|
||||
assert_eq!(
|
||||
t.ctx.stock_system_msg(
|
||||
StockMessage::MsgAddMember,
|
||||
"alice@example.com",
|
||||
"",
|
||||
contact_id,
|
||||
),
|
||||
"Member Alice (alice@example.com) added by Bob."
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_system_msg_grp_name() {
|
||||
let t = dummy_context();
|
||||
assert_eq!(
|
||||
t.ctx.stock_system_msg(
|
||||
StockMessage::MsgGrpName,
|
||||
"Some chat",
|
||||
"Other chat",
|
||||
DC_CONTACT_ID_SELF as u32
|
||||
),
|
||||
"Group name changed from \"Some chat\" to \"Other chat\" by me."
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stock_system_msg_grp_name_other() {
|
||||
let t = dummy_context();
|
||||
let contact_id = unsafe {
|
||||
let name = CString::new("Alice").unwrap();
|
||||
let addr = CString::new("alice@example.com").unwrap();
|
||||
let id = dc_create_contact(&t.ctx, name.as_ptr(), addr.as_ptr());
|
||||
assert!(id > 0, "Failed to create contact Alice");
|
||||
id
|
||||
};
|
||||
assert_eq!(
|
||||
t.ctx.stock_system_msg(
|
||||
StockMessage::MsgGrpName,
|
||||
"Some chat",
|
||||
"Other chat",
|
||||
contact_id
|
||||
),
|
||||
"Group name changed from \"Some chat\" to \"Other chat\" by Alice."
|
||||
)
|
||||
}
|
||||
}
|
||||
50
src/test_utils.rs
Normal file
50
src/test_utils.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
//! Utilities to help writing tests.
|
||||
//!
|
||||
//! This module is only compiled for test runs.
|
||||
|
||||
use tempfile::{tempdir, TempDir};
|
||||
|
||||
use crate::context::{dc_context_new, dc_open, Context};
|
||||
use crate::types::dc_callback_t;
|
||||
|
||||
use crate::dc_tools::OsStrExt;
|
||||
|
||||
/// A Context and temporary directory.
|
||||
///
|
||||
/// The temporary directory can be used to store the SQLite database,
|
||||
/// see e.g. [test_context] which does this.
|
||||
pub struct TestContext {
|
||||
pub ctx: Context,
|
||||
pub dir: TempDir,
|
||||
}
|
||||
|
||||
/// Create a new, opened [TestContext] using given callback.
|
||||
///
|
||||
/// The [Context] will be opened with the SQLite database named
|
||||
/// "db.sqlite" in the [TestContext.dir] directory.
|
||||
///
|
||||
/// [Context]: crate::context::Context
|
||||
pub fn test_context(cb: Option<dc_callback_t>) -> TestContext {
|
||||
unsafe {
|
||||
let mut ctx = dc_context_new(cb, std::ptr::null_mut(), std::ptr::null_mut());
|
||||
let dir = tempdir().unwrap();
|
||||
let dbfile = dir.path().join("db.sqlite");
|
||||
let dbfile_c = dbfile.to_c_string().unwrap();
|
||||
assert_eq!(
|
||||
dc_open(&mut ctx, dbfile_c.as_ptr(), std::ptr::null()),
|
||||
1,
|
||||
"Failed to open {}",
|
||||
dbfile.display(),
|
||||
);
|
||||
TestContext { ctx: ctx, dir: dir }
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a dummy [TestContext].
|
||||
///
|
||||
/// The context will be opened and use the SQLite database as
|
||||
/// specified in [test_context] but there is no callback hooked up,
|
||||
/// i.e. [Context::call_cb] will always return `0`.
|
||||
pub fn dummy_context() -> TestContext {
|
||||
test_context(None)
|
||||
}
|
||||
Reference in New Issue
Block a user