refactor(chat): store rust strings in the chat struct

This commit is contained in:
dignifiedquire
2019-08-16 00:24:39 +02:00
parent 6b3245ddfc
commit 25e97df641
9 changed files with 113 additions and 157 deletions

View File

@@ -26,9 +26,9 @@ pub struct Chat<'a> {
pub context: &'a Context,
pub id: u32,
pub typ: Chattype,
pub name: *mut libc::c_char,
pub name: String,
archived: bool,
pub grpid: *mut libc::c_char,
pub grpid: String,
blocked: Blocked,
pub param: Params,
pub gossiped_timestamp: i64,
@@ -43,30 +43,19 @@ impl<'a> Chat<'a> {
FROM chats c WHERE c.id=?;",
params![chat_id as i32],
|row| {
let mut c = Chat {
let c = Chat {
context,
id: 0,
typ: Chattype::Undefined,
name: std::ptr::null_mut(),
archived: false,
grpid: std::ptr::null_mut(),
blocked: Blocked::Not,
param: Params::new(),
gossiped_timestamp: 0,
is_sending_locations: false,
id: row.get(0)?,
typ: row.get(1)?,
name: row.get::<_, String>(2)?,
grpid: row.get::<_, String>(3)?,
param: row.get::<_, String>(4)?.parse().unwrap_or_default(),
archived: row.get(5)?,
blocked: row.get::<_, Option<_>>(6)?.unwrap_or_default(),
gossiped_timestamp: row.get(7)?,
is_sending_locations: row.get(8)?,
};
c.id = row.get(0)?;
c.typ = row.get(1)?;
c.name = unsafe { row.get::<_, String>(2)?.strdup() };
c.grpid = unsafe { row.get::<_, String>(3)?.strdup() };
c.param = row.get::<_, String>(4)?.parse().unwrap_or_default();
c.archived = row.get(5)?;
c.blocked = row.get::<_, Option<_>>(6)?.unwrap_or_default();
c.gossiped_timestamp = row.get(7)?;
c.is_sending_locations = row.get(8)?;
Ok(c)
},
);
@@ -84,44 +73,33 @@ impl<'a> Chat<'a> {
},
Ok(mut chat) => {
match chat.id {
1 => unsafe {
free(chat.name.cast());
chat.name = chat.context.stock_str(StockMessage::DeadDrop).strdup();
},
6 => unsafe {
free(chat.name.cast());
1 => {
chat.name = chat.context.stock_str(StockMessage::DeadDrop).into();
}
6 => {
let tempname = chat.context.stock_str(StockMessage::ArchivedChats);
let cnt = dc_get_archived_cnt(chat.context);
chat.name = format!("{} ({})", tempname, cnt).strdup();
},
5 => unsafe {
free(chat.name.cast());
chat.name = chat.context.stock_str(StockMessage::StarredMsgs).strdup();
},
chat.name = format!("{} ({})", tempname, cnt);
}
5 => {
chat.name = chat.context.stock_str(StockMessage::StarredMsgs).into();
}
_ => {
unsafe {
if chat.typ == Chattype::Single {
free(chat.name.cast());
let contacts = get_chat_contacts(chat.context, chat.id);
let mut chat_name = "Err [Name not found]".to_owned();
if chat.typ == Chattype::Single {
let contacts = get_chat_contacts(chat.context, chat.id);
let mut chat_name = "Err [Name not found]".to_owned();
if !(*contacts).is_empty() {
if let Ok(contact) =
Contact::get_by_id(chat.context, contacts[0])
{
chat_name = contact.get_display_name().to_owned();
}
if !(*contacts).is_empty() {
if let Ok(contact) = Contact::get_by_id(chat.context, contacts[0]) {
chat_name = contact.get_display_name().to_owned();
}
chat.name = (&chat_name).strdup();
}
chat.name = chat_name;
}
if chat.param.exists(Param::Selftalk) {
unsafe {
free(chat.name as *mut libc::c_void);
chat.name = chat.context.stock_str(StockMessage::SelfMsg).strdup();
}
chat.name = chat.context.stock_str(StockMessage::SelfMsg).into();
}
}
}
@@ -143,29 +121,30 @@ impl<'a> Chat<'a> {
)
}
pub unsafe fn get_id(&self) -> u32 {
pub fn get_id(&self) -> u32 {
self.id
}
pub unsafe fn get_type(&self) -> Chattype {
pub fn get_type(&self) -> Chattype {
self.typ
}
pub unsafe fn get_name(&self) -> *mut libc::c_char {
dc_strdup(self.name)
pub fn get_name(&self) -> &str {
&self.name
}
pub unsafe fn get_subtitle(&self) -> *mut libc::c_char {
/* returns either the address or the number of chat members */
pub fn get_subtitle(&self) -> String {
// returns either the address or the number of chat members
let mut ret: *mut libc::c_char = std::ptr::null_mut();
if self.typ == Chattype::Single && self.param.exists(Param::Selftalk) {
ret = self
return self
.context
.stock_str(StockMessage::SelfTalkSubTitle)
.strdup();
} else if self.typ == Chattype::Single {
let ret_raw: String = self
.into();
}
if self.typ == Chattype::Single {
return self
.context
.sql
.query_row_col(
@@ -177,24 +156,22 @@ impl<'a> Chat<'a> {
0,
)
.unwrap_or_else(|| "Err".into());
ret = ret_raw.strdup();
} else if self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup {
}
if self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup {
if self.id == 1 {
ret = self.context.stock_str(StockMessage::DeadDrop).strdup();
} else {
let cnt = get_chat_contact_cnt(self.context, self.id);
ret = self
.context
.stock_string_repl_int(StockMessage::Member, cnt)
.strdup();
return self.context.stock_str(StockMessage::DeadDrop).into();
}
let cnt = get_chat_contact_cnt(self.context, self.id);
return self
.context
.stock_string_repl_int(StockMessage::Member, cnt)
.into();
}
if !ret.is_null() {
ret
} else {
dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char)
}
return "Err".into();
}
unsafe fn get_parent_mime_headers(
&self,
parent_rfc724_mid: *mut *mut libc::c_char,
@@ -264,7 +241,7 @@ impl<'a> Chat<'a> {
}
pub fn get_color(&self) -> u32 {
let mut color: u32 = 0i32 as u32;
let mut color = 0;
if self.typ == Chattype::Single {
let contacts = get_chat_contacts(self.context, self.id);
@@ -274,7 +251,7 @@ impl<'a> Chat<'a> {
}
}
} else {
color = unsafe { dc_str_to_color(self.name) } as u32
color = dc_str_to_color(&self.name);
}
color
@@ -338,7 +315,7 @@ impl<'a> Chat<'a> {
let from_c = CString::yolo(from.unwrap());
new_rfc724_mid = dc_create_outgoing_rfc724_mid(
if self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup {
self.grpid
self.grpid.strdup()
} else {
ptr::null_mut()
},
@@ -1663,7 +1640,7 @@ pub unsafe fn remove_contact_from_chat(
if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
(*msg).type_0 = Viewtype::Text;
if contact.id == DC_CONTACT_ID_SELF as u32 {
set_group_explicitly_left(context, chat.grpid);
set_group_explicitly_left(context, chat.grpid).unwrap();
(*msg).text = Some(context.stock_system_msg(
StockMessage::MsgGroupLeft,
"",
@@ -1707,41 +1684,38 @@ pub unsafe fn remove_contact_from_chat(
success
}
// Should return Result
fn set_group_explicitly_left(context: &Context, grpid: *const libc::c_char) {
if 0 == is_group_explicitly_left(context, grpid) {
fn set_group_explicitly_left(context: &Context, grpid: impl AsRef<str>) -> Result<(), Error> {
if !is_group_explicitly_left(context, grpid.as_ref())? {
sql::execute(
context,
&context.sql,
"INSERT INTO leftgrps (grpid) VALUES(?);",
params![as_str(grpid)],
)
.ok();
params![grpid.as_ref()],
)?;
}
Ok(())
}
// TODO should return bool /rtn
pub fn is_group_explicitly_left(context: &Context, grpid: *const libc::c_char) -> libc::c_int {
context
.sql
.exists(
"SELECT id FROM leftgrps WHERE grpid=?;",
params![as_str(grpid)],
)
.unwrap_or_default() as libc::c_int
pub fn is_group_explicitly_left(context: &Context, grpid: impl AsRef<str>) -> Result<bool, Error> {
context.sql.exists(
"SELECT id FROM leftgrps WHERE grpid=?;",
params![grpid.as_ref()],
)
}
// TODO should return bool /rtn
pub unsafe fn set_chat_name(
context: &Context,
chat_id: u32,
new_name: *const libc::c_char,
new_name: impl AsRef<str>,
) -> libc::c_int {
/* the function only sets the names of group chats; normal chats get their names from the contacts */
let mut success: libc::c_int = 0i32;
let mut msg = dc_msg_new_untyped(context);
if new_name.is_null() || *new_name.offset(0isize) as libc::c_int == 0 || chat_id <= 9 {
if new_name.as_ref().is_empty() || chat_id <= DC_CHAT_ID_LAST_SPECIAL as u32 {
return 0;
}
@@ -1749,9 +1723,9 @@ pub unsafe fn set_chat_name(
if !(0i32 == real_group_exists(context, chat_id) || chat.is_err()) {
let chat = chat.unwrap();
if strcmp(chat.name, new_name) == 0i32 {
success = 1i32
} else if !(is_contact_in_chat(context, chat_id, 1i32 as u32) == 1i32) {
if &chat.name == new_name.as_ref() {
success = 1;
} else if !(is_contact_in_chat(context, chat_id, 1) == 1) {
log_event!(
context,
Event::ERROR_SELF_NOT_IN_GROUP,
@@ -1765,7 +1739,7 @@ pub unsafe fn set_chat_name(
&context.sql,
format!(
"UPDATE chats SET name='{}' WHERE id={};",
as_str(new_name),
new_name.as_ref(),
chat_id as i32
),
params![],
@@ -1776,13 +1750,13 @@ pub unsafe fn set_chat_name(
(*msg).type_0 = Viewtype::Text;
(*msg).text = Some(context.stock_system_msg(
StockMessage::MsgGrpName,
as_str(chat.name),
as_str(new_name),
&chat.name,
new_name.as_ref(),
DC_CONTACT_ID_SELF as u32,
));
(*msg).param.set_int(Param::Cmd, 2);
if !chat.name.is_null() {
(*msg).param.set(Param::Arg, as_str(chat.name));
if !chat.name.is_empty() {
(*msg).param.set(Param::Arg, &chat.name);
}
(*msg).id = send_msg(context, chat_id, msg).unwrap_or_default();
context.call_cb(
@@ -2088,12 +2062,3 @@ pub fn add_device_msg(context: &Context, chat_id: u32, text: *const libc::c_char
msg_id as uintptr_t,
);
}
impl<'a> Drop for Chat<'a> {
fn drop(&mut self) {
unsafe {
free(self.name.cast());
free(self.grpid.cast());
}
}
}

View File

@@ -791,7 +791,7 @@ impl<'a> Contact<'a> {
/// and can be used for an fallback avatar with white initials
/// as well as for headlines in bubbles of group chats.
pub fn get_color(&self) -> u32 {
dc_str_to_color_safe(&self.addr)
dc_str_to_color(&self.addr)
}
/// Check if a contact was verified. E.g. by a secure-join QR code scan

View File

@@ -548,14 +548,15 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
imf_fields,
mailimf_field_new_custom(
strdup(b"Chat-Group-ID\x00" as *const u8 as *const libc::c_char),
dc_strdup(chat.grpid),
chat.grpid.strdup(),
),
);
let name = CString::yolo(chat.name.as_bytes());
mailimf_fields_add(
imf_fields,
mailimf_field_new_custom(
strdup(b"Chat-Group-Name\x00" as *const u8 as *const libc::c_char),
dc_encode_header_words(chat.name),
dc_encode_header_words(name.as_ptr()),
),
);
if command == 5 {
@@ -1090,12 +1091,13 @@ unsafe fn get_subject(
if (*msg).param.get_int(Param::Cmd).unwrap_or_default() == 6 {
ret = context.stock_str(StockMessage::AcSetupMsgSubject).strdup()
} else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
ret = dc_mprintf(
b"Chat: %s: %s%s\x00" as *const u8 as *const libc::c_char,
ret = format!(
"Chat: {}: {}{}",
chat.name,
fwd,
raw_subject,
to_string(fwd),
to_string(raw_subject),
)
.strdup()
} else {
ret = dc_mprintf(
b"Chat: %s%s\x00" as *const u8 as *const libc::c_char,

View File

@@ -1041,7 +1041,7 @@ unsafe fn create_or_lookup_group(
ret_chat_id: *mut uint32_t,
ret_chat_id_blocked: &mut Blocked,
) {
let group_explicitly_left: libc::c_int;
let group_explicitly_left: bool;
let mut chat_id = 0;
let mut chat_id_blocked = Blocked::Not;
let mut chat_id_verified = 0;
@@ -1252,7 +1252,8 @@ unsafe fn create_or_lookup_group(
}
// check if the group does not exist but should be created
group_explicitly_left = chat::is_group_explicitly_left(context, grpid);
group_explicitly_left =
chat::is_group_explicitly_left(context, as_str(grpid)).unwrap_or_default();
let self_addr = context
.sql
@@ -1265,7 +1266,7 @@ unsafe fn create_or_lookup_group(
// otherwise, a pending "quit" message may pop up
&& X_MrRemoveFromGrp.is_null()
// re-create explicitly left groups only if ourself is re-added
&& (0 == group_explicitly_left
&& (!group_explicitly_left
|| !X_MrAddToGrp.is_null() && addr_cmp(&self_addr, as_str(X_MrAddToGrp)))
{
let mut create_verified: libc::c_int = 0;
@@ -1301,7 +1302,7 @@ unsafe fn create_or_lookup_group(
// again, check chat_id
if chat_id <= DC_CHAT_ID_LAST_SPECIAL as u32 {
chat_id = 0;
if 0 != group_explicitly_left {
if group_explicitly_left {
chat_id = DC_CHAT_ID_TRASH as u32;
} else {
create_or_lookup_adhoc_group(

View File

@@ -14,7 +14,6 @@ use crate::dc_lot::*;
use crate::dc_mimeparser::*;
use crate::dc_msg::*;
use crate::dc_qr::*;
use crate::dc_strencode::*;
use crate::dc_token::*;
use crate::dc_tools::*;
use crate::key::*;
@@ -36,8 +35,6 @@ pub unsafe fn dc_get_securejoin_qr(
let mut fingerprint = 0 as *mut libc::c_char;
let mut invitenumber: *mut libc::c_char;
let mut auth: *mut libc::c_char;
let mut group_name = 0 as *mut libc::c_char;
let mut group_name_urlencoded = 0 as *mut libc::c_char;
let mut qr: Option<String> = None;
dc_ensure_secret_key_exists(context).ok();
@@ -53,12 +50,10 @@ pub unsafe fn dc_get_securejoin_qr(
}
let self_addr = context.sql.get_config(context, "configured_addr");
let cleanup = |fingerprint, group_name, group_name_urlencoded| {
let cleanup = |fingerprint| {
free(fingerprint as *mut libc::c_void);
free(invitenumber as *mut libc::c_void);
free(auth as *mut libc::c_void);
free(group_name as *mut libc::c_void);
free(group_name_urlencoded as *mut libc::c_void);
if let Some(qr) = qr {
qr.strdup()
@@ -69,7 +64,7 @@ pub unsafe fn dc_get_securejoin_qr(
if self_addr.is_none() {
error!(context, 0, "Not configured, cannot generate QR code.",);
return cleanup(fingerprint, group_name, group_name_urlencoded);
return cleanup(fingerprint);
}
let self_addr = self_addr.unwrap();
@@ -81,7 +76,7 @@ pub unsafe fn dc_get_securejoin_qr(
fingerprint = get_self_fingerprint(context);
if fingerprint.is_null() {
return cleanup(fingerprint, group_name, group_name_urlencoded);
return cleanup(fingerprint);
}
let self_addr_urlencoded = utf8_percent_encode(&self_addr, NON_ALPHANUMERIC).to_string();
@@ -89,15 +84,16 @@ pub unsafe fn dc_get_securejoin_qr(
qr = if 0 != group_chat_id {
if let Ok(chat) = Chat::load_from_db(context, group_chat_id) {
group_name = chat.get_name();
group_name_urlencoded = dc_urlencode(group_name);
let group_name = chat.get_name();
let group_name_urlencoded =
utf8_percent_encode(&group_name, NON_ALPHANUMERIC).to_string();
Some(format!(
"OPENPGP4FPR:{}#a={}&g={}&x={}&i={}&s={}",
as_str(fingerprint),
self_addr_urlencoded,
as_str(group_name_urlencoded),
as_str(chat.grpid),
&group_name_urlencoded,
&chat.grpid,
as_str(invitenumber),
as_str(auth),
))
@@ -106,7 +102,7 @@ pub unsafe fn dc_get_securejoin_qr(
context,
0, "Cannot get QR-code for chat-id {}", group_chat_id,
);
return cleanup(fingerprint, group_name, group_name_urlencoded);
return cleanup(fingerprint);
}
} else {
Some(format!(
@@ -121,7 +117,7 @@ pub unsafe fn dc_get_securejoin_qr(
info!(context, 0, "Generated QR code: {}", qr.as_ref().unwrap());
cleanup(fingerprint, group_name, group_name_urlencoded)
cleanup(fingerprint)
}
fn get_self_fingerprint(context: &Context) -> *mut libc::c_char {

View File

@@ -532,7 +532,7 @@ const COLORS: [u32; 16] = [
0x39b249, 0xbb243b, 0x964078, 0x66874f, 0x308ab9, 0x127ed0, 0xbe450c,
];
pub fn dc_str_to_color_safe(s: impl AsRef<str>) -> u32 {
pub fn dc_str_to_color(s: impl AsRef<str>) -> u32 {
let str_lower = s.as_ref().to_lowercase();
let mut checksum = 0;
let bytes = str_lower.as_bytes();
@@ -545,10 +545,6 @@ pub fn dc_str_to_color_safe(s: impl AsRef<str>) -> u32 {
COLORS[color_index]
}
pub unsafe fn dc_str_to_color(str: *const libc::c_char) -> libc::c_int {
dc_str_to_color_safe(as_str(str)) as libc::c_int
}
/* clist tools */
/* calls free() for each item content */
pub unsafe fn clist_free_content(haystack: *const clist) {