mirror of
https://github.com/chatmail/core.git
synced 2026-04-02 05:22:14 +03:00
Compare commits
2 Commits
8518d3fc3a
...
mimeparser
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d9bb929ad | ||
|
|
84bcc81fda |
@@ -12,6 +12,7 @@ use crate::context::Context;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::Result;
|
||||
use crate::events::Event;
|
||||
use crate::headerdef::HeaderDef;
|
||||
use crate::job::*;
|
||||
use crate::location;
|
||||
use crate::message::{self, MessageState, MsgId};
|
||||
@@ -60,9 +61,9 @@ pub fn dc_receive_imf(
|
||||
mime_parser.unwrap()
|
||||
};
|
||||
|
||||
if mime_parser.header.is_empty() {
|
||||
// Error - even adding an empty record won't help as we do not know the message ID
|
||||
warn!(context, "No header.");
|
||||
if mime_parser.get(HeaderDef::From_).is_none() {
|
||||
// Error - even adding an empty record won't help as we do not know the sender
|
||||
warn!(context, "No From header.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -114,7 +115,7 @@ pub fn dc_receive_imf(
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(value) = mime_parser.lookup_field("Date") {
|
||||
if let Some(value) = mime_parser.get(HeaderDef::Date) {
|
||||
// is not yet checked against bad times! we do this later if we have the database information.
|
||||
sent_timestamp = mailparse::dateparse(value).unwrap_or_default();
|
||||
}
|
||||
@@ -122,7 +123,7 @@ pub 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)
|
||||
// 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
|
||||
if let Some(field_from) = mime_parser.lookup_field("From") {
|
||||
if let Some(field_from) = mime_parser.get(HeaderDef::From_) {
|
||||
let mut check_self = false;
|
||||
let mut from_list = Vec::with_capacity(16);
|
||||
dc_add_or_lookup_contacts_by_address_list(
|
||||
@@ -147,7 +148,7 @@ pub fn dc_receive_imf(
|
||||
}
|
||||
|
||||
// Make sure, to_ids starts with the first To:-address (Cc: is added in the loop below pass)
|
||||
if let Some(field) = mime_parser.lookup_field("To") {
|
||||
if let Some(field) = mime_parser.get(HeaderDef::To) {
|
||||
dc_add_or_lookup_contacts_by_address_list(
|
||||
context,
|
||||
&field,
|
||||
@@ -307,7 +308,7 @@ fn add_parts(
|
||||
// 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.lookup_field("Cc") {
|
||||
if let Some(fld_cc) = mime_parser.get(HeaderDef::Cc) {
|
||||
dc_add_or_lookup_contacts_by_address_list(
|
||||
context,
|
||||
fld_cc,
|
||||
@@ -372,7 +373,7 @@ fn add_parts(
|
||||
|
||||
// handshake messages must be processed _before_ chats are created
|
||||
// (eg. contacs may be marked as verified)
|
||||
if mime_parser.lookup_field("Secure-Join").is_some() {
|
||||
if mime_parser.get(HeaderDef::SecureJoin).is_some() {
|
||||
// avoid discarding by show_emails setting
|
||||
msgrmsg = 1;
|
||||
*chat_id = 0;
|
||||
@@ -581,11 +582,11 @@ fn add_parts(
|
||||
// if the mime-headers should be saved, find out its size
|
||||
// (the mime-header ends with an empty line)
|
||||
let save_mime_headers = context.get_config_bool(Config::SaveMimeHeaders);
|
||||
if let Some(raw) = mime_parser.lookup_field("In-Reply-To") {
|
||||
if let Some(raw) = mime_parser.get(HeaderDef::InReplyTo) {
|
||||
mime_in_reply_to = raw.clone();
|
||||
}
|
||||
|
||||
if let Some(raw) = mime_parser.lookup_field("References") {
|
||||
if let Some(raw) = mime_parser.get(HeaderDef::References) {
|
||||
mime_references = raw.clone();
|
||||
}
|
||||
|
||||
@@ -797,7 +798,6 @@ fn create_or_lookup_group(
|
||||
to_ids: &[u32],
|
||||
) -> Result<(u32, Blocked)> {
|
||||
let mut chat_id_blocked = Blocked::Not;
|
||||
let mut grpname = None;
|
||||
let to_ids_cnt = to_ids.len();
|
||||
let mut recreate_member_list = false;
|
||||
let mut send_EVENT_CHAT_MODIFIED = false;
|
||||
@@ -814,20 +814,21 @@ fn create_or_lookup_group(
|
||||
set_better_msg(mime_parser, &better_msg);
|
||||
|
||||
let mut grpid = "".to_string();
|
||||
if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-ID") {
|
||||
if let Some(optional_field) = mime_parser.get(HeaderDef::ChatGroupId) {
|
||||
grpid = optional_field.clone();
|
||||
}
|
||||
|
||||
if grpid.is_empty() {
|
||||
if let Some(value) = mime_parser.lookup_field("Message-ID") {
|
||||
if let Some(value) = mime_parser.get(HeaderDef::MessageId) {
|
||||
if let Some(extracted_grpid) = dc_extract_grpid_from_rfc724_mid(&value) {
|
||||
grpid = extracted_grpid.to_string();
|
||||
}
|
||||
}
|
||||
if grpid.is_empty() {
|
||||
if let Some(extracted_grpid) = get_grpid_from_list(mime_parser, "In-Reply-To") {
|
||||
if let Some(extracted_grpid) = extract_grpid(mime_parser, HeaderDef::InReplyTo) {
|
||||
grpid = extracted_grpid;
|
||||
} else if let Some(extracted_grpid) = get_grpid_from_list(mime_parser, "References") {
|
||||
} else if let Some(extracted_grpid) = extract_grpid(mime_parser, HeaderDef::References)
|
||||
{
|
||||
grpid = extracted_grpid;
|
||||
} else {
|
||||
return create_or_lookup_adhoc_group(
|
||||
@@ -846,13 +847,9 @@ fn create_or_lookup_group(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Name").cloned() {
|
||||
grpname = Some(optional_field);
|
||||
}
|
||||
let field = mime_parser
|
||||
.lookup_field("Chat-Group-Member-Removed")
|
||||
.cloned();
|
||||
if let Some(optional_field) = field {
|
||||
let grpname = mime_parser.get(HeaderDef::ChatGroupName).cloned();
|
||||
|
||||
if let Some(optional_field) = mime_parser.get(HeaderDef::ChatGroupMemberRemoved).cloned() {
|
||||
X_MrRemoveFromGrp = Some(optional_field);
|
||||
mime_parser.is_system_message = SystemMessage::MemberRemovedFromGroup;
|
||||
let left_group = Contact::lookup_id_by_addr(context, X_MrRemoveFromGrp.as_ref().unwrap())
|
||||
@@ -868,11 +865,11 @@ fn create_or_lookup_group(
|
||||
from_id as u32,
|
||||
)
|
||||
} else {
|
||||
let field = mime_parser.lookup_field("Chat-Group-Member-Added").cloned();
|
||||
let field = mime_parser.get(HeaderDef::ChatGroupMemberAdded).cloned();
|
||||
if let Some(optional_field) = field {
|
||||
X_MrAddToGrp = Some(optional_field);
|
||||
mime_parser.is_system_message = SystemMessage::MemberAddedToGroup;
|
||||
if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Image").cloned() {
|
||||
if let Some(optional_field) = mime_parser.get(HeaderDef::ChatGroupImage).cloned() {
|
||||
X_MrGrpImageChanged = optional_field;
|
||||
}
|
||||
better_msg = context.stock_system_msg(
|
||||
@@ -882,7 +879,7 @@ fn create_or_lookup_group(
|
||||
from_id as u32,
|
||||
)
|
||||
} else {
|
||||
let field = mime_parser.lookup_field("Chat-Group-Name-Changed");
|
||||
let field = mime_parser.get(HeaderDef::ChatGroupNameChanged);
|
||||
if let Some(field) = field {
|
||||
X_MrGrpNameChanged = true;
|
||||
better_msg = context.stock_system_msg(
|
||||
@@ -897,8 +894,7 @@ fn create_or_lookup_group(
|
||||
);
|
||||
|
||||
mime_parser.is_system_message = SystemMessage::GroupNameChanged;
|
||||
} else if let Some(optional_field) =
|
||||
mime_parser.lookup_field("Chat-Group-Image").cloned()
|
||||
} else if let Some(optional_field) = mime_parser.get(HeaderDef::ChatGroupImage).cloned()
|
||||
{
|
||||
// fld_value is a pointer somewhere into mime_parser, must not be freed
|
||||
X_MrGrpImageChanged = optional_field;
|
||||
@@ -954,7 +950,7 @@ fn create_or_lookup_group(
|
||||
|| X_MrAddToGrp.is_some() && addr_cmp(&self_addr, X_MrAddToGrp.as_ref().unwrap()))
|
||||
{
|
||||
// group does not exist but should be created
|
||||
let create_verified = if mime_parser.lookup_field("Chat-Verified").is_some() {
|
||||
let create_verified = if mime_parser.get(HeaderDef::ChatVerified).is_some() {
|
||||
if let Err(err) =
|
||||
check_verified_properties(context, mime_parser, from_id as u32, to_ids)
|
||||
{
|
||||
@@ -1130,8 +1126,8 @@ fn create_or_lookup_group(
|
||||
}
|
||||
|
||||
/// try extract a grpid from a message-id list header value
|
||||
fn get_grpid_from_list(mime_parser: &MimeParser, header_key: &str) -> Option<String> {
|
||||
if let Some(value) = mime_parser.lookup_field(header_key) {
|
||||
fn extract_grpid(mime_parser: &MimeParser, headerdef: HeaderDef) -> Option<String> {
|
||||
if let Some(value) = mime_parser.get(headerdef) {
|
||||
for part in value.split(',').map(str::trim) {
|
||||
if !part.is_empty() {
|
||||
if let Some(extracted_grpid) = dc_extract_grpid_from_rfc724_mid(part) {
|
||||
@@ -1486,13 +1482,13 @@ fn is_reply_to_known_message(context: &Context, mime_parser: &MimeParser) -> boo
|
||||
/* 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) */
|
||||
|
||||
if let Some(field) = mime_parser.lookup_field("In-Reply-To") {
|
||||
if let Some(field) = mime_parser.get(HeaderDef::InReplyTo) {
|
||||
if is_known_rfc724_mid_in_list(context, &field) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(field) = mime_parser.lookup_field("References") {
|
||||
if let Some(field) = mime_parser.get(HeaderDef::References) {
|
||||
if is_known_rfc724_mid_in_list(context, &field) {
|
||||
return true;
|
||||
}
|
||||
@@ -1538,13 +1534,13 @@ fn is_known_rfc724_mid(context: &Context, rfc724_mid: &mailparse::MailAddr) -> b
|
||||
/// - 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)
|
||||
fn is_reply_to_messenger_message(context: &Context, mime_parser: &MimeParser) -> bool {
|
||||
if let Some(value) = mime_parser.lookup_field("In-Reply-To") {
|
||||
if let Some(value) = mime_parser.get(HeaderDef::InReplyTo) {
|
||||
if is_msgrmsg_rfc724_mid_in_list(context, &value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value) = mime_parser.lookup_field("References") {
|
||||
if let Some(value) = mime_parser.get(HeaderDef::References) {
|
||||
if is_msgrmsg_rfc724_mid_in_list(context, &value) {
|
||||
return true;
|
||||
}
|
||||
@@ -1683,9 +1679,9 @@ mod tests {
|
||||
\n\
|
||||
hello\x00";
|
||||
let mimeparser = MimeParser::from_bytes(&context.ctx, &raw[..]).unwrap();
|
||||
assert_eq!(get_grpid_from_list(&mimeparser, "In-Reply-To"), None);
|
||||
assert_eq!(extract_grpid(&mimeparser, HeaderDef::InReplyTo), None);
|
||||
let grpid = Some("HcxyMARjyJy".to_string());
|
||||
assert_eq!(get_grpid_from_list(&mimeparser, "References"), grpid);
|
||||
assert_eq!(extract_grpid(&mimeparser, HeaderDef::References), grpid);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1699,7 +1695,7 @@ mod tests {
|
||||
hello\x00";
|
||||
let mimeparser = MimeParser::from_bytes(&context.ctx, &raw[..]).unwrap();
|
||||
let grpid = Some("HcxyMARjyJy".to_string());
|
||||
assert_eq!(get_grpid_from_list(&mimeparser, "In-Reply-To"), grpid);
|
||||
assert_eq!(get_grpid_from_list(&mimeparser, "References"), grpid);
|
||||
assert_eq!(extract_grpid(&mimeparser, HeaderDef::InReplyTo), grpid);
|
||||
assert_eq!(extract_grpid(&mimeparser, HeaderDef::References), grpid);
|
||||
}
|
||||
}
|
||||
|
||||
43
src/headerdef.rs
Normal file
43
src/headerdef.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
#[derive(Debug, Display, Clone, PartialEq, Eq, EnumVariantNames)]
|
||||
#[strum(serialize_all = "kebab_case")]
|
||||
#[allow(dead_code)]
|
||||
pub enum HeaderDef {
|
||||
MessageId,
|
||||
Subject,
|
||||
Date,
|
||||
From_,
|
||||
To,
|
||||
Cc,
|
||||
Disposition,
|
||||
OriginalMessageId,
|
||||
ListId,
|
||||
References,
|
||||
InReplyTo,
|
||||
Precedence,
|
||||
ChatVersion,
|
||||
ChatGroupId,
|
||||
ChatGroupName,
|
||||
ChatGroupNameChanged,
|
||||
ChatVerified,
|
||||
ChatGroupImage,
|
||||
ChatVoiceMessage,
|
||||
ChatGroupMemberRemoved,
|
||||
ChatGroupMemberAdded,
|
||||
ChatContent,
|
||||
ChatDuration,
|
||||
ChatDispositionNotificationTo,
|
||||
AutocryptSetupMessage,
|
||||
SecureJoin,
|
||||
SecureJoinGroup,
|
||||
SecureJoinFingerprint,
|
||||
SecureJoinInvitenumber,
|
||||
SecureJoinAuth,
|
||||
_TestHeader,
|
||||
}
|
||||
|
||||
impl HeaderDef {
|
||||
/// Returns the corresponding Event id.
|
||||
pub fn get_headername(&self) -> String {
|
||||
self.to_string()
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,8 @@ mod log;
|
||||
#[macro_use]
|
||||
pub mod error;
|
||||
|
||||
pub mod headerdef;
|
||||
|
||||
pub(crate) mod events;
|
||||
pub use events::*;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ use crate::dc_simplify::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::e2ee;
|
||||
use crate::error::Result;
|
||||
use crate::headerdef::HeaderDef;
|
||||
use crate::job::{job_add, Action};
|
||||
use crate::location;
|
||||
use crate::message;
|
||||
@@ -28,7 +29,7 @@ use crate::{bail, ensure};
|
||||
pub struct MimeParser<'a> {
|
||||
pub context: &'a Context,
|
||||
pub parts: Vec<Part>,
|
||||
pub header: HashMap<String, String>,
|
||||
header: HashMap<String, String>,
|
||||
pub decrypting_failed: bool,
|
||||
pub signatures: HashSet<String>,
|
||||
pub gossipped_addr: HashSet<String>,
|
||||
@@ -144,7 +145,7 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
|
||||
fn parse_headers(&mut self) -> Result<()> {
|
||||
if self.lookup_field("Autocrypt-Setup-Message").is_some() {
|
||||
if self.get(HeaderDef::AutocryptSetupMessage).is_some() {
|
||||
let has_setup_file = self.parts.iter().any(|p| {
|
||||
p.mimetype.is_some() && p.mimetype.as_ref().unwrap().as_ref() == MIME_AC_SETUP_FILE
|
||||
});
|
||||
@@ -175,12 +176,12 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(value) = self.lookup_field("Chat-Content") {
|
||||
} else if let Some(value) = self.get(HeaderDef::ChatContent) {
|
||||
if value == "location-streaming-enabled" {
|
||||
self.is_system_message = SystemMessage::LocationStreamingEnabled;
|
||||
}
|
||||
}
|
||||
if self.lookup_field("Chat-Group-Image").is_some() && !self.parts.is_empty() {
|
||||
if self.get(HeaderDef::ChatGroupImage).is_some() && !self.parts.is_empty() {
|
||||
let textpart = &self.parts[0];
|
||||
if textpart.typ == Viewtype::Text && self.parts.len() >= 2 {
|
||||
let imgpart = &mut self.parts[1];
|
||||
@@ -255,13 +256,13 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
if self.parts.len() == 1 {
|
||||
if self.parts[0].typ == Viewtype::Audio
|
||||
&& self.lookup_field("Chat-Voice-Message").is_some()
|
||||
&& self.get(HeaderDef::ChatVoiceMessage).is_some()
|
||||
{
|
||||
let part_mut = &mut self.parts[0];
|
||||
part_mut.typ = Viewtype::Voice;
|
||||
}
|
||||
if self.parts[0].typ == Viewtype::Image {
|
||||
if let Some(value) = self.lookup_field("Chat-Content") {
|
||||
if let Some(value) = self.get(HeaderDef::ChatContent) {
|
||||
if value == "sticker" {
|
||||
let part_mut = &mut self.parts[0];
|
||||
part_mut.typ = Viewtype::Sticker;
|
||||
@@ -273,7 +274,7 @@ impl<'a> MimeParser<'a> {
|
||||
|| part.typ == Viewtype::Voice
|
||||
|| part.typ == Viewtype::Video
|
||||
{
|
||||
if let Some(field_0) = self.lookup_field("Chat-Duration") {
|
||||
if let Some(field_0) = self.get(HeaderDef::ChatDuration) {
|
||||
let duration_ms = field_0.parse().unwrap_or_default();
|
||||
if duration_ms > 0 && duration_ms < 24 * 60 * 60 * 1000 {
|
||||
let part_mut = &mut self.parts[0];
|
||||
@@ -283,12 +284,12 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
}
|
||||
if !self.decrypting_failed {
|
||||
if let Some(dn_field) = self.lookup_field("Chat-Disposition-Notification-To") {
|
||||
if let Some(dn_field) = self.get(HeaderDef::ChatDispositionNotificationTo) {
|
||||
if self.get_last_nonmeta().is_some() {
|
||||
let addrs = mailparse::addrparse(&dn_field).unwrap();
|
||||
|
||||
if let Some(dn_to_addr) = addrs.first() {
|
||||
if let Some(from_field) = self.lookup_field("From") {
|
||||
if let Some(from_field) = self.get(HeaderDef::From_) {
|
||||
let from_addrs = mailparse::addrparse(&from_field).unwrap();
|
||||
|
||||
if let Some(from_addr) = from_addrs.first() {
|
||||
@@ -338,7 +339,7 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
|
||||
pub(crate) fn get_subject(&self) -> Option<String> {
|
||||
if let Some(s) = self.header.get("subject") {
|
||||
if let Some(s) = self.get(HeaderDef::Subject) {
|
||||
if s.is_empty() {
|
||||
return None;
|
||||
}
|
||||
@@ -348,8 +349,8 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup_field(&self, field_name: &str) -> Option<&String> {
|
||||
self.header.get(&field_name.to_lowercase())
|
||||
pub fn get(&self, headerdef: HeaderDef) -> Option<&String> {
|
||||
self.header.get(&headerdef.get_headername())
|
||||
}
|
||||
|
||||
fn parse_mime_recursive(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result<bool> {
|
||||
@@ -649,11 +650,11 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
|
||||
pub fn is_mailinglist_message(&self) -> bool {
|
||||
if self.lookup_field("List-Id").is_some() {
|
||||
if self.get(HeaderDef::ListId).is_some() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(precedence) = self.lookup_field("Precedence") {
|
||||
if let Some(precedence) = self.get(HeaderDef::Precedence) {
|
||||
precedence == "list" || precedence == "bulk"
|
||||
} else {
|
||||
false
|
||||
@@ -662,7 +663,7 @@ impl<'a> MimeParser<'a> {
|
||||
|
||||
pub fn sender_equals_recipient(&self) -> bool {
|
||||
/* get From: and check there is exactly one sender */
|
||||
if let Some(field) = self.lookup_field("From") {
|
||||
if let Some(field) = self.get(HeaderDef::From_) {
|
||||
if let Ok(addrs) = mailparse::addrparse(field) {
|
||||
if addrs.len() != 1 {
|
||||
return false;
|
||||
@@ -693,11 +694,11 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
|
||||
pub fn get_rfc724_mid(&self) -> Option<String> {
|
||||
// get Message-ID from header
|
||||
if let Some(field) = self.lookup_field("Message-ID") {
|
||||
return parse_message_id(field);
|
||||
if let Some(msgid) = self.get(HeaderDef::MessageId) {
|
||||
parse_message_id(msgid)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn hash_header(&mut self, fields: &[mailparse::MailHeader<'_>]) {
|
||||
@@ -727,9 +728,10 @@ impl<'a> MimeParser<'a> {
|
||||
let (report_fields, _) = mailparse::parse_headers(&report_body)?;
|
||||
|
||||
// must be present
|
||||
if let Some(_disposition) = report_fields.get_first_value("Disposition").ok().flatten() {
|
||||
let disp = HeaderDef::Disposition.get_headername();
|
||||
if let Some(_disposition) = report_fields.get_first_value(&disp).ok().flatten() {
|
||||
if let Some(original_message_id) = report_fields
|
||||
.get_first_value("Original-Message-ID")
|
||||
.get_first_value(&HeaderDef::OriginalMessageId.get_headername())
|
||||
.ok()
|
||||
.flatten()
|
||||
.and_then(|v| parse_message_id(&v))
|
||||
@@ -1108,14 +1110,14 @@ mod tests {
|
||||
let raw = b"From: hello\n\
|
||||
Content-Type: multipart/mixed; boundary=\"==break==\";\n\
|
||||
Subject: outer-subject\n\
|
||||
X-Special-A: special-a\n\
|
||||
Foo: Bar\nChat-Version: 0.0\n\
|
||||
Secure-Join-Group: no\n\
|
||||
Test-Header: Bar\nChat-Version: 0.0\n\
|
||||
\n\
|
||||
--==break==\n\
|
||||
Content-Type: text/plain; protected-headers=\"v1\";\n\
|
||||
Subject: inner-subject\n\
|
||||
X-Special-B: special-b\n\
|
||||
Foo: Xy\n\
|
||||
SecureBar-Join-Group: yes\n\
|
||||
Test-Header: Xy\n\
|
||||
Chat-Version: 1.0\n\
|
||||
\n\
|
||||
test1\n\
|
||||
@@ -1125,15 +1127,18 @@ mod tests {
|
||||
\x00";
|
||||
let mimeparser = MimeParser::from_bytes(&context.ctx, &raw[..]).unwrap();
|
||||
|
||||
// test that we treat Subject as a protected header that can
|
||||
// bubble upwards
|
||||
assert_eq!(mimeparser.get_subject(), Some("inner-subject".into()));
|
||||
|
||||
let of = mimeparser.lookup_field("X-Special-A").unwrap();
|
||||
assert_eq!(of, "special-a");
|
||||
let of = mimeparser.get(HeaderDef::SecureJoinGroup).unwrap();
|
||||
assert_eq!(of, "no");
|
||||
|
||||
let of = mimeparser.lookup_field("Foo").unwrap();
|
||||
// unprotected headers do not bubble upwards
|
||||
let of = mimeparser.get(HeaderDef::_TestHeader).unwrap();
|
||||
assert_eq!(of, "Bar");
|
||||
|
||||
let of = mimeparser.lookup_field("Chat-Version").unwrap();
|
||||
let of = mimeparser.get(HeaderDef::ChatVersion).unwrap();
|
||||
assert_eq!(of, "1.0");
|
||||
assert_eq!(mimeparser.parts.len(), 1);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::context::Context;
|
||||
use crate::e2ee::*;
|
||||
use crate::error::Error;
|
||||
use crate::events::Event;
|
||||
use crate::headerdef::HeaderDef;
|
||||
use crate::key::*;
|
||||
use crate::lot::LotState;
|
||||
use crate::message::Message;
|
||||
@@ -350,7 +351,7 @@ pub(crate) fn handle_securejoin_handshake(
|
||||
"handle_securejoin_handshake(): called with special contact id"
|
||||
);
|
||||
let step = mimeparser
|
||||
.lookup_field("Secure-Join")
|
||||
.get(HeaderDef::SecureJoin)
|
||||
.ok_or_else(|| format_err!("This message is not a Secure-Join message"))?;
|
||||
|
||||
info!(
|
||||
@@ -378,7 +379,7 @@ pub(crate) 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,
|
||||
// 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
|
||||
let invitenumber = match mimeparser.lookup_field("Secure-Join-Invitenumber") {
|
||||
let invitenumber = match mimeparser.get(HeaderDef::SecureJoinInvitenumber) {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
warn!(context, "Secure-join denied (invitenumber missing).",);
|
||||
@@ -467,7 +468,7 @@ pub(crate) fn handle_securejoin_handshake(
|
||||
==== Step 6 in "Out-of-band verified groups" protocol ====
|
||||
============================================================ */
|
||||
// verify that Secure-Join-Fingerprint:-header matches the fingerprint of Bob
|
||||
let fingerprint = match mimeparser.lookup_field("Secure-Join-Fingerprint") {
|
||||
let fingerprint = match mimeparser.get(HeaderDef::SecureJoinFingerprint) {
|
||||
Some(fp) => fp,
|
||||
None => {
|
||||
could_not_establish_secure_connection(
|
||||
@@ -496,7 +497,7 @@ pub(crate) fn handle_securejoin_handshake(
|
||||
}
|
||||
info!(context, "Fingerprint verified.",);
|
||||
// verify that the `Secure-Join-Auth:`-header matches the secret written to the QR code
|
||||
let auth_0 = match mimeparser.lookup_field("Secure-Join-Auth") {
|
||||
let auth_0 = match mimeparser.get(HeaderDef::SecureJoinAuth) {
|
||||
Some(auth) => auth,
|
||||
None => {
|
||||
could_not_establish_secure_connection(
|
||||
@@ -526,7 +527,7 @@ pub(crate) fn handle_securejoin_handshake(
|
||||
inviter_progress!(context, contact_id, 600);
|
||||
if join_vg {
|
||||
let field_grpid = mimeparser
|
||||
.lookup_field("Secure-Join-Group")
|
||||
.get(HeaderDef::SecureJoinGroup)
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or_else(|| "");
|
||||
let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, field_grpid);
|
||||
@@ -600,7 +601,7 @@ pub(crate) fn handle_securejoin_handshake(
|
||||
Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined);
|
||||
emit_event!(context, Event::ContactsChanged(None));
|
||||
let cg_member_added = mimeparser
|
||||
.lookup_field("Chat-Group-Member-Added")
|
||||
.get(HeaderDef::ChatGroupMemberAdded)
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or_else(|| "");
|
||||
if join_vg && !addr_equals_self(context, cg_member_added) {
|
||||
@@ -635,7 +636,7 @@ pub(crate) fn handle_securejoin_handshake(
|
||||
inviter_progress!(context, contact_id, 800);
|
||||
inviter_progress!(context, contact_id, 1000);
|
||||
let field_grpid = mimeparser
|
||||
.lookup_field("Secure-Join-Group")
|
||||
.get(HeaderDef::SecureJoinGroup)
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or_else(|| "");
|
||||
let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, &field_grpid);
|
||||
|
||||
Reference in New Issue
Block a user