Change type of function from `const char *' to &str (#451)

Change type of function from `const char *' to &str
This commit is contained in:
Friedel Ziegelmayer
2019-09-08 11:51:16 +02:00
committed by GitHub
6 changed files with 274 additions and 346 deletions

View File

@@ -171,51 +171,20 @@ impl<'a> Chat<'a> {
return "Err".into(); return "Err".into();
} }
unsafe fn get_parent_mime_headers( pub fn get_parent_mime_headers(&self) -> Option<(String, String, String)> {
&self, let collect = |row: &rusqlite::Row| Ok((row.get(0)?, row.get(1)?, row.get(2)?));
parent_rfc724_mid: *mut *mut libc::c_char, let params = params![self.id as i32, DC_CONTACT_ID_SELF as i32];
parent_in_reply_to: *mut *mut libc::c_char, let sql = &self.context.sql;
parent_references: *mut *mut libc::c_char, let main_query = "SELECT rfc724_mid, mime_in_reply_to, mime_references \
) -> Result<(), Error> {
if !(parent_rfc724_mid.is_null()
|| parent_in_reply_to.is_null()
|| parent_references.is_null())
{
// prefer a last message that isn't from us
let next = self
.context
.sql
.query_row(
"SELECT rfc724_mid, mime_in_reply_to, mime_references \
FROM msgs WHERE chat_id=?1 AND timestamp=(SELECT max(timestamp) \ FROM msgs WHERE chat_id=?1 AND timestamp=(SELECT max(timestamp) \
FROM msgs WHERE chat_id=?1 AND from_id!=?2);", FROM msgs WHERE chat_id=?1 AND from_id!=?2);";
params![self.id as i32, DC_CONTACT_ID_SELF as i32], let fallback_query = "SELECT rfc724_mid, mime_in_reply_to, mime_references \
|row| {
*parent_rfc724_mid = row.get::<_, String>(0)?.strdup();
*parent_in_reply_to = row.get::<_, String>(1)?.strdup();
*parent_references = row.get::<_, String>(2)?.strdup();
Ok(())
},
)
.is_ok();
if !next {
self.context.sql.query_row(
"SELECT rfc724_mid, mime_in_reply_to, mime_references \
FROM msgs WHERE chat_id=?1 AND timestamp=(SELECT min(timestamp) \ FROM msgs WHERE chat_id=?1 AND timestamp=(SELECT min(timestamp) \
FROM msgs WHERE chat_id=?1 AND from_id==?2);", FROM msgs WHERE chat_id=?1 AND from_id==?2);";
params![self.id as i32, DC_CONTACT_ID_SELF as i32],
|row| {
*parent_rfc724_mid = row.get::<_, String>(0)?.strdup();
*parent_in_reply_to = row.get::<_, String>(1)?.strdup();
*parent_references = row.get::<_, String>(2)?.strdup();
Ok(())
},
)?;
}
}
Ok(()) sql.query_row(main_query, params, collect)
.or_else(|_| sql.query_row(fallback_query, params, collect))
.ok()
} }
pub unsafe fn get_profile_image(&self) -> Option<String> { pub unsafe fn get_profile_image(&self) -> Option<String> {
@@ -277,13 +246,8 @@ impl<'a> Chat<'a> {
) -> Result<u32, Error> { ) -> Result<u32, Error> {
let mut do_guarantee_e2ee: libc::c_int; let mut do_guarantee_e2ee: libc::c_int;
let e2ee_enabled: libc::c_int; let e2ee_enabled: libc::c_int;
let mut OK_TO_CONTINUE = true; let mut new_references = "".into();
let mut parent_rfc724_mid = ptr::null_mut(); let mut new_in_reply_to = "".into();
let mut parent_references = ptr::null_mut();
let mut parent_in_reply_to = ptr::null_mut();
let mut new_rfc724_mid = ptr::null_mut();
let mut new_references = ptr::null_mut();
let mut new_in_reply_to = ptr::null_mut();
let mut msg_id = 0; let mut msg_id = 0;
let mut to_id = 0; let mut to_id = 0;
let mut location_id = 0; let mut location_id = 0;
@@ -293,7 +257,10 @@ impl<'a> Chat<'a> {
|| self.typ == Chattype::VerifiedGroup) || self.typ == Chattype::VerifiedGroup)
{ {
error!(context, 0, "Cannot send to chat type #{}.", self.typ,); error!(context, 0, "Cannot send to chat type #{}.", self.typ,);
} else if (self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup) return Ok(0);
}
if (self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup)
&& 0 == is_contact_in_chat(context, self.id, 1 as u32) && 0 == is_contact_in_chat(context, self.id, 1 as u32)
{ {
log_event!( log_event!(
@@ -302,17 +269,17 @@ impl<'a> Chat<'a> {
0, 0,
"Cannot send message; self not in group.", "Cannot send message; self not in group.",
); );
} else { return Ok(0);
}
if let Some(from) = context.sql.get_config(context, "configured_addr") { if let Some(from) = context.sql.get_config(context, "configured_addr") {
let from_c = CString::yolo(from); let new_rfc724_mid = {
new_rfc724_mid = dc_create_outgoing_rfc724_mid( let grpid = match self.typ {
if self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup { Chattype::Group | Chattype::VerifiedGroup => Some(self.grpid.as_str()),
self.grpid.strdup() _ => None,
} else { };
ptr::null_mut() dc_create_outgoing_rfc724_mid_safe(grpid, &from)
}, };
from_c.as_ptr(),
);
if self.typ == Chattype::Single { if self.typ == Chattype::Single {
if let Some(id) = context.sql.query_row_col( if let Some(id) = context.sql.query_row_col(
@@ -327,7 +294,7 @@ impl<'a> Chat<'a> {
context, context,
0, "Cannot send message, contact for chat #{} not found.", self.id, 0, "Cannot send message, contact for chat #{} not found.", self.id,
); );
OK_TO_CONTINUE = false; return Ok(0);
} }
} else { } else {
if self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup { if self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup {
@@ -337,7 +304,7 @@ impl<'a> Chat<'a> {
} }
} }
} }
if OK_TO_CONTINUE {
/* check if we can guarantee E2EE for this message. /* check if we can guarantee E2EE for this message.
if we guarantee E2EE, and circumstances change if we guarantee E2EE, and circumstances change
so that E2EE is no longer available at a later point (reset, changed settings), so that E2EE is no longer available at a later point (reset, changed settings),
@@ -405,56 +372,29 @@ impl<'a> Chat<'a> {
msg.param.set_int(Param::GuranteeE2ee, 1); msg.param.set_int(Param::GuranteeE2ee, 1);
} }
msg.param.remove(Param::ErroneousE2ee); msg.param.remove(Param::ErroneousE2ee);
if !self.is_self_talk() if !self.is_self_talk() {
&& self if let Some((parent_rfc724_mid, parent_in_reply_to, parent_references)) =
.get_parent_mime_headers( self.get_parent_mime_headers()
&mut parent_rfc724_mid,
&mut parent_in_reply_to,
&mut parent_references,
)
.is_ok()
{ {
if !parent_rfc724_mid.is_null() if !parent_rfc724_mid.is_empty() {
&& 0 != *parent_rfc724_mid.offset(0isize) as libc::c_int new_in_reply_to = parent_rfc724_mid.clone();
{
new_in_reply_to = dc_strdup(parent_rfc724_mid)
} }
if !parent_references.is_null() { let parent_references = if let Some(n) = parent_references.find(' ') {
let space: *mut libc::c_char; &parent_references[0..n]
space = strchr(parent_references, ' ' as i32); } else {
if !space.is_null() { &parent_references
*space = 0 as libc::c_char };
if !parent_references.is_empty() && !parent_rfc724_mid.is_empty() {
new_references = format!("{} {}", parent_references, parent_rfc724_mid);
} else if !parent_references.is_empty() {
new_references = parent_references.to_string();
} else if !parent_in_reply_to.is_empty() && !parent_rfc724_mid.is_empty() {
new_references = format!("{} {}", parent_in_reply_to, parent_rfc724_mid);
} else if !parent_in_reply_to.is_empty() {
new_references = parent_in_reply_to.clone();
} }
} }
if !parent_references.is_null()
&& 0 != *parent_references.offset(0isize) as libc::c_int
&& !parent_rfc724_mid.is_null()
&& 0 != *parent_rfc724_mid.offset(0isize) as libc::c_int
{
new_references = dc_mprintf(
b"%s %s\x00" as *const u8 as *const libc::c_char,
parent_references,
parent_rfc724_mid,
)
} else if !parent_references.is_null()
&& 0 != *parent_references.offset(0isize) as libc::c_int
{
new_references = dc_strdup(parent_references)
} else if !parent_in_reply_to.is_null()
&& 0 != *parent_in_reply_to.offset(0isize) as libc::c_int
&& !parent_rfc724_mid.is_null()
&& 0 != *parent_rfc724_mid.offset(0isize) as libc::c_int
{
new_references = dc_mprintf(
b"%s %s\x00" as *const u8 as *const libc::c_char,
parent_in_reply_to,
parent_rfc724_mid,
)
} else if !parent_in_reply_to.is_null()
&& 0 != *parent_in_reply_to.offset(0isize) as libc::c_int
{
new_references = dc_strdup(parent_in_reply_to)
}
} }
// add independent location to database // add independent location to database
@@ -495,7 +435,7 @@ impl<'a> Chat<'a> {
&context.sql, &context.sql,
"INSERT INTO msgs (rfc724_mid, chat_id, from_id, to_id, timestamp, type, state, txt, param, hidden, mime_in_reply_to, mime_references, location_id) VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?,?);", "INSERT INTO msgs (rfc724_mid, chat_id, from_id, to_id, timestamp, type, state, txt, param, hidden, mime_in_reply_to, mime_references, location_id) VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?,?);",
params![ params![
as_str(new_rfc724_mid), new_rfc724_mid,
self.id as i32, self.id as i32,
1i32, 1i32,
to_id as i32, to_id as i32,
@@ -505,8 +445,8 @@ impl<'a> Chat<'a> {
msg.text.as_ref().map_or("", String::as_str), msg.text.as_ref().map_or("", String::as_str),
msg.param.to_string(), msg.param.to_string(),
msg.hidden, msg.hidden,
to_string(new_in_reply_to), new_in_reply_to,
to_string(new_references), new_references,
location_id as i32, location_id as i32,
] ]
).is_ok() { ).is_ok() {
@@ -515,7 +455,7 @@ impl<'a> Chat<'a> {
&context.sql, &context.sql,
"msgs", "msgs",
"rfc724_mid", "rfc724_mid",
as_str(new_rfc724_mid), new_rfc724_mid,
); );
} else { } else {
error!( error!(
@@ -525,18 +465,9 @@ impl<'a> Chat<'a> {
self.id, self.id,
); );
} }
}
} else { } else {
error!(context, 0, "Cannot send message, not configured.",); error!(context, 0, "Cannot send message, not configured.",);
} }
}
free(parent_rfc724_mid as *mut libc::c_void);
free(parent_in_reply_to as *mut libc::c_void);
free(parent_references as *mut libc::c_void);
free(new_rfc724_mid as *mut libc::c_void);
free(new_in_reply_to as *mut libc::c_void);
free(new_references as *mut libc::c_void);
Ok(msg_id) Ok(msg_id)
} }

View File

@@ -148,7 +148,7 @@ pub unsafe fn dc_mimefactory_load_msg(
for row in rows { for row in rows {
let (authname, addr) = row?; let (authname, addr) = row?;
let addr_c = addr.strdup(); let addr_c = addr.strdup();
if clist_search_string_nocase(factory.recipients_addr, addr_c) == 0 { if !clist_search_string_nocase(factory.recipients_addr, addr_c) {
clist_insert_after( clist_insert_after(
factory.recipients_names, factory.recipients_names,
(*factory.recipients_names).last, (*factory.recipients_names).last,
@@ -183,7 +183,7 @@ pub unsafe fn dc_mimefactory_load_msg(
.unwrap_or_default(); .unwrap_or_default();
if !email_to_remove.is_empty() && email_to_remove != self_addr { if !email_to_remove.is_empty() && email_to_remove != self_addr {
if clist_search_string_nocase(factory.recipients_addr, email_to_remove_c) == 0 { if !clist_search_string_nocase(factory.recipients_addr, email_to_remove_c) {
clist_insert_after( clist_insert_after(
factory.recipients_names, factory.recipients_names,
(*factory.recipients_names).last, (*factory.recipients_names).last,

View File

@@ -32,10 +32,10 @@ dc_mimeparser_t has no deep dependencies to Context or to the database
#[repr(C)] #[repr(C)]
pub struct dc_mimepart_t { pub struct dc_mimepart_t {
pub type_0: Viewtype, pub type_0: Viewtype,
pub is_meta: libc::c_int, pub is_meta: bool,
pub int_mimetype: libc::c_int, pub int_mimetype: libc::c_int,
pub msg: Option<String>, pub msg: Option<String>,
pub msg_raw: *mut libc::c_char, pub msg_raw: Option<String>,
pub bytes: libc::c_int, pub bytes: libc::c_int,
pub param: Params, pub param: Params,
} }
@@ -50,11 +50,11 @@ pub struct dc_mimeparser_t<'a> {
pub header: HashMap<String, *mut mailimf_field>, pub header: HashMap<String, *mut mailimf_field>,
pub header_root: *mut mailimf_fields, pub header_root: *mut mailimf_fields,
pub header_protected: *mut mailimf_fields, pub header_protected: *mut mailimf_fields,
pub subject: *mut libc::c_char, pub subject: Option<String>,
pub is_send_by_messenger: bool, pub is_send_by_messenger: bool,
pub decrypting_failed: libc::c_int, pub decrypting_failed: bool,
pub e2ee_helper: E2eeHelper, pub e2ee_helper: E2eeHelper,
pub is_forwarded: libc::c_int, pub is_forwarded: bool,
pub context: &'a Context, pub context: &'a Context,
pub reports: Vec<*mut mailmime>, pub reports: Vec<*mut mailmime>,
pub is_system_message: libc::c_int, pub is_system_message: libc::c_int,
@@ -69,11 +69,11 @@ pub fn dc_mimeparser_new(context: &Context) -> dc_mimeparser_t {
header: Default::default(), header: Default::default(),
header_root: std::ptr::null_mut(), header_root: std::ptr::null_mut(),
header_protected: std::ptr::null_mut(), header_protected: std::ptr::null_mut(),
subject: std::ptr::null_mut(), subject: None,
is_send_by_messenger: false, is_send_by_messenger: false,
decrypting_failed: 0, decrypting_failed: false,
e2ee_helper: Default::default(), e2ee_helper: Default::default(),
is_forwarded: 0, is_forwarded: false,
context, context,
reports: Vec::new(), reports: Vec::new(),
is_system_message: 0, is_system_message: 0,
@@ -87,10 +87,7 @@ pub unsafe fn dc_mimeparser_unref(mimeparser: &mut dc_mimeparser_t) {
} }
unsafe fn dc_mimeparser_empty(mimeparser: &mut dc_mimeparser_t) { unsafe fn dc_mimeparser_empty(mimeparser: &mut dc_mimeparser_t) {
for part in mimeparser.parts.drain(..) { mimeparser.parts = vec![];
dc_mimepart_unref(part);
}
assert!(mimeparser.parts.is_empty());
mimeparser.header_root = ptr::null_mut(); mimeparser.header_root = ptr::null_mut();
mimeparser.header.clear(); mimeparser.header.clear();
if !mimeparser.header_protected.is_null() { if !mimeparser.header_protected.is_null() {
@@ -99,26 +96,20 @@ unsafe fn dc_mimeparser_empty(mimeparser: &mut dc_mimeparser_t) {
} }
mimeparser.is_send_by_messenger = false; mimeparser.is_send_by_messenger = false;
mimeparser.is_system_message = 0i32; mimeparser.is_system_message = 0i32;
free(mimeparser.subject as *mut libc::c_void); mimeparser.subject = None;
mimeparser.subject = ptr::null_mut();
if !mimeparser.mimeroot.is_null() { if !mimeparser.mimeroot.is_null() {
mailmime_free(mimeparser.mimeroot); mailmime_free(mimeparser.mimeroot);
mimeparser.mimeroot = ptr::null_mut() mimeparser.mimeroot = ptr::null_mut()
} }
mimeparser.is_forwarded = 0i32; mimeparser.is_forwarded = false;
mimeparser.reports.clear(); mimeparser.reports.clear();
mimeparser.decrypting_failed = 0i32; mimeparser.decrypting_failed = false;
mimeparser.e2ee_helper.thanks(); mimeparser.e2ee_helper.thanks();
mimeparser.location_kml = None; mimeparser.location_kml = None;
mimeparser.message_kml = None; mimeparser.message_kml = None;
} }
unsafe fn dc_mimepart_unref(mut mimepart: dc_mimepart_t) {
mimepart.msg = None;
free(mimepart.msg_raw as *mut libc::c_void);
mimepart.msg_raw = ptr::null_mut();
}
const DC_MIMETYPE_AC_SETUP_FILE: i32 = 111; const DC_MIMETYPE_AC_SETUP_FILE: i32 = 111;
pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_mimeparser_t<'a> { pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_mimeparser_t<'a> {
@@ -141,7 +132,15 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
dc_mimeparser_parse_mime_recursive(mimeparser_ref, mimeparser_ref.mimeroot); dc_mimeparser_parse_mime_recursive(mimeparser_ref, mimeparser_ref.mimeroot);
let field: *mut mailimf_field = dc_mimeparser_lookup_field(&mimeparser, "Subject"); let field: *mut mailimf_field = dc_mimeparser_lookup_field(&mimeparser, "Subject");
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int {
mimeparser.subject = dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value) let decoded = dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value);
if decoded.is_null()
/* XXX: can it happen? */
{
mimeparser.subject = None
} else {
mimeparser.subject = Some(to_string(decoded));
free(decoded.cast());
}
} }
if !dc_mimeparser_lookup_optional_field(&mut mimeparser, "Chat-Version").is_null() { if !dc_mimeparser_lookup_optional_field(&mut mimeparser, "Chat-Version").is_null() {
mimeparser.is_send_by_messenger = true mimeparser.is_send_by_messenger = true
@@ -169,8 +168,7 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
let mut i = 0; let mut i = 0;
while i != mimeparser.parts.len() { while i != mimeparser.parts.len() {
if mimeparser.parts[i].int_mimetype != 111 { if mimeparser.parts[i].int_mimetype != 111 {
let part = mimeparser.parts.remove(i); mimeparser.parts.remove(i);
dc_mimepart_unref(part);
} else { } else {
i += 1; i += 1;
} }
@@ -196,7 +194,7 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
if mimeparser.parts.len() >= 2 { if mimeparser.parts.len() >= 2 {
let imgpart = &mut mimeparser.parts[1]; let imgpart = &mut mimeparser.parts[1];
if imgpart.type_0 == Viewtype::Image { if imgpart.type_0 == Viewtype::Image {
imgpart.is_meta = 1i32 imgpart.is_meta = true;
} }
} }
} }
@@ -212,7 +210,7 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
|| filepart.type_0 == Viewtype::Voice || filepart.type_0 == Viewtype::Voice
|| filepart.type_0 == Viewtype::Video || filepart.type_0 == Viewtype::Video
|| filepart.type_0 == Viewtype::File) || filepart.type_0 == Viewtype::File)
&& 0 == filepart.is_meta && !filepart.is_meta
}; };
if need_drop { if need_drop {
@@ -225,42 +223,37 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
mimeparser.parts[0].msg = None; mimeparser.parts[0].msg = None;
// swap new with old // swap new with old
let old = std::mem::replace(&mut mimeparser.parts[0], filepart); std::mem::replace(&mut mimeparser.parts[0], filepart);
// unref old one
dc_mimepart_unref(old);
} }
} }
if !mimeparser.subject.is_null() { if let Some(ref subject) = mimeparser.subject {
let mut prepend_subject: libc::c_int = 1i32; let mut prepend_subject: libc::c_int = 1i32;
if 0 == mimeparser.decrypting_failed { if !mimeparser.decrypting_failed {
let p: *mut libc::c_char = strchr(mimeparser.subject, ':' as i32); let colon = subject.find(':');
if p.wrapping_offset_from(mimeparser.subject) == 2 if colon == Some(2)
|| p.wrapping_offset_from(mimeparser.subject) == 3 || colon == Some(3)
|| mimeparser.is_send_by_messenger || mimeparser.is_send_by_messenger
|| !strstr( || subject.contains("Chat:")
mimeparser.subject,
b"Chat:\x00" as *const u8 as *const libc::c_char,
)
.is_null()
{ {
prepend_subject = 0i32 prepend_subject = 0i32
} }
} }
if 0 != prepend_subject { if 0 != prepend_subject {
let subj: *mut libc::c_char = dc_strdup(mimeparser.subject); let subj = if let Some(n) = subject.find('[') {
let p_0: *mut libc::c_char = strchr(subj, '[' as i32); &subject[0..n]
if !p_0.is_null() { } else {
*p_0 = 0i32 as libc::c_char subject
} }
dc_trim(subj); .trim();
if 0 != *subj.offset(0isize) {
if !subj.is_empty() {
let subj_c = CString::yolo(subj);
for part in mimeparser.parts.iter_mut() { for part in mimeparser.parts.iter_mut() {
if part.type_0 == Viewtype::Text { if part.type_0 == Viewtype::Text {
let msg_c = part.msg.as_ref().unwrap().strdup(); let msg_c = part.msg.as_ref().unwrap().strdup();
let new_txt: *mut libc::c_char = dc_mprintf( let new_txt: *mut libc::c_char = dc_mprintf(
b"%s \xe2\x80\x93 %s\x00" as *const u8 as *const libc::c_char, b"%s \xe2\x80\x93 %s\x00" as *const u8 as *const libc::c_char,
subj, subj_c.as_ptr(),
msg_c, msg_c,
); );
free(msg_c.cast()); free(msg_c.cast());
@@ -270,10 +263,9 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
} }
} }
} }
free(subj as *mut libc::c_void);
} }
} }
if 0 != mimeparser.is_forwarded { if mimeparser.is_forwarded {
for part in mimeparser.parts.iter_mut() { for part in mimeparser.parts.iter_mut() {
part.param.set_int(Param::Forwarded, 1); part.param.set_int(Param::Forwarded, 1);
} }
@@ -301,7 +293,7 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
} }
} }
} }
if 0 == mimeparser.decrypting_failed { if !mimeparser.decrypting_failed {
let dn_field: *const mailimf_optional_field = dc_mimeparser_lookup_optional_field( let dn_field: *const mailimf_optional_field = dc_mimeparser_lookup_optional_field(
&mimeparser, &mimeparser,
"Chat-Disposition-Notification-To", "Chat-Disposition-Notification-To",
@@ -350,10 +342,12 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
if dc_mimeparser_get_last_nonmeta(&mut mimeparser).is_none() && mimeparser.reports.is_empty() { if dc_mimeparser_get_last_nonmeta(&mut mimeparser).is_none() && mimeparser.reports.is_empty() {
let mut part_5 = dc_mimepart_new(); let mut part_5 = dc_mimepart_new();
part_5.type_0 = Viewtype::Text; part_5.type_0 = Viewtype::Text;
if !mimeparser.subject.is_null() && !mimeparser.is_send_by_messenger {
part_5.msg = Some(to_string(mimeparser.subject));
} else {
part_5.msg = Some("".into()); part_5.msg = Some("".into());
if let Some(ref subject) = mimeparser.subject {
if !mimeparser.is_send_by_messenger {
part_5.msg = Some(subject.to_string())
}
} }
mimeparser.parts.push(part_5); mimeparser.parts.push(part_5);
}; };
@@ -366,10 +360,10 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
unsafe fn dc_mimepart_new() -> dc_mimepart_t { unsafe fn dc_mimepart_new() -> dc_mimepart_t {
dc_mimepart_t { dc_mimepart_t {
type_0: Viewtype::Unknown, type_0: Viewtype::Unknown,
is_meta: 0, is_meta: false,
int_mimetype: 0, int_mimetype: 0,
msg: None, msg: None,
msg_raw: std::ptr::null_mut(), msg_raw: None,
bytes: 0, bytes: 0,
param: Params::new(), param: Params::new(),
} }
@@ -378,11 +372,7 @@ unsafe fn dc_mimepart_new() -> dc_mimepart_t {
pub fn dc_mimeparser_get_last_nonmeta<'a>( pub fn dc_mimeparser_get_last_nonmeta<'a>(
mimeparser: &'a mut dc_mimeparser_t, mimeparser: &'a mut dc_mimeparser_t,
) -> Option<&'a mut dc_mimepart_t> { ) -> Option<&'a mut dc_mimepart_t> {
mimeparser mimeparser.parts.iter_mut().rev().find(|part| !part.is_meta)
.parts
.iter_mut()
.rev()
.find(|part| part.is_meta == 0)
} }
/*the result must be freed*/ /*the result must be freed*/
@@ -596,12 +586,12 @@ unsafe fn dc_mimeparser_parse_mime_recursive(
.stock_str(StockMessage::CantDecryptMsgBody); .stock_str(StockMessage::CantDecryptMsgBody);
let txt = format!("[{}]", msg_body); let txt = format!("[{}]", msg_body);
part.msg_raw = txt.strdup(); part.msg_raw = Some(txt.clone());
part.msg = Some(txt); part.msg = Some(txt);
mimeparser.parts.push(part); mimeparser.parts.push(part);
any_part_added = 1i32; any_part_added = 1i32;
mimeparser.decrypting_failed = 1i32 mimeparser.decrypting_failed = true;
} }
46 => { 46 => {
cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
@@ -1124,13 +1114,18 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
part.type_0 = Viewtype::Text; part.type_0 = Viewtype::Text;
part.int_mimetype = mime_type; part.int_mimetype = mime_type;
part.msg = Some(simplified_txt); part.msg = Some(simplified_txt);
part.msg_raw = part.msg_raw = {
let raw_c =
strndup(decoded_data, decoded_data_bytes as libc::c_ulong); strndup(decoded_data, decoded_data_bytes as libc::c_ulong);
let raw = to_string(raw_c);
free(raw_c.cast());
Some(raw)
};
do_add_single_part(mimeparser, part); do_add_single_part(mimeparser, part);
} }
if simplifier.unwrap().is_forwarded { if simplifier.unwrap().is_forwarded {
mimeparser.is_forwarded = 1i32 mimeparser.is_forwarded = true;
} }
} }
} }
@@ -1284,7 +1279,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
mimeparser, mimeparser,
msg_type, msg_type,
mime_type, mime_type,
raw_mime, as_str(raw_mime),
decoded_data, decoded_data,
decoded_data_bytes, decoded_data_bytes,
desired_filename, desired_filename,
@@ -1312,7 +1307,7 @@ unsafe fn do_add_single_file_part(
parser: &mut dc_mimeparser_t, parser: &mut dc_mimeparser_t,
msg_type: Viewtype, msg_type: Viewtype,
mime_type: libc::c_int, mime_type: libc::c_int,
raw_mime: *const libc::c_char, raw_mime: &str,
decoded_data: *const libc::c_char, decoded_data: *const libc::c_char,
decoded_data_bytes: size_t, decoded_data_bytes: size_t,
desired_filename: *const libc::c_char, desired_filename: *const libc::c_char,
@@ -1338,7 +1333,7 @@ unsafe fn do_add_single_file_part(
part.int_mimetype = mime_type; part.int_mimetype = mime_type;
part.bytes = decoded_data_bytes as libc::c_int; part.bytes = decoded_data_bytes as libc::c_int;
part.param.set(Param::File, as_str(pathNfilename)); part.param.set(Param::File, as_str(pathNfilename));
part.param.set(Param::MimeType, as_str(raw_mime)); part.param.set(Param::MimeType, raw_mime);
if mime_type == 80 { if mime_type == 80 {
assert!(!decoded_data.is_null(), "invalid image data"); assert!(!decoded_data.is_null(), "invalid image data");
let data = std::slice::from_raw_parts( let data = std::slice::from_raw_parts(
@@ -1655,9 +1650,7 @@ pub unsafe fn dc_mimeparser_repl_msg_by_error(
let part = &mut mimeparser.parts[0]; let part = &mut mimeparser.parts[0];
part.type_0 = Viewtype::Text; part.type_0 = Viewtype::Text;
part.msg = Some(format!("[{}]", to_string(error_msg))); part.msg = Some(format!("[{}]", to_string(error_msg)));
for part in mimeparser.parts.drain(1..) { mimeparser.parts.truncate(1);
dc_mimepart_unref(part);
}
assert_eq!(mimeparser.parts.len(), 1); assert_eq!(mimeparser.parts.len(), 1);
} }
@@ -1814,10 +1807,7 @@ mod tests {
let raw = b"Content-Type: multipart/mixed; boundary=\"==break==\";\nSubject: outer-subject\nX-Special-A: special-a\nFoo: Bar\nChat-Version: 0.0\n\n--==break==\nContent-Type: text/plain; protected-headers=\"v1\";\nSubject: inner-subject\nX-Special-B: special-b\nFoo: Xy\nChat-Version: 1.0\n\ntest1\n\n--==break==--\n\n\x00"; let raw = b"Content-Type: multipart/mixed; boundary=\"==break==\";\nSubject: outer-subject\nX-Special-A: special-a\nFoo: Bar\nChat-Version: 0.0\n\n--==break==\nContent-Type: text/plain; protected-headers=\"v1\";\nSubject: inner-subject\nX-Special-B: special-b\nFoo: Xy\nChat-Version: 1.0\n\ntest1\n\n--==break==--\n\n\x00";
let mut mimeparser = dc_mimeparser_parse(&context.ctx, &raw[..]); let mut mimeparser = dc_mimeparser_parse(&context.ctx, &raw[..]);
assert_eq!( assert_eq!(mimeparser.subject, Some("inner-subject".into()));
&to_string(mimeparser.subject as *const libc::c_char),
"inner-subject",
);
let mut of: *mut mailimf_optional_field = let mut of: *mut mailimf_optional_field =
dc_mimeparser_lookup_optional_field(&mimeparser, "X-Special-A"); dc_mimeparser_lookup_optional_field(&mimeparser, "X-Special-A");

View File

@@ -1,3 +1,4 @@
use std::ffi::CString;
use std::ptr; use std::ptr;
use itertools::join; use itertools::join;
@@ -625,7 +626,7 @@ unsafe fn add_parts(
|mut stmt, conn| { |mut stmt, conn| {
for i in 0..icnt { for i in 0..icnt {
let part = &mut mime_parser.parts[i]; let part = &mut mime_parser.parts[i];
if part.is_meta != 0 { if part.is_meta {
continue; continue;
} }
@@ -641,14 +642,18 @@ unsafe fn add_parts(
} }
} }
if part.type_0 == Viewtype::Text { if part.type_0 == Viewtype::Text {
let msg_raw = CString::yolo(part.msg_raw.as_ref().unwrap().clone());
let subject_c = CString::yolo(
mime_parser
.subject
.as_ref()
.map(|s| s.to_string())
.unwrap_or("".into()),
);
txt_raw = dc_mprintf( txt_raw = dc_mprintf(
b"%s\n\n%s\x00" as *const u8 as *const libc::c_char, b"%s\n\n%s\x00" as *const u8 as *const libc::c_char,
if !mime_parser.subject.is_null() { subject_c.as_ptr(),
mime_parser.subject msg_raw.as_ptr(),
} else {
b"\x00" as *const u8 as *const libc::c_char
},
part.msg_raw,
) )
} }
if 0 != mime_parser.is_system_message { if 0 != mime_parser.is_system_message {
@@ -1568,8 +1573,8 @@ unsafe fn create_or_lookup_adhoc_group(
} }
// use subject as initial chat name // use subject as initial chat name
if !mime_parser.subject.is_null() && 0 != *mime_parser.subject.offset(0isize) as libc::c_int { if let Some(subject) = mime_parser.subject.as_ref().filter(|s| !s.is_empty()) {
grpname = dc_strdup(mime_parser.subject) grpname = subject.strdup();
} else { } else {
grpname = context grpname = context
.stock_string_repl_int(StockMessage::Member, member_ids.len() as libc::c_int) .stock_string_repl_int(StockMessage::Member, member_ids.len() as libc::c_int)

View File

@@ -435,21 +435,10 @@ pub unsafe fn clist_free_content(haystack: *const clist) {
pub unsafe fn clist_search_string_nocase( pub unsafe fn clist_search_string_nocase(
haystack: *const clist, haystack: *const clist,
needle: *const libc::c_char, needle: *const libc::c_char,
) -> libc::c_int { ) -> bool {
let mut iter = (*haystack).first; (&*haystack)
.into_iter()
while !iter.is_null() { .any(|data| strcasecmp(data.cast(), needle) == 0)
if strcasecmp((*iter).data as *const libc::c_char, needle) == 0 {
return 1;
}
iter = if !iter.is_null() {
(*iter).next
} else {
ptr::null_mut()
}
}
0
} }
/* date/time tools */ /* date/time tools */
@@ -630,6 +619,21 @@ pub unsafe fn dc_create_outgoing_rfc724_mid(
ret ret
} }
/// Generate globally-unique message-id for a new outgoing message.
///
/// Note: Do not add a counter or any private data as as this may give
/// unneeded information to the receiver
pub fn dc_create_outgoing_rfc724_mid_safe(grpid: Option<&str>, from_addr: &str) -> String {
let hostname = from_addr
.find('@')
.map(|k| &from_addr[k..])
.unwrap_or("@nohost");
match grpid {
Some(grpid) => format!("Gr.{}.{}{}", grpid, dc_create_id(), hostname),
None => format!("Mr.{}.{}{}", dc_create_id(), dc_create_id(), hostname),
}
}
/// Extract the group id (grpid) from a message id (mid) /// Extract the group id (grpid) from a message id (mid)
/// ///
/// # Arguments /// # Arguments

View File

@@ -692,9 +692,7 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
); );
} else { } else {
/* unrecoverable */ /* unrecoverable */
if clist_search_string_nocase(mimefactory.recipients_addr, mimefactory.from_addr) if !clist_search_string_nocase(mimefactory.recipients_addr, mimefactory.from_addr) {
== 0i32
{
clist_insert_after( clist_insert_after(
mimefactory.recipients_names, mimefactory.recipients_names,
(*mimefactory.recipients_names).last, (*mimefactory.recipients_names).last,