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();
}
unsafe fn get_parent_mime_headers(
&self,
parent_rfc724_mid: *mut *mut libc::c_char,
parent_in_reply_to: *mut *mut libc::c_char,
parent_references: *mut *mut libc::c_char,
) -> 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 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(())
},
)
.is_ok();
pub fn get_parent_mime_headers(&self) -> Option<(String, String, String)> {
let collect = |row: &rusqlite::Row| Ok((row.get(0)?, row.get(1)?, row.get(2)?));
let params = params![self.id as i32, DC_CONTACT_ID_SELF as i32];
let sql = &self.context.sql;
let main_query = "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 from_id!=?2);";
let fallback_query = "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 from_id==?2);";
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 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> {
@@ -277,13 +246,8 @@ impl<'a> Chat<'a> {
) -> Result<u32, Error> {
let mut do_guarantee_e2ee: libc::c_int;
let e2ee_enabled: libc::c_int;
let mut OK_TO_CONTINUE = true;
let mut parent_rfc724_mid = ptr::null_mut();
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 new_references = "".into();
let mut new_in_reply_to = "".into();
let mut msg_id = 0;
let mut to_id = 0;
let mut location_id = 0;
@@ -293,7 +257,10 @@ impl<'a> Chat<'a> {
|| self.typ == Chattype::VerifiedGroup)
{
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)
{
log_event!(
@@ -302,200 +269,173 @@ impl<'a> Chat<'a> {
0,
"Cannot send message; self not in group.",
);
} else {
if let Some(from) = context.sql.get_config(context, "configured_addr") {
let from_c = CString::yolo(from);
new_rfc724_mid = dc_create_outgoing_rfc724_mid(
if self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup {
self.grpid.strdup()
} else {
ptr::null_mut()
},
from_c.as_ptr(),
);
return Ok(0);
}
if self.typ == Chattype::Single {
if let Some(id) = context.sql.query_row_col(
context,
"SELECT contact_id FROM chats_contacts WHERE chat_id=?;",
params![self.id as i32],
0,
) {
to_id = id;
} else {
error!(
context,
0, "Cannot send message, contact for chat #{} not found.", self.id,
);
OK_TO_CONTINUE = false;
}
if let Some(from) = context.sql.get_config(context, "configured_addr") {
let new_rfc724_mid = {
let grpid = match self.typ {
Chattype::Group | Chattype::VerifiedGroup => Some(self.grpid.as_str()),
_ => None,
};
dc_create_outgoing_rfc724_mid_safe(grpid, &from)
};
if self.typ == Chattype::Single {
if let Some(id) = context.sql.query_row_col(
context,
"SELECT contact_id FROM chats_contacts WHERE chat_id=?;",
params![self.id as i32],
0,
) {
to_id = id;
} else {
if self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup {
if self.param.get_int(Param::Unpromoted).unwrap_or_default() == 1 {
self.param.remove(Param::Unpromoted);
self.update_param().unwrap();
}
error!(
context,
0, "Cannot send message, contact for chat #{} not found.", self.id,
);
return Ok(0);
}
} else {
if self.typ == Chattype::Group || self.typ == Chattype::VerifiedGroup {
if self.param.get_int(Param::Unpromoted).unwrap_or_default() == 1 {
self.param.remove(Param::Unpromoted);
self.update_param().unwrap();
}
}
if OK_TO_CONTINUE {
/* check if we can guarantee E2EE for this message.
if we guarantee E2EE, and circumstances change
so that E2EE is no longer available at a later point (reset, changed settings),
we do not send the message out at all */
do_guarantee_e2ee = 0;
e2ee_enabled = context
.sql
.get_config_int(context, "e2ee_enabled")
.unwrap_or_else(|| 1);
if 0 != e2ee_enabled
&& msg.param.get_int(Param::ForcePlaintext).unwrap_or_default() == 0
{
let mut can_encrypt = 1;
let mut all_mutual = 1;
}
let res = context.sql.query_row(
"SELECT ps.prefer_encrypted, c.addr \
FROM chats_contacts cc \
LEFT JOIN contacts c ON cc.contact_id=c.id \
LEFT JOIN acpeerstates ps ON c.addr=ps.addr \
WHERE cc.chat_id=? AND cc.contact_id>9;",
params![self.id],
|row| {
let state: String = row.get(1)?;
/* check if we can guarantee E2EE for this message.
if we guarantee E2EE, and circumstances change
so that E2EE is no longer available at a later point (reset, changed settings),
we do not send the message out at all */
do_guarantee_e2ee = 0;
e2ee_enabled = context
.sql
.get_config_int(context, "e2ee_enabled")
.unwrap_or_else(|| 1);
if 0 != e2ee_enabled
&& msg.param.get_int(Param::ForcePlaintext).unwrap_or_default() == 0
{
let mut can_encrypt = 1;
let mut all_mutual = 1;
if let Some(prefer_encrypted) = row.get::<_, Option<i32>>(0)? {
if prefer_encrypted != 1 {
info!(
context,
0,
"[autocrypt] peerstate for {} is {}",
state,
if prefer_encrypted == 0 {
"NOPREFERENCE"
} else {
"RESET"
},
);
all_mutual = 0;
}
} else {
info!(context, 0, "[autocrypt] no peerstate for {}", state,);
can_encrypt = 0;
all_mutual = 0;
}
Ok(())
},
);
match res {
Ok(_) => {}
Err(err) => {
warn!(context, 0, "chat: failed to load peerstates: {:?}", err);
}
}
if 0 != can_encrypt {
if 0 != all_mutual {
do_guarantee_e2ee = 1;
} else if last_msg_in_chat_encrypted(context, &context.sql, self.id) {
do_guarantee_e2ee = 1;
let res = context.sql.query_row(
"SELECT ps.prefer_encrypted, c.addr \
FROM chats_contacts cc \
LEFT JOIN contacts c ON cc.contact_id=c.id \
LEFT JOIN acpeerstates ps ON c.addr=ps.addr \
WHERE cc.chat_id=? AND cc.contact_id>9;",
params![self.id],
|row| {
let state: String = row.get(1)?;
if let Some(prefer_encrypted) = row.get::<_, Option<i32>>(0)? {
if prefer_encrypted != 1 {
info!(
context,
0,
"[autocrypt] peerstate for {} is {}",
state,
if prefer_encrypted == 0 {
"NOPREFERENCE"
} else {
"RESET"
},
);
all_mutual = 0;
}
} else {
info!(context, 0, "[autocrypt] no peerstate for {}", state,);
can_encrypt = 0;
all_mutual = 0;
}
Ok(())
},
);
match res {
Ok(_) => {}
Err(err) => {
warn!(context, 0, "chat: failed to load peerstates: {:?}", err);
}
if 0 != do_guarantee_e2ee {
msg.param.set_int(Param::GuranteeE2ee, 1);
}
if 0 != can_encrypt {
if 0 != all_mutual {
do_guarantee_e2ee = 1;
} else if last_msg_in_chat_encrypted(context, &context.sql, self.id) {
do_guarantee_e2ee = 1;
}
msg.param.remove(Param::ErroneousE2ee);
if !self.is_self_talk()
&& 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()
&& 0 != *parent_rfc724_mid.offset(0isize) as libc::c_int
{
new_in_reply_to = dc_strdup(parent_rfc724_mid)
}
if !parent_references.is_null() {
let space: *mut libc::c_char;
space = strchr(parent_references, ' ' as i32);
if !space.is_null() {
*space = 0 as libc::c_char
}
}
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)
}
}
}
if 0 != do_guarantee_e2ee {
msg.param.set_int(Param::GuranteeE2ee, 1);
}
msg.param.remove(Param::ErroneousE2ee);
if !self.is_self_talk() {
if let Some((parent_rfc724_mid, parent_in_reply_to, parent_references)) =
self.get_parent_mime_headers()
{
if !parent_rfc724_mid.is_empty() {
new_in_reply_to = parent_rfc724_mid.clone();
}
let parent_references = if let Some(n) = parent_references.find(' ') {
&parent_references[0..n]
} else {
&parent_references
};
// add independent location to database
if msg.param.exists(Param::SetLatitude) {
if sql::execute(
context,
&context.sql,
"INSERT INTO locations \
(timestamp,from_id,chat_id, latitude,longitude,independent)\
VALUES (?,?,?, ?,?,1);",
params![
timestamp,
DC_CONTACT_ID_SELF,
self.id as i32,
msg.param.get_float(Param::SetLatitude).unwrap_or_default(),
msg.param.get_float(Param::SetLongitude).unwrap_or_default(),
],
)
.is_ok()
{
location_id = sql::get_rowid2(
context,
&context.sql,
"locations",
"timestamp",
timestamp,
"from_id",
DC_CONTACT_ID_SELF as i32,
);
}
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();
}
}
}
// add message to the database
// add independent location to database
if sql::execute(
if msg.param.exists(Param::SetLatitude) {
if sql::execute(
context,
&context.sql,
"INSERT INTO locations \
(timestamp,from_id,chat_id, latitude,longitude,independent)\
VALUES (?,?,?, ?,?,1);",
params![
timestamp,
DC_CONTACT_ID_SELF,
self.id as i32,
msg.param.get_float(Param::SetLatitude).unwrap_or_default(),
msg.param.get_float(Param::SetLongitude).unwrap_or_default(),
],
)
.is_ok()
{
location_id = sql::get_rowid2(
context,
&context.sql,
"locations",
"timestamp",
timestamp,
"from_id",
DC_CONTACT_ID_SELF as i32,
);
}
}
// add message to the database
if sql::execute(
context,
&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 (?,?,?,?,?, ?,?,?,?,?, ?,?,?);",
params![
as_str(new_rfc724_mid),
new_rfc724_mid,
self.id as i32,
1i32,
to_id as i32,
@@ -505,8 +445,8 @@ impl<'a> Chat<'a> {
msg.text.as_ref().map_or("", String::as_str),
msg.param.to_string(),
msg.hidden,
to_string(new_in_reply_to),
to_string(new_references),
new_in_reply_to,
new_references,
location_id as i32,
]
).is_ok() {
@@ -515,7 +455,7 @@ impl<'a> Chat<'a> {
&context.sql,
"msgs",
"rfc724_mid",
as_str(new_rfc724_mid),
new_rfc724_mid,
);
} else {
error!(
@@ -525,19 +465,10 @@ impl<'a> Chat<'a> {
self.id,
);
}
}
} else {
error!(context, 0, "Cannot send message, not configured.",);
}
} else {
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)
}
}

View File

@@ -148,7 +148,7 @@ pub unsafe fn dc_mimefactory_load_msg(
for row in rows {
let (authname, addr) = row?;
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(
factory.recipients_names,
(*factory.recipients_names).last,
@@ -183,7 +183,7 @@ pub unsafe fn dc_mimefactory_load_msg(
.unwrap_or_default();
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(
factory.recipients_names,
(*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)]
pub struct dc_mimepart_t {
pub type_0: Viewtype,
pub is_meta: libc::c_int,
pub is_meta: bool,
pub int_mimetype: libc::c_int,
pub msg: Option<String>,
pub msg_raw: *mut libc::c_char,
pub msg_raw: Option<String>,
pub bytes: libc::c_int,
pub param: Params,
}
@@ -50,11 +50,11 @@ pub struct dc_mimeparser_t<'a> {
pub header: HashMap<String, *mut mailimf_field>,
pub header_root: *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 decrypting_failed: libc::c_int,
pub decrypting_failed: bool,
pub e2ee_helper: E2eeHelper,
pub is_forwarded: libc::c_int,
pub is_forwarded: bool,
pub context: &'a Context,
pub reports: Vec<*mut mailmime>,
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_root: std::ptr::null_mut(),
header_protected: std::ptr::null_mut(),
subject: std::ptr::null_mut(),
subject: None,
is_send_by_messenger: false,
decrypting_failed: 0,
decrypting_failed: false,
e2ee_helper: Default::default(),
is_forwarded: 0,
is_forwarded: false,
context,
reports: Vec::new(),
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) {
for part in mimeparser.parts.drain(..) {
dc_mimepart_unref(part);
}
assert!(mimeparser.parts.is_empty());
mimeparser.parts = vec![];
mimeparser.header_root = ptr::null_mut();
mimeparser.header.clear();
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_system_message = 0i32;
free(mimeparser.subject as *mut libc::c_void);
mimeparser.subject = ptr::null_mut();
mimeparser.subject = None;
if !mimeparser.mimeroot.is_null() {
mailmime_free(mimeparser.mimeroot);
mimeparser.mimeroot = ptr::null_mut()
}
mimeparser.is_forwarded = 0i32;
mimeparser.is_forwarded = false;
mimeparser.reports.clear();
mimeparser.decrypting_failed = 0i32;
mimeparser.decrypting_failed = false;
mimeparser.e2ee_helper.thanks();
mimeparser.location_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;
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);
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 {
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() {
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;
while i != mimeparser.parts.len() {
if mimeparser.parts[i].int_mimetype != 111 {
let part = mimeparser.parts.remove(i);
dc_mimepart_unref(part);
mimeparser.parts.remove(i);
} else {
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 {
let imgpart = &mut mimeparser.parts[1];
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::Video
|| filepart.type_0 == Viewtype::File)
&& 0 == filepart.is_meta
&& !filepart.is_meta
};
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;
// swap new with old
let old = std::mem::replace(&mut mimeparser.parts[0], filepart);
// unref old one
dc_mimepart_unref(old);
std::mem::replace(&mut mimeparser.parts[0], filepart);
}
}
if !mimeparser.subject.is_null() {
if let Some(ref subject) = mimeparser.subject {
let mut prepend_subject: libc::c_int = 1i32;
if 0 == mimeparser.decrypting_failed {
let p: *mut libc::c_char = strchr(mimeparser.subject, ':' as i32);
if p.wrapping_offset_from(mimeparser.subject) == 2
|| p.wrapping_offset_from(mimeparser.subject) == 3
if !mimeparser.decrypting_failed {
let colon = subject.find(':');
if colon == Some(2)
|| colon == Some(3)
|| mimeparser.is_send_by_messenger
|| !strstr(
mimeparser.subject,
b"Chat:\x00" as *const u8 as *const libc::c_char,
)
.is_null()
|| subject.contains("Chat:")
{
prepend_subject = 0i32
}
}
if 0 != prepend_subject {
let subj: *mut libc::c_char = dc_strdup(mimeparser.subject);
let p_0: *mut libc::c_char = strchr(subj, '[' as i32);
if !p_0.is_null() {
*p_0 = 0i32 as libc::c_char
let subj = if let Some(n) = subject.find('[') {
&subject[0..n]
} else {
subject
}
dc_trim(subj);
if 0 != *subj.offset(0isize) {
.trim();
if !subj.is_empty() {
let subj_c = CString::yolo(subj);
for part in mimeparser.parts.iter_mut() {
if part.type_0 == Viewtype::Text {
let msg_c = part.msg.as_ref().unwrap().strdup();
let new_txt: *mut libc::c_char = dc_mprintf(
b"%s \xe2\x80\x93 %s\x00" as *const u8 as *const libc::c_char,
subj,
subj_c.as_ptr(),
msg_c,
);
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() {
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(
&mimeparser,
"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() {
let mut part_5 = dc_mimepart_new();
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);
};
@@ -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 {
dc_mimepart_t {
type_0: Viewtype::Unknown,
is_meta: 0,
is_meta: false,
int_mimetype: 0,
msg: None,
msg_raw: std::ptr::null_mut(),
msg_raw: None,
bytes: 0,
param: Params::new(),
}
@@ -378,11 +372,7 @@ unsafe fn dc_mimepart_new() -> dc_mimepart_t {
pub fn dc_mimeparser_get_last_nonmeta<'a>(
mimeparser: &'a mut dc_mimeparser_t,
) -> Option<&'a mut dc_mimepart_t> {
mimeparser
.parts
.iter_mut()
.rev()
.find(|part| part.is_meta == 0)
mimeparser.parts.iter_mut().rev().find(|part| !part.is_meta)
}
/*the result must be freed*/
@@ -596,12 +586,12 @@ unsafe fn dc_mimeparser_parse_mime_recursive(
.stock_str(StockMessage::CantDecryptMsgBody);
let txt = format!("[{}]", msg_body);
part.msg_raw = txt.strdup();
part.msg_raw = Some(txt.clone());
part.msg = Some(txt);
mimeparser.parts.push(part);
any_part_added = 1i32;
mimeparser.decrypting_failed = 1i32
mimeparser.decrypting_failed = true;
}
46 => {
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.int_mimetype = mime_type;
part.msg = Some(simplified_txt);
part.msg_raw =
strndup(decoded_data, decoded_data_bytes as libc::c_ulong);
part.msg_raw = {
let raw_c =
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);
}
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,
msg_type,
mime_type,
raw_mime,
as_str(raw_mime),
decoded_data,
decoded_data_bytes,
desired_filename,
@@ -1312,7 +1307,7 @@ unsafe fn do_add_single_file_part(
parser: &mut dc_mimeparser_t,
msg_type: Viewtype,
mime_type: libc::c_int,
raw_mime: *const libc::c_char,
raw_mime: &str,
decoded_data: *const libc::c_char,
decoded_data_bytes: size_t,
desired_filename: *const libc::c_char,
@@ -1338,7 +1333,7 @@ unsafe fn do_add_single_file_part(
part.int_mimetype = mime_type;
part.bytes = decoded_data_bytes as libc::c_int;
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 {
assert!(!decoded_data.is_null(), "invalid image data");
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];
part.type_0 = Viewtype::Text;
part.msg = Some(format!("[{}]", to_string(error_msg)));
for part in mimeparser.parts.drain(1..) {
dc_mimepart_unref(part);
}
mimeparser.parts.truncate(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 mut mimeparser = dc_mimeparser_parse(&context.ctx, &raw[..]);
assert_eq!(
&to_string(mimeparser.subject as *const libc::c_char),
"inner-subject",
);
assert_eq!(mimeparser.subject, Some("inner-subject".into()));
let mut of: *mut mailimf_optional_field =
dc_mimeparser_lookup_optional_field(&mimeparser, "X-Special-A");

View File

@@ -1,3 +1,4 @@
use std::ffi::CString;
use std::ptr;
use itertools::join;
@@ -625,7 +626,7 @@ unsafe fn add_parts(
|mut stmt, conn| {
for i in 0..icnt {
let part = &mut mime_parser.parts[i];
if part.is_meta != 0 {
if part.is_meta {
continue;
}
@@ -641,14 +642,18 @@ unsafe fn add_parts(
}
}
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(
b"%s\n\n%s\x00" as *const u8 as *const libc::c_char,
if !mime_parser.subject.is_null() {
mime_parser.subject
} else {
b"\x00" as *const u8 as *const libc::c_char
},
part.msg_raw,
subject_c.as_ptr(),
msg_raw.as_ptr(),
)
}
if 0 != mime_parser.is_system_message {
@@ -1568,8 +1573,8 @@ unsafe fn create_or_lookup_adhoc_group(
}
// use subject as initial chat name
if !mime_parser.subject.is_null() && 0 != *mime_parser.subject.offset(0isize) as libc::c_int {
grpname = dc_strdup(mime_parser.subject)
if let Some(subject) = mime_parser.subject.as_ref().filter(|s| !s.is_empty()) {
grpname = subject.strdup();
} else {
grpname = context
.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(
haystack: *const clist,
needle: *const libc::c_char,
) -> libc::c_int {
let mut iter = (*haystack).first;
while !iter.is_null() {
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
) -> bool {
(&*haystack)
.into_iter()
.any(|data| strcasecmp(data.cast(), needle) == 0)
}
/* date/time tools */
@@ -630,6 +619,21 @@ pub unsafe fn dc_create_outgoing_rfc724_mid(
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)
///
/// # Arguments

View File

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