Compare commits

...

10 Commits

Author SHA1 Message Date
holger krekel
2955ed39ee fix the fix 2019-12-19 16:46:47 +01:00
holger krekel
149a3eeeb5 address @r10s comment 2019-12-19 16:11:44 +01:00
holger krekel
cd3c9cd39c another reverse mut bites the dust 2019-12-19 15:51:36 +01:00
holger krekel
754605d89a not sure it's much better but using a static-sized array is probably better than a dynamically sized vec, thanks @dignifiedquire 2019-12-19 15:02:30 +01:00
holger krekel
9c96ff220c remove unused include_in_contactlist 2019-12-19 14:36:18 +01:00
holger krekel
1767ae57cd Origin::is_verified() -> Origin::is_known() because this has nothing to do with verified groups or contacts 2019-12-19 14:33:46 +01:00
holger krekel
fd8dc7f079 don't pass incoming_origin as &mut as the caller doesn't need it 2019-12-19 14:29:00 +01:00
holger krekel
d3b4764399 also don't pass "to_id" and don't make it mut inside add_parts 2019-12-19 12:19:00 +01:00
holger krekel
762d00baf6 - move CC-parsing next to To-parsing where it blongs
- pass to_ids and from_id as immutable to add_parts
2019-12-19 12:19:00 +01:00
holger krekel
4b92b06ddf add a test that contacts are properly created and fix ordering in dc_receive_imf to pass the test 2019-12-19 12:19:00 +01:00
3 changed files with 72 additions and 89 deletions

View File

@@ -1209,6 +1209,15 @@ class TestGroupStressTests:
print("chat is", msg.chat)
assert len(msg.chat.get_contacts()) == 4
lp.sec("ac3: checking that 'ac4' is a known contact")
ac3 = accounts[1]
msg3 = ac3.wait_next_incoming_message()
assert msg3.text == "hello"
contacts = ac3.get_contacts()
assert len(contacts) == 3
ac4_contacts = ac3.get_contacts(query=accounts[2].get_config("addr"))
assert len(ac4_contacts) == 1
lp.sec("ac1: removing one contacts and checking things are right")
to_remove = msg.chat.get_contacts()[-1]
msg.chat.remove_contact(to_remove)

View File

