diff --git a/python/src/deltachat/chatting.py b/python/src/deltachat/chatting.py index d4dd763ac..3ba6ba6ce 100644 --- a/python/src/deltachat/chatting.py +++ b/python/src/deltachat/chatting.py @@ -417,7 +417,7 @@ class Chat(object): class Location: def __init__(self, latitude, longitude, accuracy, timestamp): - assert isinstance(timestamp, datetime.datetime) + assert isinstance(timestamp, datetime) self.latitude = latitude self.longitude = longitude self.accuracy = accuracy diff --git a/python/tests/test_account.py b/python/tests/test_account.py index 839dc7510..ef583d806 100644 --- a/python/tests/test_account.py +++ b/python/tests/test_account.py @@ -827,17 +827,20 @@ class TestOnlineAccount: lp.sec("ac1: enable location sending in chat") chat1.enable_sending_locations(seconds=100) assert chat1.is_sending_locations() + ac1._evlogger.get_matching("DC_EVENT_SMTP_MESSAGE_SENT") - lp.sec("ac1: setting location") - ac1.set_location(latitude=1.0, longitude=2.0) + ac1.set_location(latitude=2.0, longitude=3.0) ac1._evlogger.get_matching("DC_EVENT_LOCATION_CHANGED") chat1.send_text("hello") ac1._evlogger.get_matching("DC_EVENT_SMTP_MESSAGE_SENT") - ac1._evlogger.get_matching("DC_EVENT_SMTP_MESSAGE_SENT") lp.sec("ac2: wait for incoming location message") - ac2._evlogger.get_matching("DC_EVENT_INCOMING_MSG") - ac2._evlogger.get_matching("DC_EVENT_INCOMING_MSG") + ac2._evlogger.get_matching("DC_EVENT_INCOMING_MSG") # "enabled-location streaming" + + # currently core emits location changed before event_incoming message + ac2._evlogger.get_matching("DC_EVENT_LOCATION_CHANGED") + ac2._evlogger.get_matching("DC_EVENT_INCOMING_MSG") # text message with location + # contact = ac2.create_contact(ac1.get_config("addr")) locations = chat2.get_locations() # XXX per contact assert len(locations) >= 1 diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index 8a39fd568..65ed62f71 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -598,7 +598,7 @@ impl<'a> MimeParser<'a> { let mut decoded_data = match wrapmime::mailmime_transfer_decode(mime) { Ok(decoded_data) => decoded_data, Err(_) => { - // Note that it's now always an error - might be no data + // Note that it's not always an error - might be no data return false; } }; @@ -736,27 +736,13 @@ impl<'a> MimeParser<'a> { return false; } } - if desired_filename.starts_with("location") && desired_filename.ends_with(".kml") { - if !decoded_data.is_empty() { - let d = std::string::String::from_utf8_lossy(&decoded_data); - self.location_kml = location::Kml::parse(self.context, &d).ok(); - } - } else if desired_filename.starts_with("message") - && desired_filename.ends_with(".kml") - { - if !decoded_data.is_empty() { - let d = std::string::String::from_utf8_lossy(&decoded_data); - self.message_kml = location::Kml::parse(self.context, &d).ok(); - } - } else if !decoded_data.is_empty() { - self.do_add_single_file_part( - msg_type, - mime_type, - raw_mime.as_ref(), - &decoded_data, - &desired_filename, - ); - } + self.do_add_single_file_part( + msg_type, + mime_type, + raw_mime.as_ref(), + &decoded_data, + &desired_filename, + ); } _ => {} } @@ -770,20 +756,47 @@ impl<'a> MimeParser<'a> { mime_type: libc::c_int, raw_mime: Option<&String>, decoded_data: &[u8], - desired_filename: &str, + filename: &str, ) { - /* write decoded data to new blob file */ - let blob = match BlobObject::create(self.context, desired_filename, decoded_data) { + if decoded_data.is_empty() { + return; + } + // treat location/message kml file attachments specially + if filename.ends_with(".kml") { + // XXX what if somebody sends eg an "location-highlights.kml" + // attachment unrelated to location streaming? + if filename.starts_with("location") || filename.starts_with("message") { + let d = std::string::String::from_utf8_lossy(&decoded_data); + let parsed = match location::Kml::parse(self.context, &d) { + Ok(res) => Some(res), + Err(err) => { + warn!(self.context, "failed to parse kml part: {}", err); + None + } + }; + if filename.starts_with("location") { + self.location_kml = parsed; + } else { + self.message_kml = parsed; + } + return; + } + } + /* we have a regular file attachment, + write decoded data to new blob object */ + + let blob = match BlobObject::create(self.context, filename, decoded_data) { Ok(blob) => blob, Err(err) => { error!( self.context, - "Could not add blob for mime part {}, error {}", desired_filename, err + "Could not add blob for mime part {}, error {}", filename, err ); return; } }; + /* create and register Mime part referencing the new Blob object */ let mut part = Part::default(); part.typ = msg_type; part.mimetype = mime_type; @@ -803,10 +816,18 @@ impl<'a> MimeParser<'a> { } fn do_add_single_part(&mut self, mut part: Part) { - if self.encrypted && self.signatures.len() > 0 { - part.param.set_int(Param::GuaranteeE2ee, 1); - } else if self.encrypted { - part.param.set_int(Param::ErroneousE2ee, 0x2); + // we transfer the encryption-state to each part + // because each part lands to each part ? Autocrypt does not define "partially encrypted" + // so either the whole message is encrypted properly or nothing + if self.encrypted { + if self.signatures.len() > 0 { + part.param.set_int(Param::GuaranteeE2ee, 1); + } else { + // XXX if the message was encrypted but not signed + // it's not neccessarily an error we need to signal. + // we could just treat it as if it was not encrypted. + part.param.set_int(Param::ErroneousE2ee, 0x2); + } } self.parts.push(part); } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 65db4591f..b8fab04d8 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -227,7 +227,7 @@ pub unsafe fn dc_receive_imf( &mut created_db_entries, &mut create_event_to_send, ) { - info!(context, "{}", err); + warn!(context, "{}", err); cleanup( context, @@ -257,7 +257,7 @@ pub unsafe fn dc_receive_imf( ); } - if !mime_parser.message_kml.is_none() && chat_id > DC_CHAT_ID_LAST_SPECIAL { + if mime_parser.location_kml.is_some() || mime_parser.message_kml.is_some() { save_locations( context, &mime_parser, @@ -604,6 +604,7 @@ unsafe fn add_parts( // into only one message; mails sent by other clients may result in several messages // (eg. one per attachment)) let icnt = mime_parser.parts.len(); + let mut txt_raw = None; context.sql.prepare( @@ -644,17 +645,6 @@ unsafe fn add_parts( .set_int(Param::Cmd, mime_parser.is_system_message as i32); } - /* - info!( - context, - "received mime message {:?}", - String::from_utf8_lossy(std::slice::from_raw_parts( - imf_raw_not_terminated as *const u8, - imf_raw_bytes, - )) - ); - */ - stmt.execute(params![ rfc724_mid, server_folder.as_ref(), @@ -850,10 +840,20 @@ fn save_locations( insert_msg_id: MsgId, hidden: i32, ) { + if chat_id <= DC_CHAT_ID_LAST_SPECIAL as libc::c_uint { + return (); + } let mut location_id_written = false; let mut send_event = false; - if !mime_parser.message_kml.is_none() && chat_id > DC_CHAT_ID_LAST_SPECIAL as libc::c_uint { + info!( + context, + "saving locations chat_id={} insert_msg_id={}", + chat_id, + insert_msg_id.to_u32() + ); + + if mime_parser.message_kml.is_some() { let locations = &mime_parser.message_kml.as_ref().unwrap().locations; let newest_location_id = location::save(context, chat_id, from_id, locations, 1).unwrap_or_default(); @@ -865,12 +865,10 @@ fn save_locations( } } - if !mime_parser.location_kml.is_none() && chat_id > DC_CHAT_ID_LAST_SPECIAL as libc::c_uint { + if mime_parser.location_kml.is_some() { if let Some(ref addr) = mime_parser.location_kml.as_ref().unwrap().addr { if let Ok(contact) = Contact::get_by_id(context, from_id) { - if !contact.get_addr().is_empty() - && contact.get_addr().to_lowercase() == addr.to_lowercase() - { + if contact.get_addr().to_lowercase() == addr.to_lowercase() { let locations = &mime_parser.location_kml.as_ref().unwrap().locations; let newest_location_id = location::save(context, chat_id, from_id, locations, 0).unwrap_or_default();