Merge branch 'master' into refactor/remove-mprintf

This commit is contained in:
holger krekel
2019-09-17 15:46:05 +02:00
10 changed files with 1304 additions and 1543 deletions

View File

@@ -7,6 +7,7 @@ use crate::config::*;
use crate::constants::*; use crate::constants::*;
use crate::contact::*; use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_mimeparser::SystemMessage;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::error::Error; use crate::error::Error;
use crate::events::Event; use crate::events::Event;
@@ -1669,7 +1670,8 @@ pub fn set_chat_profile_image(
if chat.update_param(context).is_ok() { if chat.update_param(context).is_ok() {
if chat.is_promoted() { if chat.is_promoted() {
let mut msg = dc_msg_new_untyped(); let mut msg = dc_msg_new_untyped();
msg.param.set_int(Param::Cmd, DC_CMD_GROUPIMAGE_CHANGED); msg.param
.set_int(Param::Cmd, SystemMessage::GroupImageChanged as i32);
msg.type_0 = Viewtype::Text; msg.type_0 = Viewtype::Text;
msg.text = Some(context.stock_system_msg( msg.text = Some(context.stock_system_msg(
if new_image_rel == "" { if new_image_rel == "" {

View File

@@ -314,12 +314,3 @@ pub enum KeyType {
Public = 0, Public = 0,
Private = 1, Private = 1,
} }
pub const DC_CMD_GROUPNAME_CHANGED: libc::c_int = 2;
pub const DC_CMD_GROUPIMAGE_CHANGED: libc::c_int = 3;
pub const DC_CMD_MEMBER_ADDED_TO_GROUP: libc::c_int = 4;
pub const DC_CMD_MEMBER_REMOVED_FROM_GROUP: libc::c_int = 5;
pub const DC_CMD_AUTOCRYPT_SETUP_MESSAGE: libc::c_int = 6;
pub const DC_CMD_SECUREJOIN_MESSAGE: libc::c_int = 7;
pub const DC_CMD_LOCATION_STREAMING_ENABLED: libc::c_int = 8;
pub const DC_CMD_LOCATION_ONLY: libc::c_int = 9;

View File

@@ -478,10 +478,9 @@ pub unsafe fn dc_normalize_setup_code(
pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) { pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) {
let mut ok_to_continue = true; let mut ok_to_continue = true;
let mut success: libc::c_int = 0; let mut success: libc::c_int = 0;
let what: libc::c_int;
if dc_alloc_ongoing(context) { if dc_alloc_ongoing(context) {
what = job.param.get_int(Param::Cmd).unwrap_or_default(); let what = job.param.get_int(Param::Cmd).unwrap_or_default();
let param1_s = job.param.get(Param::Arg).unwrap_or_default(); let param1_s = job.param.get(Param::Arg).unwrap_or_default();
let param1 = CString::yolo(param1_s); let param1 = CString::yolo(param1_s);
let _param2 = CString::yolo(job.param.get(Param::Arg2).unwrap_or_default()); let _param2 = CString::yolo(job.param.get(Param::Arg2).unwrap_or_default());

View File

@@ -16,6 +16,7 @@ use crate::chat::{self, Chat};
use crate::constants::*; use crate::constants::*;
use crate::contact::*; use crate::contact::*;
use crate::context::{get_version_str, Context}; use crate::context::{get_version_str, Context};
use crate::dc_mimeparser::SystemMessage;
use crate::dc_strencode::*; use crate::dc_strencode::*;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::e2ee::*; use crate::e2ee::*;
@@ -169,10 +170,10 @@ pub unsafe fn dc_mimefactory_load_msg(
) )
.unwrap(); .unwrap();
let command = factory.msg.param.get_int(Param::Cmd).unwrap_or_default(); let command = factory.msg.param.get_cmd();
let msg = &factory.msg; let msg = &factory.msg;
if command == 5 { if command == SystemMessage::MemberRemovedFromGroup {
let email_to_remove = msg.param.get(Param::Arg).unwrap_or_default(); let email_to_remove = msg.param.get(Param::Arg).unwrap_or_default();
let email_to_remove_c = email_to_remove.strdup(); let email_to_remove_c = email_to_remove.strdup();
@@ -196,8 +197,8 @@ pub unsafe fn dc_mimefactory_load_msg(
} }
} }
} }
if command != 6 if command != SystemMessage::AutocryptSetupMessage
&& command != 7 && command != SystemMessage::SecurejoinMessage
&& 0 != context && 0 != context
.sql .sql
.get_config_int(context, "mdns_enabled") .get_config_int(context, "mdns_enabled")
@@ -525,7 +526,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
} }
/* build header etc. */ /* build header etc. */
let command = factory.msg.param.get_int(Param::Cmd).unwrap_or_default(); let command = factory.msg.param.get_cmd();
if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
mailimf_fields_add( mailimf_fields_add(
imf_fields, imf_fields,
@@ -541,7 +542,8 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
dc_encode_header_words(&chat.name), dc_encode_header_words(&chat.name),
), ),
); );
if command == DC_CMD_MEMBER_REMOVED_FROM_GROUP {
if command == SystemMessage::MemberRemovedFromGroup {
let email_to_remove = factory let email_to_remove = factory
.msg .msg
.param .param
@@ -560,7 +562,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
), ),
); );
} }
} else if command == DC_CMD_MEMBER_ADDED_TO_GROUP { } else if command == SystemMessage::MemberAddedToGroup {
let msg = &factory.msg; let msg = &factory.msg;
do_gossip = 1; do_gossip = 1;
let email_to_add = msg.param.get(Param::Arg).unwrap_or_default().strdup(); let email_to_add = msg.param.get(Param::Arg).unwrap_or_default().strdup();
@@ -591,7 +593,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
), ),
); );
} }
} else if command == DC_CMD_GROUPNAME_CHANGED { } else if command == SystemMessage::GroupNameChanged {
let msg = &factory.msg; let msg = &factory.msg;
let value_to_add = msg.param.get(Param::Arg).unwrap_or_default().strdup(); let value_to_add = msg.param.get(Param::Arg).unwrap_or_default().strdup();
@@ -604,7 +606,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
value_to_add, value_to_add,
), ),
); );
} else if command == DC_CMD_GROUPIMAGE_CHANGED { } else if command == SystemMessage::GroupImageChanged {
let msg = &factory.msg; let msg = &factory.msg;
grpimage = msg.param.get(Param::Arg); grpimage = msg.param.get(Param::Arg);
if grpimage.is_none() { if grpimage.is_none() {
@@ -618,7 +620,8 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
} }
} }
} }
if command == DC_CMD_LOCATION_STREAMING_ENABLED {
if command == SystemMessage::LocationStreamingEnabled {
mailimf_fields_add( mailimf_fields_add(
imf_fields, imf_fields,
mailimf_field_new_custom( mailimf_field_new_custom(
@@ -629,7 +632,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
), ),
); );
} }
if command == DC_CMD_AUTOCRYPT_SETUP_MESSAGE { if command == SystemMessage::AutocryptSetupMessage {
mailimf_fields_add( mailimf_fields_add(
imf_fields, imf_fields,
mailimf_field_new_custom( mailimf_field_new_custom(
@@ -644,8 +647,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
.to_string(), .to_string(),
); );
} }
if command == SystemMessage::SecurejoinMessage {
if command == DC_CMD_SECUREJOIN_MESSAGE {
let msg = &factory.msg; let msg = &factory.msg;
let step = msg.param.get(Param::Arg).unwrap_or_default().strdup(); let step = msg.param.get(Param::Arg).unwrap_or_default().strdup();
if strlen(step) > 0 { if strlen(step) > 0 {
@@ -719,6 +721,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
} }
} }
} }
if let Some(grpimage) = grpimage { if let Some(grpimage) = grpimage {
info!(factory.context, "setting group image '{}'", grpimage); info!(factory.context, "setting group image '{}'", grpimage);
let mut meta = dc_msg_new_untyped(); let mut meta = dc_msg_new_untyped();
@@ -1061,7 +1064,7 @@ unsafe fn get_subject(
dc_msg_get_summarytext_by_raw(msg.type_0, msg.text.as_ref(), &mut msg.param, 32, context); dc_msg_get_summarytext_by_raw(msg.type_0, msg.text.as_ref(), &mut msg.param, 32, context);
let fwd = if 0 != afwd_email { "Fwd: " } else { "" }; let fwd = if 0 != afwd_email { "Fwd: " } else { "" };
if msg.param.get_int(Param::Cmd).unwrap_or_default() == DC_CMD_AUTOCRYPT_SETUP_MESSAGE { if msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage {
ret = context.stock_str(StockMessage::AcSetupMsgSubject).strdup() ret = context.stock_str(StockMessage::AcSetupMsgSubject).strdup()
} else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { } else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
ret = format!("Chat: {}: {}{}", chat.name, fwd, raw_subject,).strdup(); ret = format!("Chat: {}: {}{}", chat.name, fwd, raw_subject,).strdup();

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
use std::ffi::CString;
use std::ptr; use std::ptr;
use itertools::join; use itertools::join;
@@ -62,7 +63,8 @@ pub unsafe fn dc_receive_imf(
// somewhen, I did not found out anything that speaks against this approach yet) // somewhen, I did not found out anything that speaks against this approach yet)
let body = std::slice::from_raw_parts(imf_raw_not_terminated as *const u8, imf_raw_bytes); let body = std::slice::from_raw_parts(imf_raw_not_terminated as *const u8, imf_raw_bytes);
let mut mime_parser = dc_mimeparser_parse(context, body); let mut mime_parser = MimeParser::new(context);
mime_parser.parse(body);
if mime_parser.header.is_empty() { if mime_parser.header.is_empty() {
// Error - even adding an empty record won't help as we do not know the message ID // Error - even adding an empty record won't help as we do not know the message ID
@@ -123,7 +125,7 @@ pub unsafe fn dc_receive_imf(
} }
}; };
if let Some(field) = lookup_field(&mime_parser, "Date", MAILIMF_FIELD_ORIG_DATE) { if let Some(field) = mime_parser.lookup_field_typ("Date", MAILIMF_FIELD_ORIG_DATE) {
let orig_date = (*field).fld_data.fld_orig_date; let orig_date = (*field).fld_data.fld_orig_date;
if !orig_date.is_null() { if !orig_date.is_null() {
// is not yet checked against bad times! we do this later if we have the database information. // is not yet checked against bad times! we do this later if we have the database information.
@@ -134,7 +136,7 @@ pub unsafe fn dc_receive_imf(
// get From: and check if it is known (for known From:'s we add the other To:/Cc: in the 3rd pass) // get From: and check if it is known (for known From:'s we add the other To:/Cc: in the 3rd pass)
// or if From: is equal to SELF (in this case, it is any outgoing messages, // or if From: is equal to SELF (in this case, it is any outgoing messages,
// we do not check Return-Path any more as this is unreliable, see issue #150 // we do not check Return-Path any more as this is unreliable, see issue #150
if let Some(field) = lookup_field(&mime_parser, "From", MAILIMF_FIELD_FROM) { if let Some(field) = mime_parser.lookup_field_typ("From", MAILIMF_FIELD_FROM) {
let fld_from = (*field).fld_data.fld_from; let fld_from = (*field).fld_data.fld_from;
if !fld_from.is_null() { if !fld_from.is_null() {
let mut check_self = 0; let mut check_self = 0;
@@ -148,7 +150,7 @@ pub unsafe fn dc_receive_imf(
); );
if 0 != check_self { if 0 != check_self {
incoming = 0; incoming = 0;
if 0 != dc_mimeparser_sender_equals_recipient(&mime_parser) { if mime_parser.sender_equals_recipient() {
from_id = DC_CONTACT_ID_SELF; from_id = DC_CONTACT_ID_SELF;
} }
} else if from_list.len() >= 1 { } else if from_list.len() >= 1 {
@@ -162,7 +164,7 @@ pub unsafe fn dc_receive_imf(
} }
// Make sure, to_ids starts with the first To:-address (Cc: is added in the loop below pass) // Make sure, to_ids starts with the first To:-address (Cc: is added in the loop below pass)
if let Some(field) = lookup_field(&mime_parser, "To", MAILIMF_FIELD_TO) { if let Some(field) = mime_parser.lookup_field_typ("To", MAILIMF_FIELD_TO) {
let fld_to = (*field).fld_data.fld_to; let fld_to = (*field).fld_data.fld_to;
if !fld_to.is_null() { if !fld_to.is_null() {
dc_add_or_lookup_contacts_by_address_list( dc_add_or_lookup_contacts_by_address_list(
@@ -182,7 +184,7 @@ pub unsafe fn dc_receive_imf(
} }
// Add parts // Add parts
if dc_mimeparser_get_last_nonmeta(&mut mime_parser).is_some() { if mime_parser.get_last_nonmeta().is_some() {
if let Err(err) = add_parts( if let Err(err) = add_parts(
context, context,
&mut mime_parser, &mut mime_parser,
@@ -277,7 +279,7 @@ pub unsafe fn dc_receive_imf(
unsafe fn add_parts( unsafe fn add_parts(
context: &Context, context: &Context,
mut mime_parser: &mut dc_mimeparser_t, mut mime_parser: &mut MimeParser,
imf_raw_not_terminated: *const libc::c_char, imf_raw_not_terminated: *const libc::c_char,
imf_raw_bytes: libc::size_t, imf_raw_bytes: libc::size_t,
incoming: i32, incoming: i32,
@@ -315,7 +317,7 @@ unsafe fn add_parts(
// collect the rest information, CC: is added to the to-list, BCC: is ignored // collect the rest information, CC: is added to the to-list, BCC: is ignored
// (we should not add BCC to groups as this would split groups. We could add them as "known contacts", // (we should not add BCC to groups as this would split groups. We could add them as "known contacts",
// however, the benefit is very small and this may leak data that is expected to be hidden) // however, the benefit is very small and this may leak data that is expected to be hidden)
if let Some(field) = lookup_field(mime_parser, "Cc", MAILIMF_FIELD_CC) { if let Some(field) = mime_parser.lookup_field_typ("Cc", MAILIMF_FIELD_CC) {
let fld_cc = (*field).fld_data.fld_cc; let fld_cc = (*field).fld_data.fld_cc;
if !fld_cc.is_null() { if !fld_cc.is_null() {
dc_add_or_lookup_contacts_by_address_list( dc_add_or_lookup_contacts_by_address_list(
@@ -338,7 +340,7 @@ unsafe fn add_parts(
// change. (missing Message-IDs may come if the mail was set from this account with another // change. (missing Message-IDs may come if the mail was set from this account with another
// client that relies in the SMTP server to generate one. // client that relies in the SMTP server to generate one.
// true eg. for the Webmailer used in all-inkl-KAS) // true eg. for the Webmailer used in all-inkl-KAS)
if let Some(field) = lookup_field(mime_parser, "Message-ID", MAILIMF_FIELD_MESSAGE_ID) { if let Some(field) = mime_parser.lookup_field_typ("Message-ID", MAILIMF_FIELD_MESSAGE_ID) {
let fld_message_id = (*field).fld_data.fld_message_id; let fld_message_id = (*field).fld_data.fld_message_id;
if !fld_message_id.is_null() { if !fld_message_id.is_null() {
rfc724_mid = dc_strdup((*fld_message_id).mid_value) rfc724_mid = dc_strdup((*fld_message_id).mid_value)
@@ -383,7 +385,7 @@ unsafe fn add_parts(
// incoming non-chat messages may be discarded; // incoming non-chat messages may be discarded;
// maybe this can be optimized later, by checking the state before the message body is downloaded // maybe this can be optimized later, by checking the state before the message body is downloaded
let mut allow_creation = 1; let mut allow_creation = 1;
if mime_parser.is_system_message != DC_CMD_AUTOCRYPT_SETUP_MESSAGE && msgrmsg == 0 { if mime_parser.is_system_message != SystemMessage::AutocryptSetupMessage && msgrmsg == 0 {
let show_emails = context let show_emails = context
.sql .sql
.get_config_int(context, "show_emails") .get_config_int(context, "show_emails")
@@ -409,7 +411,7 @@ unsafe fn add_parts(
*to_id = 1; *to_id = 1;
// handshake messages must be processed _before_ chats are created // handshake messages must be processed _before_ chats are created
// (eg. contacs may be marked as verified) // (eg. contacs may be marked as verified)
if !dc_mimeparser_lookup_field(mime_parser, "Secure-Join").is_null() { if mime_parser.lookup_field("Secure-Join").is_some() {
// avoid discarding by show_emails setting // avoid discarding by show_emails setting
msgrmsg = 1; msgrmsg = 1;
*chat_id = 0; *chat_id = 0;
@@ -458,7 +460,7 @@ unsafe fn add_parts(
if *chat_id == 0 { if *chat_id == 0 {
// check if the message belongs to a mailing list // check if the message belongs to a mailing list
if dc_mimeparser_is_mailinglist_message(mime_parser) { if mime_parser.is_mailinglist_message() {
*chat_id = 3; *chat_id = 3;
info!(context, "Message belongs to a mailing list and is ignored.",); info!(context, "Message belongs to a mailing list and is ignored.",);
} }
@@ -600,7 +602,7 @@ unsafe fn add_parts(
.sql .sql
.get_config_int(context, "save_mime_headers") .get_config_int(context, "save_mime_headers")
.unwrap_or_default(); .unwrap_or_default();
if let Some(field) = lookup_field(mime_parser, "In-Reply-To", MAILIMF_FIELD_IN_REPLY_TO) { if let Some(field) = mime_parser.lookup_field_typ("In-Reply-To", MAILIMF_FIELD_IN_REPLY_TO) {
let fld_in_reply_to = (*field).fld_data.fld_in_reply_to; let fld_in_reply_to = (*field).fld_data.fld_in_reply_to;
if !fld_in_reply_to.is_null() { if !fld_in_reply_to.is_null() {
mime_in_reply_to = dc_str_from_clist( mime_in_reply_to = dc_str_from_clist(
@@ -610,7 +612,7 @@ unsafe fn add_parts(
} }
} }
if let Some(field) = lookup_field(mime_parser, "References", MAILIMF_FIELD_REFERENCES) { if let Some(field) = mime_parser.lookup_field_typ("References", MAILIMF_FIELD_REFERENCES) {
let fld_references = (*field).fld_data.fld_references; let fld_references = (*field).fld_data.fld_references;
if !fld_references.is_null() { if !fld_references.is_null() {
mime_references = dc_str_from_clist( mime_references = dc_str_from_clist(
@@ -653,7 +655,7 @@ unsafe fn add_parts(
} }
} }
} }
if part.type_0 == Viewtype::Text { if part.typ == Viewtype::Text {
let msg_raw = part.msg_raw.as_ref().cloned().unwrap_or_default(); let msg_raw = part.msg_raw.as_ref().cloned().unwrap_or_default();
let subject = mime_parser let subject = mime_parser
.subject .subject
@@ -662,9 +664,9 @@ unsafe fn add_parts(
.unwrap_or("".into()); .unwrap_or("".into());
txt_raw = Some(format!("{}\n\n{}", subject, msg_raw)); txt_raw = Some(format!("{}\n\n{}", subject, msg_raw));
} }
if 0 != mime_parser.is_system_message { if mime_parser.is_system_message != SystemMessage::Unknown {
part.param part.param
.set_int(Param::Cmd, mime_parser.is_system_message); .set_int(Param::Cmd, mime_parser.is_system_message as i32);
} }
stmt.execute(params![ stmt.execute(params![
@@ -677,7 +679,7 @@ unsafe fn add_parts(
sort_timestamp, sort_timestamp,
*sent_timestamp, *sent_timestamp,
rcvd_timestamp, rcvd_timestamp,
part.type_0, part.typ,
state, state,
msgrmsg, msgrmsg,
part.msg.as_ref().map_or("", String::as_str), part.msg.as_ref().map_or("", String::as_str),
@@ -746,24 +748,10 @@ unsafe fn add_parts(
Ok(()) Ok(())
} }
/// Lookup a mime field given its name and type.
unsafe fn lookup_field(
parser: &dc_mimeparser_t,
name: &str,
typ: u32,
) -> Option<*const mailimf_field> {
let field = dc_mimeparser_lookup_field(parser, name);
if !field.is_null() && (*field).fld_type == typ as libc::c_int {
Some(field)
} else {
None
}
}
// Handle reports (mainly MDNs) // Handle reports (mainly MDNs)
unsafe fn handle_reports( unsafe fn handle_reports(
context: &Context, context: &Context,
mime_parser: &dc_mimeparser_t, mime_parser: &MimeParser,
from_id: u32, from_id: u32,
sent_timestamp: i64, sent_timestamp: i64,
rr_event_to_send: &mut Vec<(u32, u32)>, rr_event_to_send: &mut Vec<(u32, u32)>,
@@ -926,7 +914,7 @@ unsafe fn handle_reports(
fn save_locations( fn save_locations(
context: &Context, context: &Context,
mime_parser: &dc_mimeparser_t, mime_parser: &MimeParser,
chat_id: u32, chat_id: u32,
from_id: u32, from_id: u32,
insert_msg_id: u32, insert_msg_id: u32,
@@ -1024,7 +1012,7 @@ unsafe fn calc_timestamps(
#[allow(non_snake_case)] #[allow(non_snake_case)]
unsafe fn create_or_lookup_group( unsafe fn create_or_lookup_group(
context: &Context, context: &Context,
mime_parser: &mut dc_mimeparser_t, mime_parser: &mut MimeParser,
allow_creation: libc::c_int, allow_creation: libc::c_int,
create_blocked: Blocked, create_blocked: Blocked,
from_id: u32, from_id: u32,
@@ -1036,28 +1024,20 @@ unsafe fn create_or_lookup_group(
let mut chat_id = 0; let mut chat_id = 0;
let mut chat_id_blocked = Blocked::Not; let mut chat_id_blocked = Blocked::Not;
let mut grpid = "".to_string(); let mut grpid = "".to_string();
let mut grpname = std::ptr::null_mut(); let mut grpname = None;
let to_ids_cnt = to_ids.len(); let to_ids_cnt = to_ids.len();
let mut recreate_member_list = 0; let mut recreate_member_list = 0;
let mut send_EVENT_CHAT_MODIFIED = 0; let mut send_EVENT_CHAT_MODIFIED = 0;
// pointer somewhere into mime_parser, must not be freed let mut X_MrRemoveFromGrp = None;
let mut X_MrRemoveFromGrp = std::ptr::null_mut(); let mut X_MrAddToGrp = None;
// pointer somewhere into mime_parser, must not be freed
let mut X_MrAddToGrp = std::ptr::null_mut();
let mut X_MrGrpNameChanged = 0; let mut X_MrGrpNameChanged = 0;
let mut X_MrGrpImageChanged = "".to_string(); let mut X_MrGrpImageChanged = "".to_string();
let mut better_msg: String = From::from(""); let mut better_msg: String = From::from("");
let mut failure_reason = std::ptr::null_mut();
let cleanup = |grpname: *mut libc::c_char, let cleanup = |ret_chat_id: *mut u32,
failure_reason: *mut libc::c_char,
ret_chat_id: *mut u32,
ret_chat_id_blocked: &mut Blocked, ret_chat_id_blocked: &mut Blocked,
chat_id: u32, chat_id: u32,
chat_id_blocked: Blocked| { chat_id_blocked: Blocked| {
free(grpname.cast());
free(failure_reason.cast());
if !ret_chat_id.is_null() { if !ret_chat_id.is_null() {
*ret_chat_id = chat_id; *ret_chat_id = chat_id;
} }
@@ -1068,18 +1048,18 @@ unsafe fn create_or_lookup_group(
}; };
}; };
if mime_parser.is_system_message == DC_CMD_LOCATION_STREAMING_ENABLED { if mime_parser.is_system_message == SystemMessage::LocationStreamingEnabled {
better_msg = better_msg =
context.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", from_id as u32) context.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", from_id as u32)
} }
set_better_msg(mime_parser, &better_msg); set_better_msg(mime_parser, &better_msg);
let optional_field = dc_mimeparser_lookup_optional_field(mime_parser, "Chat-Group-ID"); if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-ID") {
if !optional_field.is_null() { grpid = optional_field;
grpid = to_string((*optional_field).fld_value)
} }
if grpid.is_empty() { if grpid.is_empty() {
if let Some(field) = lookup_field(mime_parser, "Message-ID", MAILIMF_FIELD_MESSAGE_ID) { if let Some(field) = mime_parser.lookup_field_typ("Message-ID", MAILIMF_FIELD_MESSAGE_ID) {
let fld_message_id = (*field).fld_data.fld_message_id; let fld_message_id = (*field).fld_data.fld_message_id;
if !fld_message_id.is_null() { if !fld_message_id.is_null() {
if let Some(extracted_grpid) = if let Some(extracted_grpid) =
@@ -1092,7 +1072,8 @@ unsafe fn create_or_lookup_group(
} }
} }
if grpid.is_empty() { if grpid.is_empty() {
if let Some(field) = lookup_field(mime_parser, "In-Reply-To", MAILIMF_FIELD_IN_REPLY_TO) if let Some(field) =
mime_parser.lookup_field_typ("In-Reply-To", MAILIMF_FIELD_IN_REPLY_TO)
{ {
let fld_in_reply_to = (*field).fld_data.fld_in_reply_to; let fld_in_reply_to = (*field).fld_data.fld_in_reply_to;
if !fld_in_reply_to.is_null() { if !fld_in_reply_to.is_null() {
@@ -1103,7 +1084,7 @@ unsafe fn create_or_lookup_group(
} }
if grpid.is_empty() { if grpid.is_empty() {
if let Some(field) = if let Some(field) =
lookup_field(mime_parser, "References", MAILIMF_FIELD_REFERENCES) mime_parser.lookup_field_typ("References", MAILIMF_FIELD_REFERENCES)
{ {
let fld_references = (*field).fld_data.fld_references; let fld_references = (*field).fld_data.fld_references;
if !fld_references.is_null() { if !fld_references.is_null() {
@@ -1124,30 +1105,20 @@ unsafe fn create_or_lookup_group(
&mut chat_id, &mut chat_id,
&mut chat_id_blocked, &mut chat_id_blocked,
); );
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
failure_reason,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
return; return;
} }
} }
} }
} }
let optional_field = dc_mimeparser_lookup_optional_field(mime_parser, "Chat-Group-Name"); if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Name") {
if !optional_field.is_null() { grpname = Some(dc_decode_header_words_safe(&optional_field));
grpname = dc_decode_header_words((*optional_field).fld_value)
} }
let optional_field = if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Member-Removed") {
dc_mimeparser_lookup_optional_field(mime_parser, "Chat-Group-Member-Removed"); X_MrRemoveFromGrp = Some(optional_field);
if !optional_field.is_null() { mime_parser.is_system_message = SystemMessage::MemberRemovedFromGroup;
X_MrRemoveFromGrp = (*optional_field).fld_value; let left_group = (Contact::lookup_id_by_addr(context, X_MrRemoveFromGrp.as_ref().unwrap())
mime_parser.is_system_message = DC_CMD_MEMBER_REMOVED_FROM_GROUP;
let left_group = (Contact::lookup_id_by_addr(context, as_str(X_MrRemoveFromGrp))
== from_id as u32) as libc::c_int; == from_id as u32) as libc::c_int;
better_msg = context.stock_system_msg( better_msg = context.stock_system_msg(
if 0 != left_group { if 0 != left_group {
@@ -1155,47 +1126,45 @@ unsafe fn create_or_lookup_group(
} else { } else {
StockMessage::MsgDelMember StockMessage::MsgDelMember
}, },
as_str(X_MrRemoveFromGrp), X_MrRemoveFromGrp.as_ref().unwrap(),
"", "",
from_id as u32, from_id as u32,
) )
} else { } else {
let optional_field = if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Member-Added") {
dc_mimeparser_lookup_optional_field(mime_parser, "Chat-Group-Member-Added"); X_MrAddToGrp = Some(optional_field);
if !optional_field.is_null() { mime_parser.is_system_message = SystemMessage::MemberAddedToGroup;
X_MrAddToGrp = (*optional_field).fld_value; if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Image") {
mime_parser.is_system_message = DC_CMD_MEMBER_ADDED_TO_GROUP; X_MrGrpImageChanged = optional_field;
let optional_field =
dc_mimeparser_lookup_optional_field(mime_parser, "Chat-Group-Image");
if !optional_field.is_null() {
// fld_value is a pointer somewhere into mime_parser, must not be freed
X_MrGrpImageChanged = as_str((*optional_field).fld_value).to_string();
} }
better_msg = context.stock_system_msg( better_msg = context.stock_system_msg(
StockMessage::MsgAddMember, StockMessage::MsgAddMember,
as_str(X_MrAddToGrp), X_MrAddToGrp.as_ref().unwrap(),
"", "",
from_id as u32, from_id as u32,
) )
} else { } else {
let optional_field = if let Some(optional_field) =
dc_mimeparser_lookup_optional_field(mime_parser, "Chat-Group-Name-Changed"); mime_parser.lookup_optional_field("Chat-Group-Name-Changed")
if !optional_field.is_null() { {
X_MrGrpNameChanged = 1; X_MrGrpNameChanged = 1;
mime_parser.is_system_message = DC_CMD_GROUPNAME_CHANGED; mime_parser.is_system_message = SystemMessage::GroupNameChanged;
better_msg = context.stock_system_msg( better_msg = context.stock_system_msg(
StockMessage::MsgGrpName, StockMessage::MsgGrpName,
as_str((*optional_field).fld_value), &optional_field,
as_str(grpname), if let Some(ref name) = grpname {
name
} else {
""
},
from_id as u32, from_id as u32,
) )
} else { } else {
let optional_field = if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Image")
dc_mimeparser_lookup_optional_field(mime_parser, "Chat-Group-Image"); {
if !optional_field.is_null() {
// fld_value is a pointer somewhere into mime_parser, must not be freed // fld_value is a pointer somewhere into mime_parser, must not be freed
X_MrGrpImageChanged = as_str((*optional_field).fld_value).to_string(); X_MrGrpImageChanged = optional_field;
mime_parser.is_system_message = DC_CMD_GROUPIMAGE_CHANGED; mime_parser.is_system_message = SystemMessage::GroupImageChanged;
better_msg = context.stock_system_msg( better_msg = context.stock_system_msg(
if X_MrGrpImageChanged == "0" { if X_MrGrpImageChanged == "0" {
StockMessage::MsgGrpImgDeleted StockMessage::MsgGrpImgDeleted
@@ -1215,6 +1184,8 @@ unsafe fn create_or_lookup_group(
// check, if we have a chat with this group ID // check, if we have a chat with this group ID
let (mut chat_id, chat_id_verified, _blocked) = chat::get_chat_id_by_grpid(context, &grpid); let (mut chat_id, chat_id_verified, _blocked) = chat::get_chat_id_by_grpid(context, &grpid);
if chat_id != 0 { if chat_id != 0 {
let mut failure_reason = std::ptr::null_mut();
if chat_id_verified if chat_id_verified
&& 0 == check_verified_properties( && 0 == check_verified_properties(
context, context,
@@ -1224,8 +1195,10 @@ unsafe fn create_or_lookup_group(
&mut failure_reason, &mut failure_reason,
) )
{ {
dc_mimeparser_repl_msg_by_error(mime_parser, failure_reason); mime_parser.repl_msg_by_error(to_string(failure_reason));
} }
free(failure_reason.cast());
} }
// check if the sender is a member of the existing group - // check if the sender is a member of the existing group -
@@ -1242,18 +1215,20 @@ unsafe fn create_or_lookup_group(
.get_config(context, "configured_addr") .get_config(context, "configured_addr")
.unwrap_or_default(); .unwrap_or_default();
if chat_id == 0 if chat_id == 0
&& !dc_mimeparser_is_mailinglist_message(mime_parser) && !mime_parser.is_mailinglist_message()
&& !grpid.is_empty() && !grpid.is_empty()
&& !grpname.is_null() && grpname.is_some()
// otherwise, a pending "quit" message may pop up // otherwise, a pending "quit" message may pop up
&& X_MrRemoveFromGrp.is_null() && X_MrRemoveFromGrp.is_none()
// re-create explicitly left groups only if ourself is re-added // re-create explicitly left groups only if ourself is re-added
&& (!group_explicitly_left && (!group_explicitly_left
|| !X_MrAddToGrp.is_null() && addr_cmp(&self_addr, as_str(X_MrAddToGrp))) || X_MrAddToGrp.is_some() && addr_cmp(&self_addr, X_MrAddToGrp.as_ref().unwrap()))
{ {
let mut create_verified = VerifiedStatus::Unverified; let mut create_verified = VerifiedStatus::Unverified;
if !dc_mimeparser_lookup_field(mime_parser, "Chat-Verified").is_null() { if mime_parser.lookup_field("Chat-Verified").is_some() {
create_verified = VerifiedStatus::Verified; create_verified = VerifiedStatus::Verified;
let mut failure_reason = std::ptr::null_mut();
if 0 == check_verified_properties( if 0 == check_verified_properties(
context, context,
mime_parser, mime_parser,
@@ -1261,21 +1236,21 @@ unsafe fn create_or_lookup_group(
to_ids, to_ids,
&mut failure_reason, &mut failure_reason,
) { ) {
dc_mimeparser_repl_msg_by_error(mime_parser, failure_reason); mime_parser.repl_msg_by_error(to_string(failure_reason));
} }
free(failure_reason.cast());
} }
if 0 == allow_creation { if 0 == allow_creation {
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
failure_reason,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
return; return;
} }
chat_id = create_group_record(context, &grpid, grpname, create_blocked, create_verified); chat_id = create_group_record(
context,
&grpid,
grpname.as_ref().unwrap(),
create_blocked,
create_verified,
);
chat_id_blocked = create_blocked; chat_id_blocked = create_blocked;
recreate_member_list = 1; recreate_member_list = 1;
} }
@@ -1297,31 +1272,28 @@ unsafe fn create_or_lookup_group(
&mut chat_id_blocked, &mut chat_id_blocked,
); );
} }
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
failure_reason,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
return; return;
} }
// execute group commands // execute group commands
if !X_MrAddToGrp.is_null() || !X_MrRemoveFromGrp.is_null() { if X_MrAddToGrp.is_some() || X_MrRemoveFromGrp.is_some() {
recreate_member_list = 1; recreate_member_list = 1;
} else if 0 != X_MrGrpNameChanged && !grpname.is_null() && strlen(grpname) < 200 { } else if 0 != X_MrGrpNameChanged {
info!(context, "updating grpname for chat {}", chat_id); if let Some(ref grpname) = grpname {
if sql::execute( if grpname.len() < 200 {
context, info!(context, "updating grpname for chat {}", chat_id);
&context.sql, if sql::execute(
"UPDATE chats SET name=? WHERE id=?;", context,
params![as_str(grpname), chat_id as i32], &context.sql,
) "UPDATE chats SET name=? WHERE id=?;",
.is_ok() params![grpname, chat_id as i32],
{ )
context.call_cb(Event::ChatModified(chat_id)); .is_ok()
{
context.call_cb(Event::ChatModified(chat_id));
}
}
} }
} }
if !X_MrGrpImageChanged.is_empty() { if !X_MrGrpImageChanged.is_empty() {
@@ -1335,7 +1307,7 @@ unsafe fn create_or_lookup_group(
changed = true; changed = true;
} else { } else {
for part in &mut mime_parser.parts { for part in &mut mime_parser.parts {
if part.type_0 == Viewtype::Image { if part.typ == Viewtype::Image {
grpimage = part grpimage = part
.param .param
.get(Param::File) .get(Param::File)
@@ -1367,11 +1339,7 @@ unsafe fn create_or_lookup_group(
// than the one that is responsible for the current member list, see // than the one that is responsible for the current member list, see
// https://github.com/deltachat/deltachat-core/issues/127 // https://github.com/deltachat/deltachat-core/issues/127
let skip = if !X_MrRemoveFromGrp.is_null() { let skip = X_MrRemoveFromGrp.as_ref();
X_MrRemoveFromGrp
} else {
ptr::null_mut()
};
sql::execute( sql::execute(
context, context,
&context.sql, &context.sql,
@@ -1379,21 +1347,20 @@ unsafe fn create_or_lookup_group(
params![chat_id as i32], params![chat_id as i32],
) )
.ok(); .ok();
if skip.is_null() || !addr_cmp(&self_addr, as_str(skip)) { if skip.is_none() || !addr_cmp(&self_addr, skip.unwrap()) {
chat::add_to_chat_contacts_table(context, chat_id, DC_CONTACT_ID_SELF); chat::add_to_chat_contacts_table(context, chat_id, DC_CONTACT_ID_SELF);
} }
if from_id > DC_CHAT_ID_LAST_SPECIAL { if from_id > DC_CHAT_ID_LAST_SPECIAL {
if !Contact::addr_equals_contact(context, &self_addr, from_id as u32) if !Contact::addr_equals_contact(context, &self_addr, from_id as u32)
&& (skip.is_null() && (skip.is_none()
|| !Contact::addr_equals_contact(context, to_string(skip), from_id as u32)) || !Contact::addr_equals_contact(context, skip.unwrap(), from_id as u32))
{ {
chat::add_to_chat_contacts_table(context, chat_id, from_id as u32); chat::add_to_chat_contacts_table(context, chat_id, from_id as u32);
} }
} }
for &to_id in to_ids.iter() { for &to_id in to_ids.iter() {
if !Contact::addr_equals_contact(context, &self_addr, to_id) if !Contact::addr_equals_contact(context, &self_addr, to_id)
&& (skip.is_null() && (skip.is_none() || !Contact::addr_equals_contact(context, skip.unwrap(), to_id))
|| !Contact::addr_equals_contact(context, to_string(skip), to_id))
{ {
chat::add_to_chat_contacts_table(context, chat_id, to_id); chat::add_to_chat_contacts_table(context, chat_id, to_id);
} }
@@ -1427,20 +1394,13 @@ unsafe fn create_or_lookup_group(
} }
} }
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
failure_reason,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
} }
/// Handle groups for received messages /// Handle groups for received messages
unsafe fn create_or_lookup_adhoc_group( unsafe fn create_or_lookup_adhoc_group(
context: &Context, context: &Context,
mime_parser: &dc_mimeparser_t, mime_parser: &MimeParser,
allow_creation: libc::c_int, allow_creation: libc::c_int,
create_blocked: Blocked, create_blocked: Blocked,
from_id: u32, from_id: u32,
@@ -1452,15 +1412,11 @@ unsafe fn create_or_lookup_adhoc_group(
// group matching the to-list or if we can create one // group matching the to-list or if we can create one
let mut chat_id = 0; let mut chat_id = 0;
let mut chat_id_blocked = Blocked::Not; let mut chat_id_blocked = Blocked::Not;
let mut grpname = ptr::null_mut();
let cleanup = |grpname: *mut libc::c_char, let cleanup = |ret_chat_id: *mut u32,
ret_chat_id: *mut u32,
ret_chat_id_blocked: &mut Blocked, ret_chat_id_blocked: &mut Blocked,
chat_id: u32, chat_id: u32,
chat_id_blocked: Blocked| { chat_id_blocked: Blocked| {
free(grpname as *mut libc::c_void);
if !ret_chat_id.is_null() { if !ret_chat_id.is_null() {
*ret_chat_id = chat_id; *ret_chat_id = chat_id;
} }
@@ -1468,15 +1424,9 @@ unsafe fn create_or_lookup_adhoc_group(
}; };
// build member list from the given ids // build member list from the given ids
if to_ids.is_empty() || dc_mimeparser_is_mailinglist_message(mime_parser) { if to_ids.is_empty() || mime_parser.is_mailinglist_message() {
// too few contacts or a mailinglist // too few contacts or a mailinglist
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
return; return;
} }
@@ -1489,13 +1439,7 @@ unsafe fn create_or_lookup_adhoc_group(
} }
if member_ids.len() < 3 { if member_ids.len() < 3 {
// too few contacts given // too few contacts given
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
return; return;
} }
@@ -1518,25 +1462,13 @@ unsafe fn create_or_lookup_adhoc_group(
chat_id = id as u32; chat_id = id as u32;
chat_id_blocked = id_blocked; chat_id_blocked = id_blocked;
/* success, chat found */ /* success, chat found */
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
return; return;
} }
} }
if 0 == allow_creation { if 0 == allow_creation {
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
return; return;
} }
// we do not check if the message is a reply to another group, this may result in // we do not check if the message is a reply to another group, this may result in
@@ -1546,24 +1478,16 @@ unsafe fn create_or_lookup_adhoc_group(
// - there is no need to check if this group exists; otherwise we would have caught it above // - there is no need to check if this group exists; otherwise we would have caught it above
let grpid = create_adhoc_grp_id(context, &member_ids); let grpid = create_adhoc_grp_id(context, &member_ids);
if grpid.is_empty() { if grpid.is_empty() {
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
return; return;
} }
// use subject as initial chat name // use subject as initial chat name
if let Some(subject) = mime_parser.subject.as_ref().filter(|s| !s.is_empty()) { let grpname = if let Some(subject) = mime_parser.subject.as_ref().filter(|s| !s.is_empty()) {
grpname = subject.strdup(); subject.to_string()
} else { } else {
grpname = context 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) };
.strdup();
}
// create group record // create group record
chat_id = create_group_record( chat_id = create_group_record(
@@ -1580,19 +1504,13 @@ unsafe fn create_or_lookup_adhoc_group(
context.call_cb(Event::ChatModified(chat_id)); context.call_cb(Event::ChatModified(chat_id));
cleanup( cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
grpname,
ret_chat_id,
ret_chat_id_blocked,
chat_id,
chat_id_blocked,
);
} }
fn create_group_record( fn create_group_record(
context: &Context, context: &Context,
grpid: impl AsRef<str>, grpid: impl AsRef<str>,
grpname: *const libc::c_char, grpname: impl AsRef<str>,
create_blocked: Blocked, create_blocked: Blocked,
create_verified: VerifiedStatus, create_verified: VerifiedStatus,
) -> u32 { ) -> u32 {
@@ -1606,7 +1524,7 @@ fn create_group_record(
} else { } else {
Chattype::Group Chattype::Group
}, },
as_str(grpname), grpname.as_ref(),
grpid.as_ref(), grpid.as_ref(),
create_blocked, create_blocked,
], ],
@@ -1729,7 +1647,7 @@ fn search_chat_ids_by_contact_ids(context: &Context, unsorted_contact_ids: &Vec<
unsafe fn check_verified_properties( unsafe fn check_verified_properties(
context: &Context, context: &Context,
mimeparser: &dc_mimeparser_t, mimeparser: &MimeParser,
from_id: u32, from_id: u32,
to_ids: &Vec<u32>, to_ids: &Vec<u32>,
failure_reason: *mut *mut libc::c_char, failure_reason: *mut *mut libc::c_char,
@@ -1829,46 +1747,54 @@ unsafe fn check_verified_properties(
1 1
} }
unsafe fn set_better_msg<T: AsRef<str>>(mime_parser: &mut dc_mimeparser_t, better_msg: T) { fn set_better_msg(mime_parser: &mut MimeParser, better_msg: impl AsRef<str>) {
let msg = better_msg.as_ref(); let msg = better_msg.as_ref();
if msg.len() > 0 && !mime_parser.parts.is_empty() { if msg.len() > 0 && !mime_parser.parts.is_empty() {
let part = &mut mime_parser.parts[0]; let part = &mut mime_parser.parts[0];
if (*part).type_0 == Viewtype::Text { if part.typ == Viewtype::Text {
part.msg = Some(msg.to_string()); part.msg = Some(msg.to_string());
} }
}; };
} }
unsafe fn dc_is_reply_to_known_message( unsafe fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimeParser) -> libc::c_int {
context: &Context,
mime_parser: &dc_mimeparser_t,
) -> libc::c_int {
/* check if the message is a reply to a known message; the replies are identified by the Message-ID from /* check if the message is a reply to a known message; the replies are identified by the Message-ID from
`In-Reply-To`/`References:` (to support non-Delta-Clients) or from `Chat-Predecessor:` (Delta clients, see comment in dc_chat.c) */ `In-Reply-To`/`References:` (to support non-Delta-Clients) or from `Chat-Predecessor:` (Delta clients, see comment in dc_chat.c) */
let optional_field = dc_mimeparser_lookup_optional_field(mime_parser, "Chat-Predecessor"); if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Predecessor") {
if !optional_field.is_null() { let optional_field_c = CString::new(optional_field).unwrap();
if 0 != is_known_rfc724_mid(context, (*optional_field).fld_value) { if 0 != is_known_rfc724_mid(context, optional_field_c.as_ptr()) {
return 1; return 1;
} }
} }
let field = dc_mimeparser_lookup_field(mime_parser, "In-Reply-To");
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int { if let Some(field) = mime_parser.lookup_field("In-Reply-To") {
let fld_in_reply_to: *mut mailimf_in_reply_to = (*field).fld_data.fld_in_reply_to; if (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int {
if !fld_in_reply_to.is_null() { let fld_in_reply_to = (*field).fld_data.fld_in_reply_to;
if is_known_rfc724_mid_in_list(context, (*(*field).fld_data.fld_in_reply_to).mid_list) { if !fld_in_reply_to.is_null() {
return 1; if is_known_rfc724_mid_in_list(
context,
(*(*field).fld_data.fld_in_reply_to).mid_list,
) {
return 1;
}
} }
} }
} }
let field = dc_mimeparser_lookup_field(mime_parser, "References");
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int { if let Some(field) = mime_parser.lookup_field("References") {
let fld_references: *mut mailimf_references = (*field).fld_data.fld_references; if (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int {
if !fld_references.is_null() { let fld_references = (*field).fld_data.fld_references;
if is_known_rfc724_mid_in_list(context, (*(*field).fld_data.fld_references).mid_list) { if !fld_references.is_null() {
return 1; if is_known_rfc724_mid_in_list(
context,
(*(*field).fld_data.fld_references).mid_list,
) {
return 1;
}
} }
} }
} }
0 0
} }
@@ -1905,37 +1831,42 @@ fn is_known_rfc724_mid(context: &Context, rfc724_mid: *const libc::c_char) -> li
unsafe fn dc_is_reply_to_messenger_message( unsafe fn dc_is_reply_to_messenger_message(
context: &Context, context: &Context,
mime_parser: &dc_mimeparser_t, mime_parser: &MimeParser,
) -> libc::c_int { ) -> libc::c_int {
/* function checks, if the message defined by mime_parser references a message send by us from Delta Chat. /* function checks, if the message defined by mime_parser references a message send by us from Delta Chat.
This is similar to is_reply_to_known_message() but This is similar to is_reply_to_known_message() but
- checks also if any of the referenced IDs are send by a messenger - checks also if any of the referenced IDs are send by a messenger
- it is okay, if the referenced messages are moved to trash here - it is okay, if the referenced messages are moved to trash here
- no check for the Chat-* headers (function is only called if it is no messenger message itself) */ - no check for the Chat-* headers (function is only called if it is no messenger message itself) */
let field = dc_mimeparser_lookup_field(mime_parser, "In-Reply-To");
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int { if let Some(field) = mime_parser.lookup_field("In-Reply-To") {
let fld_in_reply_to: *mut mailimf_in_reply_to = (*field).fld_data.fld_in_reply_to; if (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int {
if !fld_in_reply_to.is_null() { let fld_in_reply_to = (*field).fld_data.fld_in_reply_to;
if 0 != is_msgrmsg_rfc724_mid_in_list( if !fld_in_reply_to.is_null() {
context, if 0 != is_msgrmsg_rfc724_mid_in_list(
(*(*field).fld_data.fld_in_reply_to).mid_list, context,
) { (*(*field).fld_data.fld_in_reply_to).mid_list,
return 1; ) {
return 1;
}
} }
} }
} }
let field = dc_mimeparser_lookup_field(mime_parser, "References");
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int { if let Some(field) = mime_parser.lookup_field("References") {
let fld_references: *mut mailimf_references = (*field).fld_data.fld_references; if (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int {
if !fld_references.is_null() { let fld_references: *mut mailimf_references = (*field).fld_data.fld_references;
if 0 != is_msgrmsg_rfc724_mid_in_list( if !fld_references.is_null() {
context, if 0 != is_msgrmsg_rfc724_mid_in_list(
(*(*field).fld_data.fld_references).mid_list, context,
) { (*(*field).fld_data.fld_references).mid_list,
return 1; ) {
return 1;
}
} }
} }
} }
0 0
} }

View File

@@ -386,16 +386,17 @@ impl E2eeHelper {
/*just a pointer into mailmime structure, must not be freed*/ /*just a pointer into mailmime structure, must not be freed*/
let imffields: *mut mailimf_fields = mailmime_find_mailimf_fields(in_out_message); let imffields: *mut mailimf_fields = mailmime_find_mailimf_fields(in_out_message);
let mut message_time = 0; let mut message_time = 0;
let mut from: *mut libc::c_char = ptr::null_mut(); let mut from = None;
let mut private_keyring = Keyring::default(); let mut private_keyring = Keyring::default();
let mut public_keyring_for_validate = Keyring::default(); let mut public_keyring_for_validate = Keyring::default();
let mut gossip_headers: *mut mailimf_fields = ptr::null_mut(); let mut gossip_headers: *mut mailimf_fields = ptr::null_mut();
if !(in_out_message.is_null() || imffields.is_null()) { if !(in_out_message.is_null() || imffields.is_null()) {
let mut field: *mut mailimf_field = let mut field = mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int);
mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int);
if !field.is_null() && !(*field).fld_data.fld_from.is_null() { if !field.is_null() && !(*field).fld_data.fld_from.is_null() {
from = mailimf_find_first_addr((*(*field).fld_data.fld_from).frm_mb_list) from = mailimf_find_first_addr((*(*field).fld_data.fld_from).frm_mb_list)
} }
field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int); field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int);
if !field.is_null() && !(*field).fld_data.fld_orig_date.is_null() { if !field.is_null() && !(*field).fld_data.fld_orig_date.is_null() {
let orig_date: *mut mailimf_orig_date = (*field).fld_data.fld_orig_date; let orig_date: *mut mailimf_orig_date = (*field).fld_data.fld_orig_date;
@@ -407,25 +408,28 @@ impl E2eeHelper {
} }
} }
let mut peerstate = None; let mut peerstate = None;
let autocryptheader = let autocryptheader = from
as_opt_str(from).and_then(|from| Aheader::from_imffields(from, imffields)); .as_ref()
if message_time > 0 && !from.is_null() { .and_then(|from| Aheader::from_imffields(from, imffields));
peerstate = Peerstate::from_addr(context, &context.sql, as_str(from)); if message_time > 0 {
if let Some(ref from) = from {
peerstate = Peerstate::from_addr(context, &context.sql, from);
if let Some(ref mut peerstate) = peerstate { if let Some(ref mut peerstate) = peerstate {
if let Some(ref header) = autocryptheader { if let Some(ref header) = autocryptheader {
peerstate.apply_header(&header, message_time); peerstate.apply_header(&header, message_time);
peerstate.save_to_db(&context.sql, false); peerstate.save_to_db(&context.sql, false);
} else if message_time > peerstate.last_seen_autocrypt } else if message_time > peerstate.last_seen_autocrypt
&& !contains_report(in_out_message) && !contains_report(in_out_message)
{ {
peerstate.degrade_encryption(message_time); peerstate.degrade_encryption(message_time);
peerstate.save_to_db(&context.sql, false); peerstate.save_to_db(&context.sql, false);
}
} else if let Some(ref header) = autocryptheader {
let p = Peerstate::from_header(context, header, message_time);
assert!(p.save_to_db(&context.sql, true));
peerstate = Some(p);
} }
} else if let Some(ref header) = autocryptheader {
let p = Peerstate::from_header(context, header, message_time);
assert!(p.save_to_db(&context.sql, true));
peerstate = Some(p);
} }
} }
/* load private key for decryption */ /* load private key for decryption */
@@ -437,7 +441,8 @@ impl E2eeHelper {
&context.sql, &context.sql,
) { ) {
if peerstate.as_ref().map(|p| p.last_seen).unwrap_or_else(|| 0) == 0 { if peerstate.as_ref().map(|p| p.last_seen).unwrap_or_else(|| 0) == 0 {
peerstate = Peerstate::from_addr(&context, &context.sql, as_str(from)); peerstate =
Peerstate::from_addr(&context, &context.sql, &from.unwrap_or_default());
} }
if let Some(ref peerstate) = peerstate { if let Some(ref peerstate) = peerstate {
if peerstate.degrade_event.is_some() { if peerstate.degrade_event.is_some() {
@@ -486,8 +491,6 @@ impl E2eeHelper {
if !gossip_headers.is_null() { if !gossip_headers.is_null() {
mailimf_fields_free(gossip_headers); mailimf_fields_free(gossip_headers);
} }
free(from as *mut libc::c_void);
} }
} }

View File

@@ -9,6 +9,7 @@ use crate::chat::{self, Chat};
use crate::constants::*; use crate::constants::*;
use crate::contact::*; use crate::contact::*;
use crate::context::*; use crate::context::*;
use crate::dc_mimeparser::SystemMessage;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::error::Error; use crate::error::Error;
use crate::events::Event; use crate::events::Event;
@@ -767,7 +768,7 @@ pub fn dc_msg_get_summarytext_by_raw(
Viewtype::Video => context.stock_str(StockMessage::Video).into_owned(), Viewtype::Video => context.stock_str(StockMessage::Video).into_owned(),
Viewtype::Voice => context.stock_str(StockMessage::VoiceMessage).into_owned(), Viewtype::Voice => context.stock_str(StockMessage::VoiceMessage).into_owned(),
Viewtype::Audio | Viewtype::File => { Viewtype::Audio | Viewtype::File => {
if param.get_int(Param::Cmd) == Some(6) { if param.get_cmd() == SystemMessage::AutocryptSetupMessage {
append_text = false; append_text = false;
context context
.stock_str(StockMessage::AcSetupMsgSubject) .stock_str(StockMessage::AcSetupMsgSubject)
@@ -793,7 +794,7 @@ pub fn dc_msg_get_summarytext_by_raw(
} }
} }
_ => { _ => {
if param.get_int(Param::Cmd) != Some(9) { if param.get_cmd() != SystemMessage::LocationOnly {
"".to_string() "".to_string()
} else { } else {
append_text = false; append_text = false;
@@ -839,10 +840,10 @@ pub fn dc_msg_is_forwarded(msg: &Message) -> bool {
} }
pub fn dc_msg_is_info(msg: &Message) -> bool { pub fn dc_msg_is_info(msg: &Message) -> bool {
let cmd = msg.param.get_int(Param::Cmd).unwrap_or_default(); let cmd = msg.param.get_cmd();
msg.from_id == 2i32 as libc::c_uint msg.from_id == 2i32 as libc::c_uint
|| msg.to_id == 2i32 as libc::c_uint || msg.to_id == 2i32 as libc::c_uint
|| 0 != cmd && cmd != 6i32 || cmd != SystemMessage::Unknown && cmd != SystemMessage::AutocryptSetupMessage
} }
pub fn dc_msg_is_increation(msg: &Message) -> bool { pub fn dc_msg_is_increation(msg: &Message) -> bool {
@@ -854,7 +855,7 @@ pub fn dc_msg_is_setupmessage(msg: &Message) -> bool {
return false; return false;
} }
msg.param.get_int(Param::Cmd) == Some(6) msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage
} }
pub unsafe fn dc_msg_get_setupcodebegin(context: &Context, msg: &Message) -> *mut libc::c_char { pub unsafe fn dc_msg_get_setupcodebegin(context: &Context, msg: &Message) -> *mut libc::c_char {

View File

@@ -4,6 +4,7 @@ use std::str;
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use crate::dc_mimeparser::SystemMessage;
use crate::error; use crate::error;
/// Available param keys. /// Available param keys.
@@ -178,6 +179,13 @@ impl Params {
self.get(key).and_then(|s| s.parse().ok()) self.get(key).and_then(|s| s.parse().ok())
} }
/// Get the parameter behind `Param::Cmd` interpreted as `SystemMessage`.
pub fn get_cmd(&self) -> SystemMessage {
self.get_int(Param::Cmd)
.and_then(SystemMessage::from_i32)
.unwrap_or_default()
}
/// Get the given parameter and parse as `f64`. /// Get the given parameter and parse as `f64`.
pub fn get_float(&self, key: Param) -> Option<f64> { pub fn get_float(&self, key: Param) -> Option<f64> {
self.get(key).and_then(|s| s.parse().ok()) self.get(key).and_then(|s| s.parse().ok())

View File

@@ -1,6 +1,4 @@
use mmime::mailimf_types::*;
use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC}; use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC};
use std::ptr;
use crate::aheader::EncryptPreference; use crate::aheader::EncryptPreference;
use crate::chat::{self, Chat}; use crate::chat::{self, Chat};
@@ -10,7 +8,6 @@ use crate::constants::*;
use crate::contact::*; use crate::contact::*;
use crate::context::Context; use crate::context::Context;
use crate::dc_mimeparser::*; use crate::dc_mimeparser::*;
use crate::dc_tools::*;
use crate::e2ee::*; use crate::e2ee::*;
use crate::error::Error; use crate::error::Error;
use crate::events::Event; use crate::events::Event;
@@ -335,7 +332,7 @@ fn fingerprint_equals_sender(
/* library private: secure-join */ /* library private: secure-join */
pub fn handle_securejoin_handshake( pub fn handle_securejoin_handshake(
context: &Context, context: &Context,
mimeparser: &dc_mimeparser_t, mimeparser: &MimeParser,
contact_id: u32, contact_id: u32,
) -> libc::c_int { ) -> libc::c_int {
let own_fingerprint: String; let own_fingerprint: String;
@@ -343,7 +340,7 @@ pub fn handle_securejoin_handshake(
if contact_id <= DC_CONTACT_ID_LAST_SPECIAL { if contact_id <= DC_CONTACT_ID_LAST_SPECIAL {
return 0; return 0;
} }
let step = match lookup_field(mimeparser, "Secure-Join") { let step = match mimeparser.lookup_optional_field("Secure-Join") {
Some(s) => s, Some(s) => s,
None => { None => {
return 0; return 0;
@@ -372,7 +369,7 @@ pub fn handle_securejoin_handshake(
// it just ensures, we have Bobs key now. If we do _not_ have the key because eg. MitM has removed it, // it just ensures, we have Bobs key now. If we do _not_ have the key because eg. MitM has removed it,
// send_message() will fail with the error "End-to-end-encryption unavailable unexpectedly.", so, there is no additional check needed here. // send_message() will fail with the error "End-to-end-encryption unavailable unexpectedly.", so, there is no additional check needed here.
// verify that the `Secure-Join-Invitenumber:`-header matches invitenumber written to the QR code // verify that the `Secure-Join-Invitenumber:`-header matches invitenumber written to the QR code
let invitenumber = match lookup_field(mimeparser, "Secure-Join-Invitenumber") { let invitenumber = match mimeparser.lookup_optional_field("Secure-Join-Invitenumber") {
Some(n) => n, Some(n) => n,
None => { None => {
warn!(context, "Secure-join denied (invitenumber missing).",); warn!(context, "Secure-join denied (invitenumber missing).",);
@@ -459,7 +456,7 @@ pub fn handle_securejoin_handshake(
==== Step 6 in "Out-of-band verified groups" protocol ==== ==== Step 6 in "Out-of-band verified groups" protocol ====
============================================================ */ ============================================================ */
// verify that Secure-Join-Fingerprint:-header matches the fingerprint of Bob // verify that Secure-Join-Fingerprint:-header matches the fingerprint of Bob
let fingerprint = match lookup_field(mimeparser, "Secure-Join-Fingerprint") { let fingerprint = match mimeparser.lookup_optional_field("Secure-Join-Fingerprint") {
Some(fp) => fp, Some(fp) => fp,
None => { None => {
could_not_establish_secure_connection( could_not_establish_secure_connection(
@@ -488,7 +485,7 @@ pub fn handle_securejoin_handshake(
} }
info!(context, "Fingerprint verified.",); info!(context, "Fingerprint verified.",);
// verify that the `Secure-Join-Auth:`-header matches the secret written to the QR code // verify that the `Secure-Join-Auth:`-header matches the secret written to the QR code
let auth_0 = match lookup_field(mimeparser, "Secure-Join-Auth") { let auth_0 = match mimeparser.lookup_optional_field("Secure-Join-Auth") {
Some(auth) => auth, Some(auth) => auth,
None => { None => {
could_not_establish_secure_connection( could_not_establish_secure_connection(
@@ -517,7 +514,9 @@ pub fn handle_securejoin_handshake(
emit_event!(context, Event::ContactsChanged(Some(contact_id))); emit_event!(context, Event::ContactsChanged(Some(contact_id)));
inviter_progress!(context, contact_id, 600); inviter_progress!(context, contact_id, 600);
if join_vg { if join_vg {
let field_grpid = lookup_field(mimeparser, "Secure-Join-Group").unwrap_or_default(); let field_grpid = mimeparser
.lookup_optional_field("Secure-Join-Group")
.unwrap_or_default();
let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, &field_grpid); let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, &field_grpid);
if group_chat_id == 0 { if group_chat_id == 0 {
error!(context, "Chat {} not found.", &field_grpid); error!(context, "Chat {} not found.", &field_grpid);
@@ -586,8 +585,9 @@ pub fn handle_securejoin_handshake(
} }
Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined); Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined);
emit_event!(context, Event::ContactsChanged(None)); emit_event!(context, Event::ContactsChanged(None));
let cg_member_added = let cg_member_added = mimeparser
lookup_field(mimeparser, "Chat-Group-Member-Added").unwrap_or_default(); .lookup_optional_field("Chat-Group-Member-Added")
.unwrap_or_default();
if join_vg && !addr_equals_self(context, cg_member_added) { if join_vg && !addr_equals_self(context, cg_member_added) {
info!(context, "Message belongs to a different handshake (scaled up contact anyway to allow creation of group)."); info!(context, "Message belongs to a different handshake (scaled up contact anyway to allow creation of group).");
return ret; return ret;
@@ -651,24 +651,6 @@ fn secure_connection_established(context: &Context, contact_chat_id: u32) {
emit_event!(context, Event::ChatModified(contact_chat_id)); emit_event!(context, Event::ChatModified(contact_chat_id));
} }
fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> Option<String> {
let field: *mut mailimf_field = dc_mimeparser_lookup_field(mimeparser, key);
unsafe {
let mut value: *const libc::c_char = ptr::null();
if field.is_null()
|| (*field).fld_type != MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int
|| (*field).fld_data.fld_optional_field.is_null()
|| {
value = (*(*field).fld_data.fld_optional_field).fld_value;
value.is_null()
}
{
return None;
}
Some(as_str(value).to_string())
}
}
fn could_not_establish_secure_connection(context: &Context, contact_chat_id: u32, details: &str) { fn could_not_establish_secure_connection(context: &Context, contact_chat_id: u32, details: &str) {
let contact_id = chat_id_2_contact_id(context, contact_chat_id); let contact_id = chat_id_2_contact_id(context, contact_chat_id);
let contact = Contact::get_by_id(context, contact_id); let contact = Contact::get_by_id(context, contact_id);
@@ -706,10 +688,7 @@ fn mark_peer_as_verified(context: &Context, fingerprint: impl AsRef<str>) -> Res
* Tools: Misc. * Tools: Misc.
******************************************************************************/ ******************************************************************************/
fn encrypted_and_signed( fn encrypted_and_signed(mimeparser: &MimeParser, expected_fingerprint: impl AsRef<str>) -> bool {
mimeparser: &dc_mimeparser_t,
expected_fingerprint: impl AsRef<str>,
) -> bool {
if !mimeparser.e2ee_helper.encrypted { if !mimeparser.e2ee_helper.encrypted {
warn!(mimeparser.context, "Message not encrypted.",); warn!(mimeparser.context, "Message not encrypted.",);
false false