@@ -114,14 +114,11 @@ impl Default for Origin {
}
impl Origin {
/// Contacts that are verified and known not to be spam.
pub fn is_verified(self) -> bool {
self as i32 >= 0x100
}
/// Contacts that are shown in the contact list.
pub fn include_in_contactlist(self) -> bool {
self as i32 >= DC_ORIGIN_MIN_CONTACT_LIST
/// Contacts that are known, i. e. they came in via accepted contacts or
/// themselves an accepted contact. Known contacts are shown in the
/// contact list when one creates a chat and wants to add members etc.
pub fn is_known(self) -> bool {
self >= Origin::IncomingReplyTo
}
}
@@ -401,6 +398,7 @@ impl Contact {
{
row_id = sql::get_rowid(context, &context.sql, "contacts", "addr", addr);
sth_modified = Modifier::Created;
info!(context, "added contact id={} addr={}", row_id, addr);
} else {
error!(context, "Cannot add contact.");
}
@@ -486,7 +484,7 @@ impl Contact {
params![
self_addr,
DC_CONTACT_ID_LAST_SPECIAL as i32,
0x100,
Origin::IncomingReplyTo,
&s3str_like_cmd,
&s3str_like_cmd,
if flag_verified_only { 0 } else { 1 },

View File

@@ -61,9 +61,6 @@ pub fn dc_receive_imf(
ensure!(mime_parser.has_headers(), "No Headers Found");
// the function returns the number of created messages in the database
let mut incoming = true;
let mut incoming_origin = Origin::Unknown;
let mut to_id = 0u32;
let mut chat_id = 0;
let mut hidden = false;
@@ -74,8 +71,6 @@ pub fn dc_receive_imf(
let mut created_db_entries = Vec::new();
let mut create_event_to_send = Some(CreateEvent::MsgsChanged);
let mut to_ids = ContactIds::new();
// helper method to handle early exit and memory cleanup
let cleanup = |context: &Context,
create_event_to_send: &Option<CreateEvent>,
@@ -102,48 +97,31 @@ pub fn dc_receive_imf(
sent_timestamp = mailparse::dateparse(value).unwrap_or_default();
}
// Make sure, to_ids starts with the first To:-address (Cc: is added in the loop below pass)
if let Some(field) = mime_parser.get(HeaderDef::To) {
dc_add_or_lookup_contacts_by_address_list(
context,
&field,
if !incoming {
Origin::OutgoingTo
} else if incoming_origin.is_verified() {
Origin::IncomingTo
} else {
Origin::IncomingUnknownTo
},
&mut to_ids,
)?;
}
// get From: (it can be an address list!) 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,
// we do not check Return-Path any more as this is unreliable, see issue #150)
let mut from_id = 0;
let mut from_id_blocked = false;
let mut incoming = true;
let mut incoming_origin = Origin::Unknown;
if let Some(field_from) = mime_parser.get(HeaderDef::From_) {
let mut from_ids = ContactIds::new();
dc_add_or_lookup_contacts_by_address_list(
let from_ids = dc_add_or_lookup_contacts_by_address_list(
context,
&field_from,
Origin::IncomingUnknownFrom,
&mut from_ids,
)?;
if from_ids.len() > 1 {
warn!(
context,
"mail has more than one address in From: {:?}", field_from
"mail has more than one From address, only using first: {:?}", field_from
);
}
if from_ids.contains(&DC_CONTACT_ID_SELF) {
incoming = false;
if to_ids.len() == 1 && to_ids.contains(&DC_CONTACT_ID_SELF) {
from_id = DC_CONTACT_ID_SELF;
}
from_id = DC_CONTACT_ID_SELF;
incoming_origin = Origin::OutgoingBcc;
} else if !from_ids.is_empty() {
from_id = from_ids.get_index(0).cloned().unwrap_or_default();
incoming_origin = Contact::get_origin_by_id(context, from_id, &mut from_id_blocked)
@@ -155,6 +133,23 @@ pub fn dc_receive_imf(
}
}
let mut to_ids = ContactIds::new();
for header_def in &[HeaderDef::To, HeaderDef::Cc] {
if let Some(field) = mime_parser.get(header_def.clone()) {
to_ids.extend(&dc_add_or_lookup_contacts_by_address_list(
context,
&field,
if !incoming {
Origin::OutgoingTo
} else if incoming_origin.is_known() {
Origin::IncomingTo
} else {
Origin::IncomingUnknownTo
},
)?);
}
}
// Add parts
let rfc724_mid = match mime_parser.get_rfc724_mid() {
@@ -177,17 +172,16 @@ pub fn dc_receive_imf(
&mut mime_parser,
imf_raw,
incoming,
&mut incoming_origin,
incoming_origin,
server_folder.as_ref(),
server_uid,
&mut to_ids,
&to_ids,
&rfc724_mid,
&mut sent_timestamp,
&mut from_id,
from_id,
from_id_blocked,
&mut hidden,
&mut chat_id,
&mut to_id,
flags,
&mut needs_delete_job,
&mut insert_msg_id,
@@ -257,17 +251,16 @@ fn add_parts(
mut mime_parser: &mut MimeParser,
imf_raw: &[u8],
incoming: bool,
incoming_origin: &mut Origin,
incoming_origin: Origin,
server_folder: impl AsRef<str>,
server_uid: u32,
to_ids: &mut ContactIds,
to_ids: &ContactIds,
rfc724_mid: &str,
sent_timestamp: &mut i64,
from_id: &mut u32,
from_id: u32,
from_id_blocked: bool,
hidden: &mut bool,
chat_id: &mut u32,
to_id: &mut u32,
flags: u32,
needs_delete_job: &mut bool,
insert_msg_id: &mut MsgId,
@@ -281,24 +274,7 @@ fn add_parts(
let mut rcvd_timestamp = 0;
let mut mime_in_reply_to = String::new();
let mut mime_references = String::new();
// 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",
// however, the benefit is very small and this may leak data that is expected to be hidden)
if let Some(fld_cc) = mime_parser.get(HeaderDef::Cc) {
dc_add_or_lookup_contacts_by_address_list(
context,
fld_cc,
if !incoming {
Origin::OutgoingCc
} else if incoming_origin.is_verified() {
Origin::IncomingCc
} else {
Origin::IncomingUnknownCc
},
to_ids,
)?;
}
let mut incoming_origin = incoming_origin;
// check, if the mail is already in our database - if so, just update the folder/uid
// (if the mail was moved around) and finish. (we may get a mail twice eg. if it is
@@ -338,13 +314,15 @@ fn add_parts(
// - outgoing messages introduce a chat with the first to: address if they are sent by a messenger
// - incoming messages introduce a chat only for known contacts if they are sent by a messenger
// (of course, the user can add other chats manually later)
let to_id: u32;
if incoming {
state = if 0 != flags & DC_IMAP_SEEN {
MessageState::InSeen
} else {
MessageState::InFresh
};
*to_id = DC_CONTACT_ID_SELF;
to_id = DC_CONTACT_ID_SELF;
let mut needs_stop_ongoing_process = false;
// handshake messages must be processed _before_ chats are created
@@ -354,7 +332,7 @@ fn add_parts(
msgrmsg = 1;
*chat_id = 0;
allow_creation = true;
match handle_securejoin_handshake(context, mime_parser, *from_id) {
match handle_securejoin_handshake(context, mime_parser, from_id) {
Ok(ret) => {
if ret.hide_this_msg {
*hidden = true;
@@ -376,7 +354,7 @@ fn add_parts(
}
let (test_normal_chat_id, test_normal_chat_id_blocked) =
chat::lookup_by_contact_id(context, *from_id).unwrap_or_default();
chat::lookup_by_contact_id(context, from_id).unwrap_or_default();
// get the chat_id - a chat_id here is no indicator that the chat is displayed in the normal list,
// it might also be blocked and displayed in the deaddrop as a result
@@ -396,7 +374,7 @@ fn add_parts(
&mut mime_parser,
allow_creation,
create_blocked,
*from_id,
from_id,
to_ids,
)?;
*chat_id = new_chat_id;
@@ -417,7 +395,7 @@ fn add_parts(
if *chat_id == 0 {
// try to create a normal chat
let create_blocked = if *from_id == *to_id {
let create_blocked = if from_id == to_id {
Blocked::Not
} else {
Blocked::Deaddrop
@@ -428,7 +406,7 @@ fn add_parts(
chat_id_blocked = test_normal_chat_id_blocked;
} else if allow_creation {
let (id, bl) =
chat::create_or_lookup_by_contact_id(context, *from_id, create_blocked)
chat::create_or_lookup_by_contact_id(context, from_id, create_blocked)
.unwrap_or_default();
*chat_id = id;
chat_id_blocked = bl;
@@ -440,13 +418,13 @@ fn add_parts(
} else if is_reply_to_known_message(context, mime_parser) {
// we do not want any chat to be created implicitly. Because of the origin-scale-up,
// the contact requests will pop up and this should be just fine.
Contact::scaleup_origin_by_id(context, *from_id, Origin::IncomingReplyTo);
Contact::scaleup_origin_by_id(context, from_id, Origin::IncomingReplyTo);
info!(
context,
"Message is a reply to a known message, mark sender as known.",
);
if !incoming_origin.is_verified() {
*incoming_origin = Origin::IncomingReplyTo;
if !incoming_origin.is_known() {
incoming_origin = Origin::IncomingReplyTo;
}
}
}
@@ -461,7 +439,7 @@ fn add_parts(
// to not result in a chatlist-contact-request (this would require the state FRESH)
if Blocked::Not != chat_id_blocked
&& state == MessageState::InFresh
&& !incoming_origin.is_verified()
&& !incoming_origin.is_known()
&& msgrmsg == 0
&& show_emails != ShowEmails::All
{
@@ -480,16 +458,15 @@ fn add_parts(
// the mail is on the IMAP server, probably it is also delivered.
// We cannot recreate other states (read, error).
state = MessageState::OutDelivered;
*from_id = DC_CONTACT_ID_SELF;
to_id = to_ids.get_index(0).cloned().unwrap_or_default();
if !to_ids.is_empty() {
*to_id = to_ids.get_index(0).cloned().unwrap_or_default();
if *chat_id == 0 {
let (new_chat_id, new_chat_id_blocked) = create_or_lookup_group(
context,
&mut mime_parser,
allow_creation,
Blocked::Not,
*from_id,
from_id,
to_ids,
)?;
*chat_id = new_chat_id;
@@ -501,14 +478,13 @@ fn add_parts(
}
}
if *chat_id == 0 && allow_creation {
let create_blocked = if 0 != msgrmsg && !Contact::is_blocked_load(context, *to_id) {
let create_blocked = if 0 != msgrmsg && !Contact::is_blocked_load(context, to_id) {
Blocked::Not
} else {
Blocked::Deaddrop
};
let (id, bl) =
chat::create_or_lookup_by_contact_id(context, *to_id, create_blocked)
.unwrap_or_default();
let (id, bl) = chat::create_or_lookup_by_contact_id(context, to_id, create_blocked)
.unwrap_or_default();
*chat_id = id;
chat_id_blocked = bl;
@@ -521,7 +497,7 @@ fn add_parts(
}
}
}
let self_sent = *from_id == DC_CONTACT_ID_SELF
let self_sent = from_id == DC_CONTACT_ID_SELF
&& to_ids.len() == 1
&& to_ids.contains(&DC_CONTACT_ID_SELF);
@@ -548,7 +524,7 @@ fn add_parts(
calc_timestamps(
context,
*chat_id,
*from_id,
from_id,
*sent_timestamp,
0 == flags & DC_IMAP_SEEN,
&mut sort_timestamp,
@@ -612,8 +588,8 @@ fn add_parts(
server_folder.as_ref(),
server_uid as i32,
*chat_id as i32,
*from_id as i32,
*to_id as i32,
from_id as i32,
to_id as i32,
sort_timestamp,
*sent_timestamp,
rcvd_timestamp,
@@ -1537,8 +1513,7 @@ fn dc_add_or_lookup_contacts_by_address_list(
context: &Context,
addr_list_raw: &str,
origin: Origin,
to_ids: &mut ContactIds,
) -> Result<()> {
) -> Result<ContactIds> {
let addrs = match mailparse::addrparse(addr_list_raw) {
Ok(addrs) => addrs,
Err(err) => {
@@ -1546,10 +1521,11 @@ fn dc_add_or_lookup_contacts_by_address_list(
}
};
let mut contact_ids = ContactIds::new();
for addr in addrs.iter() {
match addr {
mailparse::MailAddr::Single(info) => {
to_ids.insert(add_or_lookup_contact_by_addr(
contact_ids.insert(add_or_lookup_contact_by_addr(
context,
&info.display_name,
&info.addr,
@@ -1558,7 +1534,7 @@ fn dc_add_or_lookup_contacts_by_address_list(
}
mailparse::MailAddr::Group(infos) => {
for info in &infos.addrs {
to_ids.insert(add_or_lookup_contact_by_addr(
contact_ids.insert(add_or_lookup_contact_by_addr(
context,
&info.display_name,
&info.addr,
@@ -1569,7 +1545,7 @@ fn dc_add_or_lookup_contacts_by_address_list(
}
}
Ok(())
Ok(contact_ids)
}
/// Add contacts to database on receiving messages.