From d2de2aef071854dd59dc5f746b04803fa1ca7323 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 27 Nov 2019 23:48:26 +0100 Subject: [PATCH 01/20] first compile --- Cargo.lock | 18 + Cargo.toml | 1 + src/dc_mimeparser.rs | 1140 ++++++++++++++++++++--------------------- src/dc_receive_imf.rs | 281 +++++----- src/securejoin.rs | 607 +++++++++++----------- 5 files changed, 1005 insertions(+), 1042 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 163a27e0c..cd6d60e4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -631,6 +631,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "mailparse 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "mmime 0.1.2", "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1416,6 +1417,16 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mailparse" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quoted_printable 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "matches" version = "0.1.8" @@ -1906,6 +1917,11 @@ dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quoted_printable" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "r2d2" version = "0.8.6" @@ -3388,6 +3404,7 @@ dependencies = [ "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" +"checksum mailparse 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "51a60bad00d8aa905d31cf239f207ad4ef16c963ea53cf522d5fd7dc7f3ecfe2" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" @@ -3439,6 +3456,7 @@ dependencies = [ "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum quoted_printable 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86cedf331228892e747bb85beb130b6bb23fc628c40dde9ea01eb6becea3c798" "checksum r2d2 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e48fa64898ef0286b6ee4b4d8f61483f9182acf5e44e62a398b1c7f56f2f861d" "checksum r2d2_sqlite 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "806e268035ce9e5a604bf617ac8a073ef28b59ef2e48e8338db0baf530caef33" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" diff --git a/Cargo.toml b/Cargo.toml index 4ba349169..9aee209b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,7 @@ stop-token = { version = "0.1.1", features = ["unstable"] } rustls = "0.16.0" webpki-roots = "0.18.0" webpki = "0.21.0" +mailparse = "0.9.2" [dev-dependencies] tempfile = "3.0" diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index fc264ace5..920c8656c 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -28,9 +28,10 @@ use crate::stock::StockMessage; use crate::wrapmime; #[derive(Debug)] -pub struct MimeParser<'a> { +pub struct MimeParser<'a, 'b> { pub context: &'a Context, pub parts: Vec, + mail: Option>, pub mimeroot: *mut Mailmime, pub header: HashMap, pub header_root: *mut mailimf_fields, @@ -83,10 +84,11 @@ const DC_MIMETYPE_VIDEO: i32 = 100; const DC_MIMETYPE_FILE: i32 = 110; const DC_MIMETYPE_AC_SETUP_FILE: i32 = 111; -impl<'a> MimeParser<'a> { +impl<'a, 'b> MimeParser<'a, 'b> { pub fn new(context: &'a Context) -> Self { MimeParser { parts: Vec::new(), + mail: None, mimeroot: std::ptr::null_mut(), header: Default::default(), header_root: std::ptr::null_mut(), @@ -106,229 +108,204 @@ impl<'a> MimeParser<'a> { } } - pub unsafe fn parse(&mut self, body: &[u8]) -> Result<(), Error> { + pub fn parse(&mut self, body: &'b [u8]) -> Result<(), Error> { let mut index = 0; - let r = mailmime_parse( - body.as_ptr() as *const libc::c_char, - body.len(), - &mut index, - &mut self.mimeroot, - ); + self.mail = Some(mailparse::parse_mail(body).unwrap()); - if r == MAILIMF_NO_ERROR as libc::c_int && !self.mimeroot.is_null() { - match e2ee::try_decrypt(self.context, self.mimeroot) { - Ok((encrypted, signatures, gossipped_addr)) => { - self.encrypted = encrypted; - self.signatures = signatures; - self.gossipped_addr = gossipped_addr; - } - Err(err) => { - // continue with the current, still encrypted, mime tree. - // unencrypted parts will be replaced by an error message - // that is added as "the message" to the chat then. - // - // if we just return here, the header is missing - // and the caller cannot display the message - // and try to assign the message to a chat - warn!(self.context, "decryption failed: {}", err); - } - } + // TODO: decrypt + // match e2ee::try_decrypt(self.context, self.mimeroot) { + // Ok((encrypted, signatures, gossipped_addr)) => { + // self.encrypted = encrypted; + // self.signatures = signatures; + // self.gossipped_addr = gossipped_addr; + // } + // Err(err) => { + // // continue with the current, still encrypted, mime tree. + // // unencrypted parts will be replaced by an error message + // // that is added as "the message" to the chat then. + // // + // // if we just return here, the header is missing + // // and the caller cannot display the message + // // and try to assign the message to a chat + // warn!(self.context, "decryption failed: {}", err); + // } + // } - self.parse_mime_recursive(self.mimeroot); + self.parse_mime_recursive(None); - if let Some(field) = self.lookup_field("Subject") { - if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { - let subj = (*(*field).fld_data.fld_subject).sbj_value; - self.subject = to_opt_string_lossy(subj).map(|x| dc_decode_header_words(&x)); - } - } + if let Some(field) = self.lookup_field("Subject") { + self.subject = Some(field.get_value().unwrap()); + } - if self.lookup_optional_field("Chat-Version").is_some() { - self.is_send_by_messenger = true - } + if self.lookup_field("Chat-Version").is_some() { + self.is_send_by_messenger = true + } - if self.lookup_field("Autocrypt-Setup-Message").is_some() { - let has_setup_file = self - .parts - .iter() - .any(|p| p.mimetype == DC_MIMETYPE_AC_SETUP_FILE); + if self.lookup_field("Autocrypt-Setup-Message").is_some() { + let has_setup_file = self + .parts + .iter() + .any(|p| p.mimetype == DC_MIMETYPE_AC_SETUP_FILE); - if has_setup_file { - self.is_system_message = SystemMessage::AutocryptSetupMessage; + if has_setup_file { + self.is_system_message = SystemMessage::AutocryptSetupMessage; - // TODO: replace the following code with this - // once drain_filter stabilizes. - // - // See https://doc.rust-lang.org/std/vec/struct.Vec.html#method.drain_filter - // and https://github.com/rust-lang/rust/issues/43244 - // - // mimeparser - // .parts - // .drain_filter(|part| part.int_mimetype != 111) - // .for_each(|part| dc_mimepart_unref(part)); + // TODO: replace the following code with this + // once drain_filter stabilizes. + // + // See https://doc.rust-lang.org/std/vec/struct.Vec.html#method.drain_filter + // and https://github.com/rust-lang/rust/issues/43244 + // + // mimeparser + // .parts + // .drain_filter(|part| part.int_mimetype != 111) + // .for_each(|part| dc_mimepart_unref(part)); - let mut i = 0; - while i != self.parts.len() { - if self.parts[i].mimetype != 111 { - self.parts.remove(i); - } else { - i += 1; - } - } - } - } else if let Some(optional_field) = self.lookup_optional_field("Chat-Content") { - if optional_field == "location-streaming-enabled" { - self.is_system_message = SystemMessage::LocationStreamingEnabled; - } - } - if self.lookup_field("Chat-Group-Image").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]; - if imgpart.typ == Viewtype::Image { - imgpart.is_meta = true; - } - } - } - if self.is_send_by_messenger && self.parts.len() == 2 { - let need_drop = { - let textpart = &self.parts[0]; - let filepart = &self.parts[1]; - textpart.typ == Viewtype::Text - && (filepart.typ == Viewtype::Image - || filepart.typ == Viewtype::Gif - || filepart.typ == Viewtype::Sticker - || filepart.typ == Viewtype::Audio - || filepart.typ == Viewtype::Voice - || filepart.typ == Viewtype::Video - || filepart.typ == Viewtype::File) - && !filepart.is_meta - }; - - if need_drop { - let mut filepart = self.parts.swap_remove(1); - - // insert new one - filepart.msg = self.parts[0].msg.as_ref().map(|s| s.to_string()); - - // forget the one we use now - self.parts[0].msg = None; - - // swap new with old - std::mem::replace(&mut self.parts[0], filepart); - } - } - if let Some(ref subject) = self.subject { - let mut prepend_subject: libc::c_int = 1i32; - if !self.decrypting_failed { - let colon = subject.find(':'); - if colon == Some(2) - || colon == Some(3) - || self.is_send_by_messenger - || subject.contains("Chat:") - { - prepend_subject = 0i32 - } - } - if 0 != prepend_subject { - let subj = if let Some(n) = subject.find('[') { - &subject[0..n] + let mut i = 0; + while i != self.parts.len() { + if self.parts[i].mimetype != 111 { + self.parts.remove(i); } else { - subject + i += 1; } - .trim(); + } + } + } else if let Some(optional_field) = self.lookup_field("Chat-Content") { + let value = optional_field.get_value(); + if value.is_ok() && value.as_ref().unwrap() == "location-streaming-enabled" { + self.is_system_message = SystemMessage::LocationStreamingEnabled; + } + } + if self.lookup_field("Chat-Group-Image").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]; + if imgpart.typ == Viewtype::Image { + imgpart.is_meta = true; + } + } + } + if self.is_send_by_messenger && self.parts.len() == 2 { + let need_drop = { + let textpart = &self.parts[0]; + let filepart = &self.parts[1]; + textpart.typ == Viewtype::Text + && (filepart.typ == Viewtype::Image + || filepart.typ == Viewtype::Gif + || filepart.typ == Viewtype::Sticker + || filepart.typ == Viewtype::Audio + || filepart.typ == Viewtype::Voice + || filepart.typ == Viewtype::Video + || filepart.typ == Viewtype::File) + && !filepart.is_meta + }; - if !subj.is_empty() { - for part in self.parts.iter_mut() { - if part.typ == Viewtype::Text { - let new_txt = format!( - "{} – {}", - subj, - part.msg.as_ref().expect("missing msg part") - ); - part.msg = Some(new_txt); - break; - } - } - } - } - } - if self.is_forwarded { - for part in self.parts.iter_mut() { - part.param.set_int(Param::Forwarded, 1); - } - } - if self.parts.len() == 1 { - if self.parts[0].typ == Viewtype::Audio { - if self.lookup_optional_field("Chat-Voice-Message").is_some() { - let part_mut = &mut self.parts[0]; - part_mut.typ = Viewtype::Voice; - } - } - if self.parts[0].typ == Viewtype::Image { - if let Some(content_type) = self.lookup_optional_field("Chat-Content") { - if content_type == "sticker" { - let part_mut = &mut self.parts[0]; - part_mut.typ = Viewtype::Sticker; - } - } - } - let part = &self.parts[0]; - if part.typ == Viewtype::Audio - || part.typ == Viewtype::Voice - || part.typ == Viewtype::Video - { - if let Some(field_0) = self.lookup_optional_field("Chat-Duration") { - 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]; - part_mut.param.set_int(Param::Duration, duration_ms); - } - } - } + if need_drop { + let mut filepart = self.parts.swap_remove(1); + + // insert new one + filepart.msg = self.parts[0].msg.as_ref().map(|s| s.to_string()); + + // forget the one we use now + self.parts[0].msg = None; + + // swap new with old + std::mem::replace(&mut self.parts[0], filepart); } + } + if let Some(ref subject) = self.subject { + let mut prepend_subject: libc::c_int = 1i32; if !self.decrypting_failed { - if let Some(dn_field) = - self.lookup_optional_field("Chat-Disposition-Notification-To") + let colon = subject.find(':'); + if colon == Some(2) + || colon == Some(3) + || self.is_send_by_messenger + || subject.contains("Chat:") { - if self.get_last_nonmeta().is_some() { - let mut mb_list: *mut mailimf_mailbox_list = ptr::null_mut(); - let mut index_0 = 0; - let dn_field_c = CString::new(dn_field).unwrap_or_default(); + prepend_subject = 0i32 + } + } + if 0 != prepend_subject { + let subj = if let Some(n) = subject.find('[') { + &subject[0..n] + } else { + subject + } + .trim(); - if mailimf_mailbox_list_parse( - dn_field_c.as_ptr(), - strlen(dn_field_c.as_ptr()), - &mut index_0, - &mut mb_list, - ) == MAILIMF_NO_ERROR as libc::c_int - && !mb_list.is_null() - { - if let Some(dn_to_addr) = wrapmime::mailimf_find_first_addr(mb_list) { - if let Some(from_field) = self.lookup_field("From") { - if (*from_field).fld_type == MAILIMF_FIELD_FROM as libc::c_int - && !(*from_field).fld_data.fld_from.is_null() - { - let from_addr = wrapmime::mailimf_find_first_addr( - (*(*from_field).fld_data.fld_from).frm_mb_list, - ); - if let Some(from_addr) = from_addr { - if from_addr == dn_to_addr { - if let Some(part_4) = self.get_last_nonmeta() { - part_4.param.set_int(Param::WantsMdn, 1); - } - } - } - } - } - } - mailimf_mailbox_list_free(mb_list); + if !subj.is_empty() { + for part in self.parts.iter_mut() { + if part.typ == Viewtype::Text { + let new_txt = format!( + "{} – {}", + subj, + part.msg.as_ref().expect("missing msg part") + ); + part.msg = Some(new_txt); + break; } } } } } + if self.is_forwarded { + for part in self.parts.iter_mut() { + part.param.set_int(Param::Forwarded, 1); + } + } + if self.parts.len() == 1 { + if self.parts[0].typ == Viewtype::Audio { + if self.lookup_field("Chat-Voice-Message").is_some() { + let part_mut = &mut self.parts[0]; + part_mut.typ = Viewtype::Voice; + } + } + if self.parts[0].typ == Viewtype::Image { + if let Some(content_type) = self.lookup_field("Chat-Content") { + let value = content_type.get_value(); + if value.is_ok() && value.as_ref().unwrap() == "sticker" { + let part_mut = &mut self.parts[0]; + part_mut.typ = Viewtype::Sticker; + } + } + } + let part = &self.parts[0]; + if part.typ == Viewtype::Audio + || part.typ == Viewtype::Voice + || part.typ == Viewtype::Video + { + if let Some(field_0) = self.lookup_field("Chat-Duration") { + let duration_ms = field_0.get_value().unwrap().parse().unwrap_or_default(); + if duration_ms > 0 && duration_ms < 24 * 60 * 60 * 1000 { + let part_mut = &mut self.parts[0]; + part_mut.param.set_int(Param::Duration, duration_ms); + } + } + } + } + if !self.decrypting_failed { + if let Some(dn_field) = self.lookup_field("Chat-Disposition-Notification-To") { + if self.get_last_nonmeta().is_some() { + let addrs = mailparse::addrparse(&dn_field.get_value().unwrap()).unwrap(); + + if let Some(dn_to_addr) = addrs.first() { + if let Some(from_field) = self.lookup_field("From") { + let value = from_field.get_value().unwrap(); + let from_addrs = mailparse::addrparse(&value).unwrap(); + if let Some(from_addr) = from_addrs.first() { + if from_addr == dn_to_addr { + if let Some(part_4) = self.get_last_nonmeta_mut() { + part_4.param.set_int(Param::WantsMdn, 1); + } + } + } + } + } + } + } + } + /* Cleanup - and try to create at least an empty part if there are no parts yet */ if self.get_last_nonmeta().is_none() && self.reports.is_empty() { let mut part_5 = Part::default(); @@ -345,66 +322,41 @@ impl<'a> MimeParser<'a> { Ok(()) } - pub fn get_last_nonmeta(&mut self) -> Option<&mut Part> { + pub fn get_last_nonmeta(&self) -> Option<&Part> { + self.parts.iter().rev().find(|part| !part.is_meta) + } + + pub fn get_last_nonmeta_mut(&mut self) -> Option<&mut Part> { self.parts.iter_mut().rev().find(|part| !part.is_meta) } /* the following functions can be used only after a call to parse() */ - pub fn lookup_field(&self, field_name: &str) -> Option<*mut mailimf_field> { - match self.header.get(field_name) { - Some(v) => { - if v.is_null() { - None - } else { - Some(*v) - } - } - None => None, + pub fn lookup_field(&self, field_name: &str) -> Option<&'b mailparse::MailHeader<'_>> { + if let Some(ref mail) = self.mail { + return mail + .headers + .iter() + .find(|header| header.get_key().unwrap() == field_name); } - } - - pub fn lookup_optional_field(&self, field_name: &str) -> Option { - if let Some(field) = self.lookup_field_typ(field_name, MAILIMF_FIELD_OPTIONAL_FIELD) { - let val = unsafe { (*field).fld_data.fld_optional_field }; - if val.is_null() { - return None; - } else { - return Some(unsafe { to_string_lossy((*val).fld_value) }); - } - } - None } - pub fn lookup_field_typ(&self, name: &str, typ: u32) -> Option<*const mailimf_field> { - if let Some(field) = self.lookup_field(name) { - if unsafe { (*field).fld_type } == typ as libc::c_int { - Some(field) - } else { - None - } - } else { - None - } - } + fn parse_mime_recursive(&mut self, omail: Option>) -> bool { + let mail = omail + .as_ref() + .unwrap_or_else(|| self.mail.as_ref().unwrap()); - unsafe fn parse_mime_recursive(&mut self, mime: *mut Mailmime) -> bool { - if mime.is_null() { - return false; - } + let ctype = mailparse::parse_content_type( + &self + .lookup_field("Content-Type") + .unwrap() + .get_value() + .unwrap(), + ); - if !mailmime_find_ct_parameter(mime, "protected-headers").is_null() { - let mime = *mime; - - if mime.mm_type == MAILMIME_SINGLE as libc::c_int - && (*(*mime.mm_content_type).ct_type).tp_type - == MAILMIME_TYPE_DISCRETE_TYPE as libc::c_int - && (*(*(*mime.mm_content_type).ct_type).tp_data.tp_discrete_type).dt_type - == MAILMIME_DISCRETE_TYPE_TEXT as libc::c_int - && !(*mime.mm_content_type).ct_subtype.is_null() - && &to_string_lossy((*mime.mm_content_type).ct_subtype) == "rfc822-headers" - { + if let Some(protected_headers) = ctype.params.get("protected-headers") { + if mail.subparts.is_empty() && ctype.mimetype == "text/rfc822-headers" { info!( self.context, "Protected headers found in text/rfc822-headers attachment: Will be ignored.", @@ -413,21 +365,23 @@ impl<'a> MimeParser<'a> { } if self.header_protected.is_null() { - /* use the most outer protected header - this is typically - created in sync with the normal, unprotected header */ - let mut dummy = 0; - if mailimf_envelope_and_optional_fields_parse( - mime.mm_mime_start, - mime.mm_length, - &mut dummy, - &mut self.header_protected, - ) != MAILIMF_NO_ERROR as libc::c_int - || self.header_protected.is_null() - { - warn!(self.context, "Protected headers parsing error.",); - } else { - hash_header(&mut self.header, self.header_protected); - } + // TODO: + + // /* use the most outer protected header - this is typically + // created in sync with the normal, unprotected header */ + // let mut dummy = 0; + // if mailimf_envelope_and_optional_fields_parse( + // mime.mm_mime_start, + // mime.mm_length, + // &mut dummy, + // &mut self.header_protected, + // ) != MAILIMF_NO_ERROR as libc::c_int + // || self.header_protected.is_null() + // { + // warn!(self.context, "Protected headers parsing error.",); + // } else { + // hash_header(&mut self.header, self.header_protected); + // } } else { info!( self.context, @@ -436,331 +390,340 @@ impl<'a> MimeParser<'a> { } } - match (*mime).mm_type as u32 { - MAILMIME_SINGLE => self.add_single_part_if_known(mime), - MAILMIME_MULTIPLE => self.handle_multiple(mime), - MAILMIME_MESSAGE => { - if self.header_root.is_null() { - self.header_root = (*mime).mm_data.mm_message.mm_fields; - hash_header(&mut self.header, self.header_root); - } - if (*mime).mm_data.mm_message.mm_msg_mime.is_null() { - return false; - } + // single = multipart/* only one + // multiple = multipart/* multiple + // message = text/rfc822 - self.parse_mime_recursive((*mime).mm_data.mm_message.mm_msg_mime) - } - _ => false, + if mail.ctype.mimetype == "text/rfc822" { + // if self.header_root.is_null() { + // self.header_root = (*mime).mm_data.mm_message.mm_fields; + // hash_header(&mut self.header, self.header_root); + // } + // if (*mime).mm_data.mm_message.mm_msg_mime.is_null() { + // return false; + // } + + let raw = mail.get_body_raw().unwrap(); + let mail = mailparse::parse_mail(&raw).unwrap(); + + return self.parse_mime_recursive(Some(mail)); } + + if mail.subparts.len() > 1 { + return self.handle_multiple(omail); + } + + if mail.subparts.len() == 1 { + return self.add_single_part_if_known(omail); + } + false } - unsafe fn handle_multiple(&mut self, mime: *mut Mailmime) -> bool { - let mut any_part_added = false; - match mailmime_get_mime_type(mime) { - /* Most times, mutlipart/alternative contains true alternatives - as text/plain and text/html. If we find a multipart/mixed - inside mutlipart/alternative, we use this (happens eg in - apple mail: "plaintext" as an alternative to "html+PDF attachment") */ - (DC_MIMETYPE_MP_ALTERNATIVE, _, _) => { - for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - if mailmime_get_mime_type(cur_data as *mut _).0 == DC_MIMETYPE_MP_MIXED { - any_part_added = self.parse_mime_recursive(cur_data as *mut _); - break; - } - } - if !any_part_added { - /* search for text/plain and add this */ - for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - if mailmime_get_mime_type(cur_data as *mut _).0 == DC_MIMETYPE_TEXT_PLAIN { - any_part_added = self.parse_mime_recursive(cur_data as *mut _); - break; - } - } - } - if !any_part_added { - /* `text/plain` not found - use the first part */ - for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - if self.parse_mime_recursive(cur_data as *mut _) { - any_part_added = true; - break; - } - } - } - } - (DC_MIMETYPE_MP_RELATED, _, _) => { - /* add the "root part" - the other parts may be referenced which is - not interesting for us (eg. embedded images) we assume he "root part" - being the first one, which may not be always true ... - however, most times it seems okay. */ - let cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; - if !cur.is_null() { - any_part_added = self.parse_mime_recursive((*cur).data as *mut Mailmime); - } - } - (DC_MIMETYPE_MP_NOT_DECRYPTABLE, _, _) => { - let mut part = Part::default(); - part.typ = Viewtype::Text; - let msg_body = self.context.stock_str(StockMessage::CantDecryptMsgBody); + fn handle_multiple(&mut self, omail: Option>) -> bool { + // let mut any_part_added = false; + // match mailmime_get_mime_type(mime) { + // /* Most times, mutlipart/alternative contains true alternatives + // as text/plain and text/html. If we find a multipart/mixed + // inside mutlipart/alternative, we use this (happens eg in + // apple mail: "plaintext" as an alternative to "html+PDF attachment") */ + // (DC_MIMETYPE_MP_ALTERNATIVE, _, _) => { + // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { + // if mailmime_get_mime_type(cur_data as *mut _).0 == DC_MIMETYPE_MP_MIXED { + // any_part_added = self.parse_mime_recursive(cur_data as *mut _); + // break; + // } + // } + // if !any_part_added { + // /* search for text/plain and add this */ + // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { + // if mailmime_get_mime_type(cur_data as *mut _).0 == DC_MIMETYPE_TEXT_PLAIN { + // any_part_added = self.parse_mime_recursive(cur_data as *mut _); + // break; + // } + // } + // } + // if !any_part_added { + // /* `text/plain` not found - use the first part */ + // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { + // if self.parse_mime_recursive(cur_data as *mut _) { + // any_part_added = true; + // break; + // } + // } + // } + // } + // (DC_MIMETYPE_MP_RELATED, _, _) => { + // /* add the "root part" - the other parts may be referenced which is + // not interesting for us (eg. embedded images) we assume he "root part" + // being the first one, which may not be always true ... + // however, most times it seems okay. */ + // let cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + // if !cur.is_null() { + // any_part_added = self.parse_mime_recursive((*cur).data as *mut Mailmime); + // } + // } + // (DC_MIMETYPE_MP_NOT_DECRYPTABLE, _, _) => { + // let mut part = Part::default(); + // part.typ = Viewtype::Text; + // let msg_body = self.context.stock_str(StockMessage::CantDecryptMsgBody); - let txt = format!("[{}]", msg_body); - part.msg_raw = Some(txt.clone()); - part.msg = Some(txt); + // let txt = format!("[{}]", msg_body); + // part.msg_raw = Some(txt.clone()); + // part.msg = Some(txt); - self.parts.push(part); - any_part_added = true; - self.decrypting_failed = true; - } - (DC_MIMETYPE_MP_SIGNED, _, _) => { - /* RFC 1847: "The multipart/signed content type - contains exactly two body parts. The first body - part is the body part over which the digital signature was created [...] - The second body part contains the control information necessary to - verify the digital signature." We simpliy take the first body part and - skip the rest. (see - https://k9mail.github.io/2016/11/24/OpenPGP-Considerations-Part-I.html - for background information why we use encrypted+signed) */ - let cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; - if !cur.is_null() { - any_part_added = self.parse_mime_recursive((*cur).data as *mut _); - } - } - (DC_MIMETYPE_MP_REPORT, _, _) => { - /* RFC 6522: the first part is for humans, the second for machines */ - if (*(*mime).mm_data.mm_multipart.mm_mp_list).count >= 2 { - let report_type = mailmime_find_ct_parameter(mime, "report-type"); - if !report_type.is_null() - && !(*report_type).pa_value.is_null() - && &to_string_lossy((*report_type).pa_value) == "disposition-notification" - { - self.reports.push(mime); - } else { - /* eg. `report-type=delivery-status`; - maybe we should show them as a little error icon */ - if !(*(*mime).mm_data.mm_multipart.mm_mp_list).first.is_null() { - any_part_added = self.parse_mime_recursive( - (*(*(*mime).mm_data.mm_multipart.mm_mp_list).first).data as *mut _, - ); - } - } - } - } - _ => { - /* eg. DC_MIMETYPE_MP_MIXED - add all parts (in fact, - AddSinglePartIfKnown() later check if the parts are really supported) - HACK: the following lines are a hack for clients who use - multipart/mixed instead of multipart/alternative for - combined text/html messages (eg. Stock Android "Mail" does so). - So, if we detect such a message below, we skip the HTML - part. However, not sure, if there are useful situations to use - plain+html in multipart/mixed - if so, we should disable the hack. */ - let mut skip_part = ptr::null_mut(); - let mut html_part = ptr::null_mut(); - let mut plain_cnt = 0; - let mut html_cnt = 0; + // self.parts.push(part); + // any_part_added = true; + // self.decrypting_failed = true; + // } + // (DC_MIMETYPE_MP_SIGNED, _, _) => { + // /* RFC 1847: "The multipart/signed content type + // contains exactly two body parts. The first body + // part is the body part over which the digital signature was created [...] + // The second body part contains the control information necessary to + // verify the digital signature." We simpliy take the first body part and + // skip the rest. (see + // https://k9mail.github.io/2016/11/24/OpenPGP-Considerations-Part-I.html + // for background information why we use encrypted+signed) */ + // let cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + // if !cur.is_null() { + // any_part_added = self.parse_mime_recursive((*cur).data as *mut _); + // } + // } + // (DC_MIMETYPE_MP_REPORT, _, _) => { + // /* RFC 6522: the first part is for humans, the second for machines */ + // if (*(*mime).mm_data.mm_multipart.mm_mp_list).count >= 2 { + // let report_type = mailmime_find_ct_parameter(mime, "report-type"); + // if !report_type.is_null() + // && !(*report_type).pa_value.is_null() + // && &to_string_lossy((*report_type).pa_value) == "disposition-notification" + // { + // self.reports.push(mime); + // } else { + // /* eg. `report-type=delivery-status`; + // maybe we should show them as a little error icon */ + // if !(*(*mime).mm_data.mm_multipart.mm_mp_list).first.is_null() { + // any_part_added = self.parse_mime_recursive( + // (*(*(*mime).mm_data.mm_multipart.mm_mp_list).first).data as *mut _, + // ); + // } + // } + // } + // } + // _ => { + // /* eg. DC_MIMETYPE_MP_MIXED - add all parts (in fact, + // AddSinglePartIfKnown() later check if the parts are really supported) + // HACK: the following lines are a hack for clients who use + // multipart/mixed instead of multipart/alternative for + // combined text/html messages (eg. Stock Android "Mail" does so). + // So, if we detect such a message below, we skip the HTML + // part. However, not sure, if there are useful situations to use + // plain+html in multipart/mixed - if so, we should disable the hack. */ + // let mut skip_part = ptr::null_mut(); + // let mut html_part = ptr::null_mut(); + // let mut plain_cnt = 0; + // let mut html_cnt = 0; - for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - match mailmime_get_mime_type(cur_data as *mut _) { - (DC_MIMETYPE_TEXT_PLAIN, _, _) => { - plain_cnt += 1; - } - (DC_MIMETYPE_TEXT_HTML, _, _) => { - html_part = cur_data as *mut Mailmime; - html_cnt += 1; - } - _ => {} - } - } - if plain_cnt == 1 && html_cnt == 1 { - warn!( - self.context, - "HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted." - ); - skip_part = html_part; - } + // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { + // match mailmime_get_mime_type(cur_data as *mut _) { + // (DC_MIMETYPE_TEXT_PLAIN, _, _) => { + // plain_cnt += 1; + // } + // (DC_MIMETYPE_TEXT_HTML, _, _) => { + // html_part = cur_data as *mut Mailmime; + // html_cnt += 1; + // } + // _ => {} + // } + // } + // if plain_cnt == 1 && html_cnt == 1 { + // warn!( + // self.context, + // "HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted." + // ); + // skip_part = html_part; + // } - for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - if cur_data as *mut _ != skip_part { - if self.parse_mime_recursive(cur_data as *mut _) { - any_part_added = true; - } - } - } - } - } + // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { + // if cur_data as *mut _ != skip_part { + // if self.parse_mime_recursive(cur_data as *mut _) { + // any_part_added = true; + // } + // } + // } + // } + // } - any_part_added + // any_part_added + unimplemented!() } - unsafe fn add_single_part_if_known(&mut self, mime: *mut Mailmime) -> bool { - // return true if a part was added - if mime.is_null() || (*mime).mm_data.mm_single.is_null() { - return false; - } + fn add_single_part_if_known(&mut self, omail: Option>) -> bool { + unimplemented!() + // // return true if a part was added + // let (mime_type, msg_type, raw_mime) = mailmime_get_mime_type(mime); - let (mime_type, msg_type, raw_mime) = mailmime_get_mime_type(mime); + // let mime_data = (*mime).mm_data.mm_single; + // if (*mime_data).dt_type != MAILMIME_DATA_TEXT as libc::c_int + // /* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */ + // || (*mime_data).dt_data.dt_text.dt_data.is_null() + // || (*mime_data).dt_data.dt_text.dt_length <= 0 + // { + // return false; + // } - let mime_data = (*mime).mm_data.mm_single; - if (*mime_data).dt_type != MAILMIME_DATA_TEXT as libc::c_int - /* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */ - || (*mime_data).dt_data.dt_text.dt_data.is_null() - || (*mime_data).dt_data.dt_text.dt_length <= 0 - { - return false; - } + // let mut decoded_data = match wrapmime::mailmime_transfer_decode(mime) { + // Ok(decoded_data) => decoded_data, + // Err(_) => { + // // Note that it's not always an error - might be no data + // return false; + // } + // }; - let mut decoded_data = match wrapmime::mailmime_transfer_decode(mime) { - Ok(decoded_data) => decoded_data, - Err(_) => { - // Note that it's not always an error - might be no data - return false; - } - }; + // let old_part_count = self.parts.len(); - let old_part_count = self.parts.len(); + // /* regard `Content-Transfer-Encoding:` */ + // let mut desired_filename = String::default(); + // match mime_type { + // DC_MIMETYPE_TEXT_PLAIN | DC_MIMETYPE_TEXT_HTML => { + // /* get from `Content-Type: text/...; charset=utf-8`; must not be free()'d */ + // let charset = mailmime_content_charset_get((*mime).mm_content_type); + // if !charset.is_null() + // && strcmp(charset, b"utf-8\x00" as *const u8 as *const libc::c_char) != 0i32 + // && strcmp(charset, b"UTF-8\x00" as *const u8 as *const libc::c_char) != 0i32 + // { + // if let Some(encoding) = + // Charset::for_label(CStr::from_ptr(charset).to_string_lossy().as_bytes()) + // { + // let (res, _, _) = encoding.decode(&decoded_data); + // if res.is_empty() { + // /* no error - but nothing to add */ + // return false; + // } + // decoded_data = res.as_bytes().to_vec() + // } else { + // warn!( + // self.context, + // "Cannot convert {} bytes from \"{}\" to \"utf-8\".", + // decoded_data.len(), + // to_string_lossy(charset), + // ); + // } + // } + // /* check header directly as is_send_by_messenger is not yet set up */ + // let is_msgrmsg = self.lookup_field(mail, "Chat-Version").is_some(); - /* regard `Content-Transfer-Encoding:` */ - let mut desired_filename = String::default(); - match mime_type { - DC_MIMETYPE_TEXT_PLAIN | DC_MIMETYPE_TEXT_HTML => { - /* get from `Content-Type: text/...; charset=utf-8`; must not be free()'d */ - let charset = mailmime_content_charset_get((*mime).mm_content_type); - if !charset.is_null() - && strcmp(charset, b"utf-8\x00" as *const u8 as *const libc::c_char) != 0i32 - && strcmp(charset, b"UTF-8\x00" as *const u8 as *const libc::c_char) != 0i32 - { - if let Some(encoding) = - Charset::for_label(CStr::from_ptr(charset).to_string_lossy().as_bytes()) - { - let (res, _, _) = encoding.decode(&decoded_data); - if res.is_empty() { - /* no error - but nothing to add */ - return false; - } - decoded_data = res.as_bytes().to_vec() - } else { - warn!( - self.context, - "Cannot convert {} bytes from \"{}\" to \"utf-8\".", - decoded_data.len(), - to_string_lossy(charset), - ); - } - } - /* check header directly as is_send_by_messenger is not yet set up */ - let is_msgrmsg = self.lookup_optional_field("Chat-Version").is_some(); + // let mut simplifier = Simplify::new(); + // let simplified_txt = if decoded_data.is_empty() { + // "".into() + // } else { + // let input = std::string::String::from_utf8_lossy(&decoded_data); + // let is_html = mime_type == 70; - let mut simplifier = Simplify::new(); - let simplified_txt = if decoded_data.is_empty() { - "".into() - } else { - let input = std::string::String::from_utf8_lossy(&decoded_data); - let is_html = mime_type == 70; + // simplifier.simplify(&input, is_html, is_msgrmsg) + // }; + // if !simplified_txt.is_empty() { + // let mut part = Part::default(); + // part.typ = Viewtype::Text; + // part.mimetype = mime_type; + // part.msg = Some(simplified_txt); + // part.msg_raw = + // Some(std::string::String::from_utf8_lossy(&decoded_data).to_string()); + // self.do_add_single_part(part); + // } - simplifier.simplify(&input, is_html, is_msgrmsg) - }; - if !simplified_txt.is_empty() { - let mut part = Part::default(); - part.typ = Viewtype::Text; - part.mimetype = mime_type; - part.msg = Some(simplified_txt); - part.msg_raw = - Some(std::string::String::from_utf8_lossy(&decoded_data).to_string()); - self.do_add_single_part(part); - } + // if simplifier.is_forwarded { + // self.is_forwarded = true; + // } + // } + // DC_MIMETYPE_IMAGE + // | DC_MIMETYPE_AUDIO + // | DC_MIMETYPE_VIDEO + // | DC_MIMETYPE_FILE + // | DC_MIMETYPE_AC_SETUP_FILE => { + // /* try to get file name from + // `Content-Disposition: ... filename*=...` + // or `Content-Disposition: ... filename*0*=... filename*1*=... filename*2*=...` + // or `Content-Disposition: ... filename=...` */ + // let mut filename_parts = String::new(); - if simplifier.is_forwarded { - self.is_forwarded = true; - } - } - DC_MIMETYPE_IMAGE - | DC_MIMETYPE_AUDIO - | DC_MIMETYPE_VIDEO - | DC_MIMETYPE_FILE - | DC_MIMETYPE_AC_SETUP_FILE => { - /* try to get file name from - `Content-Disposition: ... filename*=...` - or `Content-Disposition: ... filename*0*=... filename*1*=... filename*2*=...` - or `Content-Disposition: ... filename=...` */ - let mut filename_parts = String::new(); - - for cur1 in (*(*(*mime).mm_mime_fields).fld_list).into_iter() { - let field = cur1 as *mut mailmime_field; - if !field.is_null() - && (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int - && !(*field).fld_data.fld_disposition.is_null() - { - let file_disposition: *mut mailmime_disposition = - (*field).fld_data.fld_disposition; - if !file_disposition.is_null() { - for cur2 in (*(*file_disposition).dsp_parms).into_iter() { - let dsp_param = cur2 as *mut mailmime_disposition_parm; - if !dsp_param.is_null() { - if (*dsp_param).pa_type - == MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int - && !(*dsp_param).pa_data.pa_parameter.is_null() - && !(*(*dsp_param).pa_data.pa_parameter).pa_name.is_null() - && strncmp( - (*(*dsp_param).pa_data.pa_parameter).pa_name, - b"filename*\x00" as *const u8 as *const libc::c_char, - 9, - ) == 0i32 - { - // we assume the filename*?* parts are in order, not seen anything else yet - filename_parts += &to_string_lossy( - (*(*dsp_param).pa_data.pa_parameter).pa_value, - ); - } else if (*dsp_param).pa_type - == MAILMIME_DISPOSITION_PARM_FILENAME as libc::c_int - { - // might be a wrongly encoded filename - let s = to_string_lossy((*dsp_param).pa_data.pa_filename); - // this is used only if the parts buffer stays empty - desired_filename = dc_decode_header_words(&s) - } - } - } - } - break; - } - } - if !filename_parts.is_empty() { - desired_filename = dc_decode_ext_header(filename_parts.as_bytes()).into_owned(); - } - if desired_filename.is_empty() { - let param = mailmime_find_ct_parameter(mime, "name"); - if !param.is_null() - && !(*param).pa_value.is_null() - && 0 != *(*param).pa_value.offset(0isize) as libc::c_int - { - // might be a wrongly encoded filename - desired_filename = to_string_lossy((*param).pa_value); - } - } - /* if there is still no filename, guess one */ - if desired_filename.is_empty() { - if !(*mime).mm_content_type.is_null() - && !(*(*mime).mm_content_type).ct_subtype.is_null() - { - desired_filename = format!( - "file.{}", - to_string_lossy((*(*mime).mm_content_type).ct_subtype) - ); - } else { - return false; - } - } - self.do_add_single_file_part( - msg_type, - mime_type, - raw_mime.as_ref(), - &decoded_data, - &desired_filename, - ); - } - _ => {} - } - /* add object? (we do not add all objects, eg. signatures etc. are ignored) */ - self.parts.len() > old_part_count + // for cur1 in (*(*(*mime).mm_mime_fields).fld_list).into_iter() { + // let field = cur1 as *mut mailmime_field; + // if !field.is_null() + // && (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int + // && !(*field).fld_data.fld_disposition.is_null() + // { + // let file_disposition: *mut mailmime_disposition = + // (*field).fld_data.fld_disposition; + // if !file_disposition.is_null() { + // for cur2 in (*(*file_disposition).dsp_parms).into_iter() { + // let dsp_param = cur2 as *mut mailmime_disposition_parm; + // if !dsp_param.is_null() { + // if (*dsp_param).pa_type + // == MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int + // && !(*dsp_param).pa_data.pa_parameter.is_null() + // && !(*(*dsp_param).pa_data.pa_parameter).pa_name.is_null() + // && strncmp( + // (*(*dsp_param).pa_data.pa_parameter).pa_name, + // b"filename*\x00" as *const u8 as *const libc::c_char, + // 9, + // ) == 0i32 + // { + // // we assume the filename*?* parts are in order, not seen anything else yet + // filename_parts += &to_string_lossy( + // (*(*dsp_param).pa_data.pa_parameter).pa_value, + // ); + // } else if (*dsp_param).pa_type + // == MAILMIME_DISPOSITION_PARM_FILENAME as libc::c_int + // { + // // might be a wrongly encoded filename + // let s = to_string_lossy((*dsp_param).pa_data.pa_filename); + // // this is used only if the parts buffer stays empty + // desired_filename = dc_decode_header_words(&s) + // } + // } + // } + // } + // break; + // } + // } + // if !filename_parts.is_empty() { + // desired_filename = dc_decode_ext_header(filename_parts.as_bytes()).into_owned(); + // } + // if desired_filename.is_empty() { + // let param = mailmime_find_ct_parameter(mime, "name"); + // if !param.is_null() + // && !(*param).pa_value.is_null() + // && 0 != *(*param).pa_value.offset(0isize) as libc::c_int + // { + // // might be a wrongly encoded filename + // desired_filename = to_string_lossy((*param).pa_value); + // } + // } + // /* if there is still no filename, guess one */ + // if desired_filename.is_empty() { + // if !(*mime).mm_content_type.is_null() + // && !(*(*mime).mm_content_type).ct_subtype.is_null() + // { + // desired_filename = format!( + // "file.{}", + // to_string_lossy((*(*mime).mm_content_type).ct_subtype) + // ); + // } else { + // return false; + // } + // } + // self.do_add_single_file_part( + // msg_type, + // mime_type, + // raw_mime.as_ref(), + // &decoded_data, + // &desired_filename, + // ); + // } + // _ => {} + // } + // /* add object? (we do not add all objects, eg. signatures etc. are ignored) */ + // self.parts.len() > old_part_count } unsafe fn do_add_single_file_part( @@ -844,8 +807,10 @@ impl<'a> MimeParser<'a> { return true; } - if let Some(precedence) = self.lookup_optional_field("Precedence") { - if precedence == "list" || precedence == "bulk" { + if let Some(precedence) = self.lookup_field("Precedence") { + if precedence.get_value().unwrap() == "list" + || precedence.get_value().unwrap() == "bulk" + { return true; } } @@ -906,19 +871,14 @@ impl<'a> MimeParser<'a> { pub fn get_rfc724_mid(&mut self) -> Option { // get Message-ID from header - if let Some(field) = self.lookup_field_typ("Message-ID", MAILIMF_FIELD_MESSAGE_ID) { - unsafe { - let fld_message_id = (*field).fld_data.fld_message_id; - if !fld_message_id.is_null() { - return Some(to_string_lossy((*fld_message_id).mid_value)); - } - } + if let Some(field) = self.lookup_field("Message-ID") { + return field.get_value().ok(); } None } } -impl<'a> Drop for MimeParser<'a> { +impl<'a, 'b> Drop for MimeParser<'a, 'b> { fn drop(&mut self) { if !self.header_protected.is_null() { unsafe { mailimf_fields_free(self.header_protected) }; @@ -1298,13 +1258,21 @@ mod tests { assert_eq!(mimeparser.subject, Some("inner-subject".into())); - let of = mimeparser.lookup_optional_field("X-Special-A").unwrap(); + let of = mimeparser + .lookup_field("X-Special-A") + .unwrap() + .get_value() + .unwrap(); assert_eq!(&of, "special-a"); - let of = mimeparser.lookup_optional_field("Foo").unwrap(); + let of = mimeparser.lookup_field("Foo").unwrap().get_value().unwrap(); assert_eq!(&of, "Bar"); - let of = mimeparser.lookup_optional_field("Chat-Version").unwrap(); + let of = mimeparser + .lookup_field("Chat-Version") + .unwrap() + .get_value() + .unwrap(); assert_eq!(&of, "1.0"); assert_eq!(mimeparser.parts.len(), 1); } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 466698dac..3168cd3e5 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -122,61 +122,59 @@ pub unsafe fn dc_receive_imf( } }; - if let Some(field) = mime_parser.lookup_field_typ("Date", MAILIMF_FIELD_ORIG_DATE) { - let orig_date = (*field).fld_data.fld_orig_date; - if !orig_date.is_null() { + if let Some(field) = mime_parser.lookup_field("Date") { + if let Ok(value) = field.get_value() { // is not yet checked against bad times! we do this later if we have the database information. - sent_timestamp = dc_timestamp_from_date((*orig_date).dt_date_time) + // sent_timestamp = dc_timestamp_from_date((*orig_date).dt_date_time) + // TODO } } // 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) = mime_parser.lookup_field_typ("From", MAILIMF_FIELD_FROM) { - let fld_from = (*field).fld_data.fld_from; - if !fld_from.is_null() { + if let Some(field) = mime_parser.lookup_field("From") { + if let Ok(fld_from) = field.get_value() { let mut check_self = 0; - let mut from_list = Vec::with_capacity(16); - dc_add_or_lookup_contacts_by_mailbox_list( - context, - (*fld_from).frm_mb_list, - Origin::IncomingUnknownFrom, - &mut from_list, - &mut check_self, - ); - if 0 != check_self { - incoming = 0; - if mime_parser.sender_equals_recipient() { - from_id = DC_CONTACT_ID_SELF; - } - } else if !from_list.is_empty() { - // if there is no from given, from_id stays 0 which is just fine. These messages - // are very rare, however, we have to add them to the database (they go to the - // "deaddrop" chat) to avoid a re-download from the server. See also [**] - from_id = from_list[0]; - incoming_origin = Contact::get_origin_by_id(context, from_id, &mut from_id_blocked) - } + // let mut from_list = Vec::with_capacity(16); + // dc_add_or_lookup_contacts_by_mailbox_list( + // context, + // (*fld_from).frm_mb_list, + // Origin::IncomingUnknownFrom, + // &mut from_list, + // &mut check_self, + // ); + // if 0 != check_self { + // incoming = 0; + // if mime_parser.sender_equals_recipient() { + // from_id = DC_CONTACT_ID_SELF; + // } + // } else if !from_list.is_empty() { + // // if there is no from given, from_id stays 0 which is just fine. These messages + // // are very rare, however, we have to add them to the database (they go to the + // // "deaddrop" chat) to avoid a re-download from the server. See also [**] + // from_id = from_list[0]; + // incoming_origin = Contact::get_origin_by_id(context, from_id, &mut from_id_blocked) + // } } } // 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_typ("To", MAILIMF_FIELD_TO) { - let fld_to = (*field).fld_data.fld_to; - if !fld_to.is_null() { - dc_add_or_lookup_contacts_by_address_list( - context, - (*fld_to).to_addr_list, - if 0 == incoming { - Origin::OutgoingTo - } else if incoming_origin.is_verified() { - Origin::IncomingTo - } else { - Origin::IncomingUnknownTo - }, - &mut to_ids, - &mut to_self, - ); + if let Some(field) = mime_parser.lookup_field("To") { + if let Ok(fld_to) = field.get_value() { + // dc_add_or_lookup_contacts_by_address_list( + // context, + // (*fld_to).to_addr_list, + // if 0 == incoming { + // Origin::OutgoingTo + // } else if incoming_origin.is_verified() { + // Origin::IncomingTo + // } else { + // Origin::IncomingUnknownTo + // }, + // &mut to_ids, + // &mut to_self, + // ); } } @@ -328,22 +326,21 @@ unsafe 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(field) = mime_parser.lookup_field_typ("Cc", MAILIMF_FIELD_CC) { - let fld_cc = (*field).fld_data.fld_cc; - if !fld_cc.is_null() { - dc_add_or_lookup_contacts_by_address_list( - context, - (*fld_cc).cc_addr_list, - if 0 == incoming { - Origin::OutgoingCc - } else if incoming_origin.is_verified() { - Origin::IncomingCc - } else { - Origin::IncomingUnknownCc - }, - to_ids, - std::ptr::null_mut(), - ); + if let Some(field) = mime_parser.lookup_field("Cc") { + if let Ok(fld_cc) = field.get_value() { + // dc_add_or_lookup_contacts_by_address_list( + // context, + // (*fld_cc).cc_addr_list, + // if 0 == incoming { + // Origin::OutgoingCc + // } else if incoming_origin.is_verified() { + // Origin::IncomingCc + // } else { + // Origin::IncomingUnknownCc + // }, + // to_ids, + // std::ptr::null_mut(), + // ); } } @@ -608,17 +605,15 @@ unsafe 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(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; - if !fld_in_reply_to.is_null() { - mime_in_reply_to = dc_str_from_clist((*(*field).fld_data.fld_in_reply_to).mid_list, " ") + if let Some(field) = mime_parser.lookup_field("In-Reply-To") { + if let Ok(raw) = field.get_value() { + mime_in_reply_to = raw; } } - if let Some(field) = mime_parser.lookup_field_typ("References", MAILIMF_FIELD_REFERENCES) { - let fld_references = (*field).fld_data.fld_references; - if !fld_references.is_null() { - mime_references = dc_str_from_clist((*(*field).fld_data.fld_references).mid_list, " ") + if let Some(field) = mime_parser.lookup_field("References") { + if let Ok(raw) = field.get_value() { + mime_references = raw; } } @@ -1002,43 +997,32 @@ unsafe fn create_or_lookup_group( } set_better_msg(mime_parser, &better_msg); - if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-ID") { - grpid = optional_field; + if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-ID") { + grpid = optional_field.get_value().unwrap_or_default(); } if grpid.is_empty() { - 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; - if !fld_message_id.is_null() { - if let Some(extracted_grpid) = - dc_extract_grpid_from_rfc724_mid(&to_string_lossy((*fld_message_id).mid_value)) - { - grpid = extracted_grpid.to_string(); - } else { - grpid = "".to_string(); - } + if let Some(field) = mime_parser.lookup_field("Message-ID") { + if let Ok(value) = field.get_value() { + // if let Some(extracted_grpid) = + // dc_extract_grpid_from_rfc724_mid(&to_string_lossy((*fld_message_id).mid_value)) + // { + // grpid = extracted_grpid.to_string(); + // } else { + // grpid = "".to_string(); + // } } } if grpid.is_empty() { - 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; - if !fld_in_reply_to.is_null() { - grpid = to_string_lossy(dc_extract_grpid_from_rfc724_mid_list( - (*fld_in_reply_to).mid_list, - )); + if let Some(field) = mime_parser.lookup_field("In-Reply-To") { + if let Ok(value) = field.get_value() { + grpid = value; } } if grpid.is_empty() { - if let Some(field) = - mime_parser.lookup_field_typ("References", MAILIMF_FIELD_REFERENCES) - { - let fld_references = (*field).fld_data.fld_references; - if !fld_references.is_null() { - grpid = to_string_lossy(dc_extract_grpid_from_rfc724_mid_list( - (*fld_references).mid_list, - )); + if let Some(field) = mime_parser.lookup_field("References") { + if let Ok(value) = field.get_value() { + grpid = value; } } @@ -1060,11 +1044,11 @@ unsafe fn create_or_lookup_group( } } - if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Name") { - grpname = Some(dc_decode_header_words(&optional_field)); + if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Name") { + grpname = Some(dc_decode_header_words(&optional_field.get_value().unwrap())); } - if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Member-Removed") { - X_MrRemoveFromGrp = Some(optional_field); + if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Member-Removed") { + X_MrRemoveFromGrp = optional_field.get_value().ok(); mime_parser.is_system_message = SystemMessage::MemberRemovedFromGroup; let left_group = (Contact::lookup_id_by_addr(context, X_MrRemoveFromGrp.as_ref().unwrap()) == from_id as u32) as libc::c_int; @@ -1079,11 +1063,11 @@ unsafe fn create_or_lookup_group( from_id as u32, ) } else { - if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Member-Added") { - X_MrAddToGrp = Some(optional_field); + if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Member-Added") { + X_MrAddToGrp = optional_field.get_value().ok(); mime_parser.is_system_message = SystemMessage::MemberAddedToGroup; - if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Image") { - X_MrGrpImageChanged = optional_field; + if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Image") { + X_MrGrpImageChanged = optional_field.get_value().unwrap(); } better_msg = context.stock_system_msg( StockMessage::MsgAddMember, @@ -1092,26 +1076,25 @@ unsafe fn create_or_lookup_group( from_id as u32, ) } else { - if let Some(optional_field) = - mime_parser.lookup_optional_field("Chat-Group-Name-Changed") - { + let field = mime_parser.lookup_field("Chat-Group-Name-Changed"); + if field.is_some() { X_MrGrpNameChanged = 1; - mime_parser.is_system_message = SystemMessage::GroupNameChanged; better_msg = context.stock_system_msg( StockMessage::MsgGrpName, - &optional_field, + &field.unwrap().get_value().unwrap(), if let Some(ref name) = grpname { name } else { "" }, from_id as u32, - ) + ); + drop(field); + mime_parser.is_system_message = SystemMessage::GroupNameChanged; } else { - if let Some(optional_field) = mime_parser.lookup_optional_field("Chat-Group-Image") - { + if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Image") { // fld_value is a pointer somewhere into mime_parser, must not be freed - X_MrGrpImageChanged = optional_field; + X_MrGrpImageChanged = optional_field.get_value().unwrap(); mime_parser.is_system_message = SystemMessage::GroupImageChanged; better_msg = context.stock_system_msg( if X_MrGrpImageChanged == "0" { @@ -1693,35 +1676,33 @@ fn set_better_msg(mime_parser: &mut MimeParser, better_msg: impl AsRef) { }; } -unsafe fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimeParser) -> libc::c_int { +fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimeParser) -> libc::c_int { /* 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 (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int { - let fld_in_reply_to = (*field).fld_data.fld_in_reply_to; - if !fld_in_reply_to.is_null() { - if is_known_rfc724_mid_in_list( - context, - (*(*field).fld_data.fld_in_reply_to).mid_list, - ) { - return 1; - } - } + if let Ok(value) = field.get_value() { + // if !fld_in_reply_to.is_null() { + // if is_known_rfc724_mid_in_list( + // context, + // (*(*field).fld_data.fld_in_reply_to).mid_list, + // ) { + // return 1; + // } + // } } } if let Some(field) = mime_parser.lookup_field("References") { - if (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int { - let fld_references = (*field).fld_data.fld_references; - if !fld_references.is_null() - && is_known_rfc724_mid_in_list( - context, - (*(*field).fld_data.fld_references).mid_list, - ) - { - return 1; - } + if let Ok(value) = field.get_value() { + // if !fld_references.is_null() + // && is_known_rfc724_mid_in_list( + // context, + // (*(*field).fld_data.fld_references).mid_list, + // ) + // { + // return 1; + // } } } @@ -1770,30 +1751,24 @@ unsafe fn dc_is_reply_to_messenger_message( - no check for the Chat-* headers (function is only called if it is no messenger message itself) */ if let Some(field) = mime_parser.lookup_field("In-Reply-To") { - if (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int { - let fld_in_reply_to = (*field).fld_data.fld_in_reply_to; - if !fld_in_reply_to.is_null() { - if 0 != is_msgrmsg_rfc724_mid_in_list( - context, - (*(*field).fld_data.fld_in_reply_to).mid_list, - ) { - return 1; - } - } + if let Ok(value) = field.get_value() { + // if 0 != is_msgrmsg_rfc724_mid_in_list( + // context, + // (*(*field).fld_data.fld_in_reply_to).mid_list, + // ) { + // return 1; + // } } } if let Some(field) = mime_parser.lookup_field("References") { - if (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int { - let fld_references: *mut mailimf_references = (*field).fld_data.fld_references; - if !fld_references.is_null() { - if 0 != is_msgrmsg_rfc724_mid_in_list( - context, - (*(*field).fld_data.fld_references).mid_list, - ) { - return 1; - } - } + if let Ok(value) = field.get_value() { + // if 0 != is_msgrmsg_rfc724_mid_in_list( + // context, + // (*(*field).fld_data.fld_references).mid_list, + // ) { + // return 1; + // } } } diff --git a/src/securejoin.rs b/src/securejoin.rs index d252bb811..59ba70e46 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -343,318 +343,319 @@ pub(crate) fn handle_securejoin_handshake( mimeparser: &MimeParser, contact_id: u32, ) -> Result { - let own_fingerprint: String; + unimplemented!() + // let own_fingerprint: String; - ensure!( - contact_id > DC_CONTACT_ID_LAST_SPECIAL, - "handle_securejoin_handshake(): called with special contact id" - ); - let step = match mimeparser.lookup_optional_field("Secure-Join") { - Some(s) => s, - None => { - bail!("This message is not a Secure-Join message"); - } - }; - info!( - context, - ">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received", step, - ); - let (contact_chat_id, contact_chat_id_blocked) = - chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not).unwrap_or_default(); + // ensure!( + // contact_id > DC_CONTACT_ID_LAST_SPECIAL, + // "handle_securejoin_handshake(): called with special contact id" + // ); + // let step = match mimeparser.lookup_optional_field("Secure-Join") { + // Some(s) => s, + // None => { + // bail!("This message is not a Secure-Join message"); + // } + // }; + // info!( + // context, + // ">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received", step, + // ); + // let (contact_chat_id, contact_chat_id_blocked) = + // chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not).unwrap_or_default(); - if contact_chat_id_blocked != Blocked::Not { - chat::unblock(context, contact_chat_id); - } - let join_vg = step.starts_with("vg-"); - let mut ret = HandshakeMessageStatus::default(); + // if contact_chat_id_blocked != Blocked::Not { + // chat::unblock(context, contact_chat_id); + // } + // let join_vg = step.starts_with("vg-"); + // let mut ret = HandshakeMessageStatus::default(); - match step.as_str() { - "vg-request" | "vc-request" => { - /* ========================================================= - ==== Alice - the inviter side ==== - ==== Step 3 in "Setup verified contact" protocol ==== - ========================================================= */ - // this message may be unencrypted (Bob, the joinder and the sender, might not have Alice's key yet) - // 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_optional_field("Secure-Join-Invitenumber") { - Some(n) => n, - None => { - warn!(context, "Secure-join denied (invitenumber missing).",); - return Ok(ret); - } - }; - if !token::exists(context, token::Namespace::InviteNumber, &invitenumber) { - warn!(context, "Secure-join denied (bad invitenumber).",); - return Ok(ret); - } - info!(context, "Secure-join requested.",); + // match step.as_str() { + // "vg-request" | "vc-request" => { + // /* ========================================================= + // ==== Alice - the inviter side ==== + // ==== Step 3 in "Setup verified contact" protocol ==== + // ========================================================= */ + // // this message may be unencrypted (Bob, the joinder and the sender, might not have Alice's key yet) + // // 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_optional_field("Secure-Join-Invitenumber") { + // Some(n) => n, + // None => { + // warn!(context, "Secure-join denied (invitenumber missing).",); + // return Ok(ret); + // } + // }; + // if !token::exists(context, token::Namespace::InviteNumber, &invitenumber) { + // warn!(context, "Secure-join denied (bad invitenumber).",); + // return Ok(ret); + // } + // info!(context, "Secure-join requested.",); - inviter_progress!(context, contact_id, 300); - send_handshake_msg( - context, - contact_chat_id, - &format!("{}-auth-required", &step[..2]), - "", - None, - "", - ); - } - "vg-auth-required" | "vc-auth-required" => { - let cond = { - let bob = context.bob.read().unwrap(); - let scan = bob.qr_scan.as_ref(); - scan.is_none() - || bob.expects != DC_VC_AUTH_REQUIRED - || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup - }; + // inviter_progress!(context, contact_id, 300); + // send_handshake_msg( + // context, + // contact_chat_id, + // &format!("{}-auth-required", &step[..2]), + // "", + // None, + // "", + // ); + // } + // "vg-auth-required" | "vc-auth-required" => { + // let cond = { + // let bob = context.bob.read().unwrap(); + // let scan = bob.qr_scan.as_ref(); + // scan.is_none() + // || bob.expects != DC_VC_AUTH_REQUIRED + // || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup + // }; - if cond { - warn!(context, "auth-required message out of sync.",); - // no error, just aborted somehow or a mail from another handshake - return Ok(ret); - } - let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string(); - let auth = get_qr_attr!(context, auth).to_string(); + // if cond { + // warn!(context, "auth-required message out of sync.",); + // // no error, just aborted somehow or a mail from another handshake + // return Ok(ret); + // } + // let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string(); + // let auth = get_qr_attr!(context, auth).to_string(); - if !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) { - could_not_establish_secure_connection( - context, - contact_chat_id, - if mimeparser.encrypted { - "No valid signature." - } else { - "Not encrypted." - }, - ); - ret.stop_ongoing_process = true; - ret.bob_securejoin_success = Some(false); - return Ok(ret); - } - if !fingerprint_equals_sender(context, &scanned_fingerprint_of_alice, contact_chat_id) { - could_not_establish_secure_connection( - context, - contact_chat_id, - "Fingerprint mismatch on joiner-side.", - ); - ret.stop_ongoing_process = true; - ret.bob_securejoin_success = Some(false); - return Ok(ret); - } - info!(context, "Fingerprint verified.",); - own_fingerprint = get_self_fingerprint(context).unwrap(); - joiner_progress!(context, contact_id, 400); - context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM; + // if !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) { + // could_not_establish_secure_connection( + // context, + // contact_chat_id, + // if mimeparser.encrypted { + // "No valid signature." + // } else { + // "Not encrypted." + // }, + // ); + // ret.stop_ongoing_process = true; + // ret.bob_securejoin_success = Some(false); + // return Ok(ret); + // } + // if !fingerprint_equals_sender(context, &scanned_fingerprint_of_alice, contact_chat_id) { + // could_not_establish_secure_connection( + // context, + // contact_chat_id, + // "Fingerprint mismatch on joiner-side.", + // ); + // ret.stop_ongoing_process = true; + // ret.bob_securejoin_success = Some(false); + // return Ok(ret); + // } + // info!(context, "Fingerprint verified.",); + // own_fingerprint = get_self_fingerprint(context).unwrap(); + // joiner_progress!(context, contact_id, 400); + // context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM; - send_handshake_msg( - context, - contact_chat_id, - &format!("{}-request-with-auth", &step[..2]), - auth, - Some(own_fingerprint), - if join_vg { - get_qr_attr!(context, text2).to_string() - } else { - "".to_string() - }, - ); - } - "vg-request-with-auth" | "vc-request-with-auth" => { - /* ============================================================ - ==== Alice - the inviter side ==== - ==== Steps 5+6 in "Setup verified contact" protocol ==== - ==== 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_optional_field("Secure-Join-Fingerprint") { - Some(fp) => fp, - None => { - could_not_establish_secure_connection( - context, - contact_chat_id, - "Fingerprint not provided.", - ); - return Ok(ret); - } - }; - if !encrypted_and_signed(mimeparser, &fingerprint) { - could_not_establish_secure_connection( - context, - contact_chat_id, - "Auth not encrypted.", - ); - return Ok(ret); - } - if !fingerprint_equals_sender(context, &fingerprint, contact_chat_id) { - could_not_establish_secure_connection( - context, - contact_chat_id, - "Fingerprint mismatch on inviter-side.", - ); - return Ok(ret); - } - 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_optional_field("Secure-Join-Auth") { - Some(auth) => auth, - None => { - could_not_establish_secure_connection( - context, - contact_chat_id, - "Auth not provided.", - ); - return Ok(ret); - } - }; - if !token::exists(context, token::Namespace::Auth, &auth_0) { - could_not_establish_secure_connection(context, contact_chat_id, "Auth invalid."); - return Ok(ret); - } - if mark_peer_as_verified(context, fingerprint).is_err() { - could_not_establish_secure_connection( - context, - contact_chat_id, - "Fingerprint mismatch on inviter-side.", - ); - return Ok(ret); - } - Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited); - info!(context, "Auth verified.",); - secure_connection_established(context, contact_chat_id); - emit_event!(context, Event::ContactsChanged(Some(contact_id))); - inviter_progress!(context, contact_id, 600); - if join_vg { - 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); - if group_chat_id == 0 { - error!(context, "Chat {} not found.", &field_grpid); - return Ok(ret); - } else { - if let Err(err) = - chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, true) - { - error!(context, "failed to add contact: {}", err); - } - } - } else { - send_handshake_msg(context, contact_chat_id, "vc-contact-confirm", "", None, ""); - inviter_progress!(context, contact_id, 1000); - } - } - "vg-member-added" | "vc-contact-confirm" => { - if join_vg { - ret.hide_this_msg = false; - } - if context.bob.read().unwrap().expects != DC_VC_CONTACT_CONFIRM { - info!(context, "Message belongs to a different handshake.",); - return Ok(ret); - } - let cond = { - let bob = context.bob.read().unwrap(); - let scan = bob.qr_scan.as_ref(); - scan.is_none() || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup - }; - if cond { - warn!( - context, - "Message out of sync or belongs to a different handshake.", - ); - return Ok(ret); - } - let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string(); + // send_handshake_msg( + // context, + // contact_chat_id, + // &format!("{}-request-with-auth", &step[..2]), + // auth, + // Some(own_fingerprint), + // if join_vg { + // get_qr_attr!(context, text2).to_string() + // } else { + // "".to_string() + // }, + // ); + // } + // "vg-request-with-auth" | "vc-request-with-auth" => { + // /* ============================================================ + // ==== Alice - the inviter side ==== + // ==== Steps 5+6 in "Setup verified contact" protocol ==== + // ==== 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_optional_field("Secure-Join-Fingerprint") { + // Some(fp) => fp, + // None => { + // could_not_establish_secure_connection( + // context, + // contact_chat_id, + // "Fingerprint not provided.", + // ); + // return Ok(ret); + // } + // }; + // if !encrypted_and_signed(mimeparser, &fingerprint) { + // could_not_establish_secure_connection( + // context, + // contact_chat_id, + // "Auth not encrypted.", + // ); + // return Ok(ret); + // } + // if !fingerprint_equals_sender(context, &fingerprint, contact_chat_id) { + // could_not_establish_secure_connection( + // context, + // contact_chat_id, + // "Fingerprint mismatch on inviter-side.", + // ); + // return Ok(ret); + // } + // 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_optional_field("Secure-Join-Auth") { + // Some(auth) => auth, + // None => { + // could_not_establish_secure_connection( + // context, + // contact_chat_id, + // "Auth not provided.", + // ); + // return Ok(ret); + // } + // }; + // if !token::exists(context, token::Namespace::Auth, &auth_0) { + // could_not_establish_secure_connection(context, contact_chat_id, "Auth invalid."); + // return Ok(ret); + // } + // if mark_peer_as_verified(context, fingerprint).is_err() { + // could_not_establish_secure_connection( + // context, + // contact_chat_id, + // "Fingerprint mismatch on inviter-side.", + // ); + // return Ok(ret); + // } + // Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited); + // info!(context, "Auth verified.",); + // secure_connection_established(context, contact_chat_id); + // emit_event!(context, Event::ContactsChanged(Some(contact_id))); + // inviter_progress!(context, contact_id, 600); + // if join_vg { + // 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); + // if group_chat_id == 0 { + // error!(context, "Chat {} not found.", &field_grpid); + // return Ok(ret); + // } else { + // if let Err(err) = + // chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, true) + // { + // error!(context, "failed to add contact: {}", err); + // } + // } + // } else { + // send_handshake_msg(context, contact_chat_id, "vc-contact-confirm", "", None, ""); + // inviter_progress!(context, contact_id, 1000); + // } + // } + // "vg-member-added" | "vc-contact-confirm" => { + // if join_vg { + // ret.hide_this_msg = false; + // } + // if context.bob.read().unwrap().expects != DC_VC_CONTACT_CONFIRM { + // info!(context, "Message belongs to a different handshake.",); + // return Ok(ret); + // } + // let cond = { + // let bob = context.bob.read().unwrap(); + // let scan = bob.qr_scan.as_ref(); + // scan.is_none() || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup + // }; + // if cond { + // warn!( + // context, + // "Message out of sync or belongs to a different handshake.", + // ); + // return Ok(ret); + // } + // let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string(); - let vg_expect_encrypted = if join_vg { - let group_id = get_qr_attr!(context, text2).to_string(); - let (_, is_verified_group, _) = chat::get_chat_id_by_grpid(context, group_id); - // when joining a non-verified group - // the vg-member-added message may be unencrypted - // when not all group members have keys or prefer encryption. - // So only expect encryption if this is a verified group - is_verified_group - } else { - // setup contact is always encrypted - true - }; - if vg_expect_encrypted - && !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) - { - could_not_establish_secure_connection( - context, - contact_chat_id, - "Contact confirm message not encrypted.", - ); - ret.bob_securejoin_success = Some(false); - return Ok(ret); - } + // let vg_expect_encrypted = if join_vg { + // let group_id = get_qr_attr!(context, text2).to_string(); + // let (_, is_verified_group, _) = chat::get_chat_id_by_grpid(context, group_id); + // // when joining a non-verified group + // // the vg-member-added message may be unencrypted + // // when not all group members have keys or prefer encryption. + // // So only expect encryption if this is a verified group + // is_verified_group + // } else { + // // setup contact is always encrypted + // true + // }; + // if vg_expect_encrypted + // && !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) + // { + // could_not_establish_secure_connection( + // context, + // contact_chat_id, + // "Contact confirm message not encrypted.", + // ); + // ret.bob_securejoin_success = Some(false); + // return Ok(ret); + // } - if mark_peer_as_verified(context, &scanned_fingerprint_of_alice).is_err() { - could_not_establish_secure_connection( - context, - contact_chat_id, - "Fingerprint mismatch on joiner-side.", - ); - return Ok(ret); - } - Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined); - emit_event!(context, Event::ContactsChanged(None)); - let cg_member_added = mimeparser - .lookup_optional_field("Chat-Group-Member-Added") - .unwrap_or_default(); - 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)."); - return Ok(ret); - } - secure_connection_established(context, contact_chat_id); - context.bob.write().unwrap().expects = 0; - if join_vg { - send_handshake_msg( - context, - contact_chat_id, - "vg-member-added-received", - "", - None, - "", - ); - } - ret.stop_ongoing_process = true; - ret.bob_securejoin_success = Some(true); - } - "vg-member-added-received" => { - /* ============================================================ - ==== Alice - the inviter side ==== - ==== Step 8 in "Out-of-band verified groups" protocol ==== - ============================================================ */ - if let Ok(contact) = Contact::get_by_id(context, contact_id) { - if contact.is_verified(context) == VerifiedStatus::Unverified { - warn!(context, "vg-member-added-received invalid.",); - return Ok(ret); - } - inviter_progress!(context, contact_id, 800); - inviter_progress!(context, contact_id, 1000); - 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); - context.call_cb(Event::SecurejoinMemberAdded { - chat_id: group_chat_id, - contact_id: contact_id, - }); - } else { - warn!(context, "vg-member-added-received invalid.",); - return Ok(ret); - } - } - _ => { - warn!(context, "invalid step: {}", step); - } - } - if ret.hide_this_msg { - ret.delete_this_msg = true; - } - Ok(ret) + // if mark_peer_as_verified(context, &scanned_fingerprint_of_alice).is_err() { + // could_not_establish_secure_connection( + // context, + // contact_chat_id, + // "Fingerprint mismatch on joiner-side.", + // ); + // return Ok(ret); + // } + // Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined); + // emit_event!(context, Event::ContactsChanged(None)); + // let cg_member_added = mimeparser + // .lookup_optional_field("Chat-Group-Member-Added") + // .unwrap_or_default(); + // 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)."); + // return Ok(ret); + // } + // secure_connection_established(context, contact_chat_id); + // context.bob.write().unwrap().expects = 0; + // if join_vg { + // send_handshake_msg( + // context, + // contact_chat_id, + // "vg-member-added-received", + // "", + // None, + // "", + // ); + // } + // ret.stop_ongoing_process = true; + // ret.bob_securejoin_success = Some(true); + // } + // "vg-member-added-received" => { + // /* ============================================================ + // ==== Alice - the inviter side ==== + // ==== Step 8 in "Out-of-band verified groups" protocol ==== + // ============================================================ */ + // if let Ok(contact) = Contact::get_by_id(context, contact_id) { + // if contact.is_verified(context) == VerifiedStatus::Unverified { + // warn!(context, "vg-member-added-received invalid.",); + // return Ok(ret); + // } + // inviter_progress!(context, contact_id, 800); + // inviter_progress!(context, contact_id, 1000); + // 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); + // context.call_cb(Event::SecurejoinMemberAdded { + // chat_id: group_chat_id, + // contact_id: contact_id, + // }); + // } else { + // warn!(context, "vg-member-added-received invalid.",); + // return Ok(ret); + // } + // } + // _ => { + // warn!(context, "invalid step: {}", step); + // } + // } + // if ret.hide_this_msg { + // ret.delete_this_msg = true; + // } + // Ok(ret) } fn secure_connection_established(context: &Context, contact_chat_id: u32) { From 1f8d2531cc68ad51693380daf9da63324eaafd58 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 28 Nov 2019 00:11:55 +0100 Subject: [PATCH 02/20] some things --- src/dc_mimeparser.rs | 99 +++++++++++++------------------------------- 1 file changed, 29 insertions(+), 70 deletions(-) diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index 920c8656c..5f9f94890 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -33,7 +33,7 @@ pub struct MimeParser<'a, 'b> { pub parts: Vec, mail: Option>, pub mimeroot: *mut Mailmime, - pub header: HashMap, + pub header: HashMap, pub header_root: *mut mailimf_fields, pub header_protected: *mut mailimf_fields, pub subject: Option, @@ -347,16 +347,10 @@ impl<'a, 'b> MimeParser<'a, 'b> { .as_ref() .unwrap_or_else(|| self.mail.as_ref().unwrap()); - let ctype = mailparse::parse_content_type( - &self - .lookup_field("Content-Type") - .unwrap() - .get_value() - .unwrap(), - ); + println!("ctype {:?}", mail.ctype); - if let Some(protected_headers) = ctype.params.get("protected-headers") { - if mail.subparts.is_empty() && ctype.mimetype == "text/rfc822-headers" { + if mail.ctype.params.get("protected-headers").is_some() { + if mail.subparts.is_empty() && mail.ctype.mimetype == "text/rfc822-headers" { info!( self.context, "Protected headers found in text/rfc822-headers attachment: Will be ignored.", @@ -365,23 +359,18 @@ impl<'a, 'b> MimeParser<'a, 'b> { } if self.header_protected.is_null() { - // TODO: + // use the most outer protected header - this is typically + // created in sync with the normal, unprotected header - // /* use the most outer protected header - this is typically - // created in sync with the normal, unprotected header */ - // let mut dummy = 0; - // if mailimf_envelope_and_optional_fields_parse( - // mime.mm_mime_start, - // mime.mm_length, - // &mut dummy, - // &mut self.header_protected, - // ) != MAILIMF_NO_ERROR as libc::c_int - // || self.header_protected.is_null() - // { - // warn!(self.context, "Protected headers parsing error.",); - // } else { - // hash_header(&mut self.header, self.header_protected); - // } + if let Some(part) = mail.subparts.first() { + let raw = part.get_body_raw().unwrap(); + if let Ok((protected_headers, _)) = mailparse::parse_headers(&raw) { + drop(mail); // I have won against the borrow checker!!!!11 + hash_header(&mut self.header, &protected_headers); + } else { + warn!(self.context, "Protected headers parsing error.",); + } + } } else { info!( self.context, @@ -390,6 +379,10 @@ impl<'a, 'b> MimeParser<'a, 'b> { } } + let mail = omail + .as_ref() + .unwrap_or_else(|| self.mail.as_ref().unwrap()); + // single = multipart/* only one // multiple = multipart/* multiple // message = text/rfc822 @@ -554,11 +547,13 @@ impl<'a, 'b> MimeParser<'a, 'b> { // } // any_part_added - unimplemented!() + // unimplemented!() + false } fn add_single_part_if_known(&mut self, omail: Option>) -> bool { - unimplemented!() + false + // unimplemented!() // // return true if a part was added // let (mime_type, msg_type, raw_mime) = mailmime_get_mime_type(mime); @@ -900,50 +895,14 @@ pub struct Part { pub param: Params, } -unsafe fn hash_header(out: &mut HashMap, in_0: *const mailimf_fields) { - if in_0.is_null() { - return; - } - - for cur in (*(*in_0).fld_list).into_iter() { - let field = cur as *mut mailimf_field; - // TODO match on enums /rtn - - let key = match (*field).fld_type as libc::c_uint { - MAILIMF_FIELD_RETURN_PATH => Some("Return-Path".to_string()), - MAILIMF_FIELD_ORIG_DATE => Some("Date".to_string()), - MAILIMF_FIELD_FROM => Some("From".to_string()), - MAILIMF_FIELD_SENDER => Some("Sender".to_string()), - MAILIMF_FIELD_REPLY_TO => Some("Reply-To".to_string()), - MAILIMF_FIELD_TO => Some("To".to_string()), - MAILIMF_FIELD_CC => Some("Cc".to_string()), - MAILIMF_FIELD_BCC => Some("Bcc".to_string()), - MAILIMF_FIELD_MESSAGE_ID => Some("Message-ID".to_string()), - MAILIMF_FIELD_IN_REPLY_TO => Some("In-Reply-To".to_string()), - MAILIMF_FIELD_REFERENCES => Some("References".to_string()), - MAILIMF_FIELD_SUBJECT => Some("Subject".to_string()), - MAILIMF_FIELD_OPTIONAL_FIELD => { - // MAILIMF_FIELD_OPTIONAL_FIELD - let optional_field = (*field).fld_data.fld_optional_field; - // XXX the optional field sometimes contains invalid UTF8 - // which should not happen (according to the mime standard). - // This might point to a bug in our mime parsing/processing - // logic. As mmime/dc_mimeparser is scheduled fore replacement - // anyway we just use a lossy conversion. - - if !optional_field.is_null() { - Some(to_string_lossy((*optional_field).fld_name)) - } else { - None - } - } - _ => None, - }; - if let Some(key) = key { +fn hash_header(out: &mut HashMap, fields: &[mailparse::MailHeader<'_>]) { + for field in fields { + if let Ok(key) = field.get_key() { if !out.contains_key(&key) || // key already exists, only overwrite known types (protected headers) - (*field).fld_type != MAILIMF_FIELD_OPTIONAL_FIELD as i32 || key.starts_with("Chat-") + key.starts_with("Chat-") { - out.insert(key, field); + // TODO: only overwrite known fields + out.insert(key, field.get_value().unwrap()); } } } From dbd63038290df12df3e8e577be2119559de37674 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 28 Nov 2019 19:20:43 +0100 Subject: [PATCH 03/20] remove mmime --- Cargo.lock | 500 ++- Cargo.toml | 5 +- examples/repl/cmdline.rs | 2 +- mmime/.circleci/config.yml | 42 - mmime/Cargo.toml | 23 - mmime/LICENSE-APACHE | 201 - mmime/LICENSE-MIT | 23 - mmime/LICENSE.md | 4 - mmime/README.md | 16 - mmime/src/charconv.rs | 32 - mmime/src/chash.rs | 427 -- mmime/src/clist.rs | 202 - mmime/src/constants.rs | 71 - mmime/src/display.rs | 386 -- mmime/src/lib.rs | 78 - mmime/src/mailimf/mod.rs | 5921 --------------------------- mmime/src/mailimf/types.rs | 1196 ------ mmime/src/mailimf/types_helper.rs | 89 - mmime/src/mailimf/write_generic.rs | 1985 --------- mmime/src/mailmime/content.rs | 2357 ----------- mmime/src/mailmime/decode.rs | 860 ---- mmime/src/mailmime/disposition.rs | 583 --- mmime/src/mailmime/mod.rs | 1143 ------ mmime/src/mailmime/types.rs | 891 ---- mmime/src/mailmime/types_helper.rs | 1445 ------- mmime/src/mailmime/write_generic.rs | 1979 --------- mmime/src/mailmime/write_mem.rs | 82 - mmime/src/mmapstring.rs | 397 -- mmime/src/other.rs | 1728 -------- src/aheader.rs | 47 +- src/chat.rs | 2 +- src/dc_mimeparser.rs | 1239 ------ src/dc_receive_imf.rs | 626 +-- src/dc_strencode.rs | 62 - src/dc_tools.rs | 132 +- src/e2ee.rs | 816 ++-- src/error.rs | 8 + src/imap.rs | 4 +- src/imex.rs | 2 +- src/job.rs | 11 +- src/lib.rs | 4 +- src/location.rs | 2 +- src/message.rs | 2 +- src/mimefactory.rs | 1198 +++--- src/mimeparser.rs | 1053 +++++ src/param.rs | 2 +- src/securejoin.rs | 2 +- src/wrapmime.rs | 680 +-- 48 files changed, 2746 insertions(+), 25814 deletions(-) delete mode 100644 mmime/.circleci/config.yml delete mode 100644 mmime/Cargo.toml delete mode 100644 mmime/LICENSE-APACHE delete mode 100644 mmime/LICENSE-MIT delete mode 100644 mmime/LICENSE.md delete mode 100644 mmime/README.md delete mode 100644 mmime/src/charconv.rs delete mode 100644 mmime/src/chash.rs delete mode 100644 mmime/src/clist.rs delete mode 100644 mmime/src/constants.rs delete mode 100644 mmime/src/display.rs delete mode 100644 mmime/src/lib.rs delete mode 100644 mmime/src/mailimf/mod.rs delete mode 100644 mmime/src/mailimf/types.rs delete mode 100644 mmime/src/mailimf/types_helper.rs delete mode 100644 mmime/src/mailimf/write_generic.rs delete mode 100644 mmime/src/mailmime/content.rs delete mode 100644 mmime/src/mailmime/decode.rs delete mode 100644 mmime/src/mailmime/disposition.rs delete mode 100644 mmime/src/mailmime/mod.rs delete mode 100644 mmime/src/mailmime/types.rs delete mode 100644 mmime/src/mailmime/types_helper.rs delete mode 100644 mmime/src/mailmime/write_generic.rs delete mode 100644 mmime/src/mailmime/write_mem.rs delete mode 100644 mmime/src/mmapstring.rs delete mode 100644 mmime/src/other.rs delete mode 100644 src/dc_mimeparser.rs create mode 100644 src/mimeparser.rs diff --git a/Cargo.lock b/Cargo.lock index cd6d60e4b..383cf3e49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.23" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -84,7 +84,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -93,13 +93,13 @@ version = "0.1.1" source = "git+https://github.com/async-email/async-imap#377d40837028b454c6365ff13e3f35cc341a908e" dependencies = [ "async-attributes 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "async-std 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "async-tls 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures_codec 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures_codec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "imap-proto 0.9.1 (git+https://github.com/djc/tokio-imap)", "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -118,7 +118,7 @@ dependencies = [ [[package]] name = "async-std" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -133,7 +133,7 @@ dependencies = [ "kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -166,7 +166,7 @@ name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -181,8 +181,8 @@ version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -192,7 +192,16 @@ version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -360,9 +369,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -391,7 +400,7 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -405,10 +414,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -459,8 +467,8 @@ dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -476,7 +484,7 @@ name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -502,7 +510,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -522,7 +530,7 @@ name = "crossbeam-utils" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -532,7 +540,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -550,7 +558,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -562,7 +570,7 @@ dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -611,14 +619,14 @@ name = "deltachat" version = "1.0.0-beta.8" dependencies = [ "async-imap 0.1.1 (git+https://github.com/async-email/async-imap)", - "async-std 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "async-tls 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "debug_stub_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "deltachat_derive 0.1.0", "escaper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -630,9 +638,9 @@ dependencies = [ "jetscii 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "mailparse 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mmime 0.1.2", + "lettre_email 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mailparse 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -641,7 +649,7 @@ dependencies = [ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)", "quick-xml 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "r2d2 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "r2d2 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "r2d2_sqlite 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -650,8 +658,8 @@ dependencies = [ "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sanitize-filename 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "stop-token 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -689,7 +697,7 @@ dependencies = [ "deltachat 1.0.0-beta.8", "deltachat-provider-database 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -755,7 +763,7 @@ name = "dirs" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -783,12 +791,83 @@ name = "either" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "email" +version = "0.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "encoding_rs" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -841,7 +920,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -873,9 +952,9 @@ name = "flate2" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -982,7 +1061,7 @@ dependencies = [ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1036,12 +1115,13 @@ dependencies = [ [[package]] name = "futures_codec" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1057,8 +1137,8 @@ name = "getrandom" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1081,7 +1161,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1102,7 +1182,7 @@ name = "hermit-abi" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1115,13 +1195,13 @@ name = "hostname" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "http" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1136,7 +1216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1153,8 +1233,8 @@ dependencies = [ "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "os_type 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1178,7 +1258,7 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1189,12 +1269,12 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1270,7 +1350,7 @@ name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1342,19 +1422,32 @@ dependencies = [ "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustls-connector 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lettre_email" +version = "0.9.2" +source = "git+https://github.com/deltachat/lettre?branch=feat/rustls#a422872e92e8cf089bdfb24489f3446f9865ba19" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "email 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lexical-core" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1362,7 +1455,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.65" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1387,7 +1480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lock_api" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1398,7 +1491,7 @@ name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1414,12 +1507,12 @@ name = "mach" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mailparse" -version = "0.9.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1452,15 +1545,6 @@ name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memoffset" version = "0.5.3" @@ -1493,15 +1577,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1515,8 +1599,8 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1530,26 +1614,13 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "mmime" -version = "0.1.2" -dependencies = [ - "charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1560,8 +1631,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1602,7 +1673,7 @@ dependencies = [ "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1650,7 +1721,7 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1684,7 +1755,7 @@ name = "packed_simd" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1692,25 +1763,47 @@ name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "percent-encoding" version = "1.0.1" @@ -1736,7 +1829,7 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "cast5 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfb-mode 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "circular 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "crc24 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1768,6 +1861,24 @@ dependencies = [ "zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pin-project" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pin-project-lite" version = "0.1.1" @@ -1804,7 +1915,7 @@ name = "pretty_env_logger" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1816,7 +1927,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1924,12 +2035,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "r2d2" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scheduled-thread-pool 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scheduled-thread-pool 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1937,7 +2048,7 @@ name = "r2d2_sqlite" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "r2d2 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "r2d2 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1947,7 +2058,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1959,7 +2070,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1978,7 +2089,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2052,7 +2163,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2064,7 +2175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2151,7 +2262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2166,23 +2277,23 @@ dependencies = [ "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2196,7 +2307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2226,7 +2337,7 @@ dependencies = [ "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2306,7 +2417,7 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2345,10 +2456,10 @@ dependencies = [ [[package]] name = "scheduled-thread-pool" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2371,7 +2482,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2381,30 +2492,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2414,7 +2525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2462,7 +2573,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2477,7 +2588,7 @@ name = "slice-deque" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2520,7 +2631,7 @@ name = "stop-token" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "async-std 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2558,12 +2669,12 @@ dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "subtle" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2598,7 +2709,7 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2621,7 +2732,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2639,8 +2750,8 @@ name = "tempfile" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2684,7 +2795,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2696,15 +2807,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2723,12 +2834,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2747,18 +2858,18 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2793,9 +2904,9 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2811,18 +2922,18 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2830,7 +2941,7 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2848,7 +2959,7 @@ name = "try_from" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2958,7 +3069,7 @@ name = "uuid" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2995,7 +3106,7 @@ name = "wait-timeout" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3028,7 +3139,7 @@ name = "wasm-bindgen" version = "0.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-macro 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3042,7 +3153,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3062,7 +3173,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3077,12 +3188,12 @@ name = "wasm-bindgen-webidl" version = "0.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "anyhow 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3092,7 +3203,7 @@ name = "web-sys" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "anyhow 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3244,7 +3355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3255,7 +3366,7 @@ dependencies = [ "checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum anyhow 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1072d8f55592084072d2d3cb23a4b680a8543c00f10d446118e85ad3718142" +"checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" @@ -3263,7 +3374,7 @@ dependencies = [ "checksum async-attributes 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "efd3d156917d94862e779f356c5acae312b08fd3121e792c857d7928c8088423" "checksum async-imap 0.1.1 (git+https://github.com/async-email/async-imap)" = "" "checksum async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "644a5a8de80f2085a1e7e57cd1544a2a7438f6e003c0790999bd43b92a77cdb2" -"checksum async-std 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56933da6903b273923d13f4746d829f66ff9b444173f6743d831e80f4da15446" +"checksum async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "513ee3c49800679a319912340f5601afda9e72848d7dea3a48bab489e8c1a46f" "checksum async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de6bd58f7b9cc49032559422595c81cbfcf04db2f2133592f70af19e258a1ced" "checksum async-tls 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce6977f57fa68da77ffe5542950d47e9c23d65f5bc7cb0a9f8700996913eec7" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" @@ -3272,6 +3383,7 @@ dependencies = [ "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" "checksum bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" @@ -3295,9 +3407,9 @@ dependencies = [ "checksum cast5 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ce5759b4c52ca74f9a98421817c882f1fd9b0071ae41cd61ab9f9d059c04fd6" "checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" "checksum cfb-mode 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "190e7b55d3a27cf8879becf61035a141cbc783f3258a41d16d1706719f991345" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4f426e64df1c3de26cbf44593c6ffff5dbfd43bbf9de0d075058558126b3fc73" -"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" +"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum circular 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0fc239e0f6cb375d2402d48afb92f76f5404fd1df208a41930ec81eda078bea" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -3330,6 +3442,14 @@ dependencies = [ "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)" = "845aaacc16f01178f33349e7c992ecd0cee095aa5e577f0f4dee35971bd36455" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +"checksum email 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4" +"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)" = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9" "checksum entities 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" @@ -3362,7 +3482,7 @@ dependencies = [ "checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" "checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" "checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" -"checksum futures_codec 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8efb8edac092482013e203af800eef158349c8bbf461edff59c5dd2d3c00e87" +"checksum futures_codec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b4043054a6220de5dc5c814eb82ab6fd7cd2b6574a844406f651ec688cfa6fcc" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" @@ -3372,7 +3492,7 @@ dependencies = [ "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" "checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" -"checksum http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e06e336150b178206af098a055e3621e8336027e2b4d126bda0bc64824baaf" +"checksum http 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "2790658cddc82e82b08e25176c431d7015a0adeb1718498715cbd20138a0bf68" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21638c5955a6daf3ecc42cae702335fc37a72a4abcc6959ce457b31a7d43bbdd" @@ -3395,26 +3515,26 @@ dependencies = [ "checksum kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)" = "" +"checksum lettre_email 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)" = "" "checksum lexical-core 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2304bccb228c4b020f3a4835d247df0a02a7c4686098d4167762cfbbe4c5cb14" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" "checksum libsqlite3-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5b95e89c330291768dc840238db7f9e204fd208511ab6319b56193a7f2ae25" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +"checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" -"checksum mailparse 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "51a60bad00d8aa905d31cf239f207ad4ef16c963ea53cf522d5fd7dc7f3ecfe2" +"checksum mailparse 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c00eb97cc18f08aaadd02808328dcc9be94948d8e5b54adbfd3414d2f87f7bf1" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" "checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" "checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" -"checksum mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)" = "72f4261ee7ab03cd36dc99eea4db8be6e83e4164da470e0c84f6726d6c605855" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" @@ -3433,11 +3553,15 @@ dependencies = [ "checksum os_type 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7edc011af0ae98b7f88cf7e4a83b70a54a75d2b8cb013d6efd02e5956207e9eb" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" +"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum pgp 0.3.2 (git+https://github.com/rpgp/rpgp)" = "" +"checksum pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469" +"checksum pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355" "checksum pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" "checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" @@ -3457,7 +3581,7 @@ dependencies = [ "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum quoted_printable 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86cedf331228892e747bb85beb130b6bb23fc628c40dde9ea01eb6becea3c798" -"checksum r2d2 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e48fa64898ef0286b6ee4b4d8f61483f9182acf5e44e62a398b1c7f56f2f861d" +"checksum r2d2 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "22b5c5fc5fba064373f03887337b412e0e1562d63023393db77251146cb75553" "checksum r2d2_sqlite 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "806e268035ce9e5a604bf617ac8a073ef28b59ef2e48e8338db0baf530caef33" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" @@ -3498,14 +3622,14 @@ dependencies = [ "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum sanitize-filename 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23fd0fec94ec480abfd86bb8f4f6c57e0efb36dac5c852add176ea7b04c74801" -"checksum scheduled-thread-pool 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd07742e081ff6c077f5f6b283f12f32b9e7cc765b316160d66289b74546fbb3" +"checksum scheduled-thread-pool 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f5de7bc31f28f8e6c28df5e1bf3d10610f5fdc14cc95f272853512c70a2bd779" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" -"checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8" -"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" +"checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" +"checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" +"checksum serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" @@ -3525,11 +3649,11 @@ dependencies = [ "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum strum 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6138f8f88a16d90134763314e3fc76fa3ed6a7db4725d6acf9a3ef95a3188d22" "checksum strum_macros 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0054a7df764039a6cd8592b9de84be4bec368ff081d203a7d5371cbfa8e65c81" -"checksum subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab3af2eb31c42e8f0ccf43548232556c42737e01a96db6e1777b0be108e79799" +"checksum subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" +"checksum syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f89693ae015201f8de93fd96bde2d065f8bfc3f97ce006d5bc9f900b97c0c7c0" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" @@ -3542,14 +3666,14 @@ dependencies = [ "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" +"checksum tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ca6df436c42b0c3330a82d855d2ef017cd793090ad550a6bc2184f4b933532ab" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" +"checksum tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6732fe6b53c8d11178dcb77ac6d9682af27fc6d4cb87789449152e5377377146" "checksum tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1df2fa53ac211c136832f530ccb081af9af891af22d685a9493e232c7a359bc2" "checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" -"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1739638e364e558128461fc1ad84d997702c8e31c2e6b18fb99842268199e827" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" diff --git a/Cargo.toml b/Cargo.toml index 9aee209b4..c85dfccfd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ license = "MPL" [dependencies] deltachat_derive = { path = "./deltachat_derive" } -mmime = { version = "0.1.2", path = "./mmime" } libc = "0.2.51" pgp = { git = "https://github.com/rpgp/rpgp", branch = "master", default-features = false } @@ -19,6 +18,7 @@ reqwest = { version = "0.9.15", default-features = false, features = ["rustls-tl num-derive = "0.2.5" num-traits = "0.2.6" lettre = { git = "https://github.com/deltachat/lettre", branch = "feat/rustls" } +lettre_email = { git = "https://github.com/deltachat/lettre", branch = "feat/rustls" } async-imap = { git = "https://github.com/async-email/async-imap", branch="master" } async-tls = "0.6" async-std = { version = "1.0", features = ["unstable"] } @@ -54,7 +54,7 @@ stop-token = { version = "0.1.1", features = ["unstable"] } rustls = "0.16.0" webpki-roots = "0.18.0" webpki = "0.21.0" -mailparse = "0.9.2" +mailparse = "0.10.1" [dev-dependencies] tempfile = "3.0" @@ -66,7 +66,6 @@ proptest = "0.9.4" members = [ "deltachat-ffi", "deltachat_derive", - "mmime", ] [[example]] diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index d7776d557..a90ac0785 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -95,7 +95,7 @@ pub unsafe fn dc_reset_tables(context: &Context, bits: i32) -> i32 { fn dc_poke_eml_file(context: &Context, filename: impl AsRef) -> Result<(), Error> { let data = dc_read_file(context, filename)?; - unsafe { dc_receive_imf(context, &data, "import", 0, 0) }; + dc_receive_imf(context, &data, "import", 0, 0); Ok(()) } diff --git a/mmime/.circleci/config.yml b/mmime/.circleci/config.yml deleted file mode 100644 index 74a108d88..000000000 --- a/mmime/.circleci/config.yml +++ /dev/null @@ -1,42 +0,0 @@ -# copied from http://koushiro.me/2019/04/30/Building-and-Testing-Rust-projects-on-CircleCI/ - -version: 2.1 -jobs: - build: - docker: - - image: ubuntu:18.04 - - working_directory: ~/deltachat-core-rust - - steps: - - checkout - - - run: - name: Setup build environment - command: | - apt update - apt install -y curl build-essential autoconf libtool git python pkg-config - # this will pick default toolchain from `rust-toolchain` file - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --no-modify-path --default-toolchain none -y; - source $HOME/.cargo/env - no_output_timeout: 1800s - - - run: - name: Format - command: | - export PATH=~/.cargo/bin:$PATH - rustup component add rustfmt - cargo fmt -- --check - - - run: - name: Test - command: | - export PATH=~/.cargo/bin:$PATH - export RUST_BACKTRACE=1 - cargo test - -workflows: - version: 2.1 - build: - jobs: - - build diff --git a/mmime/Cargo.toml b/mmime/Cargo.toml deleted file mode 100644 index 6a3bcadde..000000000 --- a/mmime/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "mmime" -version = "0.1.2" -authors = ["dignifiedquire "] -edition = "2018" -license = "MIT OR Apache-2.0" -homepage = "https://github.com/deltachat/deltachat-core-rust" -repository = "https://github.com/deltachat/deltachat-core-rust" -readme = "README.md" -description = "Mime parsing for email" - - -keywords = ["mail", "mim", "email", "imap", "smtp"] -categories = ["std", "email"] - -[dependencies] -libc = "0.2.54" -charset = "0.1.2" -memmap = "0.7.0" -lazy_static = "1.3.0" -rand = "0.6.5" -chrono = "0.4.6" -hex = "0.4.0" diff --git a/mmime/LICENSE-APACHE b/mmime/LICENSE-APACHE deleted file mode 100644 index f8e5e5ea0..000000000 --- a/mmime/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/mmime/LICENSE-MIT b/mmime/LICENSE-MIT deleted file mode 100644 index 468cd79a8..000000000 --- a/mmime/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/mmime/LICENSE.md b/mmime/LICENSE.md deleted file mode 100644 index 878517643..000000000 --- a/mmime/LICENSE.md +++ /dev/null @@ -1,4 +0,0 @@ -This library is primarly distributed under the terms of both the MIT license and -the Apache License (Version 2.0). - -See LICENSE-MIT and LICENSE-APACHE for details. diff --git a/mmime/README.md b/mmime/README.md deleted file mode 100644 index 16858f979..000000000 --- a/mmime/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# mmime - -[![CircleCI build status][circle-shield]][circle] [![Appveyor build status][appveyor-shield]][appveyor] [![License][license-shield]][license] - -> mmmmmmime parsing - -Base code was compiled using c2rust from libetpan. - - - -[circle-shield]: https://img.shields.io/circleci/project/github/dignifiedquire/mmime/master.svg?style=flat-square -[circle]: https://circleci.com/gh/dignifiedquire/mmime/ -[appveyor-shield]: https://ci.appveyor.com/api/projects/status/l26co5rba32knrlu/branch/master?style=flat-square -[appveyor]: https://ci.appveyor.com/project/dignifiedquire/mmime/branch/master -[license-shield]: https://img.shields.io/badge/License-MIT%2FApache2.0-green.svg?style=flat-square -[license]: https://github.com/rpgp/rpgp/blob/master/LICENSE.md diff --git a/mmime/src/charconv.rs b/mmime/src/charconv.rs deleted file mode 100644 index cbb6eca40..000000000 --- a/mmime/src/charconv.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::other::*; -use libc; -use std::ffi::{CStr, CString}; - -pub const MAIL_CHARCONV_ERROR_CONV: libc::c_uint = 3; -pub const MAIL_CHARCONV_ERROR_MEMORY: libc::c_uint = 2; -pub const MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: libc::c_uint = 1; -pub const MAIL_CHARCONV_NO_ERROR: libc::c_uint = 0; - -pub unsafe fn charconv( - tocode: *const libc::c_char, - fromcode: *const libc::c_char, - s: *const libc::c_char, - length: size_t, - result: *mut *mut libc::c_char, -) -> libc::c_int { - assert!(!fromcode.is_null(), "invalid fromcode"); - assert!(!s.is_null(), "invalid input string"); - if let Some(encoding) = - charset::Charset::for_label(CStr::from_ptr(fromcode).to_string_lossy().as_bytes()) - { - let data = std::slice::from_raw_parts(s as *const u8, strlen(s)); - - let (res, _, _) = encoding.decode(data); - let res_c = CString::new(res.as_bytes()).unwrap_or_default(); - *result = strdup(res_c.as_ptr()) as *mut _; - - MAIL_CHARCONV_NO_ERROR as libc::c_int - } else { - MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET as libc::c_int - } -} diff --git a/mmime/src/chash.rs b/mmime/src/chash.rs deleted file mode 100644 index 301b35ae9..000000000 --- a/mmime/src/chash.rs +++ /dev/null @@ -1,427 +0,0 @@ -use libc; - -use crate::other::*; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct chashdatum { - pub data: *mut libc::c_void, - pub len: libc::c_uint, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct chash { - pub size: libc::c_uint, - pub count: libc::c_uint, - pub copyvalue: libc::c_int, - pub copykey: libc::c_int, - pub cells: *mut *mut chashcell, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct chashcell { - pub func: libc::c_uint, - pub key: chashdatum, - pub value: chashdatum, - pub next: *mut chashcell, -} - -pub type chashiter = chashcell; -/* Allocates a new (empty) hash using this initial size and the given flags, - specifying which data should be copied in the hash. - CHASH_COPYNONE : Keys/Values are not copied. - CHASH_COPYKEY : Keys are dupped and freed as needed in the hash. - CHASH_COPYVALUE : Values are dupped and freed as needed in the hash. - CHASH_COPYALL : Both keys and values are dupped in the hash. -*/ -pub unsafe fn chash_new(mut size: libc::c_uint, mut flags: libc::c_int) -> *mut chash { - let mut h: *mut chash = 0 as *mut chash; - h = malloc(::std::mem::size_of::() as libc::size_t) as *mut chash; - if h.is_null() { - return 0 as *mut chash; - } - if size < 13i32 as libc::c_uint { - size = 13i32 as libc::c_uint - } - (*h).count = 0i32 as libc::c_uint; - (*h).cells = calloc( - size as libc::size_t, - ::std::mem::size_of::<*mut chashcell>() as libc::size_t, - ) as *mut *mut chashcell; - if (*h).cells.is_null() { - free(h as *mut libc::c_void); - return 0 as *mut chash; - } - (*h).size = size; - (*h).copykey = flags & 1i32; - (*h).copyvalue = flags & 2i32; - return h; -} - -/* Frees a hash */ -pub unsafe fn chash_free(mut hash: *mut chash) { - let mut indx: libc::c_uint = 0; - let mut iter: *mut chashiter = 0 as *mut chashiter; - let mut next: *mut chashiter = 0 as *mut chashiter; - indx = 0i32 as libc::c_uint; - while indx < (*hash).size { - iter = *(*hash).cells.offset(indx as isize); - while !iter.is_null() { - next = (*iter).next; - if 0 != (*hash).copykey { - free((*iter).key.data); - } - if 0 != (*hash).copyvalue { - free((*iter).value.data); - } - free(iter as *mut libc::c_void); - iter = next - } - indx = indx.wrapping_add(1) - } - free((*hash).cells as *mut libc::c_void); - free(hash as *mut libc::c_void); -} - -/* Removes all elements from a hash */ -pub unsafe fn chash_clear(mut hash: *mut chash) { - let mut indx: libc::c_uint = 0; - let mut iter: *mut chashiter = 0 as *mut chashiter; - let mut next: *mut chashiter = 0 as *mut chashiter; - indx = 0i32 as libc::c_uint; - while indx < (*hash).size { - iter = *(*hash).cells.offset(indx as isize); - while !iter.is_null() { - next = (*iter).next; - if 0 != (*hash).copykey { - free((*iter).key.data); - } - if 0 != (*hash).copyvalue { - free((*iter).value.data); - } - free(iter as *mut libc::c_void); - iter = next - } - indx = indx.wrapping_add(1) - } - memset( - (*hash).cells as *mut libc::c_void, - 0i32, - ((*hash).size as libc::size_t) - .wrapping_mul(::std::mem::size_of::<*mut chashcell>() as libc::size_t), - ); - (*hash).count = 0i32 as libc::c_uint; -} -/* Adds an entry in the hash table. -Length can be 0 if key/value are strings. -If an entry already exists for this key, it is replaced, and its value -is returned. Otherwise, the data pointer will be NULL and the length -field be set to TRUE or FALSe to indicate success or failure. */ -pub unsafe fn chash_set( - mut hash: *mut chash, - mut key: *mut chashdatum, - mut value: *mut chashdatum, - mut oldvalue: *mut chashdatum, -) -> libc::c_int { - let mut current_block: u64; - let mut func: libc::c_uint = 0; - let mut indx: libc::c_uint = 0; - let mut iter: *mut chashiter = 0 as *mut chashiter; - let mut cell: *mut chashiter = 0 as *mut chashiter; - let mut r: libc::c_int = 0; - if (*hash).count > (*hash).size.wrapping_mul(3i32 as libc::c_uint) { - r = chash_resize( - hash, - (*hash) - .count - .wrapping_div(3i32 as libc::c_uint) - .wrapping_mul(2i32 as libc::c_uint) - .wrapping_add(1i32 as libc::c_uint), - ); - if r < 0i32 { - current_block = 17701753836843438419; - } else { - current_block = 7095457783677275021; - } - } else { - current_block = 7095457783677275021; - } - match current_block { - 7095457783677275021 => { - func = chash_func((*key).data as *const libc::c_char, (*key).len); - indx = func.wrapping_rem((*hash).size); - iter = *(*hash).cells.offset(indx as isize); - loop { - if iter.is_null() { - current_block = 17788412896529399552; - break; - } - if (*iter).key.len == (*key).len - && (*iter).func == func - && 0 == memcmp((*iter).key.data, (*key).data, (*key).len as libc::size_t) - { - /* found, replacing entry */ - if 0 != (*hash).copyvalue { - let mut data: *mut libc::c_char = 0 as *mut libc::c_char; - data = chash_dup((*value).data, (*value).len); - if data.is_null() { - current_block = 17701753836843438419; - break; - } - free((*iter).value.data); - (*iter).value.data = data as *mut libc::c_void; - (*iter).value.len = (*value).len - } else { - if !oldvalue.is_null() { - (*oldvalue).data = (*iter).value.data; - (*oldvalue).len = (*iter).value.len - } - (*iter).value.data = (*value).data; - (*iter).value.len = (*value).len - } - if 0 == (*hash).copykey { - (*iter).key.data = (*key).data - } - if !oldvalue.is_null() { - (*oldvalue).data = (*value).data; - (*oldvalue).len = (*value).len - } - return 0i32; - } else { - iter = (*iter).next - } - } - match current_block { - 17701753836843438419 => {} - _ => { - if !oldvalue.is_null() { - (*oldvalue).data = 0 as *mut libc::c_void; - (*oldvalue).len = 0i32 as libc::c_uint - } - cell = malloc(::std::mem::size_of::() as libc::size_t) - as *mut chashcell; - if !cell.is_null() { - if 0 != (*hash).copykey { - (*cell).key.data = - chash_dup((*key).data, (*key).len) as *mut libc::c_void; - if (*cell).key.data.is_null() { - current_block = 4267898785354516004; - } else { - current_block = 7226443171521532240; - } - } else { - (*cell).key.data = (*key).data; - current_block = 7226443171521532240; - } - match current_block { - 7226443171521532240 => { - (*cell).key.len = (*key).len; - if 0 != (*hash).copyvalue { - (*cell).value.data = - chash_dup((*value).data, (*value).len) as *mut libc::c_void; - if (*cell).value.data.is_null() { - if 0 != (*hash).copykey { - free((*cell).key.data); - } - current_block = 4267898785354516004; - } else { - current_block = 6717214610478484138; - } - } else { - (*cell).value.data = (*value).data; - current_block = 6717214610478484138; - } - match current_block { - 4267898785354516004 => {} - _ => { - (*cell).value.len = (*value).len; - (*cell).func = func; - (*cell).next = *(*hash).cells.offset(indx as isize); - let ref mut fresh0 = *(*hash).cells.offset(indx as isize); - *fresh0 = cell; - (*hash).count = (*hash).count.wrapping_add(1); - return 0i32; - } - } - } - _ => {} - } - free(cell as *mut libc::c_void); - } - } - } - } - _ => {} - } - return -1i32; -} -#[inline] -unsafe fn chash_dup(mut data: *const libc::c_void, mut len: libc::c_uint) -> *mut libc::c_char { - let mut r: *mut libc::c_void = 0 as *mut libc::c_void; - r = malloc(len as libc::size_t) as *mut libc::c_char as *mut libc::c_void; - if r.is_null() { - return 0 as *mut libc::c_char; - } - memcpy(r, data, len as libc::size_t); - return r as *mut libc::c_char; -} - -#[inline] -unsafe fn chash_func(mut key: *const libc::c_char, mut len: libc::c_uint) -> libc::c_uint { - let mut c: libc::c_uint = 5381i32 as libc::c_uint; - let mut k: *const libc::c_char = key; - loop { - let fresh1 = len; - len = len.wrapping_sub(1); - if !(0 != fresh1) { - break; - } - let fresh2 = k; - k = k.offset(1); - c = (c << 5i32) - .wrapping_add(c) - .wrapping_add(*fresh2 as libc::c_uint) - } - return c; -} - -/* Resizes the hash table to the passed size. */ -pub unsafe fn chash_resize(mut hash: *mut chash, mut size: libc::c_uint) -> libc::c_int { - let mut cells: *mut *mut chashcell = 0 as *mut *mut chashcell; - let mut indx: libc::c_uint = 0; - let mut nindx: libc::c_uint = 0; - let mut iter: *mut chashiter = 0 as *mut chashiter; - let mut next: *mut chashiter = 0 as *mut chashiter; - if (*hash).size == size { - return 0i32; - } - cells = calloc( - size as libc::size_t, - ::std::mem::size_of::<*mut chashcell>() as libc::size_t, - ) as *mut *mut chashcell; - if cells.is_null() { - return -1i32; - } - indx = 0i32 as libc::c_uint; - while indx < (*hash).size { - iter = *(*hash).cells.offset(indx as isize); - while !iter.is_null() { - next = (*iter).next; - nindx = (*iter).func.wrapping_rem(size); - (*iter).next = *cells.offset(nindx as isize); - let ref mut fresh3 = *cells.offset(nindx as isize); - *fresh3 = iter; - iter = next - } - indx = indx.wrapping_add(1) - } - free((*hash).cells as *mut libc::c_void); - (*hash).size = size; - (*hash).cells = cells; - return 0i32; -} - -/* Retrieves the data associated to the key if it is found in the hash table. -The data pointer and the length will be NULL if not found*/ -pub unsafe fn chash_get( - mut hash: *mut chash, - mut key: *mut chashdatum, - mut result: *mut chashdatum, -) -> libc::c_int { - let mut func: libc::c_uint = 0; - let mut iter: *mut chashiter = 0 as *mut chashiter; - func = chash_func((*key).data as *const libc::c_char, (*key).len); - iter = *(*hash) - .cells - .offset(func.wrapping_rem((*hash).size) as isize); - while !iter.is_null() { - if (*iter).key.len == (*key).len - && (*iter).func == func - && 0 == memcmp((*iter).key.data, (*key).data, (*key).len as libc::size_t) - { - *result = (*iter).value; - return 0i32; - } - iter = (*iter).next - } - return -1i32; -} -/* Removes the entry associated to this key if it is found in the hash table, -and returns its contents if not dupped (otherwise, pointer will be NULL -and len TRUE). If entry is not found both pointer and len will be NULL. */ -pub unsafe fn chash_delete( - mut hash: *mut chash, - mut key: *mut chashdatum, - mut oldvalue: *mut chashdatum, -) -> libc::c_int { - /* chashdatum result = { NULL, TRUE }; */ - let mut func: libc::c_uint = 0; - let mut indx: libc::c_uint = 0; - let mut iter: *mut chashiter = 0 as *mut chashiter; - let mut old: *mut chashiter = 0 as *mut chashiter; - func = chash_func((*key).data as *const libc::c_char, (*key).len); - indx = func.wrapping_rem((*hash).size); - old = 0 as *mut chashiter; - iter = *(*hash).cells.offset(indx as isize); - while !iter.is_null() { - if (*iter).key.len == (*key).len - && (*iter).func == func - && 0 == memcmp((*iter).key.data, (*key).data, (*key).len as libc::size_t) - { - if !old.is_null() { - (*old).next = (*iter).next - } else { - let ref mut fresh4 = *(*hash).cells.offset(indx as isize); - *fresh4 = (*iter).next - } - if 0 != (*hash).copykey { - free((*iter).key.data); - } - if 0 != (*hash).copyvalue { - free((*iter).value.data); - } else if !oldvalue.is_null() { - (*oldvalue).data = (*iter).value.data; - (*oldvalue).len = (*iter).value.len - } - free(iter as *mut libc::c_void); - (*hash).count = (*hash).count.wrapping_sub(1); - return 0i32; - } - old = iter; - iter = (*iter).next - } - return -1i32; -} -/* Returns an iterator to the first non-empty entry of the hash table */ -pub unsafe fn chash_begin(mut hash: *mut chash) -> *mut chashiter { - let mut iter: *mut chashiter = 0 as *mut chashiter; - let mut indx: libc::c_uint = 0i32 as libc::c_uint; - iter = *(*hash).cells.offset(0isize); - while iter.is_null() { - indx = indx.wrapping_add(1); - if indx >= (*hash).size { - return 0 as *mut chashiter; - } - iter = *(*hash).cells.offset(indx as isize) - } - return iter; -} -/* Returns the next non-empty entry of the hash table */ -pub unsafe fn chash_next(mut hash: *mut chash, mut iter: *mut chashiter) -> *mut chashiter { - let mut indx: libc::c_uint = 0; - if iter.is_null() { - return 0 as *mut chashiter; - } - indx = (*iter).func.wrapping_rem((*hash).size); - iter = (*iter).next; - while iter.is_null() { - indx = indx.wrapping_add(1); - if indx >= (*hash).size { - return 0 as *mut chashiter; - } - iter = *(*hash).cells.offset(indx as isize) - } - return iter; -} diff --git a/mmime/src/clist.rs b/mmime/src/clist.rs deleted file mode 100644 index eb228d8b9..000000000 --- a/mmime/src/clist.rs +++ /dev/null @@ -1,202 +0,0 @@ -use libc; - -use crate::other::*; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct clistcell { - pub data: *mut libc::c_void, - pub previous: *mut clistcell, - pub next: *mut clistcell, -} - -#[derive(Clone)] -#[repr(C)] -pub struct clist { - pub first: *mut clistcell, - pub last: *mut clistcell, - pub count: libc::c_int, -} - -impl Default for clist { - fn default() -> Self { - Self { - first: std::ptr::null_mut(), - last: std::ptr::null_mut(), - count: 0, - } - } -} - -impl Drop for clist { - fn drop(&mut self) { - unsafe { - let mut l1 = self.first; - while !l1.is_null() { - let l2 = (*l1).next; - free(l1 as *mut libc::c_void); - l1 = l2 - } - } - } -} - -pub type clistiter = clistcell; -pub struct CListIterator { - cur: *mut clistiter, -} -impl Iterator for CListIterator { - type Item = *mut libc::c_void; - fn next(&mut self) -> Option { - unsafe { - if self.cur.is_null() { - None - } else { - let data = (*self.cur).data; - self.cur = (*self.cur).next; - Some(data) - } - } - } -} - -impl IntoIterator for &clist { - type Item = *mut libc::c_void; - type IntoIter = CListIterator; - fn into_iter(self) -> Self::IntoIter { - return CListIterator { cur: self.first }; - } -} - -pub type clist_func = - Option ()>; - -/* Allocate a new pointer list */ -pub fn clist_new() -> *mut clist { - Box::into_raw(Box::new(Default::default())) -} -/* Destroys a list. Data pointed by data pointers is NOT freed. */ -pub unsafe fn clist_free(mut lst: *mut clist) { - Box::from_raw(lst); -} -/* Inserts this data pointer after the element pointed by the iterator */ -pub unsafe fn clist_insert_after( - mut lst: *mut clist, - mut iter: *mut clistiter, - mut data: *mut libc::c_void, -) -> libc::c_int { - let mut c: *mut clistcell = 0 as *mut clistcell; - c = malloc(::std::mem::size_of::() as libc::size_t) as *mut clistcell; - if c.is_null() { - return -1i32; - } - (*c).data = data; - (*lst).count += 1; - if (*lst).first == (*lst).last && (*lst).last.is_null() { - (*c).next = 0 as *mut clistcell; - (*c).previous = (*c).next; - (*lst).last = c; - (*lst).first = (*lst).last; - return 0i32; - } - if iter.is_null() { - (*c).previous = (*lst).last; - (*(*c).previous).next = c; - (*c).next = 0 as *mut clistcell; - (*lst).last = c; - return 0i32; - } - (*c).previous = iter; - (*c).next = (*iter).next; - if !(*c).next.is_null() { - (*(*c).next).previous = c - } else { - (*lst).last = c - } - (*(*c).previous).next = c; - return 0i32; -} -/* Deletes the element pointed by the iterator. -Returns an iterator to the next element. */ -pub unsafe fn clist_delete(mut lst: *mut clist, mut iter: *mut clistiter) -> *mut clistiter { - let mut ret: *mut clistiter = 0 as *mut clistiter; - if iter.is_null() { - return 0 as *mut clistiter; - } - if !(*iter).previous.is_null() { - (*(*iter).previous).next = (*iter).next - } else { - (*lst).first = (*iter).next - } - if !(*iter).next.is_null() { - (*(*iter).next).previous = (*iter).previous; - ret = (*iter).next - } else { - (*lst).last = (*iter).previous; - ret = 0 as *mut clistiter - } - free(iter as *mut libc::c_void); - (*lst).count -= 1; - return ret; -} -pub unsafe fn clist_foreach( - mut lst: *mut clist, - mut func: clist_func, - mut data: *mut libc::c_void, -) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*lst).first; - while !cur.is_null() { - func.expect("non-null function pointer")((*cur).data, data); - cur = (*cur).next - } -} - -pub unsafe fn clist_nth_data(mut lst: *mut clist, mut indx: libc::c_int) -> *mut libc::c_void { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = internal_clist_nth(lst, indx); - if cur.is_null() { - return 0 as *mut libc::c_void; - } - return (*cur).data; -} -#[inline] -unsafe fn internal_clist_nth(mut lst: *mut clist, mut indx: libc::c_int) -> *mut clistiter { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*lst).first; - while indx > 0i32 && !cur.is_null() { - cur = (*cur).next; - indx -= 1 - } - if cur.is_null() { - return 0 as *mut clistiter; - } - return cur; -} - -pub unsafe fn clist_nth(mut lst: *mut clist, mut indx: libc::c_int) -> *mut clistiter { - return internal_clist_nth(lst, indx); -} - -#[cfg(test)] -mod tests { - use super::*; - use std::ptr; - #[test] - fn test_clist_iterator() { - unsafe { - let mut c = clist_new(); - assert!(!c.is_null()); - clist_insert_after(c, ptr::null_mut(), clist_nth as _); - assert_eq!((*c).count, 1); - - /* Only one iteration */ - for data in &*c { - assert_eq!(data, clist_nth as _); - } - assert_eq!((*c).count, 1); - - clist_free(c); - } - } -} diff --git a/mmime/src/constants.rs b/mmime/src/constants.rs deleted file mode 100644 index 0f637f7bd..000000000 --- a/mmime/src/constants.rs +++ /dev/null @@ -1,71 +0,0 @@ -pub const MAIL_ERROR_SSL: libc::c_uint = 58; -pub const MAIL_ERROR_FOLDER: libc::c_uint = 57; -pub const MAIL_ERROR_UNABLE: libc::c_uint = 56; -pub const MAIL_ERROR_SYSTEM: libc::c_uint = 55; -pub const MAIL_ERROR_COMMAND: libc::c_uint = 54; -pub const MAIL_ERROR_SEND: libc::c_uint = 53; -pub const MAIL_ERROR_CHAR_ENCODING_FAILED: libc::c_uint = 52; -pub const MAIL_ERROR_SUBJECT_NOT_FOUND: libc::c_uint = 51; -/* 50 */ -pub const MAIL_ERROR_PROGRAM_ERROR: libc::c_uint = 50; -pub const MAIL_ERROR_NO_PERMISSION: libc::c_uint = 49; -pub const MAIL_ERROR_COMMAND_NOT_SUPPORTED: libc::c_uint = 48; -pub const MAIL_ERROR_NO_APOP: libc::c_uint = 47; -pub const MAIL_ERROR_READONLY: libc::c_uint = 46; -pub const MAIL_ERROR_FATAL: libc::c_uint = 45; -pub const MAIL_ERROR_CLOSE: libc::c_uint = 44; -pub const MAIL_ERROR_CAPABILITY: libc::c_uint = 43; -pub const MAIL_ERROR_PROTOCOL: libc::c_uint = 42; -/* misc errors */ -pub const MAIL_ERROR_MISC: libc::c_uint = 41; -/* 40 */ -pub const MAIL_ERROR_EXPUNGE: libc::c_uint = 40; -pub const MAIL_ERROR_NO_TLS: libc::c_uint = 39; -pub const MAIL_ERROR_CACHE_MISS: libc::c_uint = 38; -pub const MAIL_ERROR_STARTTLS: libc::c_uint = 37; -pub const MAIL_ERROR_MOVE: libc::c_uint = 36; -pub const MAIL_ERROR_FOLDER_NOT_FOUND: libc::c_uint = 35; -pub const MAIL_ERROR_REMOVE: libc::c_uint = 34; -pub const MAIL_ERROR_PART_NOT_FOUND: libc::c_uint = 33; -pub const MAIL_ERROR_INVAL: libc::c_uint = 32; -pub const MAIL_ERROR_PARSE: libc::c_uint = 31; -/* 30 */ -pub const MAIL_ERROR_MSG_NOT_FOUND: libc::c_uint = 30; -pub const MAIL_ERROR_DISKSPACE: libc::c_uint = 29; -pub const MAIL_ERROR_SEARCH: libc::c_uint = 28; -pub const MAIL_ERROR_STORE: libc::c_uint = 27; -pub const MAIL_ERROR_FETCH: libc::c_uint = 26; -pub const MAIL_ERROR_COPY: libc::c_uint = 25; -pub const MAIL_ERROR_APPEND: libc::c_uint = 24; -pub const MAIL_ERROR_LSUB: libc::c_uint = 23; -pub const MAIL_ERROR_LIST: libc::c_uint = 22; -pub const MAIL_ERROR_UNSUBSCRIBE: libc::c_uint = 21; -/* 20 */ -pub const MAIL_ERROR_SUBSCRIBE: libc::c_uint = 20; -pub const MAIL_ERROR_STATUS: libc::c_uint = 19; -pub const MAIL_ERROR_MEMORY: libc::c_uint = 18; -pub const MAIL_ERROR_SELECT: libc::c_uint = 17; -pub const MAIL_ERROR_EXAMINE: libc::c_uint = 16; -pub const MAIL_ERROR_CHECK: libc::c_uint = 15; -pub const MAIL_ERROR_RENAME: libc::c_uint = 14; -pub const MAIL_ERROR_NOOP: libc::c_uint = 13; -pub const MAIL_ERROR_LOGOUT: libc::c_uint = 12; -pub const MAIL_ERROR_DELETE: libc::c_uint = 11; -/* 10 */ -pub const MAIL_ERROR_CREATE: libc::c_uint = 10; -pub const MAIL_ERROR_LOGIN: libc::c_uint = 9; -pub const MAIL_ERROR_STREAM: libc::c_uint = 8; -pub const MAIL_ERROR_FILE: libc::c_uint = 7; -pub const MAIL_ERROR_BAD_STATE: libc::c_uint = 6; -pub const MAIL_ERROR_CONNECT: libc::c_uint = 5; -pub const MAIL_ERROR_UNKNOWN: libc::c_uint = 4; -pub const MAIL_ERROR_NOT_IMPLEMENTED: libc::c_uint = 3; -pub const MAIL_NO_ERROR_NON_AUTHENTICATED: libc::c_uint = 2; -pub const MAIL_NO_ERROR_AUTHENTICATED: libc::c_uint = 1; -pub const MAIL_NO_ERROR: libc::c_uint = 0; - -pub const MAILIMF_ERROR_FILE: libc::c_uint = 4; -pub const MAILIMF_ERROR_INVAL: libc::c_uint = 3; -pub const MAILIMF_ERROR_MEMORY: libc::c_uint = 2; -pub const MAILIMF_ERROR_PARSE: libc::c_uint = 1; -pub const MAILIMF_NO_ERROR: libc::c_uint = 0; diff --git a/mmime/src/display.rs b/mmime/src/display.rs deleted file mode 100644 index 3a895df7b..000000000 --- a/mmime/src/display.rs +++ /dev/null @@ -1,386 +0,0 @@ -use crate::clist::*; - -use crate::mailimf::types::*; -use crate::mailmime::types::*; - -use std::ffi::CStr; - -pub unsafe fn display_mime(mut mime: *mut Mailmime) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - println!("{}", (*mime).mm_type); - - match (*mime).mm_type as u32 { - MAILMIME_SINGLE => { - println!("single part"); - } - MAILMIME_MULTIPLE => { - println!("multipart"); - } - MAILMIME_MESSAGE => println!("message"), - _ => {} - } - if !(*mime).mm_mime_fields.is_null() { - if !(*(*(*mime).mm_mime_fields).fld_list).first.is_null() { - print!("MIME headers begin"); - display_mime_fields((*mime).mm_mime_fields); - println!("MIME headers end"); - } - } - display_mime_content((*mime).mm_content_type); - match (*mime).mm_type as u32 { - MAILMIME_SINGLE => { - display_mime_data((*mime).mm_data.mm_single); - } - MAILMIME_MULTIPLE => { - cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; - while !cur.is_null() { - display_mime( - (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut Mailmime, - ); - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - } - MAILMIME_MESSAGE => { - if !(*mime).mm_data.mm_message.mm_fields.is_null() { - if !(*(*(*mime).mm_data.mm_message.mm_fields).fld_list) - .first - .is_null() - { - println!("headers begin"); - display_fields((*mime).mm_data.mm_message.mm_fields); - println!("headers end"); - } - if !(*mime).mm_data.mm_message.mm_msg_mime.is_null() { - display_mime((*mime).mm_data.mm_message.mm_msg_mime); - } - } - } - _ => {} - }; -} - -unsafe fn display_mime_content(mut content_type: *mut mailmime_content) { - print!("type: "); - display_mime_type((*content_type).ct_type); - println!( - "/{}", - CStr::from_ptr((*content_type).ct_subtype).to_str().unwrap() - ); -} -unsafe fn display_mime_type(mut type_0: *mut mailmime_type) { - match (*type_0).tp_type { - 1 => { - display_mime_discrete_type((*type_0).tp_data.tp_discrete_type); - } - 2 => { - display_mime_composite_type((*type_0).tp_data.tp_composite_type); - } - _ => {} - }; -} -unsafe fn display_mime_composite_type(mut ct: *mut mailmime_composite_type) { - match (*ct).ct_type { - 1 => { - print!("message"); - } - 2 => { - print!("multipart"); - } - 3 => { - print!("{}", CStr::from_ptr((*ct).ct_token).to_str().unwrap()); - } - _ => {} - }; -} -unsafe fn display_mime_discrete_type(mut discrete_type: *mut mailmime_discrete_type) { - match (*discrete_type).dt_type { - 1 => { - print!("text"); - } - 2 => { - print!("image"); - } - 3 => { - print!("audio"); - } - 4 => { - print!("video"); - } - 5 => { - print!("application"); - } - 6 => { - print!("{}", (*discrete_type).dt_extension as u8 as char); - } - _ => {} - }; -} -pub unsafe fn display_mime_data(mut data: *mut mailmime_data) { - match (*data).dt_type { - 0 => { - println!( - "data : {} bytes", - (*data).dt_data.dt_text.dt_length as libc::c_uint, - ); - } - 1 => { - println!( - "data (file) : {}", - CStr::from_ptr((*data).dt_data.dt_filename) - .to_str() - .unwrap() - ); - } - _ => {} - }; -} -unsafe fn display_mime_dsp_parm(mut param: *mut mailmime_disposition_parm) { - match (*param).pa_type { - 0 => { - println!( - "filename: {}", - CStr::from_ptr((*param).pa_data.pa_filename) - .to_str() - .unwrap() - ); - } - _ => {} - }; -} -unsafe fn display_mime_disposition(mut disposition: *mut mailmime_disposition) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*disposition).dsp_parms).first; - while !cur.is_null() { - let mut param: *mut mailmime_disposition_parm = 0 as *mut mailmime_disposition_parm; - param = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailmime_disposition_parm; - display_mime_dsp_parm(param); - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } -} -unsafe fn display_mime_field(mut field: *mut mailmime_field) { - match (*field).fld_type { - 1 => { - print!("content-type: "); - display_mime_content((*field).fld_data.fld_content); - println!(""); - } - 6 => { - display_mime_disposition((*field).fld_data.fld_disposition); - } - _ => {} - }; -} -unsafe fn display_mime_fields(mut fields: *mut mailmime_fields) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*fields).fld_list).first; - while !cur.is_null() { - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - field = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailmime_field; - display_mime_field(field); - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } -} -unsafe fn display_date_time(mut d: *mut mailimf_date_time) { - print!( - "{:02}/{:02}/{:02} {:02}:{:02}:{:02} +{:04}", - (*d).dt_day, - (*d).dt_month, - (*d).dt_year, - (*d).dt_hour, - (*d).dt_min, - (*d).dt_sec, - (*d).dt_zone, - ); -} -unsafe fn display_orig_date(mut orig_date: *mut mailimf_orig_date) { - display_date_time((*orig_date).dt_date_time); -} -unsafe fn display_mailbox(mut mb: *mut mailimf_mailbox) { - if !(*mb).mb_display_name.is_null() { - print!( - "{}", - CStr::from_ptr((*mb).mb_display_name).to_str().unwrap() - ); - } - print!("<{}>", CStr::from_ptr((*mb).mb_addr_spec).to_str().unwrap()); -} -unsafe fn display_mailbox_list(mut mb_list: *mut mailimf_mailbox_list) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*mb_list).mb_list).first; - while !cur.is_null() { - let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox; - mb = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_mailbox; - display_mailbox(mb); - if !if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - .is_null() - { - print!(", "); - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } -} -unsafe fn display_group(mut group: *mut mailimf_group) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - print!( - "{}: ", - CStr::from_ptr((*group).grp_display_name).to_str().unwrap() - ); - cur = (*(*(*group).grp_mb_list).mb_list).first; - while !cur.is_null() { - let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox; - mb = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_mailbox; - display_mailbox(mb); - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - print!("; "); -} -unsafe fn display_address(mut a: *mut mailimf_address) { - match (*a).ad_type { - 2 => { - display_group((*a).ad_data.ad_group); - } - 1 => { - display_mailbox((*a).ad_data.ad_mailbox); - } - _ => {} - }; -} -unsafe fn display_address_list(mut addr_list: *mut mailimf_address_list) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*addr_list).ad_list).first; - while !cur.is_null() { - let mut addr: *mut mailimf_address = 0 as *mut mailimf_address; - addr = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_address; - display_address(addr); - if !if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - .is_null() - { - print!(", "); - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } -} -unsafe fn display_from(mut from: *mut mailimf_from) { - display_mailbox_list((*from).frm_mb_list); -} -unsafe fn display_to(mut to: *mut mailimf_to) { - display_address_list((*to).to_addr_list); -} -unsafe fn display_cc(mut cc: *mut mailimf_cc) { - display_address_list((*cc).cc_addr_list); -} -unsafe fn display_subject(mut subject: *mut mailimf_subject) { - print!("{}", CStr::from_ptr((*subject).sbj_value).to_str().unwrap()); -} -unsafe fn display_field(mut field: *mut mailimf_field) { - match (*field).fld_type { - 9 => { - print!("Date: "); - display_orig_date((*field).fld_data.fld_orig_date); - println!(""); - } - 10 => { - print!("From: "); - display_from((*field).fld_data.fld_from); - println!(""); - } - 13 => { - print!("To: "); - display_to((*field).fld_data.fld_to); - println!(""); - } - 14 => { - print!("Cc: "); - display_cc((*field).fld_data.fld_cc); - println!(""); - } - 19 => { - print!("Subject: "); - display_subject((*field).fld_data.fld_subject); - println!(""); - } - 16 => { - println!( - "Message-ID: {}", - CStr::from_ptr((*(*field).fld_data.fld_message_id).mid_value) - .to_str() - .unwrap(), - ); - } - _ => {} - }; -} -unsafe fn display_fields(mut fields: *mut mailimf_fields) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*fields).fld_list).first; - while !cur.is_null() { - let mut f: *mut mailimf_field = 0 as *mut mailimf_field; - f = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_field; - display_field(f); - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } -} diff --git a/mmime/src/lib.rs b/mmime/src/lib.rs deleted file mode 100644 index 4b75c5165..000000000 --- a/mmime/src/lib.rs +++ /dev/null @@ -1,78 +0,0 @@ -#![deny(clippy::correctness)] -// TODO: make all of these errors, such that clippy actually passes. -#![warn(clippy::all, clippy::perf, clippy::not_unsafe_ptr_arg_deref)] -// This is nice, but for now just annoying. -#![allow(clippy::unreadable_literal)] -#![feature(ptr_wrapping_offset_from)] -#![allow(unused_attributes)] -#![allow(unused_variables)] -#![allow(mutable_transmutes)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(non_upper_case_globals)] -#![allow(unused_assignments)] -#![allow(unused_mut)] -#![allow(unused_must_use)] -#![feature(extern_types)] -#![feature(const_raw_ptr_to_usize_cast)] - -pub mod charconv; -pub mod chash; -pub mod clist; -pub mod display; -pub mod mailimf; -pub mod mailmime; -pub mod mmapstring; -pub mod other; - -pub use self::charconv::*; -pub use self::chash::*; -pub use self::clist::*; -pub use self::display::*; -pub use self::mailimf::*; -pub use self::mailmime::*; -pub use self::mmapstring::*; -pub use self::other::*; - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn mailmime_parse_test() { - unsafe { - let data = "MIME-Version: 1.0\ - Content-Type: multipart/mixed; boundary=frontier\ - \ - This is a message with multiple parts in MIME format.\ - --frontier\ - Content-Type: text/plain\ - \ - This is the body of the message.\ - --frontier\ - Content-Type: application/octet-stream\ - Content-Transfer-Encoding: base64\ - \ - PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\ - Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==\ - --frontier--"; - let c_data = std::ffi::CString::new(data).unwrap(); - - let mut current_index = 0; - let mut mime = std::ptr::null_mut(); - let res = crate::mailmime::content::mailmime_parse( - c_data.as_ptr(), - data.len() as usize, - &mut current_index, - &mut mime, - ); - - assert_eq!(res, MAIL_NO_ERROR as libc::c_int); - assert!(!mime.is_null()); - - display_mime(mime); - - mailmime::types::mailmime_free(mime); - } - } -} diff --git a/mmime/src/mailimf/mod.rs b/mmime/src/mailimf/mod.rs deleted file mode 100644 index 5740b6c40..000000000 --- a/mmime/src/mailimf/mod.rs +++ /dev/null @@ -1,5921 +0,0 @@ -pub mod types; -pub mod types_helper; -pub(crate) mod write_generic; - -use libc::{self, toupper}; - -use crate::clist::*; -use crate::mailimf::types::*; -use crate::mailmime::decode::*; -use crate::mailmime::types::*; -use crate::mmapstring::*; -use crate::other::*; - -pub const UNSTRUCTURED_START: libc::c_uint = 0; -pub const UNSTRUCTURED_LF: libc::c_uint = 2; -pub const UNSTRUCTURED_CR: libc::c_uint = 1; -pub const UNSTRUCTURED_WSP: libc::c_uint = 3; -pub const UNSTRUCTURED_OUT: libc::c_uint = 4; - -pub const STATE_ZONE_ERR: libc::c_uint = 4; -pub const STATE_ZONE_OK: libc::c_uint = 3; -pub const STATE_ZONE_3: libc::c_uint = 2; -pub const STATE_ZONE_2: libc::c_uint = 1; -pub const STATE_ZONE_CONT: libc::c_uint = 5; -pub const STATE_ZONE_1: libc::c_uint = 0; - -pub const MONTH_A: libc::c_uint = 5; -pub const MONTH_MA: libc::c_uint = 4; -pub const MONTH_M: libc::c_uint = 3; -pub const MONTH_JU: libc::c_uint = 2; -pub const MONTH_J: libc::c_uint = 1; -pub const MONTH_START: libc::c_uint = 0; -pub const DAY_NAME_S: libc::c_uint = 2; -pub const DAY_NAME_T: libc::c_uint = 1; -pub const DAY_NAME_START: libc::c_uint = 0; -pub const HEADER_RES: libc::c_uint = 5; -pub const HEADER_S: libc::c_uint = 4; -pub const HEADER_RE: libc::c_uint = 3; -pub const HEADER_R: libc::c_uint = 2; -pub const HEADER_C: libc::c_uint = 1; -pub const HEADER_START: libc::c_uint = 0; - -/* -day-name = "Mon" / "Tue" / "Wed" / "Thu" / - "Fri" / "Sat" / "Sun" -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_token_value { - pub value: libc::c_int, - pub str_0: *mut libc::c_char, -} - -/* - mailimf_message_parse will parse the given message - - @param message this is a string containing the message content - @param length this is the size of the given string - @param indx this is a pointer to the start of the message in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_message_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_message, -) -> libc::c_int { - let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields; - let mut body: *mut mailimf_body = 0 as *mut mailimf_body; - let mut msg: *mut mailimf_message = 0 as *mut mailimf_message; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_fields_parse(message, length, &mut cur_token, &mut fields); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - r = mailimf_body_parse(message, length, &mut cur_token, &mut body); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - msg = mailimf_message_new(fields, body); - if msg.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - mailimf_body_free(body); - } else { - *indx = cur_token; - *result = msg; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_fields_free(fields); - } - } - return res; -} -/* - mailimf_body_parse will parse the given text part of a message - - @param message this is a string containing the message text part - @param length this is the size of the given string - @param indx this is a pointer to the start of the message text part in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_body_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_body, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut body: *mut mailimf_body = 0 as *mut mailimf_body; - cur_token = *indx; - body = mailimf_body_new( - message.offset(cur_token as isize), - length.wrapping_sub(cur_token), - ); - if body.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - cur_token = length; - *result = body; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailimf_crlf_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_char_parse(message, length, &mut cur_token, '\r' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_char_parse(message, length, &mut cur_token, '\n' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailimf_char_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut token: libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - cur_token = *indx; - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - if *message.offset(cur_token as isize) as libc::c_int == token as libc::c_int { - cur_token = cur_token.wrapping_add(1); - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } else { - return MAILIMF_ERROR_PARSE as libc::c_int; - }; -} -/* - mailimf_fields_parse will parse the given header fields - - @param message this is a string containing the header fields - @param length this is the size of the given string - @param indx this is a pointer to the start of the header fields in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_fields_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_fields, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut list: *mut clist = 0 as *mut clist; - let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - list = 0 as *mut clist; - r = mailimf_struct_multiple_parse( - message, - length, - &mut cur_token, - &mut list, - ::std::mem::transmute::< - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut *mut mailimf_field, - ) -> libc::c_int, - >, - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut libc::c_void, - ) -> libc::c_int, - >, - >(Some(mailimf_field_parse)), - ::std::mem::transmute::< - Option ()>, - Option libc::c_int>, - >(Some(mailimf_field_free)), - ); - /* - if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { - res = r; - goto err; - } - */ - match r { - 0 => { - /* do nothing */ - current_block = 11050875288958768710; - } - 1 => { - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 6724962012950341805; - } else { - current_block = 11050875288958768710; - } - } - _ => { - res = r; - current_block = 6724962012950341805; - } - } - match current_block { - 11050875288958768710 => { - fields = mailimf_fields_new(list); - if fields.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !list.is_null() { - clist_foreach( - list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailimf_field_free)), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - } else { - *result = fields; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - _ => {} - } - return res; -} -unsafe fn mailimf_field_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_field, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut type_0: libc::c_int = 0; - let mut return_path: *mut mailimf_return = 0 as *mut mailimf_return; - let mut resent_date: *mut mailimf_orig_date = 0 as *mut mailimf_orig_date; - let mut resent_from: *mut mailimf_from = 0 as *mut mailimf_from; - let mut resent_sender: *mut mailimf_sender = 0 as *mut mailimf_sender; - let mut resent_to: *mut mailimf_to = 0 as *mut mailimf_to; - let mut resent_cc: *mut mailimf_cc = 0 as *mut mailimf_cc; - let mut resent_bcc: *mut mailimf_bcc = 0 as *mut mailimf_bcc; - let mut resent_msg_id: *mut mailimf_message_id = 0 as *mut mailimf_message_id; - let mut orig_date: *mut mailimf_orig_date = 0 as *mut mailimf_orig_date; - let mut from: *mut mailimf_from = 0 as *mut mailimf_from; - let mut sender: *mut mailimf_sender = 0 as *mut mailimf_sender; - let mut reply_to: *mut mailimf_reply_to = 0 as *mut mailimf_reply_to; - let mut to: *mut mailimf_to = 0 as *mut mailimf_to; - let mut cc: *mut mailimf_cc = 0 as *mut mailimf_cc; - let mut bcc: *mut mailimf_bcc = 0 as *mut mailimf_bcc; - let mut message_id: *mut mailimf_message_id = 0 as *mut mailimf_message_id; - let mut in_reply_to: *mut mailimf_in_reply_to = 0 as *mut mailimf_in_reply_to; - let mut references: *mut mailimf_references = 0 as *mut mailimf_references; - let mut subject: *mut mailimf_subject = 0 as *mut mailimf_subject; - let mut comments: *mut mailimf_comments = 0 as *mut mailimf_comments; - let mut keywords: *mut mailimf_keywords = 0 as *mut mailimf_keywords; - let mut optional_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - let mut guessed_type: libc::c_int = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - return_path = 0 as *mut mailimf_return; - resent_date = 0 as *mut mailimf_orig_date; - resent_from = 0 as *mut mailimf_from; - resent_sender = 0 as *mut mailimf_sender; - resent_to = 0 as *mut mailimf_to; - resent_cc = 0 as *mut mailimf_cc; - resent_bcc = 0 as *mut mailimf_bcc; - resent_msg_id = 0 as *mut mailimf_message_id; - orig_date = 0 as *mut mailimf_orig_date; - from = 0 as *mut mailimf_from; - sender = 0 as *mut mailimf_sender; - reply_to = 0 as *mut mailimf_reply_to; - to = 0 as *mut mailimf_to; - cc = 0 as *mut mailimf_cc; - bcc = 0 as *mut mailimf_bcc; - message_id = 0 as *mut mailimf_message_id; - in_reply_to = 0 as *mut mailimf_in_reply_to; - references = 0 as *mut mailimf_references; - subject = 0 as *mut mailimf_subject; - comments = 0 as *mut mailimf_comments; - keywords = 0 as *mut mailimf_keywords; - optional_field = 0 as *mut mailimf_optional_field; - guessed_type = guess_header_type(message, length, cur_token); - type_0 = MAILIMF_FIELD_NONE as libc::c_int; - match guessed_type { - 9 => { - r = mailimf_orig_date_parse(message, length, &mut cur_token, &mut orig_date); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILIMF_FIELD_ORIG_DATE as libc::c_int; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 10 => { - r = mailimf_from_parse(message, length, &mut cur_token, &mut from); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 11 => { - r = mailimf_sender_parse(message, length, &mut cur_token, &mut sender); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 12 => { - r = mailimf_reply_to_parse(message, length, &mut cur_token, &mut reply_to); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 13 => { - r = mailimf_to_parse(message, length, &mut cur_token, &mut to); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 14 => { - r = mailimf_cc_parse(message, length, &mut cur_token, &mut cc); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 15 => { - r = mailimf_bcc_parse(message, length, &mut cur_token, &mut bcc); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 16 => { - r = mailimf_message_id_parse(message, length, &mut cur_token, &mut message_id); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 17 => { - r = mailimf_in_reply_to_parse(message, length, &mut cur_token, &mut in_reply_to); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 18 => { - r = mailimf_references_parse(message, length, &mut cur_token, &mut references); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 19 => { - r = mailimf_subject_parse(message, length, &mut cur_token, &mut subject); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 20 => { - r = mailimf_comments_parse(message, length, &mut cur_token, &mut comments); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 21 => { - r = mailimf_keywords_parse(message, length, &mut cur_token, &mut keywords); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 1 => { - r = mailimf_return_parse(message, length, &mut cur_token, &mut return_path); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 2 => { - r = mailimf_resent_date_parse(message, length, &mut cur_token, &mut resent_date); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 3 => { - r = mailimf_resent_from_parse(message, length, &mut cur_token, &mut resent_from); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 4 => { - r = mailimf_resent_sender_parse(message, length, &mut cur_token, &mut resent_sender); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 5 => { - r = mailimf_resent_to_parse(message, length, &mut cur_token, &mut resent_to); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 6 => { - r = mailimf_resent_cc_parse(message, length, &mut cur_token, &mut resent_cc); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 7 => { - r = mailimf_resent_bcc_parse(message, length, &mut cur_token, &mut resent_bcc); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - 8 => { - r = mailimf_resent_msg_id_parse(message, length, &mut cur_token, &mut resent_msg_id); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 9846950269610550213; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9846950269610550213; - } else { - /* do nothing */ - res = r; - current_block = 10956553358380301606; - } - } - _ => { - current_block = 9846950269610550213; - } - } - match current_block { - 9846950269610550213 => { - if type_0 == MAILIMF_FIELD_NONE as libc::c_int { - r = mailimf_optional_field_parse( - message, - length, - &mut cur_token, - &mut optional_field, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 10956553358380301606; - } else { - type_0 = MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int; - current_block = 2920409193602730479; - } - } else { - current_block = 2920409193602730479; - } - match current_block { - 10956553358380301606 => {} - _ => { - field = mailimf_field_new( - type_0, - return_path, - resent_date, - resent_from, - resent_sender, - resent_to, - resent_cc, - resent_bcc, - resent_msg_id, - orig_date, - from, - sender, - reply_to, - to, - cc, - bcc, - message_id, - in_reply_to, - references, - subject, - comments, - keywords, - optional_field, - ); - if field.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !return_path.is_null() { - mailimf_return_free(return_path); - } - if !resent_date.is_null() { - mailimf_orig_date_free(resent_date); - } - if !resent_from.is_null() { - mailimf_from_free(resent_from); - } - if !resent_sender.is_null() { - mailimf_sender_free(resent_sender); - } - if !resent_to.is_null() { - mailimf_to_free(resent_to); - } - if !resent_cc.is_null() { - mailimf_cc_free(resent_cc); - } - if !resent_bcc.is_null() { - mailimf_bcc_free(resent_bcc); - } - if !resent_msg_id.is_null() { - mailimf_message_id_free(resent_msg_id); - } - if !orig_date.is_null() { - mailimf_orig_date_free(orig_date); - } - if !from.is_null() { - mailimf_from_free(from); - } - if !sender.is_null() { - mailimf_sender_free(sender); - } - if !reply_to.is_null() { - mailimf_reply_to_free(reply_to); - } - if !to.is_null() { - mailimf_to_free(to); - } - if !cc.is_null() { - mailimf_cc_free(cc); - } - if !bcc.is_null() { - mailimf_bcc_free(bcc); - } - if !message_id.is_null() { - mailimf_message_id_free(message_id); - } - if !in_reply_to.is_null() { - mailimf_in_reply_to_free(in_reply_to); - } - if !references.is_null() { - mailimf_references_free(references); - } - if !subject.is_null() { - mailimf_subject_free(subject); - } - if !comments.is_null() { - mailimf_comments_free(comments); - } - if !keywords.is_null() { - mailimf_keywords_free(keywords); - } - if !optional_field.is_null() { - mailimf_optional_field_free(optional_field); - } - } else { - *result = field; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - _ => {} - } - return res; -} -unsafe fn mailimf_optional_field_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_optional_field, -) -> libc::c_int { - let mut name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut optional_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_field_name_parse(message, length, &mut cur_token, &mut name); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstructured_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - optional_field = mailimf_optional_field_new(name, value); - if optional_field.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = optional_field; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_unstructured_free(value); - } - } - mailimf_field_name_free(name); - } - return res; -} -unsafe fn mailimf_unstrict_crlf_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - mailimf_cfws_parse(message, length, &mut cur_token); - r = mailimf_char_parse(message, length, &mut cur_token, '\r' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_char_parse(message, length, &mut cur_token, '\n' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailimf_cfws_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut has_comment: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - has_comment = 0i32; - loop { - r = mailimf_cfws_fws_comment_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - break; - } - return r; - } else { - has_comment = 1i32 - } - } - if 0 == has_comment { - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -/* internal use, exported for MIME */ -pub unsafe fn mailimf_fws_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut final_token: size_t = 0; - let mut fws_1: libc::c_int = 0; - let mut fws_2: libc::c_int = 0; - let mut fws_3: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - fws_1 = 0i32; - loop { - r = mailimf_wsp_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - break; - } - return r; - } else { - fws_1 = 1i32 - } - } - final_token = cur_token; - r = mailimf_crlf_parse(message, length, &mut cur_token); - match r { - 0 => fws_2 = 1i32, - 1 => fws_2 = 0i32, - _ => return r, - } - fws_3 = 0i32; - if 0 != fws_2 { - loop { - r = mailimf_wsp_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - break; - } - return r; - } else { - fws_3 = 1i32 - } - } - } - if 0 == fws_1 && 0 == fws_3 { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - if 0 == fws_3 { - cur_token = final_token - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -#[inline] -unsafe fn mailimf_wsp_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - cur_token = *indx; - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - if *message.offset(cur_token as isize) as libc::c_int != ' ' as i32 - && *message.offset(cur_token as isize) as libc::c_int != '\t' as i32 - { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - cur_token = cur_token.wrapping_add(1); - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -/* -[FWS] comment -*/ -#[inline] -unsafe fn mailimf_cfws_fws_comment_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_comment_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -#[inline] -unsafe fn mailimf_comment_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_oparenth_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - loop { - r = mailimf_comment_fws_ccontent_parse(message, length, &mut cur_token); - if !(r != MAILIMF_NO_ERROR as libc::c_int) { - continue; - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - break; - } - return r; - } - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_cparenth_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_cparenth_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_char_parse(message, length, indx, ')' as i32 as libc::c_char); -} -#[inline] -unsafe fn mailimf_comment_fws_ccontent_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_ccontent_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -#[inline] -unsafe fn mailimf_ccontent_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut ch: libc::c_char = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - if 0 != is_ctext(*message.offset(cur_token as isize)) { - cur_token = cur_token.wrapping_add(1) - } else { - r = mailimf_quoted_pair_parse(message, length, &mut cur_token, &mut ch); - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_comment_parse(message, length, &mut cur_token) - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -#[inline] -unsafe fn mailimf_quoted_pair_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - cur_token = *indx; - if cur_token.wrapping_add(1i32 as libc::size_t) >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - if *message.offset(cur_token as isize) as libc::c_int != '\\' as i32 { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - cur_token = cur_token.wrapping_add(1); - *result = *message.offset(cur_token as isize); - cur_token = cur_token.wrapping_add(1); - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -/* -ctext = NO-WS-CTL / ; Non white space controls - - %d33-39 / ; The rest of the US-ASCII - %d42-91 / ; characters not including "(", - %d93-126 ; ")", or "\" -*/ -#[inline] -unsafe fn is_ctext(mut ch: libc::c_char) -> libc::c_int { - let mut uch: libc::c_uchar = ch as libc::c_uchar; - if 0 != is_no_ws_ctl(ch) { - return 1i32; - } - if (uch as libc::c_int) < 33i32 { - return 0i32; - } - if uch as libc::c_int == 40i32 || uch as libc::c_int == 41i32 { - return 0i32; - } - if uch as libc::c_int == 92i32 { - return 0i32; - } - if uch as libc::c_int == 127i32 { - return 0i32; - } - return 1i32; -} -/* ************************************************************************ */ -/* RFC 2822 grammar */ -/* -NO-WS-CTL = %d1-8 / ; US-ASCII control characters - %d11 / ; that do not include the - %d12 / ; carriage return, line feed, - %d14-31 / ; and white space characters - %d127 -*/ -#[inline] -unsafe fn is_no_ws_ctl(mut ch: libc::c_char) -> libc::c_int { - if ch as libc::c_int == 9i32 || ch as libc::c_int == 10i32 || ch as libc::c_int == 13i32 { - return 0i32; - } - if ch as libc::c_int == 127i32 { - return 1i32; - } - return (ch as libc::c_int >= 1i32 && ch as libc::c_int <= 31i32) as libc::c_int; -} -unsafe fn mailimf_oparenth_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_char_parse(message, length, indx, '(' as i32 as libc::c_char); -} -unsafe fn mailimf_unstructured_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut state: libc::c_int = 0; - let mut begin: size_t = 0; - let mut terminal: size_t = 0; - let mut str: *mut libc::c_char = 0 as *mut libc::c_char; - cur_token = *indx; - loop { - let mut r: libc::c_int = 0; - r = mailimf_wsp_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - continue; - } - /* do nothing */ - if r == MAILIMF_ERROR_PARSE as libc::c_int { - break; - } - return r; - } - state = UNSTRUCTURED_START as libc::c_int; - begin = cur_token; - terminal = cur_token; - while state != UNSTRUCTURED_OUT as libc::c_int { - match state { - 0 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - terminal = cur_token; - match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = UNSTRUCTURED_CR as libc::c_int, - 10 => state = UNSTRUCTURED_LF as libc::c_int, - _ => state = UNSTRUCTURED_START as libc::c_int, - } - } - 1 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 10 => state = UNSTRUCTURED_LF as libc::c_int, - _ => state = UNSTRUCTURED_START as libc::c_int, - } - } - 2 => { - if cur_token >= length { - state = UNSTRUCTURED_OUT as libc::c_int - } else { - match *message.offset(cur_token as isize) as libc::c_int { - 9 | 32 => state = UNSTRUCTURED_WSP as libc::c_int, - _ => state = UNSTRUCTURED_OUT as libc::c_int, - } - } - } - 3 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = UNSTRUCTURED_CR as libc::c_int, - 10 => state = UNSTRUCTURED_LF as libc::c_int, - _ => state = UNSTRUCTURED_START as libc::c_int, - } - } - _ => {} - } - cur_token = cur_token.wrapping_add(1) - } - str = malloc( - terminal - .wrapping_sub(begin) - .wrapping_add(1i32 as libc::size_t), - ) as *mut libc::c_char; - if str.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - strncpy( - str, - message.offset(begin as isize), - terminal.wrapping_sub(begin), - ); - *str.offset(terminal.wrapping_sub(begin) as isize) = '\u{0}' as i32 as libc::c_char; - *indx = terminal; - *result = str; - return MAILIMF_NO_ERROR as libc::c_int; -} - -unsafe fn mailimf_colon_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_unstrict_char_parse(message, length, indx, ':' as i32 as libc::c_char); -} - -pub unsafe fn mailimf_unstrict_char_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut token: libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_char_parse(message, length, &mut cur_token, token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_field_name_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut field_name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut cur_token: size_t = 0; - let mut end: size_t = 0; - cur_token = *indx; - end = cur_token; - if end >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - while 0 != is_ftext(*message.offset(end as isize)) { - end = end.wrapping_add(1); - if end >= length { - break; - } - } - if end == cur_token { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - field_name = malloc( - end.wrapping_sub(cur_token) - .wrapping_add(1i32 as libc::size_t), - ) as *mut libc::c_char; - if field_name.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - strncpy( - field_name, - message.offset(cur_token as isize), - end.wrapping_sub(cur_token), - ); - *field_name.offset(end.wrapping_sub(cur_token) as isize) = '\u{0}' as i32 as libc::c_char; - cur_token = end; - *indx = cur_token; - *result = field_name; - return MAILIMF_NO_ERROR as libc::c_int; -} -/* -field-name = 1*ftext -*/ -#[inline] -unsafe fn is_ftext(mut ch: libc::c_char) -> libc::c_int { - let mut uch: libc::c_uchar = ch as libc::c_uchar; - if (uch as libc::c_int) < 33i32 { - return 0i32; - } - if uch as libc::c_int == 58i32 { - return 0i32; - } - return 1i32; -} -unsafe fn mailimf_resent_msg_id_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_message_id, -) -> libc::c_int { - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut cur_token: size_t = 0; - let mut message_id: *mut mailimf_message_id = 0 as *mut mailimf_message_id; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Resent-Message-ID\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Resent-Message-ID\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_msg_id_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - message_id = mailimf_message_id_new(value); - if message_id.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = message_id; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_msg_id_free(value); - } - } - } - return res; -} - -pub unsafe fn mailimf_msg_id_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut msg_id: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_lower_parse(message, length, &mut cur_token); - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_addr_spec_msg_id_parse(message, length, &mut cur_token, &mut msg_id); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - *result = msg_id; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } else if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_lower_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - current_block = 2668756484064249700; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 2668756484064249700; - } else { - // ok - res = r; - current_block = 9394595304415473402; - } - match current_block { - 9394595304415473402 => {} - _ => { - r = mailimf_addr_spec_msg_id_parse(message, length, &mut cur_token, &mut msg_id); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_greater_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - free(msg_id as *mut libc::c_void); - res = r - } else { - r = mailimf_greater_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int - || r == MAILIMF_ERROR_PARSE as libc::c_int - { - current_block = 6450636197030046351; - } else { - // ok - free(msg_id as *mut libc::c_void); - res = r; - current_block = 9394595304415473402; - } - match current_block { - 9394595304415473402 => {} - _ => { - *result = msg_id; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - } - } - } - return res; -} -unsafe fn mailimf_greater_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_unstrict_char_parse(message, length, indx, '>' as i32 as libc::c_char); -} -/* -for msg id -addr-spec = local-part "@" domain -*/ -unsafe fn mailimf_addr_spec_msg_id_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut addr_spec: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut begin: size_t = 0; - let mut end: size_t = 0; - let mut final_0: libc::c_int = 0; - let mut count: size_t = 0; - let mut src: *const libc::c_char = 0 as *const libc::c_char; - let mut dest: *mut libc::c_char = 0 as *mut libc::c_char; - let mut i: size_t = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - end = cur_token; - if end >= length { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - begin = cur_token; - final_0 = 0i32; - loop { - match *message.offset(end as isize) as libc::c_int { - 62 | 13 | 10 => final_0 = 1i32, - _ => {} - } - if 0 != final_0 { - break; - } - end = end.wrapping_add(1); - if end >= length { - break; - } - } - if end == begin { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - addr_spec = malloc( - end.wrapping_sub(cur_token) - .wrapping_add(1i32 as libc::size_t), - ) as *mut libc::c_char; - if addr_spec.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - count = end.wrapping_sub(cur_token); - src = message.offset(cur_token as isize); - dest = addr_spec; - i = 0i32 as size_t; - while i < count { - if *src as libc::c_int != ' ' as i32 && *src as libc::c_int != '\t' as i32 { - *dest = *src; - dest = dest.offset(1isize) - } - src = src.offset(1isize); - i = i.wrapping_add(1) - } - *dest = '\u{0}' as i32 as libc::c_char; - cur_token = end; - *result = addr_spec; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - return res; -} -unsafe fn mailimf_lower_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_unstrict_char_parse(message, length, indx, '<' as i32 as libc::c_char); -} - -pub unsafe fn mailimf_token_case_insensitive_len_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut token: *mut libc::c_char, - mut token_length: size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - cur_token = *indx; - if cur_token - .wrapping_add(token_length) - .wrapping_sub(1i32 as libc::size_t) - >= length - { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - if strncasecmp(message.offset(cur_token as isize), token, token_length) == 0i32 { - cur_token = (cur_token as libc::size_t).wrapping_add(token_length) as size_t as size_t; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } else { - return MAILIMF_ERROR_PARSE as libc::c_int; - }; -} -unsafe fn mailimf_resent_bcc_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_bcc, -) -> libc::c_int { - let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - let mut bcc: *mut mailimf_bcc = 0 as *mut mailimf_bcc; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - bcc = 0 as *mut mailimf_bcc; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Resent-Bcc\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Resent-Bcc\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - addr_list = 0 as *mut mailimf_address_list; - r = mailimf_address_list_parse(message, length, &mut cur_token, &mut addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - bcc = mailimf_bcc_new(addr_list); - if bcc.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = bcc; - *indx = cur_token; - return 1i32; - } - } - mailimf_address_list_free(addr_list); - } - } - } - return res; -} -/* - mailimf_address_list_parse will parse the given address list - - @param message this is a string containing the address list - @param length this is the size of the given string - @param indx this is a pointer to the start of the address list in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_address_list_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_address_list, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut list: *mut clist = 0 as *mut clist; - let mut address_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_struct_list_parse( - message, - length, - &mut cur_token, - &mut list, - ',' as i32 as libc::c_char, - ::std::mem::transmute::< - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut *mut mailimf_address, - ) -> libc::c_int, - >, - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut libc::c_void, - ) -> libc::c_int, - >, - >(Some(mailimf_address_parse)), - ::std::mem::transmute::< - Option ()>, - Option libc::c_int>, - >(Some(mailimf_address_free)), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - address_list = mailimf_address_list_new(list); - if address_list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - clist_foreach( - list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailimf_address_free), - ), - 0 as *mut libc::c_void, - ); - clist_free(list); - } else { - *result = address_list; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} -/* - mailimf_address_parse will parse the given address - - @param message this is a string containing the address - @param length this is the size of the given string - @param indx this is a pointer to the start of the address in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_address_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_address, -) -> libc::c_int { - let mut type_0: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut mailbox: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox; - let mut group: *mut mailimf_group = 0 as *mut mailimf_group; - let mut address: *mut mailimf_address = 0 as *mut mailimf_address; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - mailbox = 0 as *mut mailimf_mailbox; - group = 0 as *mut mailimf_group; - type_0 = MAILIMF_ADDRESS_ERROR as libc::c_int; - r = mailimf_group_parse(message, length, &mut cur_token, &mut group); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILIMF_ADDRESS_GROUP as libc::c_int - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_mailbox_parse(message, length, &mut cur_token, &mut mailbox); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILIMF_ADDRESS_MAILBOX as libc::c_int - } - } - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - address = mailimf_address_new(type_0, mailbox, group); - if address.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !mailbox.is_null() { - mailimf_mailbox_free(mailbox); - } - if !group.is_null() { - mailimf_group_free(group); - } - } else { - *result = address; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} -/* - mailimf_mailbox_parse will parse the given address - - @param message this is a string containing the mailbox - @param length this is the size of the given string - @param indx this is a pointer to the start of the mailbox in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_mailbox_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_mailbox, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut display_name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut mailbox: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox; - let mut addr_spec: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - display_name = 0 as *mut libc::c_char; - addr_spec = 0 as *mut libc::c_char; - r = mailimf_name_addr_parse( - message, - length, - &mut cur_token, - &mut display_name, - &mut addr_spec, - ); - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_addr_spec_parse(message, length, &mut cur_token, &mut addr_spec) - } - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - mailbox = mailimf_mailbox_new(display_name, addr_spec); - if mailbox.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !display_name.is_null() { - mailimf_display_name_free(display_name); - } - if !addr_spec.is_null() { - mailimf_addr_spec_free(addr_spec); - } - } else { - *result = mailbox; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} -unsafe fn mailimf_addr_spec_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut addr_spec: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut begin: size_t = 0; - let mut end: size_t = 0; - let mut final_0: libc::c_int = 0; - let mut count: size_t = 0; - let mut src: *const libc::c_char = 0 as *const libc::c_char; - let mut dest: *mut libc::c_char = 0 as *mut libc::c_char; - let mut i: size_t = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - end = cur_token; - if end >= length { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - begin = cur_token; - final_0 = 0i32; - loop { - match *message.offset(end as isize) as libc::c_int { - 62 | 44 | 13 | 10 | 40 | 41 | 58 | 59 => final_0 = 1i32, - _ => {} - } - if 0 != final_0 { - break; - } - end = end.wrapping_add(1); - if end >= length { - break; - } - } - if end == begin { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - addr_spec = malloc( - end.wrapping_sub(cur_token) - .wrapping_add(1i32 as libc::size_t), - ) as *mut libc::c_char; - if addr_spec.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - count = end.wrapping_sub(cur_token); - src = message.offset(cur_token as isize); - dest = addr_spec; - i = 0i32 as size_t; - while i < count { - if *src as libc::c_int != ' ' as i32 && *src as libc::c_int != '\t' as i32 { - *dest = *src; - dest = dest.offset(1isize) - } - src = src.offset(1isize); - i = i.wrapping_add(1) - } - *dest = '\u{0}' as i32 as libc::c_char; - cur_token = end; - *result = addr_spec; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - return res; -} -unsafe fn mailimf_name_addr_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut pdisplay_name: *mut *mut libc::c_char, - mut pangle_addr: *mut *mut libc::c_char, -) -> libc::c_int { - let mut display_name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut angle_addr: *mut libc::c_char = 0 as *mut libc::c_char; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - display_name = 0 as *mut libc::c_char; - angle_addr = 0 as *mut libc::c_char; - r = mailimf_display_name_parse(message, length, &mut cur_token, &mut display_name); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - r = mailimf_angle_addr_parse(message, length, &mut cur_token, &mut angle_addr); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - if !display_name.is_null() { - mailimf_display_name_free(display_name); - } - } else { - *pdisplay_name = display_name; - *pangle_addr = angle_addr; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} -unsafe fn mailimf_angle_addr_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut addr_spec: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_lower_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_addr_spec_parse(message, length, &mut cur_token, &mut addr_spec); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_greater_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - free(addr_spec as *mut libc::c_void); - return r; - } - *result = addr_spec; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_display_name_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - return mailimf_phrase_parse(message, length, indx, result); -} -unsafe fn mailimf_phrase_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut current_block: u64; - let mut gphrase: *mut MMAPString = 0 as *mut MMAPString; - let mut word: *mut libc::c_char = 0 as *mut libc::c_char; - let mut first: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut str: *mut libc::c_char = 0 as *mut libc::c_char; - let mut has_missing_closing_quote: libc::c_int = 0; - cur_token = *indx; - has_missing_closing_quote = 0i32; - gphrase = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - if gphrase.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - first = 1i32; - loop { - let mut missing_quote: libc::c_int = 0i32; - r = mailimf_fws_word_parse( - message, - length, - &mut cur_token, - &mut word, - &mut missing_quote, - ); - if 0 != missing_quote { - has_missing_closing_quote = 1i32 - } - if r == MAILIMF_NO_ERROR as libc::c_int { - if 0 == first { - if mmap_string_append_c(gphrase, ' ' as i32 as libc::c_char).is_null() { - mailimf_word_free(word); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 17261756273978092585; - break; - } - } - if mmap_string_append(gphrase, word).is_null() { - mailimf_word_free(word); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 17261756273978092585; - break; - } else { - mailimf_word_free(word); - first = 0i32 - } - } else { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 11636175345244025579; - break; - } - res = r; - current_block = 17261756273978092585; - break; - } - } - match current_block { - 11636175345244025579 => { - if 0 != first { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - if 0 != has_missing_closing_quote { - r = mailimf_char_parse( - message, - length, - &mut cur_token, - '\"' as i32 as libc::c_char, - ) - } - str = strdup((*gphrase).str_0); - if str.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - mmap_string_free(gphrase); - *result = str; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - _ => {} - } - mmap_string_free(gphrase); - } - return res; -} - -pub unsafe fn mailimf_fws_word_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, - mut p_missing_closing_quote: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut word: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut missing_closing_quote: libc::c_int = 0; - cur_token = *indx; - missing_closing_quote = 0i32; - r = mailimf_fws_atom_for_word_parse( - message, - length, - &mut cur_token, - &mut word, - &mut missing_closing_quote, - ); - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_fws_quoted_string_parse(message, length, &mut cur_token, &mut word) - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *result = word; - *indx = cur_token; - *p_missing_closing_quote = missing_closing_quote; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailimf_fws_quoted_string_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut gstr: *mut MMAPString = 0 as *mut MMAPString; - let mut ch: libc::c_char = 0; - let mut str: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - r = mailimf_dquote_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - gstr = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - if gstr.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - loop { - r = mailimf_fws_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - if mmap_string_append_c(gstr, ' ' as i32 as libc::c_char).is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 15096897878952122875; - break; - } - } else if r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r; - current_block = 15096897878952122875; - break; - } - r = mailimf_qcontent_parse(message, length, &mut cur_token, &mut ch); - if r == MAILIMF_NO_ERROR as libc::c_int { - if !mmap_string_append_c(gstr, ch).is_null() { - continue; - } - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 15096897878952122875; - break; - } else { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 5494826135382683477; - break; - } - res = r; - current_block = 15096897878952122875; - break; - } - } - match current_block { - 5494826135382683477 => { - r = mailimf_dquote_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - str = strdup((*gstr).str_0); - if str.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - mmap_string_free(gstr); - *indx = cur_token; - *result = str; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - _ => {} - } - mmap_string_free(gstr); - } - } - } - return res; -} -unsafe fn mailimf_dquote_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_char_parse(message, length, indx, '\"' as i32 as libc::c_char); -} -unsafe fn mailimf_qcontent_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut ch: libc::c_char = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - if 0 != is_qtext(*message.offset(cur_token as isize)) { - ch = *message.offset(cur_token as isize); - cur_token = cur_token.wrapping_add(1) - } else { - r = mailimf_quoted_pair_parse(message, length, &mut cur_token, &mut ch); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - *result = ch; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -/* -dot-atom = [CFWS] dot-atom-text [CFWS] -*/ -/* -dot-atom-text = 1*atext *("." 1*atext) -*/ -/* -qtext = NO-WS-CTL / ; Non white space controls - - %d33 / ; The rest of the US-ASCII - %d35-91 / ; characters not including "\" - %d93-126 ; or the quote character -*/ -#[inline] -unsafe fn is_qtext(mut ch: libc::c_char) -> libc::c_int { - let mut uch: libc::c_uchar = ch as libc::c_uchar; - if 0 != is_no_ws_ctl(ch) { - return 1i32; - } - if (uch as libc::c_int) < 33i32 { - return 0i32; - } - if uch as libc::c_int == 34i32 { - return 0i32; - } - if uch as libc::c_int == 92i32 { - return 0i32; - } - if uch as libc::c_int == 127i32 { - return 0i32; - } - return 1i32; -} -unsafe fn mailimf_fws_atom_for_word_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, - mut p_missing_closing_quote: *mut libc::c_int, -) -> libc::c_int { - let mut end: size_t = 0; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut word: *mut mailmime_encoded_word = 0 as *mut mailmime_encoded_word; - let mut has_fwd: libc::c_int = 0; - let mut missing_closing_quote: libc::c_int = 0; - let mut atom: *mut libc::c_char = 0 as *mut libc::c_char; - cur_token = *indx; - missing_closing_quote = 0i32; - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - end = cur_token; - r = mailmime_encoded_word_parse( - message, - length, - &mut cur_token, - &mut word, - &mut has_fwd, - &mut missing_closing_quote, - ); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - return mailimf_fws_atom_parse(message, length, indx, result); - } - mailmime_encoded_word_free(word); - atom = malloc( - cur_token - .wrapping_sub(end) - .wrapping_add(1i32 as libc::size_t), - ) as *mut libc::c_char; - if atom.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - strncpy( - atom, - message.offset(end as isize), - cur_token.wrapping_sub(end), - ); - *atom.offset(cur_token.wrapping_sub(end) as isize) = '\u{0}' as i32 as libc::c_char; - *result = atom; - *indx = cur_token; - *p_missing_closing_quote = missing_closing_quote; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - return res; -} - -pub unsafe fn mailimf_fws_atom_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut atom: *mut libc::c_char = 0 as *mut libc::c_char; - let mut end: size_t = 0; - cur_token = *indx; - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - end = cur_token; - if end >= length { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - while 0 != is_atext(*message.offset(end as isize)) { - end = end.wrapping_add(1); - if end >= length { - break; - } - } - if end == cur_token { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - atom = malloc( - end.wrapping_sub(cur_token) - .wrapping_add(1i32 as libc::size_t), - ) as *mut libc::c_char; - if atom.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - strncpy( - atom, - message.offset(cur_token as isize), - end.wrapping_sub(cur_token), - ); - *atom.offset(end.wrapping_sub(cur_token) as isize) = - '\u{0}' as i32 as libc::c_char; - cur_token = end; - *indx = cur_token; - *result = atom; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - return res; -} -/* -atext = ALPHA / DIGIT / ; Any character except controls, - "!" / "#" / ; SP, and specials. - "$" / "%" / ; Used for atoms - "&" / "'" / - "*" / "+" / - "-" / "/" / - "=" / "?" / - "^" / "_" / - "`" / "{" / - "|" / "}" / - "~" -*/ -#[inline] -unsafe fn is_atext(mut ch: libc::c_char) -> libc::c_int { - match ch as libc::c_int { - 32 | 9 | 10 | 13 | 60 | 62 | 44 | 34 | 58 | 59 => return 0i32, - _ => return 1i32, - }; -} -unsafe fn mailimf_group_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_group, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut display_name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut mailbox_list: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list; - let mut group: *mut mailimf_group = 0 as *mut mailimf_group; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut list: *mut clist = 0 as *mut clist; - cur_token = *indx; - mailbox_list = 0 as *mut mailimf_mailbox_list; - r = mailimf_display_name_parse(message, length, &mut cur_token, &mut display_name); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_mailbox_list_parse(message, length, &mut cur_token, &mut mailbox_list); - match r { - 0 => { - current_block = 1608152415753874203; - } - 1 => { - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - res = r; - current_block = 14904789583098922708; - } else { - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14904789583098922708; - } else { - mailbox_list = mailimf_mailbox_list_new(list); - if mailbox_list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - clist_free(list); - current_block = 14904789583098922708; - } else { - current_block = 1608152415753874203; - } - } - } - } - _ => { - res = r; - current_block = 14904789583098922708; - } - } - match current_block { - 14904789583098922708 => {} - _ => { - r = mailimf_semi_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - group = mailimf_group_new(display_name, mailbox_list); - if group.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *indx = cur_token; - *result = group; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - if !mailbox_list.is_null() { - mailimf_mailbox_list_free(mailbox_list); - } - } - } - } - mailimf_display_name_free(display_name); - } - return res; -} - -unsafe fn mailimf_semi_colon_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_unstrict_char_parse(message, length, indx, ';' as i32 as libc::c_char); -} - -/* - mailimf_mailbox_list_parse will parse the given mailbox list - - @param message this is a string containing the mailbox list - @param length this is the size of the given string - @param indx this is a pointer to the start of the mailbox list in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_mailbox_list_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_mailbox_list, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut list: *mut clist = 0 as *mut clist; - let mut mailbox_list: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_struct_list_parse( - message, - length, - &mut cur_token, - &mut list, - ',' as i32 as libc::c_char, - ::std::mem::transmute::< - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut *mut mailimf_mailbox, - ) -> libc::c_int, - >, - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut libc::c_void, - ) -> libc::c_int, - >, - >(Some(mailimf_mailbox_parse)), - ::std::mem::transmute::< - Option ()>, - Option libc::c_int>, - >(Some(mailimf_mailbox_free)), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - mailbox_list = mailimf_mailbox_list_new(list); - if mailbox_list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - clist_foreach( - list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailimf_mailbox_free), - ), - 0 as *mut libc::c_void, - ); - clist_free(list); - } else { - *result = mailbox_list; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} -unsafe fn mailimf_struct_list_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut clist, - mut symbol: libc::c_char, - mut parser: Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut libc::c_void, - ) -> libc::c_int, - >, - mut destructor: Option libc::c_int>, -) -> libc::c_int { - let mut current_block: u64; - let mut struct_list: *mut clist = 0 as *mut clist; - let mut cur_token: size_t = 0; - let mut value: *mut libc::c_void = 0 as *mut libc::c_void; - let mut final_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = parser.expect("non-null function pointer")( - message, - length, - &mut cur_token, - &mut value as *mut *mut libc::c_void as *mut libc::c_void, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - struct_list = clist_new(); - if struct_list.is_null() { - destructor.expect("non-null function pointer")(value); - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - r = clist_insert_after(struct_list, (*struct_list).last, value); - if r < 0i32 { - destructor.expect("non-null function pointer")(value); - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - final_token = cur_token; - loop { - r = mailimf_unstrict_char_parse(message, length, &mut cur_token, symbol); - if r != MAILIMF_NO_ERROR as libc::c_int { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9853141518545631134; - break; - } - res = r; - current_block = 17524159567010234572; - break; - } else { - r = parser.expect("non-null function pointer")( - message, - length, - &mut cur_token, - &mut value as *mut *mut libc::c_void as *mut libc::c_void, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 9853141518545631134; - break; - } - res = r; - current_block = 17524159567010234572; - break; - } else { - r = clist_insert_after(struct_list, (*struct_list).last, value); - if r < 0i32 { - destructor.expect("non-null function pointer")(value); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 17524159567010234572; - break; - } else { - final_token = cur_token - } - } - } - } - match current_block { - 17524159567010234572 => {} - _ => { - *result = struct_list; - *indx = final_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - clist_foreach( - struct_list, - ::std::mem::transmute::< - Option libc::c_int>, - clist_func, - >(destructor), - 0 as *mut libc::c_void, - ); - clist_free(struct_list); - } - } - return res; -} -unsafe fn mailimf_resent_cc_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_cc, -) -> libc::c_int { - let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - let mut cc: *mut mailimf_cc = 0 as *mut mailimf_cc; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Resent-Cc\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Resent-Cc\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_address_list_parse(message, length, &mut cur_token, &mut addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - cc = mailimf_cc_new(addr_list); - if cc.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = cc; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_address_list_free(addr_list); - } - } - } - return res; -} -unsafe fn mailimf_resent_to_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_to, -) -> libc::c_int { - let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - let mut to: *mut mailimf_to = 0 as *mut mailimf_to; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Resent-To\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Resent-To\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_address_list_parse(message, length, &mut cur_token, &mut addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - to = mailimf_to_new(addr_list); - if to.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = to; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_address_list_free(addr_list); - } - } - } - return res; -} -unsafe fn mailimf_resent_sender_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_sender, -) -> libc::c_int { - let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox; - let mut sender: *mut mailimf_sender = 0 as *mut mailimf_sender; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = length; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Resent-Sender\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Resent-Sender\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_mailbox_parse(message, length, &mut cur_token, &mut mb); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - sender = mailimf_sender_new(mb); - if sender.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = sender; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_mailbox_free(mb); - } - } - } - return res; -} -unsafe fn mailimf_resent_from_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_from, -) -> libc::c_int { - let mut mb_list: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list; - let mut from: *mut mailimf_from = 0 as *mut mailimf_from; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Resent-From\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Resent-From\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_mailbox_list_parse(message, length, &mut cur_token, &mut mb_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - from = mailimf_from_new(mb_list); - if from.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = from; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_mailbox_list_free(mb_list); - } - } - } - return res; -} -unsafe fn mailimf_resent_date_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_orig_date, -) -> libc::c_int { - let mut orig_date: *mut mailimf_orig_date = 0 as *mut mailimf_orig_date; - let mut date_time: *mut mailimf_date_time = 0 as *mut mailimf_date_time; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Resent-Date\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Resent-Date\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_date_time_parse(message, length, &mut cur_token, &mut date_time); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - orig_date = mailimf_orig_date_new(date_time); - if orig_date.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = orig_date; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_date_time_free(date_time); - } - } - } - return res; -} -/* - mailimf_date_time_parse will parse the given RFC 2822 date - - @param message this is a string containing the date - @param length this is the size of the given string - @param indx this is a pointer to the start of the date in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_date_time_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_date_time, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut day_of_week: libc::c_int = 0; - let mut date_time: *mut mailimf_date_time = 0 as *mut mailimf_date_time; - let mut day: libc::c_int = 0; - let mut month: libc::c_int = 0; - let mut year: libc::c_int = 0; - let mut hour: libc::c_int = 0; - let mut min: libc::c_int = 0; - let mut sec: libc::c_int = 0; - let mut zone: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - day_of_week = -1i32; - r = mailimf_day_of_week_parse(message, length, &mut cur_token, &mut day_of_week); - if r == MAILIMF_NO_ERROR as libc::c_int { - r = mailimf_comma_parse(message, length, &mut cur_token); - if !(r == MAILIMF_ERROR_PARSE as libc::c_int) { - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - } else if r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - day = 0i32; - month = 0i32; - year = 0i32; - r = mailimf_date_parse( - message, - length, - &mut cur_token, - &mut day, - &mut month, - &mut year, - ); - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_broken_date_parse( - message, - length, - &mut cur_token, - &mut day, - &mut month, - &mut year, - ) - } else if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - hour = 0i32; - min = 0i32; - sec = 0i32; - zone = 0i32; - r = mailimf_time_parse( - message, - length, - &mut cur_token, - &mut hour, - &mut min, - &mut sec, - &mut zone, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone); - if date_time.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - *indx = cur_token; - *result = date_time; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_time_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut phour: *mut libc::c_int, - mut pmin: *mut libc::c_int, - mut psec: *mut libc::c_int, - mut pzone: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut hour: libc::c_int = 0; - let mut min: libc::c_int = 0; - let mut sec: libc::c_int = 0; - let mut zone: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_time_of_day_parse( - message, - length, - &mut cur_token, - &mut hour, - &mut min, - &mut sec, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_zone_parse(message, length, &mut cur_token, &mut zone); - if !(r == MAILIMF_NO_ERROR as libc::c_int) { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - zone = 0i32 - } else { - return r; - } - } - *phour = hour; - *pmin = min; - *psec = sec; - *pzone = zone; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_zone_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut zone: libc::c_int = 0; - let mut sign: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut value: uint32_t = 0; - cur_token = *indx; - if cur_token.wrapping_add(1i32 as libc::size_t) < length { - if *message.offset(cur_token as isize) as libc::c_int == 'U' as i32 - && *message.offset(cur_token.wrapping_add(1i32 as libc::size_t) as isize) as libc::c_int - == 'T' as i32 - { - *result = 1i32; - *indx = cur_token.wrapping_add(2i32 as libc::size_t); - return MAILIMF_NO_ERROR as libc::c_int; - } - } - zone = 0i32; - if cur_token.wrapping_add(2i32 as libc::size_t) < length { - let mut state: libc::c_int = 0; - state = STATE_ZONE_1 as libc::c_int; - while state <= 2i32 { - match state { - 0 => match *message.offset(cur_token as isize) as libc::c_int { - 71 => { - if *message.offset(cur_token.wrapping_add(1i32 as libc::size_t) as isize) - as libc::c_int - == 'M' as i32 - && *message - .offset(cur_token.wrapping_add(2i32 as libc::size_t) as isize) - as libc::c_int - == 'T' as i32 - { - if cur_token.wrapping_add(3i32 as libc::size_t) < length - && (*message - .offset(cur_token.wrapping_add(3i32 as libc::size_t) as isize) - as libc::c_int - == '+' as i32 - || *message.offset( - cur_token.wrapping_add(3i32 as libc::size_t) as isize - ) as libc::c_int - == '-' as i32) - { - cur_token = (cur_token as libc::size_t) - .wrapping_add(3i32 as libc::size_t) - as size_t as size_t; - state = STATE_ZONE_CONT as libc::c_int - } else { - zone = 0i32; - state = STATE_ZONE_OK as libc::c_int - } - } else { - state = STATE_ZONE_ERR as libc::c_int - } - } - 69 => { - zone = -5i32; - state = STATE_ZONE_2 as libc::c_int - } - 67 => { - zone = -6i32; - state = STATE_ZONE_2 as libc::c_int - } - 77 => { - zone = -7i32; - state = STATE_ZONE_2 as libc::c_int - } - 80 => { - zone = -8i32; - state = STATE_ZONE_2 as libc::c_int - } - _ => state = STATE_ZONE_CONT as libc::c_int, - }, - 1 => { - match *message.offset(cur_token.wrapping_add(1i32 as libc::size_t) as isize) - as libc::c_int - { - 83 => state = STATE_ZONE_3 as libc::c_int, - 68 => { - zone += 1; - state = STATE_ZONE_3 as libc::c_int - } - _ => state = STATE_ZONE_ERR as libc::c_int, - } - } - 2 => { - if *message.offset(cur_token.wrapping_add(2i32 as libc::size_t) as isize) - as libc::c_int - == 'T' as i32 - { - zone *= 100i32; - state = STATE_ZONE_OK as libc::c_int - } else { - state = STATE_ZONE_ERR as libc::c_int - } - } - _ => {} - } - } - match state { - 3 => { - *result = zone; - *indx = cur_token.wrapping_add(3i32 as libc::size_t); - return MAILIMF_NO_ERROR as libc::c_int; - } - 4 => return MAILIMF_ERROR_PARSE as libc::c_int, - _ => {} - } - } - sign = 1i32; - r = mailimf_plus_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - sign = 1i32 - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_minus_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - sign = -1i32 - } - } - if !(r == MAILIMF_NO_ERROR as libc::c_int) { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - sign = 1i32 - } else { - return r; - } - } - r = mailimf_number_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - zone = value.wrapping_mul(sign as libc::c_uint) as libc::c_int; - *indx = cur_token; - *result = zone; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailimf_number_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut uint32_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut digit: libc::c_int = 0; - let mut number: uint32_t = 0; - let mut parsed: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - parsed = 0i32; - number = 0i32 as uint32_t; - loop { - r = mailimf_digit_parse(message, length, &mut cur_token, &mut digit); - if r != MAILIMF_NO_ERROR as libc::c_int { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - break; - } - return r; - } else { - number = (number as libc::c_uint).wrapping_mul(10i32 as libc::c_uint) as uint32_t - as uint32_t; - number = (number as libc::c_uint).wrapping_add(digit as libc::c_uint) as uint32_t - as uint32_t; - parsed = 1i32 - } - } - if 0 == parsed { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - *result = number; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_digit_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - cur_token = *indx; - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - if 0 != is_digit(*message.offset(cur_token as isize)) { - *result = *message.offset(cur_token as isize) as libc::c_int - '0' as i32; - cur_token = cur_token.wrapping_add(1); - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } else { - return MAILIMF_ERROR_PARSE as libc::c_int; - }; -} -/* *************************************************************** */ -#[inline] -unsafe fn is_digit(mut ch: libc::c_char) -> libc::c_int { - return (ch as libc::c_int >= '0' as i32 && ch as libc::c_int <= '9' as i32) as libc::c_int; -} -unsafe fn mailimf_minus_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_unstrict_char_parse(message, length, indx, '-' as i32 as libc::c_char); -} -unsafe fn mailimf_plus_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_unstrict_char_parse(message, length, indx, '+' as i32 as libc::c_char); -} -unsafe fn mailimf_time_of_day_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut phour: *mut libc::c_int, - mut pmin: *mut libc::c_int, - mut psec: *mut libc::c_int, -) -> libc::c_int { - let mut hour: libc::c_int = 0; - let mut min: libc::c_int = 0; - let mut sec: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_hour_parse(message, length, &mut cur_token, &mut hour); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_minute_parse(message, length, &mut cur_token, &mut min); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_colon_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - r = mailimf_second_parse(message, length, &mut cur_token, &mut sec); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - sec = 0i32 - } else { - return r; - } - *phour = hour; - *pmin = min; - *psec = sec; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_second_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut second: uint32_t = 0; - let mut r: libc::c_int = 0; - r = mailimf_number_parse(message, length, indx, &mut second); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *result = second as libc::c_int; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_minute_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut minute: uint32_t = 0; - let mut r: libc::c_int = 0; - r = mailimf_number_parse(message, length, indx, &mut minute); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *result = minute as libc::c_int; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_hour_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut hour: uint32_t = 0; - let mut r: libc::c_int = 0; - r = mailimf_number_parse(message, length, indx, &mut hour); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *result = hour as libc::c_int; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_broken_date_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut pday: *mut libc::c_int, - mut pmonth: *mut libc::c_int, - mut pyear: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut day: libc::c_int = 0; - let mut month: libc::c_int = 0; - let mut year: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - month = 1i32; - r = mailimf_month_parse(message, length, &mut cur_token, &mut month); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - day = 1i32; - r = mailimf_day_parse(message, length, &mut cur_token, &mut day); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - year = 2001i32; - r = mailimf_year_parse(message, length, &mut cur_token, &mut year); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *pday = day; - *pmonth = month; - *pyear = year; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_year_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut number: uint32_t = 0; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_number_parse(message, length, &mut cur_token, &mut number); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - *result = number as libc::c_int; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_day_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut day: uint32_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_number_parse(message, length, &mut cur_token, &mut day); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *result = day as libc::c_int; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_month_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut month: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_month_name_parse(message, length, &mut cur_token, &mut month); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *result = month; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_month_name_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut month: libc::c_int = 0; - let mut guessed_month: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - guessed_month = guess_month(message, length, cur_token); - if guessed_month == -1i32 { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - month_names[(guessed_month - 1i32) as usize].str_0, - strlen(month_names[(guessed_month - 1i32) as usize].str_0), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - month = guessed_month; - *result = month; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -/* -month-name = "Jan" / "Feb" / "Mar" / "Apr" / - "May" / "Jun" / "Jul" / "Aug" / - "Sep" / "Oct" / "Nov" / "Dec" -*/ -static mut month_names: [mailimf_token_value; 12] = [ - mailimf_token_value { - value: 1i32, - str_0: b"Jan\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 2i32, - str_0: b"Feb\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 3i32, - str_0: b"Mar\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 4i32, - str_0: b"Apr\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 5i32, - str_0: b"May\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 6i32, - str_0: b"Jun\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 7i32, - str_0: b"Jul\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 8i32, - str_0: b"Aug\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 9i32, - str_0: b"Sep\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 10i32, - str_0: b"Oct\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 11i32, - str_0: b"Nov\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 12i32, - str_0: b"Dec\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, -]; -unsafe fn guess_month( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: size_t, -) -> libc::c_int { - let mut state: libc::c_int = 0; - state = MONTH_START as libc::c_int; - loop { - if indx >= length { - return -1i32; - } - match state { - 0 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 74 => state = MONTH_J as libc::c_int, - 70 => return 2i32, - 77 => state = MONTH_M as libc::c_int, - 65 => state = MONTH_A as libc::c_int, - 83 => return 9i32, - 79 => return 10i32, - 78 => return 11i32, - 68 => return 12i32, - _ => return -1i32, - } - } - 1 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 65 => return 1i32, - 85 => state = MONTH_JU as libc::c_int, - _ => return -1i32, - } - } - 2 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 78 => return 6i32, - 76 => return 7i32, - _ => return -1i32, - } - } - 3 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 65 => state = MONTH_MA as libc::c_int, - _ => return -1i32, - } - } - 4 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 89 => return 5i32, - 82 => return 3i32, - _ => return -1i32, - } - } - 5 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 80 => return 4i32, - 85 => return 8i32, - _ => return -1i32, - } - } - _ => {} - } - indx = indx.wrapping_add(1) - } -} - -unsafe fn mailimf_date_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut pday: *mut libc::c_int, - mut pmonth: *mut libc::c_int, - mut pyear: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut day: libc::c_int = 0; - let mut month: libc::c_int = 0; - let mut year: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - day = 1i32; - r = mailimf_day_parse(message, length, &mut cur_token, &mut day); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - month = 1i32; - r = mailimf_month_parse(message, length, &mut cur_token, &mut month); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - year = 2001i32; - r = mailimf_year_parse(message, length, &mut cur_token, &mut year); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *pday = day; - *pmonth = month; - *pyear = year; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_comma_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_unstrict_char_parse(message, length, indx, ',' as i32 as libc::c_char); -} -unsafe fn mailimf_day_of_week_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut day_of_week: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_day_name_parse(message, length, &mut cur_token, &mut day_of_week); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - *result = day_of_week; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_day_name_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut day_of_week: libc::c_int = 0; - let mut guessed_day: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - guessed_day = guess_day_name(message, length, cur_token); - if guessed_day == -1i32 { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - day_names[(guessed_day - 1i32) as usize].str_0, - strlen(day_names[(guessed_day - 1i32) as usize].str_0), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - day_of_week = guessed_day; - *result = day_of_week; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -static mut day_names: [mailimf_token_value; 7] = [ - mailimf_token_value { - value: 1i32, - str_0: b"Mon\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 2i32, - str_0: b"Tue\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 3i32, - str_0: b"Wed\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 4i32, - str_0: b"Thu\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 5i32, - str_0: b"Fri\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 6i32, - str_0: b"Sat\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, - mailimf_token_value { - value: 7i32, - str_0: b"Sun\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - }, -]; -unsafe fn guess_day_name( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: size_t, -) -> libc::c_int { - let mut state: libc::c_int = 0; - state = DAY_NAME_START as libc::c_int; - loop { - if indx >= length { - return -1i32; - } - match state { - 0 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 77 => return 1i32, - 84 => state = DAY_NAME_T as libc::c_int, - 87 => return 3i32, - 70 => return 5i32, - 83 => state = DAY_NAME_S as libc::c_int, - _ => return -1i32, - } - } - 1 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 85 => return 2i32, - 72 => return 4i32, - _ => return -1i32, - } - } - 2 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 65 => return 6i32, - 85 => return 7i32, - _ => return -1i32, - } - } - _ => {} - } - indx = indx.wrapping_add(1) - } -} -unsafe fn mailimf_return_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_return, -) -> libc::c_int { - let mut path: *mut mailimf_path = 0 as *mut mailimf_path; - let mut return_path: *mut mailimf_return = 0 as *mut mailimf_return; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Return-Path\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Return-Path\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - path = 0 as *mut mailimf_path; - r = mailimf_path_parse(message, length, &mut cur_token, &mut path); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - return_path = mailimf_return_new(path); - if return_path.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = return_path; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_path_free(path); - } - } - } - return res; -} -unsafe fn mailimf_path_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_path, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut addr_spec: *mut libc::c_char = 0 as *mut libc::c_char; - let mut path: *mut mailimf_path = 0 as *mut mailimf_path; - let mut res: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - addr_spec = 0 as *mut libc::c_char; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - r = mailimf_lower_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_addr_spec_parse(message, length, &mut cur_token, &mut addr_spec); - match r { - 0 => { - current_block = 2370887241019905314; - } - 1 => { - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - res = r; - current_block = 14973541214802992465; - } else { - current_block = 2370887241019905314; - } - } - _ => return r, - } - match current_block { - 14973541214802992465 => {} - _ => { - r = mailimf_greater_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - path = mailimf_path_new(addr_spec); - if path.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if addr_spec.is_null() { - mailimf_addr_spec_free(addr_spec); - } - } else { - *indx = cur_token; - *result = path; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - } - } - return res; -} -unsafe fn mailimf_keywords_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_keywords, -) -> libc::c_int { - let mut keywords: *mut mailimf_keywords = 0 as *mut mailimf_keywords; - let mut list: *mut clist = 0 as *mut clist; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Keywords\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Keywords\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_struct_list_parse( - message, - length, - &mut cur_token, - &mut list, - ',' as i32 as libc::c_char, - ::std::mem::transmute::< - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut *mut libc::c_char, - ) -> libc::c_int, - >, - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut libc::c_void, - ) -> libc::c_int, - >, - >(Some(mailimf_phrase_parse)), - ::std::mem::transmute::< - Option ()>, - Option libc::c_int>, - >(Some(mailimf_phrase_free)), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - keywords = mailimf_keywords_new(list); - if keywords.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = keywords; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - clist_foreach( - list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailimf_phrase_free)), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - } - } - return res; -} -unsafe fn mailimf_comments_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_comments, -) -> libc::c_int { - let mut comments: *mut mailimf_comments = 0 as *mut mailimf_comments; - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Comments\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Comments\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstructured_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - comments = mailimf_comments_new(value); - if comments.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = comments; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_unstructured_free(value); - } - } - } - return res; -} -unsafe fn mailimf_subject_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_subject, -) -> libc::c_int { - let mut subject: *mut mailimf_subject = 0 as *mut mailimf_subject; - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Subject\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Subject\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstructured_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - subject = mailimf_subject_new(value); - if subject.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = subject; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_unstructured_free(value); - } - } - } - return res; -} - -/* exported for IMAP */ -pub unsafe fn mailimf_references_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_references, -) -> libc::c_int { - let mut references: *mut mailimf_references = 0 as *mut mailimf_references; - let mut cur_token: size_t = 0; - let mut msg_id_list: *mut clist = 0 as *mut clist; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"References\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"References\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_msg_id_list_parse(message, length, &mut cur_token, &mut msg_id_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - references = mailimf_references_new(msg_id_list); - if references.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = references; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - clist_foreach( - msg_id_list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailimf_msg_id_free)), - 0 as *mut libc::c_void, - ); - clist_free(msg_id_list); - } - } - } - return res; -} - -pub unsafe fn mailimf_msg_id_list_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut clist, -) -> libc::c_int { - return mailimf_struct_multiple_parse( - message, - length, - indx, - result, - ::std::mem::transmute::< - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut *mut libc::c_char, - ) -> libc::c_int, - >, - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut libc::c_void, - ) -> libc::c_int, - >, - >(Some(mailimf_unstrict_msg_id_parse)), - ::std::mem::transmute::< - Option ()>, - Option libc::c_int>, - >(Some(mailimf_msg_id_free)), - ); -} -unsafe fn mailimf_unstrict_msg_id_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut msgid: *mut libc::c_char = 0 as *mut libc::c_char; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_parse_unwanted_msg_id(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_msg_id_parse(message, length, &mut cur_token, &mut msgid); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_parse_unwanted_msg_id(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - free(msgid as *mut libc::c_void); - return r; - } - *result = msgid; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_parse_unwanted_msg_id( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut word: *mut libc::c_char = 0 as *mut libc::c_char; - let mut token_parsed: libc::c_int = 0; - cur_token = *indx; - token_parsed = 1i32; - while 0 != token_parsed { - token_parsed = 0i32; - r = mailimf_word_parse(message, length, &mut cur_token, &mut word); - if r == MAILIMF_NO_ERROR as libc::c_int { - mailimf_word_free(word); - token_parsed = 1i32 - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - } else { - return r; - } - r = mailimf_semi_colon_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - token_parsed = 1i32 - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - } else { - return r; - } - r = mailimf_comma_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - token_parsed = 1i32 - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - } else { - return r; - } - r = mailimf_plus_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - token_parsed = 1i32 - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - } else { - return r; - } - r = mailimf_colon_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - token_parsed = 1i32 - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - } else { - return r; - } - r = mailimf_point_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - token_parsed = 1i32 - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - } else { - return r; - } - r = mailimf_at_sign_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - token_parsed = 1i32 - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - } else { - return r; - } - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_at_sign_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_unstrict_char_parse(message, length, indx, '@' as i32 as libc::c_char); -} -unsafe fn mailimf_point_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - return mailimf_unstrict_char_parse(message, length, indx, '.' as i32 as libc::c_char); -} - -pub unsafe fn mailimf_word_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut word: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_atom_parse(message, length, &mut cur_token, &mut word); - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_quoted_string_parse(message, length, &mut cur_token, &mut word) - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *result = word; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailimf_quoted_string_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut gstr: *mut MMAPString = 0 as *mut MMAPString; - let mut ch: libc::c_char = 0; - let mut str: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - r = mailimf_dquote_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - gstr = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - if gstr.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - loop { - r = mailimf_fws_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - if mmap_string_append_c(gstr, ' ' as i32 as libc::c_char).is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14861901777624095282; - break; - } - } else if r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r; - current_block = 14861901777624095282; - break; - } - r = mailimf_qcontent_parse(message, length, &mut cur_token, &mut ch); - if r == MAILIMF_NO_ERROR as libc::c_int { - if !mmap_string_append_c(gstr, ch).is_null() { - continue; - } - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14861901777624095282; - break; - } else { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 5494826135382683477; - break; - } - res = r; - current_block = 14861901777624095282; - break; - } - } - match current_block { - 5494826135382683477 => { - r = mailimf_dquote_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - str = strdup((*gstr).str_0); - if str.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - mmap_string_free(gstr); - *indx = cur_token; - *result = str; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - _ => {} - } - mmap_string_free(gstr); - } - } - } - return res; -} - -pub unsafe fn mailimf_atom_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut atom: *mut libc::c_char = 0 as *mut libc::c_char; - let mut end: size_t = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - end = cur_token; - if end >= length { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - while 0 != is_atext(*message.offset(end as isize)) { - end = end.wrapping_add(1); - if end >= length { - break; - } - } - if end == cur_token { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - atom = malloc( - end.wrapping_sub(cur_token) - .wrapping_add(1i32 as libc::size_t), - ) as *mut libc::c_char; - if atom.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - strncpy( - atom, - message.offset(cur_token as isize), - end.wrapping_sub(cur_token), - ); - *atom.offset(end.wrapping_sub(cur_token) as isize) = - '\u{0}' as i32 as libc::c_char; - cur_token = end; - *indx = cur_token; - *result = atom; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - return res; -} -unsafe fn mailimf_struct_multiple_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut clist, - mut parser: Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut libc::c_void, - ) -> libc::c_int, - >, - mut destructor: Option libc::c_int>, -) -> libc::c_int { - let mut current_block: u64; - let mut struct_list: *mut clist = 0 as *mut clist; - let mut cur_token: size_t = 0; - let mut value: *mut libc::c_void = 0 as *mut libc::c_void; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = parser.expect("non-null function pointer")( - message, - length, - &mut cur_token, - &mut value as *mut *mut libc::c_void as *mut libc::c_void, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - struct_list = clist_new(); - if struct_list.is_null() { - destructor.expect("non-null function pointer")(value); - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - r = clist_insert_after(struct_list, (*struct_list).last, value); - if r < 0i32 { - destructor.expect("non-null function pointer")(value); - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - loop { - r = parser.expect("non-null function pointer")( - message, - length, - &mut cur_token, - &mut value as *mut *mut libc::c_void as *mut libc::c_void, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 11057878835866523405; - break; - } - res = r; - current_block = 8222683242185098763; - break; - } else { - r = clist_insert_after(struct_list, (*struct_list).last, value); - if !(r < 0i32) { - continue; - } - destructor.expect("non-null function pointer")(value); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 8222683242185098763; - break; - } - } - match current_block { - 8222683242185098763 => {} - _ => { - *result = struct_list; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - clist_foreach( - struct_list, - ::std::mem::transmute::< - Option libc::c_int>, - clist_func, - >(destructor), - 0 as *mut libc::c_void, - ); - clist_free(struct_list); - } - } - return res; -} -unsafe fn mailimf_in_reply_to_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_in_reply_to, -) -> libc::c_int { - let mut in_reply_to: *mut mailimf_in_reply_to = 0 as *mut mailimf_in_reply_to; - let mut cur_token: size_t = 0; - let mut msg_id_list: *mut clist = 0 as *mut clist; - let mut res: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"In-Reply-To\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"In-Reply-To\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_msg_id_list_parse(message, length, &mut cur_token, &mut msg_id_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - in_reply_to = mailimf_in_reply_to_new(msg_id_list); - if in_reply_to.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = in_reply_to; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - clist_foreach( - msg_id_list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailimf_msg_id_free)), - 0 as *mut libc::c_void, - ); - clist_free(msg_id_list); - } - } - } - return res; -} -unsafe fn mailimf_message_id_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_message_id, -) -> libc::c_int { - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut cur_token: size_t = 0; - let mut message_id: *mut mailimf_message_id = 0 as *mut mailimf_message_id; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Message-ID\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Message-ID\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_msg_id_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - message_id = mailimf_message_id_new(value); - if message_id.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = message_id; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_msg_id_free(value); - } - } - } - return res; -} -unsafe fn mailimf_bcc_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_bcc, -) -> libc::c_int { - let mut current_block: u64; - let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - let mut bcc: *mut mailimf_bcc = 0 as *mut mailimf_bcc; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - addr_list = 0 as *mut mailimf_address_list; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Bcc\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Bcc\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_address_list_parse(message, length, &mut cur_token, &mut addr_list); - match r { - 0 => { - /* do nothing */ - current_block = 2838571290723028321; - } - 1 => { - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - res = r; - current_block = 15260376711225273221; - } else { - current_block = 2838571290723028321; - } - } - _ => { - res = r; - current_block = 15260376711225273221; - } - } - match current_block { - 15260376711225273221 => {} - _ => { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - bcc = mailimf_bcc_new(addr_list); - if bcc.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = bcc; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - } - } - if !addr_list.is_null() { - mailimf_address_list_free(addr_list); - } - return res; -} -unsafe fn mailimf_cc_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_cc, -) -> libc::c_int { - let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - let mut cc: *mut mailimf_cc = 0 as *mut mailimf_cc; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Cc\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Cc\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_address_list_parse(message, length, &mut cur_token, &mut addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - cc = mailimf_cc_new(addr_list); - if cc.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = cc; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_address_list_free(addr_list); - } - } - } - return res; -} -unsafe fn mailimf_to_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_to, -) -> libc::c_int { - let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - let mut to: *mut mailimf_to = 0 as *mut mailimf_to; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"To\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"To\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_address_list_parse(message, length, &mut cur_token, &mut addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - to = mailimf_to_new(addr_list); - if to.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = to; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_address_list_free(addr_list); - } - } - } - return res; -} -unsafe fn mailimf_reply_to_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_reply_to, -) -> libc::c_int { - let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - let mut reply_to: *mut mailimf_reply_to = 0 as *mut mailimf_reply_to; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Reply-To\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Reply-To\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_address_list_parse(message, length, &mut cur_token, &mut addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - reply_to = mailimf_reply_to_new(addr_list); - if reply_to.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = reply_to; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_address_list_free(addr_list); - } - } - } - return res; -} -unsafe fn mailimf_sender_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_sender, -) -> libc::c_int { - let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox; - let mut sender: *mut mailimf_sender = 0 as *mut mailimf_sender; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Sender\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Sender\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_mailbox_parse(message, length, &mut cur_token, &mut mb); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - sender = mailimf_sender_new(mb); - if sender.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = sender; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_mailbox_free(mb); - } - } - } - return res; -} -unsafe fn mailimf_from_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_from, -) -> libc::c_int { - let mut mb_list: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list; - let mut from: *mut mailimf_from = 0 as *mut mailimf_from; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"From\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"From\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_colon_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_mailbox_list_parse(message, length, &mut cur_token, &mut mb_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - from = mailimf_from_new(mb_list); - if from.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = from; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - mailimf_mailbox_list_free(mb_list); - } - } - } - return res; -} -unsafe fn mailimf_orig_date_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_orig_date, -) -> libc::c_int { - let mut date_time: *mut mailimf_date_time = 0 as *mut mailimf_date_time; - let mut orig_date: *mut mailimf_orig_date = 0 as *mut mailimf_orig_date; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"Date:\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"Date:\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_date_time_parse(message, length, &mut cur_token, &mut date_time); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_ignore_unstructured_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - orig_date = mailimf_orig_date_new(date_time); - if orig_date.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = orig_date; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - mailimf_date_time_free(date_time); - } - } - return res; -} -unsafe fn mailimf_ignore_unstructured_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut state: libc::c_int = 0; - let mut terminal: size_t = 0; - cur_token = *indx; - state = UNSTRUCTURED_START as libc::c_int; - terminal = cur_token; - while state != UNSTRUCTURED_OUT as libc::c_int { - match state { - 0 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - terminal = cur_token; - match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = UNSTRUCTURED_CR as libc::c_int, - 10 => state = UNSTRUCTURED_LF as libc::c_int, - _ => state = UNSTRUCTURED_START as libc::c_int, - } - } - 1 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 10 => state = UNSTRUCTURED_LF as libc::c_int, - _ => state = UNSTRUCTURED_START as libc::c_int, - } - } - 2 => { - if cur_token >= length { - state = UNSTRUCTURED_OUT as libc::c_int - } else { - match *message.offset(cur_token as isize) as libc::c_int { - 9 | 32 => state = UNSTRUCTURED_WSP as libc::c_int, - _ => state = UNSTRUCTURED_OUT as libc::c_int, - } - } - } - 3 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = UNSTRUCTURED_CR as libc::c_int, - 10 => state = UNSTRUCTURED_LF as libc::c_int, - _ => state = UNSTRUCTURED_START as libc::c_int, - } - } - _ => {} - } - cur_token = cur_token.wrapping_add(1) - } - *indx = terminal; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn guess_header_type( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: size_t, -) -> libc::c_int { - let mut state: libc::c_int = 0; - let mut r: libc::c_int = 0; - state = HEADER_START as libc::c_int; - loop { - if indx >= length { - return MAILIMF_FIELD_NONE as libc::c_int; - } - match state { - 0 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 66 => return MAILIMF_FIELD_BCC as libc::c_int, - 67 => state = HEADER_C as libc::c_int, - 68 => return MAILIMF_FIELD_ORIG_DATE as libc::c_int, - 70 => return MAILIMF_FIELD_FROM as libc::c_int, - 73 => return MAILIMF_FIELD_IN_REPLY_TO as libc::c_int, - 75 => return MAILIMF_FIELD_KEYWORDS as libc::c_int, - 77 => return MAILIMF_FIELD_MESSAGE_ID as libc::c_int, - 82 => state = HEADER_R as libc::c_int, - 84 => return MAILIMF_FIELD_TO as libc::c_int, - 83 => state = HEADER_S as libc::c_int, - _ => return MAILIMF_FIELD_NONE as libc::c_int, - } - } - 1 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 79 => return MAILIMF_FIELD_COMMENTS as libc::c_int, - 67 => return MAILIMF_FIELD_CC as libc::c_int, - _ => return MAILIMF_FIELD_NONE as libc::c_int, - } - } - 2 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 69 => state = HEADER_RE as libc::c_int, - _ => return MAILIMF_FIELD_NONE as libc::c_int, - } - } - 3 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 70 => return MAILIMF_FIELD_REFERENCES as libc::c_int, - 80 => return MAILIMF_FIELD_REPLY_TO as libc::c_int, - 83 => state = HEADER_RES as libc::c_int, - 84 => return MAILIMF_FIELD_RETURN_PATH as libc::c_int, - _ => return MAILIMF_FIELD_NONE as libc::c_int, - } - } - 4 => { - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 69 => return MAILIMF_FIELD_SENDER as libc::c_int, - 85 => return MAILIMF_FIELD_SUBJECT as libc::c_int, - _ => return MAILIMF_FIELD_NONE as libc::c_int, - } - } - 5 => { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut indx, - b"ent-\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"ent-\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return MAILIMF_FIELD_NONE as libc::c_int; - } - if indx >= length { - return MAILIMF_FIELD_NONE as libc::c_int; - } - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 68 => return MAILIMF_FIELD_RESENT_DATE as libc::c_int, - 70 => return MAILIMF_FIELD_RESENT_FROM as libc::c_int, - 83 => return MAILIMF_FIELD_RESENT_SENDER as libc::c_int, - 84 => return MAILIMF_FIELD_RESENT_TO as libc::c_int, - 67 => return MAILIMF_FIELD_RESENT_CC as libc::c_int, - 66 => return MAILIMF_FIELD_RESENT_BCC as libc::c_int, - 77 => return MAILIMF_FIELD_RESENT_MSG_ID as libc::c_int, - _ => return MAILIMF_FIELD_NONE as libc::c_int, - } - } - _ => {} - } - indx = indx.wrapping_add(1) - } -} -/* - mailimf_envelope_fields_parse will parse the given fields (Date, - From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, - References and Subject) - - @param message this is a string containing the header fields - @param length this is the size of the given string - @param indx this is a pointer to the start of the header fields in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ - -pub unsafe fn mailimf_envelope_fields_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_fields, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut list: *mut clist = 0 as *mut clist; - let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - loop { - let mut elt: *mut mailimf_field = 0 as *mut mailimf_field; - r = mailimf_envelope_field_parse(message, length, &mut cur_token, &mut elt); - if r == MAILIMF_NO_ERROR as libc::c_int { - r = clist_insert_after(list, (*list).last, elt as *mut libc::c_void); - if !(r < 0i32) { - continue; - } - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 894413572976700158; - break; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_ignore_field_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - continue; - } - /* do nothing */ - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 2719512138335094285; - break; - } - res = r; - current_block = 894413572976700158; - break; - } else { - res = r; - current_block = 894413572976700158; - break; - } - } - match current_block { - 2719512138335094285 => { - fields = mailimf_fields_new(list); - if fields.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = fields; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - _ => {} - } - if !list.is_null() { - clist_foreach( - list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailimf_field_free), - ), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - } - return res; -} -/* - mailimf_ignore_field_parse will skip the given field - - @param message this is a string containing the header field - @param length this is the size of the given string - @param indx this is a pointer to the start of the header field in - the given string, (* indx) is modified to point at the end - of the parsed data - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_ignore_field_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut has_field: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut state: libc::c_int = 0; - let mut terminal: size_t = 0; - has_field = 0i32; - cur_token = *indx; - terminal = cur_token; - state = UNSTRUCTURED_START as libc::c_int; - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 13 => return MAILIMF_ERROR_PARSE as libc::c_int, - 10 => return MAILIMF_ERROR_PARSE as libc::c_int, - _ => {} - } - while state != UNSTRUCTURED_OUT as libc::c_int { - match state { - 0 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = UNSTRUCTURED_CR as libc::c_int, - 10 => state = UNSTRUCTURED_LF as libc::c_int, - 58 => { - has_field = 1i32; - state = UNSTRUCTURED_START as libc::c_int - } - _ => state = UNSTRUCTURED_START as libc::c_int, - } - } - 1 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 10 => state = UNSTRUCTURED_LF as libc::c_int, - 58 => { - has_field = 1i32; - state = UNSTRUCTURED_START as libc::c_int - } - _ => state = UNSTRUCTURED_START as libc::c_int, - } - } - 2 => { - if cur_token >= length { - terminal = cur_token; - state = UNSTRUCTURED_OUT as libc::c_int - } else { - match *message.offset(cur_token as isize) as libc::c_int { - 9 | 32 => state = UNSTRUCTURED_WSP as libc::c_int, - _ => { - terminal = cur_token; - state = UNSTRUCTURED_OUT as libc::c_int - } - } - } - } - 3 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = UNSTRUCTURED_CR as libc::c_int, - 10 => state = UNSTRUCTURED_LF as libc::c_int, - 58 => { - has_field = 1i32; - state = UNSTRUCTURED_START as libc::c_int - } - _ => state = UNSTRUCTURED_START as libc::c_int, - } - } - _ => {} - } - cur_token = cur_token.wrapping_add(1) - } - if 0 == has_field { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - *indx = terminal; - return MAILIMF_NO_ERROR as libc::c_int; -} -/* -static int mailimf_ftext_parse(const char * message, size_t length, - size_t * indx, gchar * result) -{ - return mailimf_typed_text_parse(message, length, indx, result, is_ftext); -} -*/ -unsafe fn mailimf_envelope_field_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_field, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut type_0: libc::c_int = 0; - let mut orig_date: *mut mailimf_orig_date = 0 as *mut mailimf_orig_date; - let mut from: *mut mailimf_from = 0 as *mut mailimf_from; - let mut sender: *mut mailimf_sender = 0 as *mut mailimf_sender; - let mut reply_to: *mut mailimf_reply_to = 0 as *mut mailimf_reply_to; - let mut to: *mut mailimf_to = 0 as *mut mailimf_to; - let mut cc: *mut mailimf_cc = 0 as *mut mailimf_cc; - let mut bcc: *mut mailimf_bcc = 0 as *mut mailimf_bcc; - let mut message_id: *mut mailimf_message_id = 0 as *mut mailimf_message_id; - let mut in_reply_to: *mut mailimf_in_reply_to = 0 as *mut mailimf_in_reply_to; - let mut references: *mut mailimf_references = 0 as *mut mailimf_references; - let mut subject: *mut mailimf_subject = 0 as *mut mailimf_subject; - let mut optional_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - let mut guessed_type: libc::c_int = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - orig_date = 0 as *mut mailimf_orig_date; - from = 0 as *mut mailimf_from; - sender = 0 as *mut mailimf_sender; - reply_to = 0 as *mut mailimf_reply_to; - to = 0 as *mut mailimf_to; - cc = 0 as *mut mailimf_cc; - bcc = 0 as *mut mailimf_bcc; - message_id = 0 as *mut mailimf_message_id; - in_reply_to = 0 as *mut mailimf_in_reply_to; - references = 0 as *mut mailimf_references; - subject = 0 as *mut mailimf_subject; - optional_field = 0 as *mut mailimf_optional_field; - guessed_type = guess_header_type(message, length, cur_token); - type_0 = MAILIMF_FIELD_NONE as libc::c_int; - match guessed_type { - 9 => { - r = mailimf_orig_date_parse(message, length, &mut cur_token, &mut orig_date); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 10 => { - r = mailimf_from_parse(message, length, &mut cur_token, &mut from); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 11 => { - r = mailimf_sender_parse(message, length, &mut cur_token, &mut sender); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 12 => { - r = mailimf_reply_to_parse(message, length, &mut cur_token, &mut reply_to); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 13 => { - r = mailimf_to_parse(message, length, &mut cur_token, &mut to); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 14 => { - r = mailimf_cc_parse(message, length, &mut cur_token, &mut cc); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 15 => { - r = mailimf_bcc_parse(message, length, &mut cur_token, &mut bcc); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 16 => { - r = mailimf_message_id_parse(message, length, &mut cur_token, &mut message_id); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 17 => { - r = mailimf_in_reply_to_parse(message, length, &mut cur_token, &mut in_reply_to); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 18 => { - r = mailimf_references_parse(message, length, &mut cur_token, &mut references); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - 19 => { - r = mailimf_subject_parse(message, length, &mut cur_token, &mut subject); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 4488496028633655612; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 4488496028633655612; - } else { - /* do nothing */ - res = r; - current_block = 15605017197726313499; - } - } - _ => { - current_block = 4488496028633655612; - } - } - match current_block { - 4488496028633655612 => { - if type_0 == MAILIMF_FIELD_NONE as libc::c_int { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - field = mailimf_field_new( - type_0, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - orig_date, - from, - sender, - reply_to, - to, - cc, - bcc, - message_id, - in_reply_to, - references, - subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - optional_field, - ); - if field.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !orig_date.is_null() { - mailimf_orig_date_free(orig_date); - } - if !from.is_null() { - mailimf_from_free(from); - } - if !sender.is_null() { - mailimf_sender_free(sender); - } - if !reply_to.is_null() { - mailimf_reply_to_free(reply_to); - } - if !to.is_null() { - mailimf_to_free(to); - } - if !cc.is_null() { - mailimf_cc_free(cc); - } - if !bcc.is_null() { - mailimf_bcc_free(bcc); - } - if !message_id.is_null() { - mailimf_message_id_free(message_id); - } - if !in_reply_to.is_null() { - mailimf_in_reply_to_free(in_reply_to); - } - if !references.is_null() { - mailimf_references_free(references); - } - if !subject.is_null() { - mailimf_subject_free(subject); - } - if !optional_field.is_null() { - mailimf_optional_field_free(optional_field); - } - } else { - *result = field; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - _ => {} - } - return res; -} -/* - mailimf_envelope_fields will parse the given fields (Date, - From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, - References and Subject), other fields will be added as optional - fields. - - @param message this is a string containing the header fields - @param length this is the size of the given string - @param indx this is a pointer to the start of the header fields in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_envelope_and_optional_fields_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_fields, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut list: *mut clist = 0 as *mut clist; - let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - list = 0 as *mut clist; - r = mailimf_struct_multiple_parse( - message, - length, - &mut cur_token, - &mut list, - ::std::mem::transmute::< - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut *mut mailimf_field, - ) -> libc::c_int, - >, - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut libc::c_void, - ) -> libc::c_int, - >, - >(Some(mailimf_envelope_or_optional_field_parse)), - ::std::mem::transmute::< - Option ()>, - Option libc::c_int>, - >(Some(mailimf_field_free)), - ); - match r { - 0 => { - /* do nothing */ - current_block = 11050875288958768710; - } - 1 => { - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 7755940856643933760; - } else { - current_block = 11050875288958768710; - } - } - _ => { - res = r; - current_block = 7755940856643933760; - } - } - match current_block { - 11050875288958768710 => { - fields = mailimf_fields_new(list); - if fields.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !list.is_null() { - clist_foreach( - list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailimf_field_free)), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - } else { - *result = fields; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - _ => {} - } - return res; -} -unsafe fn mailimf_envelope_or_optional_field_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_field, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut optional_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - r = mailimf_envelope_field_parse(message, length, indx, result); - if r == MAILIMF_NO_ERROR as libc::c_int { - return MAILIMF_NO_ERROR as libc::c_int; - } - cur_token = *indx; - r = mailimf_optional_field_parse(message, length, &mut cur_token, &mut optional_field); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - field = mailimf_field_new( - MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_reply_to, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - optional_field, - ); - if field.is_null() { - mailimf_optional_field_free(optional_field); - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - *result = field; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} - -/* - mailimf_envelope_fields will parse the given fields as optional - fields. - - @param message this is a string containing the header fields - @param length this is the size of the given string - @param indx this is a pointer to the start of the header fields in - the given string, (* indx) is modified to point at the end - of the parsed data - @param result the result of the parse operation is stored in - (* result) - - @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error -*/ -pub unsafe fn mailimf_optional_fields_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_fields, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut list: *mut clist = 0 as *mut clist; - let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - list = 0 as *mut clist; - r = mailimf_struct_multiple_parse( - message, - length, - &mut cur_token, - &mut list, - ::std::mem::transmute::< - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut *mut mailimf_field, - ) -> libc::c_int, - >, - Option< - unsafe fn( - _: *const libc::c_char, - _: size_t, - _: *mut size_t, - _: *mut libc::c_void, - ) -> libc::c_int, - >, - >(Some(mailimf_only_optional_field_parse)), - ::std::mem::transmute::< - Option ()>, - Option libc::c_int>, - >(Some(mailimf_field_free)), - ); - match r { - 0 => { - /* do nothing */ - current_block = 11050875288958768710; - } - 1 => { - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 4409055091581443388; - } else { - current_block = 11050875288958768710; - } - } - _ => { - res = r; - current_block = 4409055091581443388; - } - } - match current_block { - 11050875288958768710 => { - fields = mailimf_fields_new(list); - if fields.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !list.is_null() { - clist_foreach( - list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailimf_field_free)), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - } else { - *result = fields; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - _ => {} - } - return res; -} -unsafe fn mailimf_only_optional_field_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailimf_field, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut optional_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - cur_token = *indx; - r = mailimf_optional_field_parse(message, length, &mut cur_token, &mut optional_field); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - field = mailimf_field_new( - MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_reply_to, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - optional_field, - ); - if field.is_null() { - mailimf_optional_field_free(optional_field); - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - *result = field; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailimf_custom_string_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, - mut is_custom_char: Option libc::c_int>, -) -> libc::c_int { - let mut begin: size_t = 0; - let mut end: size_t = 0; - let mut gstr: *mut libc::c_char = 0 as *mut libc::c_char; - begin = *indx; - end = begin; - if end >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - while 0 != is_custom_char.expect("non-null function pointer")(*message.offset(end as isize)) { - end = end.wrapping_add(1); - if end >= length { - break; - } - } - if end != begin { - gstr = - malloc(end.wrapping_sub(begin).wrapping_add(1i32 as libc::size_t)) as *mut libc::c_char; - if gstr.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - strncpy( - gstr, - message.offset(begin as isize), - end.wrapping_sub(begin), - ); - *gstr.offset(end.wrapping_sub(begin) as isize) = '\u{0}' as i32 as libc::c_char; - *indx = end; - *result = gstr; - return MAILIMF_NO_ERROR as libc::c_int; - } else { - return MAILIMF_ERROR_PARSE as libc::c_int; - }; -} diff --git a/mmime/src/mailimf/types.rs b/mmime/src/mailimf/types.rs deleted file mode 100644 index b5e38cd80..000000000 --- a/mmime/src/mailimf/types.rs +++ /dev/null @@ -1,1196 +0,0 @@ -use libc; - -use crate::clist::*; -use crate::other::*; - -/* - IMPORTANT NOTE: - - All allocation functions will take as argument allocated data - and will store these data in the structure they will allocate. - Data should be persistant during all the use of the structure - and will be freed by the free function of the structure - - allocation functions will return NULL on failure -*/ -/* - mailimf_date_time is a date - - - day is the day of month (1 to 31) - - - month (1 to 12) - - - year (4 digits) - - - hour (0 to 23) - - - min (0 to 59) - - - sec (0 to 59) - - - zone (this is the decimal value that we can read, for example: - for "-0200", the value is -200) -*/ -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct mailimf_date_time { - pub dt_day: libc::c_int, - pub dt_month: libc::c_int, - pub dt_year: libc::c_int, - pub dt_hour: libc::c_int, - pub dt_min: libc::c_int, - pub dt_sec: libc::c_int, - pub dt_zone: libc::c_int, -} -/* this is the type of address */ -/* if this is a group -(group_name: address1@domain1, - address2@domain2; ) */ -pub const MAILIMF_ADDRESS_GROUP: libc::c_uint = 2; -/* if this is a mailbox (mailbox@domain) */ -pub const MAILIMF_ADDRESS_MAILBOX: libc::c_uint = 1; -/* on parse error */ -pub const MAILIMF_ADDRESS_ERROR: libc::c_uint = 0; -/* - mailimf_address is an address - - - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP - - - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX - - - group is a group if type is MAILIMF_ADDRESS_GROUP -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_address { - pub ad_type: libc::c_int, - pub ad_data: unnamed_0, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - pub ad_mailbox: *mut mailimf_mailbox, - pub ad_group: *mut mailimf_group, -} -/* - mailimf_group is a group - - - display_name is the name that will be displayed for this group, - for example 'group_name' in - 'group_name: address1@domain1, address2@domain2;', should be allocated - with malloc() - - - mb_list is a list of mailboxes -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_group { - pub grp_display_name: *mut libc::c_char, - pub grp_mb_list: *mut mailimf_mailbox_list, -} -/* - mailimf_mailbox_list is a list of mailboxes - - - list is a list of mailboxes -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_mailbox_list { - pub mb_list: *mut clist, -} -/* - mailimf_mailbox is a mailbox - - - display_name is the name that will be displayed for this mailbox, - for example 'name' in '"name" , - should be allocated with malloc() - - - addr_spec is the mailbox, for example 'mailbox@domain' - in '"name" , should be allocated with malloc() -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_mailbox { - pub mb_display_name: *mut libc::c_char, - pub mb_addr_spec: *mut libc::c_char, -} -/* - mailimf_address_list is a list of addresses - - - list is a list of addresses -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_address_list { - pub ad_list: *mut clist, -} -/* - mailimf_body is the text part of a message - - - text is the beginning of the text part, it is a substring - of an other string - - - size is the size of the text part -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_body { - pub bd_text: *const libc::c_char, - pub bd_size: size_t, -} -/* - mailimf_message is the content of the message - - - msg_fields is the header fields of the message - - - msg_body is the text part of the message -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_message { - pub msg_fields: *mut mailimf_fields, - pub msg_body: *mut mailimf_body, -} -/* - mailimf_fields is a list of header fields - - - fld_list is a list of header fields -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_fields { - pub fld_list: *mut clist, -} -/* - mailimf_field is a field - - - fld_type is the type of the field - - - fld_data.fld_return_path is the parsed content of the Return-Path - field if type is MAILIMF_FIELD_RETURN_PATH - - - fld_data.fld_resent_date is the parsed content of the Resent-Date field - if type is MAILIMF_FIELD_RESENT_DATE - - - fld_data.fld_resent_from is the parsed content of the Resent-From field - - - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field - - - fld_data.fld_resent_to is the parsed content of the Resent-To field - - - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field - - - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field - - - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID - field - - - fld_data.fld_orig_date is the parsed content of the Date field - - - fld_data.fld_from is the parsed content of the From field - - - fld_data.fld_sender is the parsed content of the Sender field - - - fld_data.fld_reply_to is the parsed content of the Reply-To field - - - fld_data.fld_to is the parsed content of the To field - - - fld_data.fld_cc is the parsed content of the Cc field - - - fld_data.fld_bcc is the parsed content of the Bcc field - - - fld_data.fld_message_id is the parsed content of the Message-ID field - - - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field - - - fld_data.fld_references is the parsed content of the References field - - - fld_data.fld_subject is the content of the Subject field - - - fld_data.fld_comments is the content of the Comments field - - - fld_data.fld_keywords is the parsed content of the Keywords field - - - fld_data.fld_optional_field is an other field and is not parsed -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_field { - pub fld_type: libc::c_int, - pub fld_data: unnamed_1, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_1 { - pub fld_return_path: *mut mailimf_return, - pub fld_resent_date: *mut mailimf_orig_date, - pub fld_resent_from: *mut mailimf_from, - pub fld_resent_sender: *mut mailimf_sender, - pub fld_resent_to: *mut mailimf_to, - pub fld_resent_cc: *mut mailimf_cc, - pub fld_resent_bcc: *mut mailimf_bcc, - pub fld_resent_msg_id: *mut mailimf_message_id, - pub fld_orig_date: *mut mailimf_orig_date, - pub fld_from: *mut mailimf_from, - pub fld_sender: *mut mailimf_sender, - pub fld_reply_to: *mut mailimf_reply_to, - pub fld_to: *mut mailimf_to, - pub fld_cc: *mut mailimf_cc, - pub fld_bcc: *mut mailimf_bcc, - pub fld_message_id: *mut mailimf_message_id, - pub fld_in_reply_to: *mut mailimf_in_reply_to, - pub fld_references: *mut mailimf_references, - pub fld_subject: *mut mailimf_subject, - pub fld_comments: *mut mailimf_comments, - pub fld_keywords: *mut mailimf_keywords, - pub fld_optional_field: *mut mailimf_optional_field, -} -/* - mailimf_optional_field is a non-parsed field - - - fld_name is the name of the field - - - fld_value is the value of the field -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_optional_field { - pub fld_name: *mut libc::c_char, - pub fld_value: *mut libc::c_char, -} -/* - mailimf_keywords is the parsed Keywords field - - - kw_list is the list of keywords -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_keywords { - pub kw_list: *mut clist, -} -/* - mailimf_comments is the parsed Comments field - - - cm_value is the value of the field -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_comments { - pub cm_value: *mut libc::c_char, -} -/* - mailimf_subject is the parsed Subject field - - - sbj_value is the value of the field -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_subject { - pub sbj_value: *mut libc::c_char, -} -/* - mailimf_references is the parsed References field - - - msg_id_list is the list of message identifiers -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_references { - pub mid_list: *mut clist, -} -/* - mailimf_in_reply_to is the parsed In-Reply-To field - - - mid_list is the list of message identifers -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_in_reply_to { - pub mid_list: *mut clist, -} -/* - mailimf_message_id is the parsed Message-ID field - - - mid_value is the message identifier -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_message_id { - pub mid_value: *mut libc::c_char, -} -/* - mailimf_bcc is the parsed Bcc field - - - bcc_addr_list is the parsed addres list -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_bcc { - pub bcc_addr_list: *mut mailimf_address_list, -} -/* - mailimf_cc is the parsed Cc field - - - cc_addr_list is the parsed addres list -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_cc { - pub cc_addr_list: *mut mailimf_address_list, -} -/* - mailimf_to is the parsed To field - - - to_addr_list is the parsed address list -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_to { - pub to_addr_list: *mut mailimf_address_list, -} -/* - mailimf_reply_to is the parsed Reply-To field - - - rt_addr_list is the parsed address list -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_reply_to { - pub rt_addr_list: *mut mailimf_address_list, -} -/* - mailimf_sender is the parsed Sender field - - - snd_mb is the parsed mailbox -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_sender { - pub snd_mb: *mut mailimf_mailbox, -} -/* - mailimf_from is the parsed From field - - - mb_list is the parsed mailbox list -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_from { - pub frm_mb_list: *mut mailimf_mailbox_list, -} -/* - mailimf_orig_date is the parsed Date field - - - date_time is the parsed date -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_orig_date { - pub dt_date_time: *mut mailimf_date_time, -} -/* - mailimf_return is the parsed Return-Path field - - - ret_path is the parsed value of Return-Path -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_return { - pub ret_path: *mut mailimf_path, -} -/* - mailimf_path is the parsed value of Return-Path - - - pt_addr_spec is a mailbox -*/ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_path { - pub pt_addr_spec: *mut libc::c_char, -} -/* other field */ -pub const MAILIMF_FIELD_OPTIONAL_FIELD: unnamed_2 = 22; -/* Keywords */ -pub const MAILIMF_FIELD_KEYWORDS: unnamed_2 = 21; -/* Comments */ -pub const MAILIMF_FIELD_COMMENTS: unnamed_2 = 20; -/* Subject */ -pub const MAILIMF_FIELD_SUBJECT: unnamed_2 = 19; -/* References */ -pub const MAILIMF_FIELD_REFERENCES: unnamed_2 = 18; -/* In-Reply-To */ -pub const MAILIMF_FIELD_IN_REPLY_TO: unnamed_2 = 17; -/* Message-ID */ -pub const MAILIMF_FIELD_MESSAGE_ID: unnamed_2 = 16; -/* Bcc */ -pub const MAILIMF_FIELD_BCC: unnamed_2 = 15; -/* Cc */ -pub const MAILIMF_FIELD_CC: unnamed_2 = 14; -/* To */ -pub const MAILIMF_FIELD_TO: unnamed_2 = 13; -/* Reply-To */ -pub const MAILIMF_FIELD_REPLY_TO: unnamed_2 = 12; -/* Sender */ -pub const MAILIMF_FIELD_SENDER: unnamed_2 = 11; -/* From */ -pub const MAILIMF_FIELD_FROM: unnamed_2 = 10; -/* Date */ -pub const MAILIMF_FIELD_ORIG_DATE: unnamed_2 = 9; -/* Resent-Message-ID */ -pub const MAILIMF_FIELD_RESENT_MSG_ID: unnamed_2 = 8; -/* Resent-Bcc */ -pub const MAILIMF_FIELD_RESENT_BCC: unnamed_2 = 7; -/* Resent-Cc */ -pub const MAILIMF_FIELD_RESENT_CC: unnamed_2 = 6; -/* Resent-To */ -pub const MAILIMF_FIELD_RESENT_TO: unnamed_2 = 5; -/* Resent-Sender */ -pub const MAILIMF_FIELD_RESENT_SENDER: unnamed_2 = 4; -/* Resent-From */ -pub const MAILIMF_FIELD_RESENT_FROM: unnamed_2 = 3; -/* Resent-Date */ -pub const MAILIMF_FIELD_RESENT_DATE: unnamed_2 = 2; -/* Return-Path */ -pub const MAILIMF_FIELD_RETURN_PATH: unnamed_2 = 1; -/* this is a type of field */ -pub type unnamed_2 = libc::c_uint; -/* on parse error */ -pub const MAILIMF_FIELD_NONE: unnamed_2 = 0; -#[no_mangle] -pub unsafe fn mailimf_date_time_new( - mut dt_day: libc::c_int, - mut dt_month: libc::c_int, - mut dt_year: libc::c_int, - mut dt_hour: libc::c_int, - mut dt_min: libc::c_int, - mut dt_sec: libc::c_int, - mut dt_zone: libc::c_int, -) -> *mut mailimf_date_time { - let mut date_time: *mut mailimf_date_time = 0 as *mut mailimf_date_time; - date_time = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailimf_date_time; - if date_time.is_null() { - return 0 as *mut mailimf_date_time; - } - (*date_time).dt_day = dt_day; - (*date_time).dt_month = dt_month; - (*date_time).dt_year = dt_year; - (*date_time).dt_hour = dt_hour; - (*date_time).dt_min = dt_min; - (*date_time).dt_sec = dt_sec; - (*date_time).dt_zone = dt_zone; - return date_time; -} -#[no_mangle] -pub unsafe fn mailimf_date_time_free(mut date_time: *mut mailimf_date_time) { - free(date_time as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_address_new( - mut ad_type: libc::c_int, - mut ad_mailbox: *mut mailimf_mailbox, - mut ad_group: *mut mailimf_group, -) -> *mut mailimf_address { - let mut address: *mut mailimf_address = 0 as *mut mailimf_address; - address = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_address; - if address.is_null() { - return 0 as *mut mailimf_address; - } - (*address).ad_type = ad_type; - match ad_type { - 1 => (*address).ad_data.ad_mailbox = ad_mailbox, - 2 => (*address).ad_data.ad_group = ad_group, - _ => {} - } - return address; -} -#[no_mangle] -pub unsafe fn mailimf_address_free(mut address: *mut mailimf_address) { - match (*address).ad_type { - 1 => { - mailimf_mailbox_free((*address).ad_data.ad_mailbox); - } - 2 => { - mailimf_group_free((*address).ad_data.ad_group); - } - _ => {} - } - free(address as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_group_free(mut group: *mut mailimf_group) { - if !(*group).grp_mb_list.is_null() { - mailimf_mailbox_list_free((*group).grp_mb_list); - } - mailimf_display_name_free((*group).grp_display_name); - free(group as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_display_name_free(mut display_name: *mut libc::c_char) { - mailimf_phrase_free(display_name); -} -#[no_mangle] -pub unsafe fn mailimf_phrase_free(mut phrase: *mut libc::c_char) { - free(phrase as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_mailbox_list_free(mut mb_list: *mut mailimf_mailbox_list) { - clist_foreach( - (*mb_list).mb_list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailimf_mailbox_free), - ), - 0 as *mut libc::c_void, - ); - clist_free((*mb_list).mb_list); - free(mb_list as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_mailbox_free(mut mailbox: *mut mailimf_mailbox) { - if !(*mailbox).mb_display_name.is_null() { - mailimf_display_name_free((*mailbox).mb_display_name); - } - mailimf_addr_spec_free((*mailbox).mb_addr_spec); - free(mailbox as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_addr_spec_free(mut addr_spec: *mut libc::c_char) { - free(addr_spec as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_mailbox_new( - mut mb_display_name: *mut libc::c_char, - mut mb_addr_spec: *mut libc::c_char, -) -> *mut mailimf_mailbox { - let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox; - mb = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_mailbox; - if mb.is_null() { - return 0 as *mut mailimf_mailbox; - } - (*mb).mb_display_name = mb_display_name; - (*mb).mb_addr_spec = mb_addr_spec; - return mb; -} -#[no_mangle] -pub unsafe fn mailimf_group_new( - mut grp_display_name: *mut libc::c_char, - mut grp_mb_list: *mut mailimf_mailbox_list, -) -> *mut mailimf_group { - let mut group: *mut mailimf_group = 0 as *mut mailimf_group; - group = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_group; - if group.is_null() { - return 0 as *mut mailimf_group; - } - (*group).grp_display_name = grp_display_name; - (*group).grp_mb_list = grp_mb_list; - return group; -} -#[no_mangle] -pub unsafe fn mailimf_mailbox_list_new(mut mb_list: *mut clist) -> *mut mailimf_mailbox_list { - let mut mbl: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list; - mbl = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailimf_mailbox_list; - if mbl.is_null() { - return 0 as *mut mailimf_mailbox_list; - } - (*mbl).mb_list = mb_list; - return mbl; -} - -pub unsafe fn mailimf_address_list_new(mut ad_list: *mut clist) -> *mut mailimf_address_list { - let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - addr_list = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailimf_address_list; - if addr_list.is_null() { - return 0 as *mut mailimf_address_list; - } - (*addr_list).ad_list = ad_list; - return addr_list; -} -#[no_mangle] -pub unsafe fn mailimf_address_list_free(mut addr_list: *mut mailimf_address_list) { - clist_foreach( - (*addr_list).ad_list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailimf_address_free), - ), - 0 as *mut libc::c_void, - ); - clist_free((*addr_list).ad_list); - free(addr_list as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_body_new( - mut bd_text: *const libc::c_char, - mut bd_size: size_t, -) -> *mut mailimf_body { - let mut body: *mut mailimf_body = 0 as *mut mailimf_body; - body = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_body; - if body.is_null() { - return 0 as *mut mailimf_body; - } - (*body).bd_text = bd_text; - (*body).bd_size = bd_size; - return body; -} -#[no_mangle] -pub unsafe fn mailimf_body_free(mut body: *mut mailimf_body) { - free(body as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_message_new( - mut msg_fields: *mut mailimf_fields, - mut msg_body: *mut mailimf_body, -) -> *mut mailimf_message { - let mut message: *mut mailimf_message = 0 as *mut mailimf_message; - message = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_message; - if message.is_null() { - return 0 as *mut mailimf_message; - } - (*message).msg_fields = msg_fields; - (*message).msg_body = msg_body; - return message; -} -#[no_mangle] -pub unsafe fn mailimf_message_free(mut message: *mut mailimf_message) { - mailimf_body_free((*message).msg_body); - mailimf_fields_free((*message).msg_fields); - free(message as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_fields_free(mut fields: *mut mailimf_fields) { - if !(*fields).fld_list.is_null() { - clist_foreach( - (*fields).fld_list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailimf_field_free), - ), - 0 as *mut libc::c_void, - ); - clist_free((*fields).fld_list); - } - free(fields as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_field_free(mut field: *mut mailimf_field) { - match (*field).fld_type { - 1 => { - mailimf_return_free((*field).fld_data.fld_return_path); - } - 2 => { - mailimf_orig_date_free((*field).fld_data.fld_resent_date); - } - 3 => { - mailimf_from_free((*field).fld_data.fld_resent_from); - } - 4 => { - mailimf_sender_free((*field).fld_data.fld_resent_sender); - } - 5 => { - mailimf_to_free((*field).fld_data.fld_resent_to); - } - 6 => { - mailimf_cc_free((*field).fld_data.fld_resent_cc); - } - 7 => { - mailimf_bcc_free((*field).fld_data.fld_resent_bcc); - } - 8 => { - mailimf_message_id_free((*field).fld_data.fld_resent_msg_id); - } - 9 => { - mailimf_orig_date_free((*field).fld_data.fld_orig_date); - } - 10 => { - mailimf_from_free((*field).fld_data.fld_from); - } - 11 => { - mailimf_sender_free((*field).fld_data.fld_sender); - } - 12 => { - mailimf_reply_to_free((*field).fld_data.fld_reply_to); - } - 13 => { - mailimf_to_free((*field).fld_data.fld_to); - } - 14 => { - mailimf_cc_free((*field).fld_data.fld_cc); - } - 15 => { - mailimf_bcc_free((*field).fld_data.fld_bcc); - } - 16 => { - mailimf_message_id_free((*field).fld_data.fld_message_id); - } - 17 => { - mailimf_in_reply_to_free((*field).fld_data.fld_in_reply_to); - } - 18 => { - mailimf_references_free((*field).fld_data.fld_references); - } - 19 => { - mailimf_subject_free((*field).fld_data.fld_subject); - } - 20 => { - mailimf_comments_free((*field).fld_data.fld_comments); - } - 21 => { - mailimf_keywords_free((*field).fld_data.fld_keywords); - } - 22 => { - mailimf_optional_field_free((*field).fld_data.fld_optional_field); - } - _ => {} - } - free(field as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_optional_field_free(mut opt_field: *mut mailimf_optional_field) { - mailimf_field_name_free((*opt_field).fld_name); - mailimf_unstructured_free((*opt_field).fld_value); - free(opt_field as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_unstructured_free(mut unstructured: *mut libc::c_char) { - free(unstructured as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_field_name_free(mut field_name: *mut libc::c_char) { - free(field_name as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_keywords_free(mut keywords: *mut mailimf_keywords) { - clist_foreach( - (*keywords).kw_list, - ::std::mem::transmute:: ()>, clist_func>(Some( - mailimf_phrase_free, - )), - 0 as *mut libc::c_void, - ); - clist_free((*keywords).kw_list); - free(keywords as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_comments_free(mut comments: *mut mailimf_comments) { - mailimf_unstructured_free((*comments).cm_value); - free(comments as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_subject_free(mut subject: *mut mailimf_subject) { - mailimf_unstructured_free((*subject).sbj_value); - free(subject as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_references_free(mut references: *mut mailimf_references) { - clist_foreach( - (*references).mid_list, - ::std::mem::transmute:: ()>, clist_func>(Some( - mailimf_msg_id_free, - )), - 0 as *mut libc::c_void, - ); - clist_free((*references).mid_list); - free(references as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_msg_id_free(mut msg_id: *mut libc::c_char) { - free(msg_id as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_in_reply_to_free(mut in_reply_to: *mut mailimf_in_reply_to) { - clist_foreach( - (*in_reply_to).mid_list, - ::std::mem::transmute:: ()>, clist_func>(Some( - mailimf_msg_id_free, - )), - 0 as *mut libc::c_void, - ); - clist_free((*in_reply_to).mid_list); - free(in_reply_to as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_message_id_free(mut message_id: *mut mailimf_message_id) { - if !(*message_id).mid_value.is_null() { - mailimf_msg_id_free((*message_id).mid_value); - } - free(message_id as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_bcc_free(mut bcc: *mut mailimf_bcc) { - if !(*bcc).bcc_addr_list.is_null() { - mailimf_address_list_free((*bcc).bcc_addr_list); - } - free(bcc as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_cc_free(mut cc: *mut mailimf_cc) { - if !(*cc).cc_addr_list.is_null() { - mailimf_address_list_free((*cc).cc_addr_list); - } - free(cc as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_to_free(mut to: *mut mailimf_to) { - if !(*to).to_addr_list.is_null() { - mailimf_address_list_free((*to).to_addr_list); - } - free(to as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_reply_to_free(mut reply_to: *mut mailimf_reply_to) { - if !(*reply_to).rt_addr_list.is_null() { - mailimf_address_list_free((*reply_to).rt_addr_list); - } - free(reply_to as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_sender_free(mut sender: *mut mailimf_sender) { - if !(*sender).snd_mb.is_null() { - mailimf_mailbox_free((*sender).snd_mb); - } - free(sender as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_from_free(mut from: *mut mailimf_from) { - if !(*from).frm_mb_list.is_null() { - mailimf_mailbox_list_free((*from).frm_mb_list); - } - free(from as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_orig_date_free(mut orig_date: *mut mailimf_orig_date) { - if !(*orig_date).dt_date_time.is_null() { - mailimf_date_time_free((*orig_date).dt_date_time); - } - free(orig_date as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_return_free(mut return_path: *mut mailimf_return) { - mailimf_path_free((*return_path).ret_path); - free(return_path as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_path_free(mut path: *mut mailimf_path) { - if !(*path).pt_addr_spec.is_null() { - mailimf_addr_spec_free((*path).pt_addr_spec); - } - free(path as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_fields_new(mut fld_list: *mut clist) -> *mut mailimf_fields { - let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields; - fields = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_fields; - if fields.is_null() { - return 0 as *mut mailimf_fields; - } - (*fields).fld_list = fld_list; - return fields; -} - -#[no_mangle] -pub unsafe fn mailimf_field_new( - mut fld_type: libc::c_int, - mut fld_return_path: *mut mailimf_return, - mut fld_resent_date: *mut mailimf_orig_date, - mut fld_resent_from: *mut mailimf_from, - mut fld_resent_sender: *mut mailimf_sender, - mut fld_resent_to: *mut mailimf_to, - mut fld_resent_cc: *mut mailimf_cc, - mut fld_resent_bcc: *mut mailimf_bcc, - mut fld_resent_msg_id: *mut mailimf_message_id, - mut fld_orig_date: *mut mailimf_orig_date, - mut fld_from: *mut mailimf_from, - mut fld_sender: *mut mailimf_sender, - mut fld_reply_to: *mut mailimf_reply_to, - mut fld_to: *mut mailimf_to, - mut fld_cc: *mut mailimf_cc, - mut fld_bcc: *mut mailimf_bcc, - mut fld_message_id: *mut mailimf_message_id, - mut fld_in_reply_to: *mut mailimf_in_reply_to, - mut fld_references: *mut mailimf_references, - mut fld_subject: *mut mailimf_subject, - mut fld_comments: *mut mailimf_comments, - mut fld_keywords: *mut mailimf_keywords, - mut fld_optional_field: *mut mailimf_optional_field, -) -> *mut mailimf_field { - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - field = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_field; - if field.is_null() { - return 0 as *mut mailimf_field; - } - (*field).fld_type = fld_type; - match fld_type { - 1 => (*field).fld_data.fld_return_path = fld_return_path, - 2 => (*field).fld_data.fld_resent_date = fld_resent_date, - 3 => (*field).fld_data.fld_resent_from = fld_resent_from, - 4 => (*field).fld_data.fld_resent_sender = fld_resent_sender, - 5 => (*field).fld_data.fld_resent_to = fld_resent_to, - 6 => (*field).fld_data.fld_resent_cc = fld_resent_cc, - 7 => (*field).fld_data.fld_resent_bcc = fld_resent_bcc, - 8 => (*field).fld_data.fld_resent_msg_id = fld_resent_msg_id, - 9 => (*field).fld_data.fld_orig_date = fld_orig_date, - 10 => (*field).fld_data.fld_from = fld_from, - 11 => (*field).fld_data.fld_sender = fld_sender, - 12 => (*field).fld_data.fld_reply_to = fld_reply_to, - 13 => (*field).fld_data.fld_to = fld_to, - 14 => (*field).fld_data.fld_cc = fld_cc, - 15 => (*field).fld_data.fld_bcc = fld_bcc, - 16 => (*field).fld_data.fld_message_id = fld_message_id, - 17 => (*field).fld_data.fld_in_reply_to = fld_in_reply_to, - 18 => (*field).fld_data.fld_references = fld_references, - 19 => (*field).fld_data.fld_subject = fld_subject, - 20 => (*field).fld_data.fld_comments = fld_comments, - 21 => (*field).fld_data.fld_keywords = fld_keywords, - 22 => (*field).fld_data.fld_optional_field = fld_optional_field, - _ => {} - } - return field; -} - -#[no_mangle] -pub unsafe fn mailimf_field_new_subject(fld_subject: *mut mailimf_subject) -> *mut mailimf_field { - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - field = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_field; - if field.is_null() { - return 0 as *mut mailimf_field; - } - (*field).fld_type = MAILIMF_FIELD_SUBJECT as libc::c_int; - (*field).fld_data.fld_subject = fld_subject; - - field -} - -#[no_mangle] -pub unsafe fn mailimf_orig_date_new( - mut dt_date_time: *mut mailimf_date_time, -) -> *mut mailimf_orig_date { - let mut orig_date: *mut mailimf_orig_date = 0 as *mut mailimf_orig_date; - orig_date = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailimf_orig_date; - if orig_date.is_null() { - return 0 as *mut mailimf_orig_date; - } - (*orig_date).dt_date_time = dt_date_time; - return orig_date; -} -#[no_mangle] -pub unsafe fn mailimf_from_new(mut frm_mb_list: *mut mailimf_mailbox_list) -> *mut mailimf_from { - let mut from: *mut mailimf_from = 0 as *mut mailimf_from; - from = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_from; - if from.is_null() { - return 0 as *mut mailimf_from; - } - (*from).frm_mb_list = frm_mb_list; - return from; -} -#[no_mangle] -pub unsafe fn mailimf_sender_new(mut snd_mb: *mut mailimf_mailbox) -> *mut mailimf_sender { - let mut sender: *mut mailimf_sender = 0 as *mut mailimf_sender; - sender = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_sender; - if sender.is_null() { - return 0 as *mut mailimf_sender; - } - (*sender).snd_mb = snd_mb; - return sender; -} -#[no_mangle] -pub unsafe fn mailimf_reply_to_new( - mut rt_addr_list: *mut mailimf_address_list, -) -> *mut mailimf_reply_to { - let mut reply_to: *mut mailimf_reply_to = 0 as *mut mailimf_reply_to; - reply_to = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_reply_to; - if reply_to.is_null() { - return 0 as *mut mailimf_reply_to; - } - (*reply_to).rt_addr_list = rt_addr_list; - return reply_to; -} -#[no_mangle] -pub unsafe fn mailimf_to_new(mut to_addr_list: *mut mailimf_address_list) -> *mut mailimf_to { - let mut to: *mut mailimf_to = 0 as *mut mailimf_to; - to = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_to; - if to.is_null() { - return 0 as *mut mailimf_to; - } - (*to).to_addr_list = to_addr_list; - return to; -} -#[no_mangle] -pub unsafe fn mailimf_cc_new(mut cc_addr_list: *mut mailimf_address_list) -> *mut mailimf_cc { - let mut cc: *mut mailimf_cc = 0 as *mut mailimf_cc; - cc = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_cc; - if cc.is_null() { - return 0 as *mut mailimf_cc; - } - (*cc).cc_addr_list = cc_addr_list; - return cc; -} -#[no_mangle] -pub unsafe fn mailimf_bcc_new(mut bcc_addr_list: *mut mailimf_address_list) -> *mut mailimf_bcc { - let mut bcc: *mut mailimf_bcc = 0 as *mut mailimf_bcc; - bcc = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_bcc; - if bcc.is_null() { - return 0 as *mut mailimf_bcc; - } - (*bcc).bcc_addr_list = bcc_addr_list; - return bcc; -} -#[no_mangle] -pub unsafe fn mailimf_message_id_new(mut mid_value: *mut libc::c_char) -> *mut mailimf_message_id { - let mut message_id: *mut mailimf_message_id = 0 as *mut mailimf_message_id; - message_id = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailimf_message_id; - if message_id.is_null() { - return 0 as *mut mailimf_message_id; - } - (*message_id).mid_value = mid_value; - return message_id; -} -#[no_mangle] -pub unsafe fn mailimf_in_reply_to_new(mut mid_list: *mut clist) -> *mut mailimf_in_reply_to { - let mut in_reply_to: *mut mailimf_in_reply_to = 0 as *mut mailimf_in_reply_to; - in_reply_to = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailimf_in_reply_to; - if in_reply_to.is_null() { - return 0 as *mut mailimf_in_reply_to; - } - (*in_reply_to).mid_list = mid_list; - return in_reply_to; -} -/* != NULL */ -#[no_mangle] -pub unsafe fn mailimf_references_new(mut mid_list: *mut clist) -> *mut mailimf_references { - let mut ref_0: *mut mailimf_references = 0 as *mut mailimf_references; - ref_0 = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailimf_references; - if ref_0.is_null() { - return 0 as *mut mailimf_references; - } - (*ref_0).mid_list = mid_list; - return ref_0; -} -#[no_mangle] -pub unsafe fn mailimf_subject_new(mut sbj_value: *mut libc::c_char) -> *mut mailimf_subject { - let mut subject: *mut mailimf_subject = 0 as *mut mailimf_subject; - subject = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_subject; - if subject.is_null() { - return 0 as *mut mailimf_subject; - } - (*subject).sbj_value = sbj_value; - return subject; -} -#[no_mangle] -pub unsafe fn mailimf_comments_new(mut cm_value: *mut libc::c_char) -> *mut mailimf_comments { - let mut comments: *mut mailimf_comments = 0 as *mut mailimf_comments; - comments = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_comments; - if comments.is_null() { - return 0 as *mut mailimf_comments; - } - (*comments).cm_value = cm_value; - return comments; -} -#[no_mangle] -pub unsafe fn mailimf_keywords_new(mut kw_list: *mut clist) -> *mut mailimf_keywords { - let mut keywords: *mut mailimf_keywords = 0 as *mut mailimf_keywords; - keywords = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_keywords; - if keywords.is_null() { - return 0 as *mut mailimf_keywords; - } - (*keywords).kw_list = kw_list; - return keywords; -} -#[no_mangle] -pub unsafe fn mailimf_return_new(mut ret_path: *mut mailimf_path) -> *mut mailimf_return { - let mut return_path: *mut mailimf_return = 0 as *mut mailimf_return; - return_path = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_return; - if return_path.is_null() { - return 0 as *mut mailimf_return; - } - (*return_path).ret_path = ret_path; - return return_path; -} -#[no_mangle] -pub unsafe fn mailimf_path_new(mut pt_addr_spec: *mut libc::c_char) -> *mut mailimf_path { - let mut path: *mut mailimf_path = 0 as *mut mailimf_path; - path = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailimf_path; - if path.is_null() { - return 0 as *mut mailimf_path; - } - (*path).pt_addr_spec = pt_addr_spec; - return path; -} -#[no_mangle] -pub unsafe fn mailimf_optional_field_new( - mut fld_name: *mut libc::c_char, - mut fld_value: *mut libc::c_char, -) -> *mut mailimf_optional_field { - let mut opt_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; - opt_field = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailimf_optional_field; - if opt_field.is_null() { - return 0 as *mut mailimf_optional_field; - } - (*opt_field).fld_name = fld_name; - (*opt_field).fld_value = fld_value; - return opt_field; -} -/* internal use */ -#[no_mangle] -pub unsafe fn mailimf_atom_free(mut atom: *mut libc::c_char) { - free(atom as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_dot_atom_free(mut dot_atom: *mut libc::c_char) { - free(dot_atom as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_dot_atom_text_free(mut dot_atom: *mut libc::c_char) { - free(dot_atom as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_quoted_string_free(mut quoted_string: *mut libc::c_char) { - free(quoted_string as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_word_free(mut word: *mut libc::c_char) { - free(word as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_angle_addr_free(mut angle_addr: *mut libc::c_char) { - free(angle_addr as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_local_part_free(mut local_part: *mut libc::c_char) { - free(local_part as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_domain_free(mut domain: *mut libc::c_char) { - free(domain as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_domain_literal_free(mut domain_literal: *mut libc::c_char) { - free(domain_literal as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_id_left_free(mut id_left: *mut libc::c_char) { - free(id_left as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_id_right_free(mut id_right: *mut libc::c_char) { - free(id_right as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_no_fold_quote_free(mut nfq: *mut libc::c_char) { - free(nfq as *mut libc::c_void); -} -#[no_mangle] -pub unsafe fn mailimf_no_fold_literal_free(mut nfl: *mut libc::c_char) { - free(nfl as *mut libc::c_void); -} diff --git a/mmime/src/mailimf/types_helper.rs b/mmime/src/mailimf/types_helper.rs deleted file mode 100644 index 8701559b1..000000000 --- a/mmime/src/mailimf/types_helper.rs +++ /dev/null @@ -1,89 +0,0 @@ -use crate::clist::*; -use crate::mailimf::types::*; -use crate::other::*; - -/* - this function creates a new mailimf_fields structure with no fields -*/ -pub unsafe fn mailimf_fields_new_empty() -> *mut mailimf_fields { - let mut list: *mut clist = 0 as *mut clist; - let mut fields_list: *mut mailimf_fields = 0 as *mut mailimf_fields; - list = clist_new(); - if list.is_null() { - return 0 as *mut mailimf_fields; - } - fields_list = mailimf_fields_new(list); - if fields_list.is_null() { - return 0 as *mut mailimf_fields; - } - return fields_list; -} -/* - this function adds a field to the mailimf_fields structure - - @return MAILIMF_NO_ERROR will be returned on success, - other code will be returned otherwise -*/ -pub unsafe fn mailimf_fields_add( - mut fields: *mut mailimf_fields, - mut field: *mut mailimf_field, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = clist_insert_after( - (*fields).fld_list, - (*(*fields).fld_list).last, - field as *mut libc::c_void, - ); - if r < 0i32 { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -/* - mailimf_field_new_custom creates a new field of type optional - - @param name should be allocated with malloc() - @param value should be allocated with malloc() -*/ -pub unsafe fn mailimf_field_new_custom( - mut name: *mut libc::c_char, - mut value: *mut libc::c_char, -) -> *mut mailimf_field { - let mut opt_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - opt_field = mailimf_optional_field_new(name, value); - if !opt_field.is_null() { - field = mailimf_field_new( - MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_reply_to, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - opt_field, - ); - if field.is_null() { - mailimf_optional_field_free(opt_field); - } else { - return field; - } - } - return 0 as *mut mailimf_field; -} diff --git a/mmime/src/mailimf/write_generic.rs b/mmime/src/mailimf/write_generic.rs deleted file mode 100644 index a449fd60e..000000000 --- a/mmime/src/mailimf/write_generic.rs +++ /dev/null @@ -1,1985 +0,0 @@ -use crate::clist::*; -use crate::mailimf::types::*; -use crate::other::*; - -pub const STATE_WORD: libc::c_uint = 1; -pub const STATE_SPACE: libc::c_uint = 2; -pub const STATE_BEGIN: libc::c_uint = 0; - -/* - mailimf_string_write writes a string to a given stream - - @param f is the stream - @param col (* col) is the column number where we will start to - write the text, the ending column will be stored in (* col) - @param str is the string to write -*/ -pub unsafe fn mailimf_string_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut str: *const libc::c_char, - mut length: size_t, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut count: size_t = 0; - let mut block_begin: *const libc::c_char = 0 as *const libc::c_char; - let mut p: *const libc::c_char = 0 as *const libc::c_char; - let mut done: libc::c_int = 0; - p = str; - block_begin = str; - count = 0i32 as size_t; - while length > 0i32 as libc::size_t { - if count >= 998i32 as libc::size_t { - r = flush_buf(do_write, data, block_begin, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = do_write.expect("non-null function pointer")( - data, - b"\r\n\x00" as *const u8 as *const libc::c_char, - (::std::mem::size_of::<[libc::c_char; 3]>() as libc::size_t) - .wrapping_sub(1i32 as libc::size_t), - ); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - count = 0i32 as size_t; - block_begin = p; - *col = 0i32 - } - match *p as libc::c_int { - 10 => { - r = flush_buf(do_write, data, block_begin, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = do_write.expect("non-null function pointer")( - data, - b"\r\n\x00" as *const u8 as *const libc::c_char, - (::std::mem::size_of::<[libc::c_char; 3]>() as libc::size_t) - .wrapping_sub(1i32 as libc::size_t), - ); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - p = p.offset(1isize); - length = length.wrapping_sub(1); - count = 0i32 as size_t; - block_begin = p; - *col = 0i32 - } - 13 => { - done = 0i32; - if length >= 2i32 as libc::size_t { - if *p.offset(1isize) as libc::c_int == '\n' as i32 { - r = flush_buf(do_write, data, block_begin, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = do_write.expect("non-null function pointer")( - data, - b"\r\n\x00" as *const u8 as *const libc::c_char, - (::std::mem::size_of::<[libc::c_char; 3]>() as libc::size_t) - .wrapping_sub(1i32 as libc::size_t), - ); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - p = p.offset(2isize); - length = (length as libc::size_t).wrapping_sub(2i32 as libc::size_t) - as size_t as size_t; - count = 0i32 as size_t; - block_begin = p; - *col = 0i32; - done = 1i32 - } - } - if 0 == done { - r = flush_buf(do_write, data, block_begin, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = do_write.expect("non-null function pointer")( - data, - b"\r\n\x00" as *const u8 as *const libc::c_char, - (::std::mem::size_of::<[libc::c_char; 3]>() as libc::size_t) - .wrapping_sub(1i32 as libc::size_t), - ); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - p = p.offset(1isize); - length = length.wrapping_sub(1); - count = 0i32 as size_t; - block_begin = p; - *col = 0i32 - } - } - _ => { - p = p.offset(1isize); - count = count.wrapping_add(1); - length = length.wrapping_sub(1) - } - } - } - r = flush_buf(do_write, data, block_begin, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *col = (*col as libc::size_t).wrapping_add(count) as libc::c_int as libc::c_int; - return MAILIMF_NO_ERROR as libc::c_int; -} -/* ************************ */ -#[inline] -unsafe fn flush_buf( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut str: *const libc::c_char, - mut length: size_t, -) -> libc::c_int { - if length != 0i32 as libc::size_t { - let mut r: libc::c_int = 0; - if length > 0i32 as libc::size_t { - r = do_write.expect("non-null function pointer")(data, str, length); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - } - } - return MAILIMF_NO_ERROR as libc::c_int; -} -/* - mailimf_fields_write writes the fields to a given stream - - @param f is the stream - @param col (* col) is the column number where we will start to - write the text, the ending column will be stored in (* col) - @param fields is the fields to write -*/ - -pub unsafe fn mailimf_fields_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut fields: *mut mailimf_fields, -) -> libc::c_int { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*fields).fld_list).first; - while !cur.is_null() { - let mut r: libc::c_int = 0; - r = mailimf_field_write_driver( - do_write, - data, - col, - (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_field, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - return MAILIMF_NO_ERROR as libc::c_int; -} -/* - mailimf_field_write writes a field to a given stream - - @param f is the stream - @param col (* col) is the column number where we will start to - write the text, the ending column will be stored in (* col) - @param field is the field to write -*/ -pub unsafe fn mailimf_field_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut field: *mut mailimf_field, -) -> libc::c_int { - let mut r: libc::c_int = 0; - match (*field).fld_type { - 1 => { - r = mailimf_return_write_driver(do_write, data, col, (*field).fld_data.fld_return_path) - } - 2 => { - r = mailimf_resent_date_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_resent_date, - ) - } - 3 => { - r = mailimf_resent_from_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_resent_from, - ) - } - 4 => { - r = mailimf_resent_sender_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_resent_sender, - ) - } - 5 => { - r = mailimf_resent_to_write_driver(do_write, data, col, (*field).fld_data.fld_resent_to) - } - 6 => { - r = mailimf_resent_cc_write_driver(do_write, data, col, (*field).fld_data.fld_resent_cc) - } - 7 => { - r = mailimf_resent_bcc_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_resent_bcc, - ) - } - 8 => { - r = mailimf_resent_msg_id_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_resent_msg_id, - ) - } - 9 => { - r = mailimf_orig_date_write_driver(do_write, data, col, (*field).fld_data.fld_orig_date) - } - 10 => r = mailimf_from_write_driver(do_write, data, col, (*field).fld_data.fld_from), - 11 => r = mailimf_sender_write_driver(do_write, data, col, (*field).fld_data.fld_sender), - 12 => { - r = mailimf_reply_to_write_driver(do_write, data, col, (*field).fld_data.fld_reply_to) - } - 13 => r = mailimf_to_write_driver(do_write, data, col, (*field).fld_data.fld_to), - 14 => r = mailimf_cc_write_driver(do_write, data, col, (*field).fld_data.fld_cc), - 15 => r = mailimf_bcc_write_driver(do_write, data, col, (*field).fld_data.fld_bcc), - 16 => { - r = mailimf_message_id_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_message_id, - ) - } - 17 => { - r = mailimf_in_reply_to_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_in_reply_to, - ) - } - 18 => { - r = mailimf_references_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_references, - ) - } - 19 => r = mailimf_subject_write_driver(do_write, data, col, (*field).fld_data.fld_subject), - 20 => { - r = mailimf_comments_write_driver(do_write, data, col, (*field).fld_data.fld_comments) - } - 21 => { - r = mailimf_keywords_write_driver(do_write, data, col, (*field).fld_data.fld_keywords) - } - 22 => { - r = mailimf_optional_field_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_optional_field, - ) - } - _ => r = MAILIMF_ERROR_INVAL as libc::c_int, - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_optional_field_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut field: *mut mailimf_optional_field, -) -> libc::c_int { - let mut r: libc::c_int = 0; - if strlen((*field).fld_name).wrapping_add(2i32 as libc::size_t) > 998i32 as libc::size_t { - return MAILIMF_ERROR_INVAL as libc::c_int; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - (*field).fld_name, - strlen((*field).fld_name), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b": \x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_header_string_write_driver( - do_write, - data, - col, - (*field).fld_value, - strlen((*field).fld_value), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -/* - mailimf_header_string_write writes a header value and fold the header - if needed. - - @param f is the stream - @param col (* col) is the column number where we will start to - write the text, the ending column will be stored in (* col) - @param str is the string to write -*/ -pub unsafe fn mailimf_header_string_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut str: *const libc::c_char, - mut length: size_t, -) -> libc::c_int { - let mut state: libc::c_int = 0; - let mut p: *const libc::c_char = 0 as *const libc::c_char; - let mut word_begin: *const libc::c_char = 0 as *const libc::c_char; - let mut first: libc::c_int = 0; - state = STATE_BEGIN as libc::c_int; - p = str; - word_begin = p; - first = 1i32; - while length > 0i32 as libc::size_t { - match state { - 0 => match *p as libc::c_int { - 13 | 10 | 32 | 9 => { - p = p.offset(1isize); - length = length.wrapping_sub(1) - } - _ => { - word_begin = p; - state = STATE_WORD as libc::c_int - } - }, - 2 => match *p as libc::c_int { - 13 | 10 | 32 | 9 => { - p = p.offset(1isize); - length = length.wrapping_sub(1) - } - _ => { - word_begin = p; - state = STATE_WORD as libc::c_int - } - }, - 1 => match *p as libc::c_int { - 13 | 10 | 32 | 9 => { - if p.wrapping_offset_from(word_begin) as libc::c_int - + *col as libc::c_int - + 1i32 as libc::c_int - > 72i32 as libc::c_int - { - mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - (::std::mem::size_of::<[libc::c_char; 4]>() as libc::size_t) - .wrapping_sub(1i32 as libc::size_t), - ); - } else if 0 == first { - mailimf_string_write_driver( - do_write, - data, - col, - b" \x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - } - first = 0i32; - mailimf_string_write_driver( - do_write, - data, - col, - word_begin, - p.wrapping_offset_from(word_begin) as libc::c_int as size_t, - ); - state = STATE_SPACE as libc::c_int - } - _ => { - if p.wrapping_offset_from(word_begin) as libc::c_int + *col as libc::c_int - >= 998i32 as libc::c_int - { - mailimf_string_write_driver( - do_write, - data, - col, - word_begin, - p.wrapping_offset_from(word_begin) as libc::c_int as size_t, - ); - mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - (::std::mem::size_of::<[libc::c_char; 4]>() as libc::size_t) - .wrapping_sub(1i32 as libc::size_t), - ); - word_begin = p - } - p = p.offset(1isize); - length = length.wrapping_sub(1) - } - }, - _ => {} - } - } - if state == STATE_WORD as libc::c_int { - if p.wrapping_offset_from(word_begin) as libc::c_int + *col as libc::c_int - >= 72i32 as libc::c_int - { - mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - (::std::mem::size_of::<[libc::c_char; 4]>() as libc::size_t) - .wrapping_sub(1i32 as libc::size_t), - ); - } else if 0 == first { - mailimf_string_write_driver( - do_write, - data, - col, - b" \x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - } - first = 0i32; - mailimf_string_write_driver( - do_write, - data, - col, - word_begin, - p.wrapping_offset_from(word_begin) as libc::c_int as size_t, - ); - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_keywords_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut keywords: *mut mailimf_keywords, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut first: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Keywords: \x00" as *const u8 as *const libc::c_char, - 10i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - first = 1i32; - cur = (*(*keywords).kw_list).first; - while !cur.is_null() { - let mut keyword: *mut libc::c_char = 0 as *mut libc::c_char; - let mut len: size_t = 0; - keyword = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut libc::c_char; - len = strlen(keyword); - if 0 == first { - r = mailimf_string_write_driver( - do_write, - data, - col, - b", \x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } else { - first = 0i32 - } - r = mailimf_header_string_write_driver(do_write, data, col, keyword, len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_comments_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut comments: *mut mailimf_comments, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Comments: \x00" as *const u8 as *const libc::c_char, - 10i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_header_string_write_driver( - do_write, - data, - col, - (*comments).cm_value, - strlen((*comments).cm_value), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_subject_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut subject: *mut mailimf_subject, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Subject: \x00" as *const u8 as *const libc::c_char, - 9i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_header_string_write_driver( - do_write, - data, - col, - (*subject).sbj_value, - strlen((*subject).sbj_value), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_references_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut references: *mut mailimf_references, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"References: \x00" as *const u8 as *const libc::c_char, - 12i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_msg_id_list_write_driver(do_write, data, col, (*references).mid_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_msg_id_list_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut mid_list: *mut clist, -) -> libc::c_int { - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut r: libc::c_int = 0; - let mut first: libc::c_int = 0; - first = 1i32; - cur = (*mid_list).first; - while !cur.is_null() { - let mut msgid: *mut libc::c_char = 0 as *mut libc::c_char; - let mut len: size_t = 0; - msgid = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut libc::c_char; - len = strlen(msgid); - if 0 == first { - if *col > 1i32 { - if (*col as libc::size_t).wrapping_add(len) >= 72i32 as libc::size_t { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - first = 1i32 - } - } - } - if 0 == first { - r = mailimf_string_write_driver( - do_write, - data, - col, - b" \x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } else { - first = 0i32 - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"<\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver(do_write, data, col, msgid, len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b">\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_in_reply_to_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut in_reply_to: *mut mailimf_in_reply_to, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"In-Reply-To: \x00" as *const u8 as *const libc::c_char, - 13i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_msg_id_list_write_driver(do_write, data, col, (*in_reply_to).mid_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_message_id_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut message_id: *mut mailimf_message_id, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Message-ID: \x00" as *const u8 as *const libc::c_char, - 12i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"<\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - (*message_id).mid_value, - strlen((*message_id).mid_value), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b">\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_bcc_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut bcc: *mut mailimf_bcc, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Bcc: \x00" as *const u8 as *const libc::c_char, - 5i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - if !(*bcc).bcc_addr_list.is_null() { - r = mailimf_address_list_write_driver(do_write, data, col, (*bcc).bcc_addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -pub unsafe fn mailimf_address_list_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut addr_list: *mut mailimf_address_list, -) -> libc::c_int { - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut r: libc::c_int = 0; - let mut first: libc::c_int = 0; - first = 1i32; - cur = (*(*addr_list).ad_list).first; - while !cur.is_null() { - let mut addr: *mut mailimf_address = 0 as *mut mailimf_address; - addr = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_address; - if 0 == first { - r = mailimf_string_write_driver( - do_write, - data, - col, - b", \x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } else { - first = 0i32 - } - r = mailimf_address_write_driver(do_write, data, col, addr); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_address_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut addr: *mut mailimf_address, -) -> libc::c_int { - let mut r: libc::c_int = 0; - match (*addr).ad_type { - 1 => { - r = mailimf_mailbox_write_driver(do_write, data, col, (*addr).ad_data.ad_mailbox); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 2 => { - r = mailimf_group_write_driver(do_write, data, col, (*addr).ad_data.ad_group); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - _ => {} - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_group_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut group: *mut mailimf_group, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_header_string_write_driver( - do_write, - data, - col, - (*group).grp_display_name, - strlen((*group).grp_display_name), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b": \x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - if !(*group).grp_mb_list.is_null() { - r = mailimf_mailbox_list_write_driver(do_write, data, col, (*group).grp_mb_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b";\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailimf_mailbox_list_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut mb_list: *mut mailimf_mailbox_list, -) -> libc::c_int { - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut r: libc::c_int = 0; - let mut first: libc::c_int = 0; - first = 1i32; - cur = (*(*mb_list).mb_list).first; - while !cur.is_null() { - let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox; - mb = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_mailbox; - if 0 == first { - r = mailimf_string_write_driver( - do_write, - data, - col, - b", \x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } else { - first = 0i32 - } - r = mailimf_mailbox_write_driver(do_write, data, col, mb); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_mailbox_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut mb: *mut mailimf_mailbox, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut do_fold: libc::c_int = 0; - if !(*mb).mb_display_name.is_null() { - if 0 != is_atext((*mb).mb_display_name) { - r = mailimf_header_string_write_driver( - do_write, - data, - col, - (*mb).mb_display_name, - strlen((*mb).mb_display_name), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } else { - if !(*mb).mb_display_name.is_null() { - if (*col as libc::size_t).wrapping_add(strlen((*mb).mb_display_name)) - >= 72i32 as libc::size_t - { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - } - if strlen((*mb).mb_display_name) > (998i32 / 2i32) as libc::size_t { - return MAILIMF_ERROR_INVAL as libc::c_int; - } - r = mailimf_quoted_string_write_driver( - do_write, - data, - col, - (*mb).mb_display_name, - strlen((*mb).mb_display_name), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - do_fold = 0i32; - if *col > 1i32 { - if (*col as libc::size_t) - .wrapping_add(strlen((*mb).mb_addr_spec)) - .wrapping_add(3i32 as libc::size_t) - >= 72i32 as libc::size_t - { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - do_fold = 1i32 - } - } - if 0 != do_fold { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"<\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ) - } else { - r = mailimf_string_write_driver( - do_write, - data, - col, - b" <\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ) - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - (*mb).mb_addr_spec, - strlen((*mb).mb_addr_spec), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b">\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } else { - if (*col as libc::size_t).wrapping_add(strlen((*mb).mb_addr_spec)) >= 72i32 as libc::size_t - { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - r = mailimf_string_write_driver( - do_write, - data, - col, - (*mb).mb_addr_spec, - strlen((*mb).mb_addr_spec), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - return MAILIMF_NO_ERROR as libc::c_int; -} -/* - mailimf_quoted_string_write writes a string that is quoted - to a given stream - - @param f is the stream - @param col (* col) is the column number where we will start to - write the text, the ending column will be stored in (* col) - @param string is the string to quote and write -*/ -pub unsafe fn mailimf_quoted_string_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut string: *const libc::c_char, - mut len: size_t, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut i: size_t = 0; - r = do_write.expect("non-null function pointer")( - data, - b"\"\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - i = 0i32 as size_t; - while i < len { - match *string.offset(i as isize) as libc::c_int { - 92 | 34 => { - r = do_write.expect("non-null function pointer")( - data, - b"\\\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - r = do_write.expect("non-null function pointer")( - data, - &*string.offset(i as isize), - 1i32 as size_t, - ); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - *col += 2i32 - } - _ => { - r = do_write.expect("non-null function pointer")( - data, - &*string.offset(i as isize), - 1i32 as size_t, - ); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - *col += 1 - } - } - i = i.wrapping_add(1) - } - r = do_write.expect("non-null function pointer")( - data, - b"\"\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r == 0i32 { - return MAILIMF_ERROR_FILE as libc::c_int; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -/* -static int -atext = ALPHA / DIGIT / ; Any character except controls, - "!" / "#" / ; SP, and specials. - "$" / "%" / ; Used for atoms - "&" / "'" / - "*" / "+" / - "-" / "/" / - "=" / "?" / - "^" / "_" / - "`" / "{" / - "|" / "}" / - "~" -*/ -unsafe fn is_atext(mut s: *const libc::c_char) -> libc::c_int { - let mut p: *const libc::c_char = 0 as *const libc::c_char; - p = s; - while *p as libc::c_int != 0i32 { - if !(0 != isalpha(*p as libc::c_uchar as libc::c_int)) { - if !(0 != isdigit(*p as libc::c_uchar as libc::c_int)) { - match *p as libc::c_int { - 32 | 9 | 33 | 35 | 36 | 37 | 38 | 39 | 42 | 43 | 45 | 47 | 61 | 63 | 94 - | 95 | 96 | 123 | 124 | 125 | 126 => {} - _ => return 0i32, - } - } - } - p = p.offset(1isize) - } - return 1i32; -} - -unsafe fn mailimf_cc_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut cc: *mut mailimf_cc, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Cc: \x00" as *const u8 as *const libc::c_char, - 4i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_address_list_write_driver(do_write, data, col, (*cc).cc_addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_to_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut to: *mut mailimf_to, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"To: \x00" as *const u8 as *const libc::c_char, - 4i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_address_list_write_driver(do_write, data, col, (*to).to_addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_reply_to_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut reply_to: *mut mailimf_reply_to, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Reply-To: \x00" as *const u8 as *const libc::c_char, - 10i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_address_list_write_driver(do_write, data, col, (*reply_to).rt_addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_sender_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut sender: *mut mailimf_sender, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Sender: \x00" as *const u8 as *const libc::c_char, - 8i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_mailbox_write_driver(do_write, data, col, (*sender).snd_mb); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_from_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut from: *mut mailimf_from, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"From: \x00" as *const u8 as *const libc::c_char, - 6i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_mailbox_list_write_driver(do_write, data, col, (*from).frm_mb_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * $Id: mailimf_write_generic.c,v 1.3 2006/05/22 13:39:42 hoa Exp $ - */ -unsafe fn mailimf_orig_date_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut date: *mut mailimf_orig_date, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Date: \x00" as *const u8 as *const libc::c_char, - 6i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_date_time_write_driver(do_write, data, col, (*date).dt_date_time); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_date_time_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut date_time: *mut mailimf_date_time, -) -> libc::c_int { - let wday = dayofweek( - (*date_time).dt_year, - (*date_time).dt_month, - (*date_time).dt_day, - ); - - let date_str = format!( - "{}, {} {} {} {:02}:{:02}:{:02} {:+05}", - week_of_day_str[wday as usize], - (*date_time).dt_day, - month_str[((*date_time).dt_month - 1i32) as usize], - (*date_time).dt_year, - (*date_time).dt_hour, - (*date_time).dt_min, - (*date_time).dt_sec, - (*date_time).dt_zone, - ); - let date_str_c = std::ffi::CString::new(date_str).unwrap_or_default(); - let r = mailimf_string_write_driver( - do_write, - data, - col, - date_str_c.as_ptr() as *mut _, - strlen(date_str_c.as_ptr()), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -static mut month_str: [&'static str; 12] = [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", -]; -static mut week_of_day_str: [&'static str; 7] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; -/* 0 = Sunday */ -/* y > 1752 */ -unsafe fn dayofweek( - mut year: libc::c_int, - mut month: libc::c_int, - mut day: libc::c_int, -) -> libc::c_int { - static mut offset: [libc::c_int; 12] = [ - 0i32, 3i32, 2i32, 5i32, 0i32, 3i32, 5i32, 1i32, 4i32, 6i32, 2i32, 4i32, - ]; - year -= (month < 3i32) as libc::c_int; - return (year + year / 4i32 - year / 100i32 - + year / 400i32 - + offset[(month - 1i32) as usize] - + day) - % 7i32; -} -unsafe fn mailimf_resent_msg_id_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut message_id: *mut mailimf_message_id, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Resent-Message-ID: \x00" as *const u8 as *const libc::c_char, - 19i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"<\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - (*message_id).mid_value, - strlen((*message_id).mid_value), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b">\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_resent_bcc_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut bcc: *mut mailimf_bcc, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Resent-Bcc: \x00" as *const u8 as *const libc::c_char, - 12i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - if !(*bcc).bcc_addr_list.is_null() { - r = mailimf_address_list_write_driver(do_write, data, col, (*bcc).bcc_addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_resent_cc_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut cc: *mut mailimf_cc, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Resent-Cc: \x00" as *const u8 as *const libc::c_char, - 11i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_address_list_write_driver(do_write, data, col, (*cc).cc_addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_resent_to_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut to: *mut mailimf_to, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Resent-To: \x00" as *const u8 as *const libc::c_char, - 11i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_address_list_write_driver(do_write, data, col, (*to).to_addr_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_resent_sender_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut sender: *mut mailimf_sender, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Resent-Sender: \x00" as *const u8 as *const libc::c_char, - 15i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_mailbox_write_driver(do_write, data, col, (*sender).snd_mb); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_resent_from_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut from: *mut mailimf_from, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Resent-From: \x00" as *const u8 as *const libc::c_char, - 13i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_mailbox_list_write_driver(do_write, data, col, (*from).frm_mb_list); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_resent_date_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut date: *mut mailimf_orig_date, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Resent-Date: \x00" as *const u8 as *const libc::c_char, - 13i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_date_time_write_driver(do_write, data, col, (*date).dt_date_time); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_return_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut return_path: *mut mailimf_return, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Return-Path: \x00" as *const u8 as *const libc::c_char, - 13i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_path_write_driver(do_write, data, col, (*return_path).ret_path); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailimf_path_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut path: *mut mailimf_path, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"<\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - if !(*path).pt_addr_spec.is_null() { - r = mailimf_string_write_driver( - do_write, - data, - col, - (*path).pt_addr_spec, - strlen((*path).pt_addr_spec), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b">\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} diff --git a/mmime/src/mailmime/content.rs b/mmime/src/mailmime/content.rs deleted file mode 100644 index c41ec180f..000000000 --- a/mmime/src/mailmime/content.rs +++ /dev/null @@ -1,2357 +0,0 @@ -use crate::clist::*; -use crate::mailimf::types::*; -use crate::mailimf::*; -use crate::mailmime::types::*; -use crate::mailmime::types_helper::*; -use crate::mailmime::*; -use crate::mmapstring::*; -use crate::other::*; - -pub const MAILMIME_DEFAULT_TYPE_TEXT_PLAIN: libc::c_uint = 0; -pub const MULTIPART_NEXT_STATE_2: libc::c_uint = 2; -pub const MULTIPART_NEXT_STATE_1: libc::c_uint = 1; -pub const MULTIPART_NEXT_STATE_0: libc::c_uint = 0; -pub const MULTIPART_CLOSE_STATE_4: libc::c_uint = 4; -pub const MULTIPART_CLOSE_STATE_3: libc::c_uint = 3; -pub const MULTIPART_CLOSE_STATE_2: libc::c_uint = 2; -pub const MULTIPART_CLOSE_STATE_1: libc::c_uint = 1; -pub const MULTIPART_CLOSE_STATE_0: libc::c_uint = 0; -pub const BODY_PART_DASH2_STATE_0: libc::c_uint = 0; -pub const BODY_PART_DASH2_STATE_6: libc::c_uint = 6; -pub const BODY_PART_DASH2_STATE_5: libc::c_uint = 5; -pub const BODY_PART_DASH2_STATE_4: libc::c_uint = 4; -pub const BODY_PART_DASH2_STATE_2: libc::c_uint = 2; -pub const BODY_PART_DASH2_STATE_1: libc::c_uint = 1; -pub const BODY_PART_DASH2_STATE_3: libc::c_uint = 3; -pub const PREAMBLE_STATE_A: libc::c_uint = 1; -pub const PREAMBLE_STATE_E: libc::c_uint = 6; -pub const PREAMBLE_STATE_D: libc::c_uint = 5; -pub const PREAMBLE_STATE_A0: libc::c_uint = 0; -pub const PREAMBLE_STATE_C: libc::c_uint = 4; -pub const PREAMBLE_STATE_B: libc::c_uint = 3; -pub const PREAMBLE_STATE_A1: libc::c_uint = 2; -pub const MAILMIME_DEFAULT_TYPE_MESSAGE: libc::c_uint = 1; -pub const STATE_NORMAL: libc::c_uint = 0; -pub const STATE_CR: libc::c_uint = 3; -pub const STATE_CODED: libc::c_uint = 1; -pub const STATE_OUT: libc::c_uint = 2; - -pub unsafe fn mailmime_content_charset_get( - mut content: *mut mailmime_content, -) -> *mut libc::c_char { - let mut charset: *mut libc::c_char = 0 as *mut libc::c_char; - charset = mailmime_content_param_get( - content, - b"charset\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - ); - if charset.is_null() { - return b"us-ascii\x00" as *const u8 as *const libc::c_char as *mut libc::c_char; - } else { - return charset; - }; -} - -pub unsafe fn mailmime_content_param_get( - mut content: *mut mailmime_content, - mut name: *mut libc::c_char, -) -> *mut libc::c_char { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*content).ct_parameters).first; - while !cur.is_null() { - let mut param: *mut mailmime_parameter = 0 as *mut mailmime_parameter; - param = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailmime_parameter; - if strcasecmp((*param).pa_name, name) == 0i32 { - return (*param).pa_value; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - return 0 as *mut libc::c_char; -} - -pub unsafe fn mailmime_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut Mailmime, -) -> libc::c_int { - let mut mime: *mut Mailmime = 0 as *mut Mailmime; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut content_message: *mut mailmime_content = 0 as *mut mailmime_content; - let mut cur_token: size_t = 0; - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - let mut data_str: *const libc::c_char = 0 as *const libc::c_char; - let mut data_size: size_t = 0; - let mut bp_token: size_t = 0; - cur_token = *indx; - content_message = mailmime_get_content_message(); - if content_message.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - mime_fields = mailmime_fields_new_empty(); - if mime_fields.is_null() { - mailmime_content_free(content_message); - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - data_str = message.offset(cur_token as isize); - data_size = length.wrapping_sub(cur_token); - bp_token = 0i32 as size_t; - r = mailmime_parse_with_default( - data_str, - data_size, - &mut bp_token, - MAILMIME_DEFAULT_TYPE_TEXT_PLAIN as libc::c_int, - content_message, - mime_fields, - &mut mime, - ); - cur_token = (cur_token as libc::size_t).wrapping_add(bp_token) as size_t as size_t; - if r != MAILIMF_NO_ERROR as libc::c_int { - mailmime_fields_free(mime_fields); - res = r; - mailmime_fields_free(mime_fields); - } else { - *indx = cur_token; - *result = mime; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - return res; -} -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * $Id: mailmime_content.c,v 1.47 2011/06/28 22:13:36 hoa Exp $ - */ -/* - RFC 2045 - RFC 2046 - RFC 2047 - - RFC 2231 -*/ -unsafe fn mailmime_parse_with_default( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut default_type: libc::c_int, - mut content_type: *mut mailmime_content, - mut mime_fields: *mut mailmime_fields, - mut result: *mut *mut Mailmime, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut body_type: libc::c_int = 0; - let mut encoding: libc::c_int = 0; - let mut body: *mut mailmime_data = 0 as *mut mailmime_data; - let mut boundary: *mut libc::c_char = 0 as *mut libc::c_char; - let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields; - let mut list: *mut clist = 0 as *mut clist; - let mut msg_mime: *mut Mailmime = 0 as *mut Mailmime; - let mut mime: *mut Mailmime = 0 as *mut Mailmime; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut preamble: *mut mailmime_data = 0 as *mut mailmime_data; - let mut epilogue: *mut mailmime_data = 0 as *mut mailmime_data; - preamble = 0 as *mut mailmime_data; - epilogue = 0 as *mut mailmime_data; - cur_token = *indx; - if content_type.is_null() { - if !mime_fields.is_null() { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*mime_fields).fld_list).first; - while !cur.is_null() { - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - field = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailmime_field; - if (*field).fld_type == MAILMIME_FIELD_TYPE as libc::c_int { - content_type = (*field).fld_data.fld_content; - (*field).fld_data.fld_content = 0 as *mut mailmime_content; - clist_delete((*mime_fields).fld_list, cur); - mailmime_field_free(field); - /* - there may be a leak due to the detached content type - in case the function fails - */ - break; - } else { - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - } - } - } - /* set default type if no content type */ - if content_type.is_null() { - /* content_type is detached, in any case, we will have to free it */ - if default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN as libc::c_int { - content_type = mailmime_get_content_text(); - if content_type.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 16594950150283576116; - } else { - current_block = 7828949454673616476; - } - } else { - /* message */ - body_type = MAILMIME_MESSAGE as libc::c_int; - content_type = mailmime_get_content_message(); - if content_type.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 16594950150283576116; - } else { - current_block = 7828949454673616476; - } - } - } else { - current_block = 7828949454673616476; - } - match current_block { - 7828949454673616476 => { - boundary = 0 as *mut libc::c_char; - match (*(*content_type).ct_type).tp_type { - 2 => match (*(*(*content_type).ct_type).tp_data.tp_composite_type).ct_type { - 2 => { - boundary = mailmime_extract_boundary(content_type); - if boundary.is_null() { - body_type = MAILMIME_SINGLE as libc::c_int - } else { - body_type = MAILMIME_MULTIPLE as libc::c_int - } - current_block = 11793792312832361944; - } - 1 => { - if strcasecmp( - (*content_type).ct_subtype, - b"rfc822\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - body_type = MAILMIME_MESSAGE as libc::c_int - } else { - body_type = MAILMIME_SINGLE as libc::c_int - } - current_block = 11793792312832361944; - } - _ => { - res = MAILIMF_ERROR_INVAL as libc::c_int; - current_block = 18099180955076792539; - } - }, - _ => { - body_type = MAILMIME_SINGLE as libc::c_int; - current_block = 11793792312832361944; - } - } - match current_block { - 11793792312832361944 => { - if !mime_fields.is_null() { - encoding = mailmime_transfer_encoding_get(mime_fields) - } else { - encoding = MAILMIME_MECHANISM_8BIT as libc::c_int - } - if body_type == MAILMIME_MESSAGE as libc::c_int { - match encoding { - 4 | 5 => body_type = MAILMIME_SINGLE as libc::c_int, - _ => {} - } - } - cur_token = *indx; - body = mailmime_data_new( - MAILMIME_DATA_TEXT as libc::c_int, - encoding, - 1i32, - message.offset(cur_token as isize), - length.wrapping_sub(cur_token), - 0 as *mut libc::c_char, - ); - if body.is_null() { - free(boundary as *mut libc::c_void); - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - list = 0 as *mut clist; - msg_mime = 0 as *mut Mailmime; - fields = 0 as *mut mailimf_fields; - match body_type { - 3 => { - let mut submime_fields: *mut mailmime_fields = - 0 as *mut mailmime_fields; - r = mailimf_envelope_and_optional_fields_parse( - message, - length, - &mut cur_token, - &mut fields, - ); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - res = r; - current_block = 18099180955076792539; - } else { - r = mailimf_crlf_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - mailimf_fields_free(fields); - res = r; - current_block = 18099180955076792539; - } else { - submime_fields = 0 as *mut mailmime_fields; - r = mailmime_fields_parse(fields, &mut submime_fields); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - mailimf_fields_free(fields); - res = r; - current_block = 18099180955076792539; - } else { - remove_unparsed_mime_headers(fields); - r = mailmime_parse_with_default( - message, - length, - &mut cur_token, - MAILMIME_DEFAULT_TYPE_TEXT_PLAIN as libc::c_int, - 0 as *mut mailmime_content, - submime_fields, - &mut msg_mime, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - current_block = 12065775993741208975; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - mailmime_fields_free(mime_fields); - msg_mime = 0 as *mut Mailmime; - current_block = 12065775993741208975; - } else { - mailmime_fields_free(mime_fields); - res = r; - current_block = 18099180955076792539; - } - } - } - } - } - 2 => { - let mut default_subtype: libc::c_int = 0; - default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN as libc::c_int; - if !content_type.is_null() { - if strcasecmp( - (*content_type).ct_subtype, - b"digest\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - default_subtype = - MAILMIME_DEFAULT_TYPE_MESSAGE as libc::c_int - } - } - cur_token = *indx; - r = mailmime_multipart_body_parse( - message, - length, - &mut cur_token, - boundary, - default_subtype, - &mut list, - &mut preamble, - &mut epilogue, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - current_block = 4804377075063615140; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 18099180955076792539; - } else { - current_block = 4804377075063615140; - } - } else { - res = r; - current_block = 18099180955076792539; - } - match current_block { - 18099180955076792539 => {} - _ => { - free(boundary as *mut libc::c_void); - current_block = 12065775993741208975; - } - } - } - _ => { - /* do nothing */ - current_block = 12065775993741208975; - } - } - match current_block { - 18099180955076792539 => {} - _ => { - mime = mailmime_new( - body_type, - message, - length, - mime_fields, - content_type, - body, - preamble, - epilogue, - list, - fields, - msg_mime, - ); - /* preamble */ - /* epilogue */ - if mime.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !epilogue.is_null() { - mailmime_data_free(epilogue); - } - if !preamble.is_null() { - mailmime_data_free(preamble); - } - if !msg_mime.is_null() { - mailmime_free(msg_mime); - } - if !list.is_null() { - clist_foreach( - list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some( - mailmime_free, - )), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - } else { - *result = mime; - *indx = length; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - } - _ => {} - } - mailmime_content_free(content_type); - } - _ => {} - } - return res; -} -unsafe fn mailmime_multipart_body_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut boundary: *mut libc::c_char, - mut default_subtype: libc::c_int, - mut result: *mut *mut clist, - mut p_preamble: *mut *mut mailmime_data, - mut p_epilogue: *mut *mut mailmime_data, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut list: *mut clist = 0 as *mut clist; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut preamble_begin: size_t = 0; - let mut preamble_length: size_t = 0; - let mut preamble_end: size_t = 0; - let mut epilogue_begin: size_t = 0; - let mut epilogue_length: size_t = 0; - let mut preamble: *mut mailmime_data = 0 as *mut mailmime_data; - let mut epilogue: *mut mailmime_data = 0 as *mut mailmime_data; - let mut part_begin: size_t = 0; - let mut final_part: libc::c_int = 0; - preamble = 0 as *mut mailmime_data; - epilogue = 0 as *mut mailmime_data; - cur_token = *indx; - preamble_begin = cur_token; - preamble_end = preamble_begin; - r = mailmime_preamble_parse(message, length, &mut cur_token, 1i32); - if r == MAILIMF_NO_ERROR as libc::c_int { - loop { - preamble_end = cur_token; - r = mailmime_boundary_parse(message, length, &mut cur_token, boundary); - if r == MAILIMF_NO_ERROR as libc::c_int { - current_block = 16924917904204750491; - break; - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailmime_preamble_parse(message, length, &mut cur_token, 0i32); - if r == MAILIMF_NO_ERROR as libc::c_int { - continue; - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 16924917904204750491; - break; - } - res = r; - current_block = 13657460241182544761; - break; - } else { - /* do nothing */ - res = r; - current_block = 13657460241182544761; - break; - } - } - } else { - current_block = 16924917904204750491; - } - match current_block { - 16924917904204750491 => { - preamble_end = (preamble_end as libc::size_t).wrapping_sub(2i32 as libc::size_t) - as size_t as size_t; - if preamble_end != preamble_begin { - if *message.offset(preamble_end.wrapping_sub(1i32 as libc::size_t) as isize) - as libc::c_int - == '\n' as i32 - { - preamble_end = preamble_end.wrapping_sub(1); - if preamble_end.wrapping_sub(1i32 as libc::size_t) >= preamble_begin { - if *message.offset(preamble_end.wrapping_sub(1i32 as libc::size_t) as isize) - as libc::c_int - == '\r' as i32 - { - preamble_end = preamble_end.wrapping_sub(1) - } - } - } else if *message.offset(preamble_end.wrapping_sub(1i32 as libc::size_t) as isize) - as libc::c_int - == '\r' as i32 - { - preamble_end = preamble_end.wrapping_sub(1) - } - } - preamble_length = preamble_end.wrapping_sub(preamble_begin); - part_begin = cur_token; - loop { - r = mailmime_lwsp_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r; - current_block = 13657460241182544761; - break; - } else { - r = mailimf_crlf_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - part_begin = cur_token - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - /* do nothing */ - current_block = 9353995356876505083; - break; - } else { - res = r; - current_block = 13657460241182544761; - break; - } - } - } - match current_block { - 13657460241182544761 => {} - _ => { - cur_token = part_begin; - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - final_part = 0i32; - loop { - if !(0 == final_part) { - current_block = 15447629348493591490; - break; - } - let mut bp_token: size_t = 0; - let mut mime_bp: *mut Mailmime = 0 as *mut Mailmime; - let mut data_str: *const libc::c_char = 0 as *const libc::c_char; - let mut data_size: size_t = 0; - let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields; - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - r = mailmime_body_part_dash2_transport_crlf_parse( - message, - length, - &mut cur_token, - boundary, - &mut data_str, - &mut data_size, - ); - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailmime_body_part_dash2_close_parse( - message, - length, - &mut cur_token, - boundary, - &mut data_str, - &mut data_size, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - final_part = 1i32 - } - } - if r == MAILIMF_NO_ERROR as libc::c_int { - bp_token = 0i32 as size_t; - r = mailimf_optional_fields_parse( - data_str, - data_size, - &mut bp_token, - &mut fields, - ); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - res = r; - current_block = 6612762688763383599; - break; - } else { - r = mailimf_crlf_parse(data_str, data_size, &mut bp_token); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - mailimf_fields_free(fields); - res = r; - current_block = 6612762688763383599; - break; - } else { - mime_fields = 0 as *mut mailmime_fields; - r = mailmime_fields_parse(fields, &mut mime_fields); - mailimf_fields_free(fields); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - res = r; - current_block = 6612762688763383599; - break; - } else { - r = mailmime_parse_with_default( - data_str, - data_size, - &mut bp_token, - default_subtype, - 0 as *mut mailmime_content, - mime_fields, - &mut mime_bp, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - r = clist_insert_after( - list, - (*list).last, - mime_bp as *mut libc::c_void, - ); - if r < 0i32 { - mailmime_free(mime_bp); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 6612762688763383599; - break; - } else { - r = mailmime_multipart_next_parse( - message, - length, - &mut cur_token, - ); - r == MAILIMF_NO_ERROR as libc::c_int; - } - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - mailmime_fields_free(mime_fields); - current_block = 15447629348493591490; - break; - } else { - mailmime_fields_free(mime_fields); - res = r; - current_block = 6612762688763383599; - break; - } - } - } - } - } else { - /* do nothing */ - res = r; - current_block = 6612762688763383599; - break; - } - } - match current_block { - 15447629348493591490 => { - epilogue_begin = length; - /* parse transport-padding */ - loop { - r = mailmime_lwsp_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - res = r; - current_block = 6612762688763383599; - break; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 13201766686570145889; - break; - } - } - match current_block { - 6612762688763383599 => {} - _ => { - r = mailimf_crlf_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - epilogue_begin = cur_token; - current_block = 1739363794695357236; - } else if r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r; - current_block = 6612762688763383599; - } else { - current_block = 1739363794695357236; - } - match current_block { - 6612762688763383599 => {} - _ => { - epilogue_length = - length.wrapping_sub(epilogue_begin); - if preamble_length != 0i32 as libc::size_t { - preamble = mailmime_data_new( - MAILMIME_DATA_TEXT as libc::c_int, - MAILMIME_MECHANISM_8BIT as libc::c_int, - 1i32, - message.offset(preamble_begin as isize), - preamble_length, - 0 as *mut libc::c_char, - ); - if preamble.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 6612762688763383599; - } else { - current_block = 5636883459695696059; - } - } else { - current_block = 5636883459695696059; - } - match current_block { - 6612762688763383599 => {} - _ => { - if epilogue_length != 0i32 as libc::size_t { - epilogue = mailmime_data_new( - MAILMIME_DATA_TEXT as libc::c_int, - MAILMIME_MECHANISM_8BIT - as libc::c_int, - 1i32, - message.offset( - epilogue_begin as isize, - ), - epilogue_length, - 0 as *mut libc::c_char, - ); - if epilogue.is_null() { - res = MAILIMF_ERROR_MEMORY - as libc::c_int; - current_block = 6612762688763383599; - } else { - current_block = 7337917895049117968; - } - } else { - current_block = 7337917895049117968; - } - match current_block { - 6612762688763383599 => {} - _ => { - cur_token = length; - *result = list; - *p_preamble = preamble; - *p_epilogue = epilogue; - *indx = cur_token; - return MAILIMF_NO_ERROR - as libc::c_int; - } - } - } - } - } - } - } - } - } - _ => {} - } - if !epilogue.is_null() { - mailmime_data_free(epilogue); - } - if !preamble.is_null() { - mailmime_data_free(preamble); - } - clist_foreach( - list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailmime_free)), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - } - } - } - _ => {} - } - return res; -} -unsafe fn mailmime_lwsp_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - cur_token = *indx; - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - while 0 != is_wsp(*message.offset(cur_token as isize)) { - cur_token = cur_token.wrapping_add(1); - if cur_token >= length { - break; - } - } - if cur_token == *indx { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn is_wsp(mut ch: libc::c_char) -> libc::c_int { - if ch as libc::c_int == ' ' as i32 || ch as libc::c_int == '\t' as i32 { - return 1i32; - } - return 0i32; -} - -pub unsafe fn mailmime_multipart_next_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut state: libc::c_int = 0; - let mut cur_token: size_t = 0; - cur_token = *indx; - state = MULTIPART_NEXT_STATE_0 as libc::c_int; - while state != MULTIPART_NEXT_STATE_2 as libc::c_int { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match state { - 0 => match *message.offset(cur_token as isize) as libc::c_int { - 32 => state = MULTIPART_NEXT_STATE_0 as libc::c_int, - 9 => state = MULTIPART_NEXT_STATE_0 as libc::c_int, - 13 => state = MULTIPART_NEXT_STATE_1 as libc::c_int, - 10 => state = MULTIPART_NEXT_STATE_2 as libc::c_int, - _ => return MAILIMF_ERROR_PARSE as libc::c_int, - }, - 1 => match *message.offset(cur_token as isize) as libc::c_int { - 10 => state = MULTIPART_NEXT_STATE_2 as libc::c_int, - _ => return MAILIMF_ERROR_PARSE as libc::c_int, - }, - _ => {} - } - cur_token = cur_token.wrapping_add(1) - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_body_part_dash2_close_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut boundary: *mut libc::c_char, - mut result: *mut *const libc::c_char, - mut result_size: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut data_str: *const libc::c_char = 0 as *const libc::c_char; - let mut data_size: size_t = 0; - let mut begin_text: *const libc::c_char = 0 as *const libc::c_char; - let mut end_text: *const libc::c_char = 0 as *const libc::c_char; - cur_token = *indx; - begin_text = message.offset(cur_token as isize); - end_text = message.offset(cur_token as isize); - loop { - r = mailmime_body_part_dash2_parse( - message, - length, - &mut cur_token, - boundary, - &mut data_str, - &mut data_size, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - end_text = data_str.offset(data_size as isize) - } else { - return r; - } - /* - There's no MIME multipart close bounary. - Ignore the issue and succeed. - https://github.com/MailCore/mailcore2/issues/122 - */ - if cur_token >= length { - break; - } - r = mailmime_multipart_close_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - break; - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - } else { - return r; - } - } - *indx = cur_token; - *result = begin_text; - *result_size = end_text.wrapping_offset_from(begin_text) as size_t; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_multipart_close_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, -) -> libc::c_int { - let mut state: libc::c_int = 0; - let mut cur_token: size_t = 0; - cur_token = *indx; - state = MULTIPART_CLOSE_STATE_0 as libc::c_int; - while state != MULTIPART_CLOSE_STATE_4 as libc::c_int { - match state { - 0 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 45 => state = MULTIPART_CLOSE_STATE_1 as libc::c_int, - _ => return MAILIMF_ERROR_PARSE as libc::c_int, - } - } - 1 => { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match *message.offset(cur_token as isize) as libc::c_int { - 45 => state = MULTIPART_CLOSE_STATE_2 as libc::c_int, - _ => return MAILIMF_ERROR_PARSE as libc::c_int, - } - } - 2 => { - if cur_token >= length { - state = MULTIPART_CLOSE_STATE_4 as libc::c_int - } else { - match *message.offset(cur_token as isize) as libc::c_int { - 32 => state = MULTIPART_CLOSE_STATE_2 as libc::c_int, - 9 => state = MULTIPART_CLOSE_STATE_2 as libc::c_int, - 13 => state = MULTIPART_CLOSE_STATE_3 as libc::c_int, - 10 => state = MULTIPART_CLOSE_STATE_4 as libc::c_int, - _ => state = MULTIPART_CLOSE_STATE_4 as libc::c_int, - } - } - } - 3 => { - if cur_token >= length { - state = MULTIPART_CLOSE_STATE_4 as libc::c_int - } else { - match *message.offset(cur_token as isize) as libc::c_int { - 10 => state = MULTIPART_CLOSE_STATE_4 as libc::c_int, - _ => state = MULTIPART_CLOSE_STATE_4 as libc::c_int, - } - } - } - _ => {} - } - cur_token = cur_token.wrapping_add(1) - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_body_part_dash2_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut boundary: *mut libc::c_char, - mut result: *mut *const libc::c_char, - mut result_size: *mut size_t, -) -> libc::c_int { - let mut state: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut size: size_t = 0; - let mut begin_text: size_t = 0; - let mut end_text: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - state = BODY_PART_DASH2_STATE_0 as libc::c_int; - begin_text = cur_token; - end_text = length; - while state != BODY_PART_DASH2_STATE_5 as libc::c_int { - if cur_token >= length { - break; - } - match state { - 0 => match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = BODY_PART_DASH2_STATE_1 as libc::c_int, - 10 => state = BODY_PART_DASH2_STATE_2 as libc::c_int, - _ => state = BODY_PART_DASH2_STATE_0 as libc::c_int, - }, - 1 => match *message.offset(cur_token as isize) as libc::c_int { - 10 => state = BODY_PART_DASH2_STATE_2 as libc::c_int, - _ => state = BODY_PART_DASH2_STATE_0 as libc::c_int, - }, - 2 => match *message.offset(cur_token as isize) as libc::c_int { - 45 => { - end_text = cur_token; - state = BODY_PART_DASH2_STATE_3 as libc::c_int - } - 13 => state = BODY_PART_DASH2_STATE_1 as libc::c_int, - 10 => state = BODY_PART_DASH2_STATE_2 as libc::c_int, - _ => state = BODY_PART_DASH2_STATE_0 as libc::c_int, - }, - 3 => match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = BODY_PART_DASH2_STATE_1 as libc::c_int, - 10 => state = BODY_PART_DASH2_STATE_2 as libc::c_int, - 45 => state = BODY_PART_DASH2_STATE_4 as libc::c_int, - _ => state = BODY_PART_DASH2_STATE_0 as libc::c_int, - }, - 4 => { - r = mailmime_boundary_parse(message, length, &mut cur_token, boundary); - if r == MAILIMF_NO_ERROR as libc::c_int { - state = BODY_PART_DASH2_STATE_5 as libc::c_int - } else { - state = BODY_PART_DASH2_STATE_6 as libc::c_int - } - } - _ => {} - } - if state != BODY_PART_DASH2_STATE_5 as libc::c_int - && state != BODY_PART_DASH2_STATE_6 as libc::c_int - { - cur_token = cur_token.wrapping_add(1) - } - if state == BODY_PART_DASH2_STATE_6 as libc::c_int { - state = BODY_PART_DASH2_STATE_0 as libc::c_int - } - } - size = end_text.wrapping_sub(begin_text); - if size >= 1i32 as libc::size_t { - if *message.offset(end_text.wrapping_sub(1i32 as libc::size_t) as isize) as libc::c_int - == '\r' as i32 - { - end_text = end_text.wrapping_sub(1); - size = size.wrapping_sub(1) - } else if size >= 1i32 as libc::size_t { - if *message.offset(end_text.wrapping_sub(1i32 as libc::size_t) as isize) as libc::c_int - == '\n' as i32 - { - end_text = end_text.wrapping_sub(1); - size = size.wrapping_sub(1); - if size >= 1i32 as libc::size_t { - if *message.offset(end_text.wrapping_sub(1i32 as libc::size_t) as isize) - as libc::c_int - == '\r' as i32 - { - end_text = end_text.wrapping_sub(1); - size = size.wrapping_sub(1) - } - } - } - } - } - size = end_text.wrapping_sub(begin_text); - if size == 0i32 as libc::size_t { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - *result = message.offset(begin_text as isize); - *result_size = size; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_boundary_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut boundary: *mut libc::c_char, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut len: size_t = 0; - cur_token = *indx; - len = strlen(boundary); - if cur_token.wrapping_add(len) >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - if strncmp(message.offset(cur_token as isize), boundary, len) != 0i32 { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - cur_token = (cur_token as libc::size_t).wrapping_add(len) as size_t as size_t; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_body_part_dash2_transport_crlf_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut boundary: *mut libc::c_char, - mut result: *mut *const libc::c_char, - mut result_size: *mut size_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut data_str: *const libc::c_char = 0 as *const libc::c_char; - let mut data_size: size_t = 0; - let mut begin_text: *const libc::c_char = 0 as *const libc::c_char; - let mut end_text: *const libc::c_char = 0 as *const libc::c_char; - cur_token = *indx; - begin_text = message.offset(cur_token as isize); - end_text = message.offset(cur_token as isize); - loop { - r = mailmime_body_part_dash2_parse( - message, - length, - &mut cur_token, - boundary, - &mut data_str, - &mut data_size, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - end_text = data_str.offset(data_size as isize) - } else { - return r; - } - loop { - r = mailmime_lwsp_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - continue; - } - /* do nothing */ - if r == MAILIMF_ERROR_PARSE as libc::c_int { - break; - } - return r; - } - r = mailimf_crlf_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - break; - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - } else { - return r; - } - } - *indx = cur_token; - *result = begin_text; - *result_size = end_text.wrapping_offset_from(begin_text) as size_t; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_preamble_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut beol: libc::c_int, -) -> libc::c_int { - let mut state: libc::c_int = 0; - let mut cur_token: size_t = 0; - cur_token = *indx; - if 0 != beol { - state = PREAMBLE_STATE_A0 as libc::c_int - } else { - state = PREAMBLE_STATE_A as libc::c_int - } - while state != PREAMBLE_STATE_E as libc::c_int { - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match state { - 0 => match *message.offset(cur_token as isize) as libc::c_int { - 45 => state = PREAMBLE_STATE_A1 as libc::c_int, - 13 => state = PREAMBLE_STATE_B as libc::c_int, - 10 => state = PREAMBLE_STATE_C as libc::c_int, - _ => state = PREAMBLE_STATE_A as libc::c_int, - }, - 1 => match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = PREAMBLE_STATE_B as libc::c_int, - 10 => state = PREAMBLE_STATE_C as libc::c_int, - _ => state = PREAMBLE_STATE_A as libc::c_int, - }, - 2 => match *message.offset(cur_token as isize) as libc::c_int { - 45 => state = PREAMBLE_STATE_E as libc::c_int, - 13 => state = PREAMBLE_STATE_B as libc::c_int, - 10 => state = PREAMBLE_STATE_C as libc::c_int, - _ => state = PREAMBLE_STATE_A as libc::c_int, - }, - 3 => match *message.offset(cur_token as isize) as libc::c_int { - 13 => state = PREAMBLE_STATE_B as libc::c_int, - 10 => state = PREAMBLE_STATE_C as libc::c_int, - 45 => state = PREAMBLE_STATE_D as libc::c_int, - _ => state = PREAMBLE_STATE_A0 as libc::c_int, - }, - 4 => match *message.offset(cur_token as isize) as libc::c_int { - 45 => state = PREAMBLE_STATE_D as libc::c_int, - 13 => state = PREAMBLE_STATE_B as libc::c_int, - 10 => state = PREAMBLE_STATE_C as libc::c_int, - _ => state = PREAMBLE_STATE_A0 as libc::c_int, - }, - 5 => match *message.offset(cur_token as isize) as libc::c_int { - 45 => state = PREAMBLE_STATE_E as libc::c_int, - _ => state = PREAMBLE_STATE_A as libc::c_int, - }, - _ => {} - } - cur_token = cur_token.wrapping_add(1) - } - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn remove_unparsed_mime_headers(mut fields: *mut mailimf_fields) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*fields).fld_list).first; - while !cur.is_null() { - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - let mut delete: libc::c_int = 0; - field = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_field; - match (*field).fld_type { - 22 => { - delete = 0i32; - if strncasecmp( - (*(*field).fld_data.fld_optional_field).fld_name, - b"Content-\x00" as *const u8 as *const libc::c_char, - 8i32 as libc::size_t, - ) == 0i32 - { - let mut name: *mut libc::c_char = 0 as *mut libc::c_char; - name = (*(*field).fld_data.fld_optional_field) - .fld_name - .offset(8isize); - if strcasecmp(name, b"Type\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcasecmp( - name, - b"Transfer-Encoding\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - || strcasecmp(name, b"ID\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcasecmp(name, b"Description\x00" as *const u8 as *const libc::c_char) - == 0i32 - || strcasecmp(name, b"Disposition\x00" as *const u8 as *const libc::c_char) - == 0i32 - || strcasecmp(name, b"Language\x00" as *const u8 as *const libc::c_char) - == 0i32 - { - delete = 1i32 - } - } else if strcasecmp( - (*(*field).fld_data.fld_optional_field).fld_name, - b"MIME-Version\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - delete = 1i32 - } - if 0 != delete { - cur = clist_delete((*fields).fld_list, cur); - mailimf_field_free(field); - } else { - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - } - _ => { - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - } - } -} - -pub unsafe fn mailmime_extract_boundary( - mut content_type: *mut mailmime_content, -) -> *mut libc::c_char { - let mut boundary: *mut libc::c_char = 0 as *mut libc::c_char; - boundary = mailmime_content_param_get( - content_type, - b"boundary\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - ); - if !boundary.is_null() { - let mut len: size_t = 0; - let mut new_boundary: *mut libc::c_char = 0 as *mut libc::c_char; - len = strlen(boundary); - new_boundary = malloc(len.wrapping_add(1i32 as libc::size_t)) as *mut libc::c_char; - if new_boundary.is_null() { - return 0 as *mut libc::c_char; - } - if *boundary.offset(0isize) as libc::c_int == '\"' as i32 { - strncpy( - new_boundary, - boundary.offset(1isize), - len.wrapping_sub(2i32 as libc::size_t), - ); - *new_boundary.offset(len.wrapping_sub(2i32 as libc::size_t) as isize) = - 0i32 as libc::c_char - } else { - strcpy(new_boundary, boundary); - } - boundary = new_boundary - } - return boundary; -} - -pub unsafe fn mailmime_get_section( - mut mime: *mut Mailmime, - mut section: *mut mailmime_section, - mut result: *mut *mut Mailmime, -) -> libc::c_int { - return mailmime_get_section_list(mime, (*(*section).sec_list).first, result); -} -unsafe fn mailmime_get_section_list( - mut mime: *mut Mailmime, - mut list: *mut clistiter, - mut result: *mut *mut Mailmime, -) -> libc::c_int { - let mut id: uint32_t = 0; - let mut data: *mut Mailmime = 0 as *mut Mailmime; - let mut submime: *mut Mailmime = 0 as *mut Mailmime; - if list.is_null() { - *result = mime; - return MAILIMF_NO_ERROR as libc::c_int; - } - id = *((if !list.is_null() { - (*list).data - } else { - 0 as *mut libc::c_void - }) as *mut uint32_t); - data = 0 as *mut Mailmime; - match (*mime).mm_type { - 1 => return MAILIMF_ERROR_INVAL as libc::c_int, - 2 => { - data = clist_nth_data( - (*mime).mm_data.mm_multipart.mm_mp_list, - id.wrapping_sub(1i32 as libc::c_uint) as libc::c_int, - ) as *mut Mailmime; - if data.is_null() { - return MAILIMF_ERROR_INVAL as libc::c_int; - } - if !if !list.is_null() { - (*list).next - } else { - 0 as *mut clistcell - } - .is_null() - { - return mailmime_get_section_list( - data, - if !list.is_null() { - (*list).next - } else { - 0 as *mut clistcell - }, - result, - ); - } else { - *result = data; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - 3 => { - submime = (*mime).mm_data.mm_message.mm_msg_mime; - match (*submime).mm_type { - 2 => { - data = clist_nth_data( - (*submime).mm_data.mm_multipart.mm_mp_list, - id.wrapping_sub(1i32 as libc::c_uint) as libc::c_int, - ) as *mut Mailmime; - if data.is_null() { - return MAILIMF_ERROR_INVAL as libc::c_int; - } - return mailmime_get_section_list( - data, - if !list.is_null() { - (*list).next - } else { - 0 as *mut clistcell - }, - result, - ); - } - _ => { - if id != 1i32 as libc::c_uint { - return MAILIMF_ERROR_INVAL as libc::c_int; - } - data = submime; - if data.is_null() { - return MAILIMF_ERROR_INVAL as libc::c_int; - } - return mailmime_get_section_list( - data, - if !list.is_null() { - (*list).next - } else { - 0 as *mut clistcell - }, - result, - ); - } - } - } - _ => return MAILIMF_ERROR_INVAL as libc::c_int, - }; -} -/* decode */ -pub unsafe fn mailmime_base64_body_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, - mut result_len: *mut size_t, -) -> libc::c_int { - return mailmime_base64_body_parse_impl(message, length, indx, result, result_len, 0i32); -} -unsafe fn mailmime_base64_body_parse_impl( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, - mut result_len: *mut size_t, - mut partial: libc::c_int, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut last_full_token_end: size_t = 0; - let mut chunk: [libc::c_char; 4] = [0; 4]; - let mut chunk_index: libc::c_int = 0; - let mut out: [libc::c_char; 3] = [0; 3]; - let mut mmapstr: *mut MMAPString = 0 as *mut MMAPString; - let mut res: libc::c_int = 0; - let mut r: libc::c_int = 0; - let mut written: size_t = 0; - chunk[0usize] = 0i32 as libc::c_char; - chunk[1usize] = 0i32 as libc::c_char; - chunk[2usize] = 0i32 as libc::c_char; - chunk[3usize] = 0i32 as libc::c_char; - cur_token = *indx; - last_full_token_end = *indx; - chunk_index = 0i32; - written = 0i32 as size_t; - mmapstr = mmap_string_sized_new( - length - .wrapping_sub(cur_token) - .wrapping_mul(3i32 as libc::size_t) - .wrapping_div(4i32 as libc::size_t), - ); - if mmapstr.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - loop { - let mut value: libc::c_schar = 0; - value = -1i32 as libc::c_schar; - while value as libc::c_int == -1i32 { - if cur_token >= length { - break; - } - value = get_base64_value(*message.offset(cur_token as isize)); - cur_token = cur_token.wrapping_add(1) - } - if value as libc::c_int == -1i32 { - current_block = 8845338526596852646; - break; - } - chunk[chunk_index as usize] = value as libc::c_char; - chunk_index += 1; - if !(chunk_index == 4i32) { - continue; - } - out[0usize] = ((chunk[0usize] as libc::c_int) << 2i32 - | chunk[1usize] as libc::c_int >> 4i32) as libc::c_char; - out[1usize] = ((chunk[1usize] as libc::c_int) << 4i32 - | chunk[2usize] as libc::c_int >> 2i32) as libc::c_char; - out[2usize] = ((chunk[2usize] as libc::c_int) << 6i32 | chunk[3usize] as libc::c_int) - as libc::c_char; - chunk[0usize] = 0i32 as libc::c_char; - chunk[1usize] = 0i32 as libc::c_char; - chunk[2usize] = 0i32 as libc::c_char; - chunk[3usize] = 0i32 as libc::c_char; - chunk_index = 0i32; - last_full_token_end = cur_token; - if mmap_string_append_len(mmapstr, out.as_mut_ptr(), 3i32 as size_t).is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 11891829943175634231; - break; - } else { - written = - (written as libc::size_t).wrapping_add(3i32 as libc::size_t) as size_t as size_t - } - } - match current_block { - 8845338526596852646 => { - if chunk_index != 0i32 && 0 == partial { - let mut len: size_t = 0; - len = 0i32 as size_t; - out[0usize] = ((chunk[0usize] as libc::c_int) << 2i32 - | chunk[1usize] as libc::c_int >> 4i32) - as libc::c_char; - len = len.wrapping_add(1); - if chunk_index >= 3i32 { - out[1usize] = ((chunk[1usize] as libc::c_int) << 4i32 - | chunk[2usize] as libc::c_int >> 2i32) - as libc::c_char; - len = len.wrapping_add(1) - } - if mmap_string_append_len(mmapstr, out.as_mut_ptr(), len).is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 11891829943175634231; - } else { - written = (written as libc::size_t).wrapping_add(len) as size_t as size_t; - current_block = 16738040538446813684; - } - } else { - current_block = 16738040538446813684; - } - match current_block { - 11891829943175634231 => {} - _ => { - if 0 != partial { - cur_token = last_full_token_end - } - r = mmap_string_ref(mmapstr); - if r < 0i32 { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *indx = cur_token; - *result = (*mmapstr).str_0; - *result_len = written; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - _ => {} - } - mmap_string_free(mmapstr); - } - return res; -} -/* ************************************************************************* */ -/* MIME part decoding */ -unsafe fn get_base64_value(mut ch: libc::c_char) -> libc::c_schar { - if ch as libc::c_int >= 'A' as i32 && ch as libc::c_int <= 'Z' as i32 { - return (ch as libc::c_int - 'A' as i32) as libc::c_schar; - } - if ch as libc::c_int >= 'a' as i32 && ch as libc::c_int <= 'z' as i32 { - return (ch as libc::c_int - 'a' as i32 + 26i32) as libc::c_schar; - } - if ch as libc::c_int >= '0' as i32 && ch as libc::c_int <= '9' as i32 { - return (ch as libc::c_int - '0' as i32 + 52i32) as libc::c_schar; - } - match ch as libc::c_int { - 43 => return 62i32 as libc::c_schar, - 47 => return 63i32 as libc::c_schar, - 61 => return -1i32 as libc::c_schar, - _ => return -1i32 as libc::c_schar, - }; -} - -pub unsafe fn mailmime_quoted_printable_body_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, - mut result_len: *mut size_t, - mut in_header: libc::c_int, -) -> libc::c_int { - return mailmime_quoted_printable_body_parse_impl( - message, length, indx, result, result_len, in_header, 0i32, - ); -} -unsafe fn mailmime_quoted_printable_body_parse_impl( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, - mut result_len: *mut size_t, - mut in_header: libc::c_int, - mut partial: libc::c_int, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut state: libc::c_int = 0; - let mut r: libc::c_int = 0; - let mut ch: libc::c_char = 0; - let mut count: size_t = 0; - let mut start: *const libc::c_char = 0 as *const libc::c_char; - let mut mmapstr: *mut MMAPString = 0 as *mut MMAPString; - let mut res: libc::c_int = 0; - let mut written: size_t = 0; - state = STATE_NORMAL as libc::c_int; - cur_token = *indx; - count = 0i32 as size_t; - start = message.offset(cur_token as isize); - written = 0i32 as size_t; - mmapstr = mmap_string_sized_new(length.wrapping_sub(cur_token)); - if mmapstr.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - loop { - if !(state != STATE_OUT as libc::c_int) { - current_block = 12693738997172594219; - break; - } - if cur_token >= length { - state = STATE_OUT as libc::c_int; - if 0 != partial { - cur_token = length - } - current_block = 12693738997172594219; - break; - } else { - match state { - 1 => { - if count > 0i32 as libc::size_t { - r = write_decoded_qp(mmapstr, start, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - break; - } else { - written = (written as libc::size_t).wrapping_add(count) as size_t - as size_t; - count = 0i32 as size_t - } - } - match *message.offset(cur_token as isize) as libc::c_int { - 61 => { - if cur_token.wrapping_add(1i32 as libc::size_t) >= length { - if 0 != partial { - state = STATE_OUT as libc::c_int - } else { - state = STATE_NORMAL as libc::c_int; - start = message.offset(cur_token as isize); - cur_token = cur_token.wrapping_add(1); - count = count.wrapping_add(1) - } - } else { - match *message.offset( - cur_token.wrapping_add(1i32 as libc::size_t) as isize, - ) as libc::c_int - { - 10 => { - cur_token = (cur_token as libc::size_t) - .wrapping_add(2i32 as libc::size_t) - as size_t - as size_t; - start = message.offset(cur_token as isize); - state = STATE_NORMAL as libc::c_int - } - 13 => { - if cur_token.wrapping_add(2i32 as libc::size_t) - >= length - { - state = STATE_OUT as libc::c_int - } else { - if *message.offset( - cur_token.wrapping_add(2i32 as libc::size_t) - as isize, - ) - as libc::c_int - == '\n' as i32 - { - cur_token = (cur_token as libc::size_t) - .wrapping_add(3i32 as libc::size_t) - as size_t - as size_t - } else { - cur_token = (cur_token as libc::size_t) - .wrapping_add(2i32 as libc::size_t) - as size_t - as size_t - } - start = message.offset(cur_token as isize); - state = STATE_NORMAL as libc::c_int - } - } - _ => { - if cur_token.wrapping_add(2i32 as libc::size_t) - >= length - { - if 0 != partial { - state = STATE_OUT as libc::c_int - } else { - cur_token = cur_token.wrapping_add(1); - start = message.offset(cur_token as isize); - count = count.wrapping_add(1); - state = STATE_NORMAL as libc::c_int - } - } else { - ch = to_char( - message - .offset(cur_token as isize) - .offset(1isize), - ); - if mmap_string_append_c(mmapstr, ch).is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13807130624542804568; - break; - } else { - cur_token = (cur_token as libc::size_t) - .wrapping_add(3i32 as libc::size_t) - as size_t - as size_t; - written = written.wrapping_add(1); - start = message.offset(cur_token as isize); - state = STATE_NORMAL as libc::c_int - } - } - } - } - } - } - _ => {} - } - } - 0 => { - /* end of STATE_ENCODED */ - match *message.offset(cur_token as isize) as libc::c_int { - 61 => { - state = STATE_CODED as libc::c_int; - current_block = 3024367268842933116; - } - 10 => { - /* flush before writing additionnal information */ - if count > 0i32 as libc::size_t { - r = write_decoded_qp(mmapstr, start, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - break; - } else { - written = (written as libc::size_t).wrapping_add(count) - as size_t - as size_t; - count = 0i32 as size_t - } - } - r = write_decoded_qp( - mmapstr, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - break; - } else { - written = (written as libc::size_t) - .wrapping_add(2i32 as libc::size_t) - as size_t - as size_t; - cur_token = cur_token.wrapping_add(1); - start = message.offset(cur_token as isize) - } - current_block = 3024367268842933116; - } - 13 => { - state = STATE_CR as libc::c_int; - cur_token = cur_token.wrapping_add(1); - current_block = 3024367268842933116; - } - 95 => { - if 0 != in_header { - if count > 0i32 as libc::size_t { - r = write_decoded_qp(mmapstr, start, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - break; - } else { - written = (written as libc::size_t).wrapping_add(count) - as size_t - as size_t; - count = 0i32 as size_t - } - } - if mmap_string_append_c(mmapstr, ' ' as i32 as libc::c_char) - .is_null() - { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13807130624542804568; - break; - } else { - written = written.wrapping_add(1); - cur_token = cur_token.wrapping_add(1); - start = message.offset(cur_token as isize) - } - current_block = 3024367268842933116; - } else { - /* WARINING : must be followed by switch default action */ - current_block = 9784205294207992806; - } - } - _ => { - current_block = 9784205294207992806; - } - } - match current_block { - 9784205294207992806 => { - if count >= 512i32 as libc::size_t { - r = write_decoded_qp(mmapstr, start, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - break; - } else { - written = (written as libc::size_t).wrapping_add(count) - as size_t - as size_t; - count = 0i32 as size_t; - start = message.offset(cur_token as isize) - } - } - count = count.wrapping_add(1); - cur_token = cur_token.wrapping_add(1) - } - _ => {} - } - } - 3 => { - /* end of STATE_NORMAL */ - match *message.offset(cur_token as isize) as libc::c_int { - 10 => { - /* flush before writing additionnal information */ - if count > 0i32 as libc::size_t { - r = write_decoded_qp(mmapstr, start, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - break; - } else { - written = (written as libc::size_t).wrapping_add(count) - as size_t - as size_t; - count = 0i32 as size_t - } - } - r = write_decoded_qp( - mmapstr, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - break; - } else { - written = (written as libc::size_t) - .wrapping_add(2i32 as libc::size_t) - as size_t - as size_t; - cur_token = cur_token.wrapping_add(1); - start = message.offset(cur_token as isize); - state = STATE_NORMAL as libc::c_int - } - } - _ => { - /* flush before writing additionnal information */ - if count > 0i32 as libc::size_t { - r = write_decoded_qp(mmapstr, start, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - break; - } else { - written = (written as libc::size_t).wrapping_add(count) - as size_t - as size_t; - count = 0i32 as size_t - } - } - start = message.offset(cur_token as isize); - r = write_decoded_qp( - mmapstr, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - break; - } else { - written = (written as libc::size_t) - .wrapping_add(2i32 as libc::size_t) - as size_t - as size_t; - state = STATE_NORMAL as libc::c_int - } - } - } - } - _ => {} - } - } - } - /* end of STATE_CR */ - match current_block { - 12693738997172594219 => { - if count > 0i32 as libc::size_t { - r = write_decoded_qp(mmapstr, start, count); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 13807130624542804568; - } else { - written = (written as libc::size_t).wrapping_add(count) as size_t as size_t; - count = 0i32 as size_t; - current_block = 9255187738567101705; - } - } else { - current_block = 9255187738567101705; - } - match current_block { - 13807130624542804568 => {} - _ => { - r = mmap_string_ref(mmapstr); - if r < 0i32 { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *indx = cur_token; - *result = (*mmapstr).str_0; - *result_len = written; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - _ => {} - } - mmap_string_free(mmapstr); - } - return res; -} -unsafe fn write_decoded_qp( - mut mmapstr: *mut MMAPString, - mut start: *const libc::c_char, - mut count: size_t, -) -> libc::c_int { - if mmap_string_append_len(mmapstr, start, count).is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -#[inline] -unsafe fn to_char(mut hexa: *const libc::c_char) -> libc::c_char { - return (hexa_to_char(*hexa.offset(0isize)) << 4i32 | hexa_to_char(*hexa.offset(1isize))) - as libc::c_char; -} -#[inline] -unsafe fn hexa_to_char(mut hexdigit: libc::c_char) -> libc::c_int { - if hexdigit as libc::c_int >= '0' as i32 && hexdigit as libc::c_int <= '9' as i32 { - return hexdigit as libc::c_int - '0' as i32; - } - if hexdigit as libc::c_int >= 'a' as i32 && hexdigit as libc::c_int <= 'f' as i32 { - return hexdigit as libc::c_int - 'a' as i32 + 10i32; - } - if hexdigit as libc::c_int >= 'A' as i32 && hexdigit as libc::c_int <= 'F' as i32 { - return hexdigit as libc::c_int - 'A' as i32 + 10i32; - } - return 0i32; -} - -pub unsafe fn mailmime_binary_body_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, - mut result_len: *mut size_t, -) -> libc::c_int { - let mut mmapstr: *mut MMAPString = 0 as *mut MMAPString; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - mmapstr = mmap_string_new_len( - message.offset(cur_token as isize), - length.wrapping_sub(cur_token), - ); - if mmapstr.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - r = mmap_string_ref(mmapstr); - if r < 0i32 { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - mmap_string_free(mmapstr); - } else { - *indx = length; - *result = (*mmapstr).str_0; - *result_len = length.wrapping_sub(cur_token); - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} -/* -mailmime_part_parse() - -This function gets full MIME part for parsing at once. -It is not suitable, if we want parse incomplete message in a stream mode. - -@return the return code is one of MAILIMF_ERROR_XXX or - MAILIMF_NO_ERROR codes -*/ -pub unsafe fn mailmime_part_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut encoding: libc::c_int, - mut result: *mut *mut libc::c_char, - mut result_len: *mut size_t, -) -> libc::c_int { - return mailmime_part_parse_impl(message, length, indx, encoding, result, result_len, 0i32); -} -unsafe fn mailmime_part_parse_impl( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut encoding: libc::c_int, - mut result: *mut *mut libc::c_char, - mut result_len: *mut size_t, - mut partial: libc::c_int, -) -> libc::c_int { - match encoding { - 5 => { - return mailmime_base64_body_parse_impl( - message, length, indx, result, result_len, partial, - ) - } - 4 => { - return mailmime_quoted_printable_body_parse_impl( - message, length, indx, result, result_len, 0i32, partial, - ) - } - 1 | 2 | 3 | _ => { - return mailmime_binary_body_parse(message, length, indx, result, result_len) - } - }; -} -/* -mailmime_part_parse_partial() - -This function may parse incomplete MIME part (i.e. in streaming mode). -It stops when detect incomplete encoding unit at the end of data. -Position of the first unparsed byte will be returned in (*indx) value. - -For parsing last portion of data must be used mailmime_part_parse() version. - -@param message Message for unparsed data. -@param length Length of the unparsed data. -@param INOUT indx Index of first unparsed symbol in the message. -@param encoding Encoding of the input data. -@param result Parsed MIME part content. Must be freed with mmap_string_unref(). -@param result_len Length of parsed data. - -@return the return code is one of MAILIMF_ERROR_XXX or - MAILIMF_NO_ERROR codes - -Example Usage: -@code -uint32_t received = 0; -uint32_t partLength = bodystructure[partId]->length; -for (;;) { - bool isThisRangeLast; - struct imap_range_t range = { received, 1024*1024 }; - char *result; - size_t result_len; - int error = imap_fetch_part_range(uid, partId, range, &result, &result_len); - if (error != NoError) { - // handle network error - break; - } - - if (result_len == 0) { - // requested range is empty. part is completely fetched - break; - } - - isThisRangeLast = (received + result_len >= partLength); // determine that the received data is the last, - // may be more difficult (in case of invalid metadata on the server). - - char *decoded; - size_t decoded_len; - if (isThisRangeLast) { - uint32_t index = 0; - mailmime_part_parse(result, result_len, encoding, &index, &decoded, &decoded_len); - break; - } - else { - uint32_t index = 0; - mailmime_part_parse_partial(result, result_len, encoding, &index, &decoded, &decoded_len); - // we may have some non-decoded bytes at the end of chunk. - // in this case we just request it in the next chunk - received += index; - } -} -@endcode -*/ -pub unsafe fn mailmime_part_parse_partial( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut encoding: libc::c_int, - mut result: *mut *mut libc::c_char, - mut result_len: *mut size_t, -) -> libc::c_int { - return mailmime_part_parse_impl(message, length, indx, encoding, result, result_len, 1i32); -} - -pub unsafe fn mailmime_get_section_id( - mut mime: *mut Mailmime, - mut result: *mut *mut mailmime_section, -) -> libc::c_int { - let mut current_block: u64; - let mut list: *mut clist = 0 as *mut clist; - let mut res: libc::c_int = 0; - let mut section_id: *mut mailmime_section = 0 as *mut mailmime_section; - let mut r: libc::c_int = 0; - if (*mime).mm_parent.is_null() { - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 11086394427076829997; - } else { - section_id = mailmime_section_new(list); - if section_id.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 11086394427076829997; - } else { - current_block = 9441801433784995173; - } - } - } else { - let mut id: uint32_t = 0; - let mut p_id: *mut uint32_t = 0 as *mut uint32_t; - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut parent: *mut Mailmime = 0 as *mut Mailmime; - r = mailmime_get_section_id((*mime).mm_parent, &mut section_id); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 11086394427076829997; - } else { - parent = (*mime).mm_parent; - match (*parent).mm_type { - 2 => { - current_block = 12048923724182970853; - match current_block { - 14310756207842895454 => { - if (*mime).mm_type == MAILMIME_SINGLE as libc::c_int - || (*mime).mm_type == MAILMIME_MESSAGE as libc::c_int - { - p_id = malloc(::std::mem::size_of::() as libc::size_t) - as *mut uint32_t; - if p_id.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14847554122685898769; - } else { - *p_id = 1i32 as uint32_t; - r = clist_insert_after( - (*section_id).sec_list, - (*(*section_id).sec_list).last, - p_id as *mut libc::c_void, - ); - if r < 0i32 { - free(p_id as *mut libc::c_void); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14847554122685898769; - } else { - current_block = 9441801433784995173; - } - } - } else { - current_block = 9441801433784995173; - } - } - _ => { - id = 1i32 as uint32_t; - cur = (*(*parent).mm_data.mm_multipart.mm_mp_list).first; - while !cur.is_null() { - if if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - } == mime as *mut libc::c_void - { - break; - } - id = id.wrapping_add(1); - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - p_id = malloc(::std::mem::size_of::() as libc::size_t) - as *mut uint32_t; - if p_id.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14847554122685898769; - } else { - *p_id = id; - r = clist_insert_after( - (*section_id).sec_list, - (*(*section_id).sec_list).last, - p_id as *mut libc::c_void, - ); - if r < 0i32 { - free(p_id as *mut libc::c_void); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14847554122685898769; - } else { - current_block = 9441801433784995173; - } - } - } - } - match current_block { - 9441801433784995173 => {} - _ => { - mailmime_section_free(section_id); - current_block = 11086394427076829997; - } - } - } - 3 => { - current_block = 14310756207842895454; - match current_block { - 14310756207842895454 => { - if (*mime).mm_type == MAILMIME_SINGLE as libc::c_int - || (*mime).mm_type == MAILMIME_MESSAGE as libc::c_int - { - p_id = malloc(::std::mem::size_of::() as libc::size_t) - as *mut uint32_t; - if p_id.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14847554122685898769; - } else { - *p_id = 1i32 as uint32_t; - r = clist_insert_after( - (*section_id).sec_list, - (*(*section_id).sec_list).last, - p_id as *mut libc::c_void, - ); - if r < 0i32 { - free(p_id as *mut libc::c_void); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14847554122685898769; - } else { - current_block = 9441801433784995173; - } - } - } else { - current_block = 9441801433784995173; - } - } - _ => { - id = 1i32 as uint32_t; - cur = (*(*parent).mm_data.mm_multipart.mm_mp_list).first; - while !cur.is_null() { - if if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - } == mime as *mut libc::c_void - { - break; - } - id = id.wrapping_add(1); - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - p_id = malloc(::std::mem::size_of::() as libc::size_t) - as *mut uint32_t; - if p_id.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14847554122685898769; - } else { - *p_id = id; - r = clist_insert_after( - (*section_id).sec_list, - (*(*section_id).sec_list).last, - p_id as *mut libc::c_void, - ); - if r < 0i32 { - free(p_id as *mut libc::c_void); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14847554122685898769; - } else { - current_block = 9441801433784995173; - } - } - } - } - match current_block { - 9441801433784995173 => {} - _ => { - mailmime_section_free(section_id); - current_block = 11086394427076829997; - } - } - } - _ => { - current_block = 9441801433784995173; - } - } - } - } - match current_block { - 11086394427076829997 => return res, - _ => { - *result = section_id; - return MAILIMF_NO_ERROR as libc::c_int; - } - }; -} diff --git a/mmime/src/mailmime/decode.rs b/mmime/src/mailmime/decode.rs deleted file mode 100644 index 3754d8187..000000000 --- a/mmime/src/mailmime/decode.rs +++ /dev/null @@ -1,860 +0,0 @@ -use libc; -use libc::toupper; - -use crate::charconv::*; -use crate::mailimf::*; -use crate::mailmime::content::*; -use crate::mailmime::types::*; -use crate::mmapstring::*; -use crate::other::*; - -pub const TYPE_WORD: libc::c_uint = 1; -pub const TYPE_ENCODED_WORD: libc::c_uint = 2; -pub const MAILMIME_ENCODING_Q: libc::c_uint = 1; -pub const MAILMIME_ENCODING_B: libc::c_uint = 0; -pub const TYPE_ERROR: libc::c_uint = 0; - -pub unsafe fn mailmime_encoded_phrase_parse( - mut default_fromcode: *const libc::c_char, - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut tocode: *const libc::c_char, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut current_block: u64; - let mut gphrase: *mut MMAPString = 0 as *mut MMAPString; - let mut word: *mut mailmime_encoded_word = 0 as *mut mailmime_encoded_word; - let mut first: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut str: *mut libc::c_char = 0 as *mut libc::c_char; - let mut wordutf8: *mut libc::c_char = 0 as *mut libc::c_char; - let mut type_0: libc::c_int = 0; - let mut missing_closing_quote: libc::c_int = 0; - cur_token = *indx; - gphrase = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - if gphrase.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - first = 1i32; - type_0 = TYPE_ERROR as libc::c_int; - loop { - let mut has_fwd: libc::c_int = 0; - word = 0 as *mut mailmime_encoded_word; - r = mailmime_encoded_word_parse( - message, - length, - &mut cur_token, - &mut word, - &mut has_fwd, - &mut missing_closing_quote, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - if 0 == first && 0 != has_fwd { - if type_0 != TYPE_ENCODED_WORD as libc::c_int { - if mmap_string_append_c(gphrase, ' ' as i32 as libc::c_char).is_null() { - mailmime_encoded_word_free(word); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13246848547199022064; - break; - } - } - } - type_0 = TYPE_ENCODED_WORD as libc::c_int; - wordutf8 = 0 as *mut libc::c_char; - r = charconv( - tocode, - (*word).wd_charset, - (*word).wd_text, - strlen((*word).wd_text), - &mut wordutf8, - ); - match r { - 2 => { - mailmime_encoded_word_free(word); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13246848547199022064; - break; - } - 1 => { - r = charconv( - tocode, - b"iso-8859-1\x00" as *const u8 as *const libc::c_char, - (*word).wd_text, - strlen((*word).wd_text), - &mut wordutf8, - ) - } - 3 => { - mailmime_encoded_word_free(word); - res = MAILIMF_ERROR_PARSE as libc::c_int; - current_block = 13246848547199022064; - break; - } - _ => {} - } - match r { - 2 => { - mailmime_encoded_word_free(word); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13246848547199022064; - break; - } - 3 => { - mailmime_encoded_word_free(word); - res = MAILIMF_ERROR_PARSE as libc::c_int; - current_block = 13246848547199022064; - break; - } - _ => { - if !wordutf8.is_null() { - if mmap_string_append(gphrase, wordutf8).is_null() { - mailmime_encoded_word_free(word); - free(wordutf8 as *mut libc::c_void); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13246848547199022064; - break; - } else { - free(wordutf8 as *mut libc::c_void); - } - } - mailmime_encoded_word_free(word); - first = 0i32 - } - } - } else if !(r == MAILIMF_ERROR_PARSE as libc::c_int) { - /* do nothing */ - res = r; - current_block = 13246848547199022064; - break; - } - if !(r == MAILIMF_ERROR_PARSE as libc::c_int) { - continue; - } - let mut raw_word: *mut libc::c_char = 0 as *mut libc::c_char; - raw_word = 0 as *mut libc::c_char; - r = mailmime_non_encoded_word_parse( - message, - length, - &mut cur_token, - &mut raw_word, - &mut has_fwd, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - if 0 == first && 0 != has_fwd { - if mmap_string_append_c(gphrase, ' ' as i32 as libc::c_char).is_null() { - free(raw_word as *mut libc::c_void); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13246848547199022064; - break; - } - } - type_0 = TYPE_WORD as libc::c_int; - wordutf8 = 0 as *mut libc::c_char; - r = charconv( - tocode, - default_fromcode, - raw_word, - strlen(raw_word), - &mut wordutf8, - ); - match r { - 2 => { - free(raw_word as *mut libc::c_void); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13246848547199022064; - break; - } - 1 | 3 => { - free(raw_word as *mut libc::c_void); - res = MAILIMF_ERROR_PARSE as libc::c_int; - current_block = 13246848547199022064; - break; - } - _ => { - if mmap_string_append(gphrase, wordutf8).is_null() { - free(wordutf8 as *mut libc::c_void); - free(raw_word as *mut libc::c_void); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13246848547199022064; - break; - } else { - free(wordutf8 as *mut libc::c_void); - free(raw_word as *mut libc::c_void); - first = 0i32 - } - } - } - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_fws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 5005389895767293342; - break; - } - if mmap_string_append_c(gphrase, ' ' as i32 as libc::c_char).is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13246848547199022064; - break; - } else { - first = 0i32; - current_block = 5005389895767293342; - break; - } - } else { - res = r; - current_block = 13246848547199022064; - break; - } - } - match current_block { - 5005389895767293342 => { - if 0 != first { - if cur_token != length { - res = MAILIMF_ERROR_PARSE as libc::c_int; - current_block = 13246848547199022064; - } else { - current_block = 7072655752890836508; - } - } else { - current_block = 7072655752890836508; - } - match current_block { - 13246848547199022064 => {} - _ => { - str = strdup((*gphrase).str_0); - if str.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - mmap_string_free(gphrase); - *result = str; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - _ => {} - } - mmap_string_free(gphrase); - } - return res; -} -unsafe fn mailmime_non_encoded_word_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, - mut p_has_fwd: *mut libc::c_int, -) -> libc::c_int { - let mut end: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut res: libc::c_int = 0; - let mut text: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut begin: size_t = 0; - let mut state: libc::c_int = 0; - let mut has_fwd: libc::c_int = 0; - cur_token = *indx; - has_fwd = 0i32; - r = mailimf_fws_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - has_fwd = 1i32 - } - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - begin = cur_token; - state = 0i32; - end = 0i32; - while !(cur_token >= length) { - let mut current_block_17: u64; - match *message.offset(cur_token as isize) as libc::c_int { - 32 | 9 | 13 | 10 => { - state = 0i32; - end = 1i32; - current_block_17 = 16924917904204750491; - } - 61 => { - state = 1i32; - current_block_17 = 16924917904204750491; - } - 63 => { - if state == 1i32 { - cur_token = cur_token.wrapping_sub(1); - end = 1i32 - } - current_block_17 = 10192508258555769664; - } - _ => { - current_block_17 = 10192508258555769664; - } - } - match current_block_17 { - 10192508258555769664 => state = 0i32, - _ => {} - } - if 0 != end { - break; - } - cur_token = cur_token.wrapping_add(1) - } - if cur_token.wrapping_sub(begin) == 0i32 as libc::size_t { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - text = malloc( - cur_token - .wrapping_sub(begin) - .wrapping_add(1i32 as libc::size_t), - ) as *mut libc::c_char; - if text.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - memcpy( - text as *mut libc::c_void, - message.offset(begin as isize) as *const libc::c_void, - cur_token.wrapping_sub(begin), - ); - *text.offset(cur_token.wrapping_sub(begin) as isize) = - '\u{0}' as i32 as libc::c_char; - *indx = cur_token; - *result = text; - *p_has_fwd = has_fwd; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - return res; -} - -pub unsafe fn mailmime_encoded_word_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_encoded_word, - mut p_has_fwd: *mut libc::c_int, - mut p_missing_closing_quote: *mut libc::c_int, -) -> libc::c_int { - let mut current_block: u64; - /* - Parse the following, when a unicode character encoding is split. - =?UTF-8?B?4Lij4Liw4LmA4Lia4Li04LiU4LiE4Lin4Liy4Lih4Lih4Lix4LiZ4Liq4LmM?= - =?UTF-8?B?4LmA4LiV4LmH4Lih4Lie4Li04LiB4Lix4LiUIFRSQU5TRk9STUVSUyA0IOC4?= - =?UTF-8?B?oeC4seC4meC4quC5jOC4hOC4o+C4muC4l+C4uOC4geC4o+C4sOC4muC4miDg?= - =?UTF-8?B?uJfguLXguYjguYDguJTguLXguKLguKfguYPguJnguYDguKHguLfguK3guIfg?= - =?UTF-8?B?uYTguJfguKI=?= - Expected result: - ระเบิดความมันส์เต็มพิกัด TRANSFORMERS 4 มันส์ครบทุกระบบ ที่เดียวในเมืองไทย - libetpan result: - ระเบิดความมันส์เต็มพิกัด TRANSFORMERS 4 ?ันส์ครบทุกระบบ ??ี่เดียวในเมือง??ทย - - See https://github.com/dinhviethoa/libetpan/pull/211 - */ - let mut cur_token: size_t = 0; - let mut charset: *mut libc::c_char = 0 as *mut libc::c_char; - let mut encoding: libc::c_int = 0; - let mut body: *mut libc::c_char = 0 as *mut libc::c_char; - let mut old_body_len: size_t = 0; - let mut text: *mut libc::c_char = 0 as *mut libc::c_char; - let mut end_encoding: size_t = 0; - let mut lookfwd_cur_token: size_t = 0; - let mut lookfwd_charset: *mut libc::c_char = 0 as *mut libc::c_char; - let mut lookfwd_encoding: libc::c_int = 0; - let mut copy_len: size_t = 0; - let mut decoded_token: size_t = 0; - let mut decoded: *mut libc::c_char = 0 as *mut libc::c_char; - let mut decoded_len: size_t = 0; - let mut ew: *mut mailmime_encoded_word = 0 as *mut mailmime_encoded_word; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut opening_quote: libc::c_int = 0; - let mut end: libc::c_int = 0; - let mut has_fwd: libc::c_int = 0; - let mut missing_closing_quote: libc::c_int = 0; - cur_token = *indx; - text = 0 as *mut libc::c_char; - lookfwd_charset = 0 as *mut libc::c_char; - missing_closing_quote = 0i32; - has_fwd = 0i32; - r = mailimf_fws_parse(message, length, &mut cur_token); - if r == MAILIMF_NO_ERROR as libc::c_int { - has_fwd = 1i32 - } - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - opening_quote = 0i32; - r = mailimf_char_parse(message, length, &mut cur_token, '\"' as i32 as libc::c_char); - if r == MAILIMF_NO_ERROR as libc::c_int { - opening_quote = 1i32; - current_block = 17788412896529399552; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 17788412896529399552; - } else { - /* do nothing */ - res = r; - current_block = 7995813543095296079; - } - match current_block { - 7995813543095296079 => {} - _ => { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"=?\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"=?\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailmime_charset_parse(message, length, &mut cur_token, &mut charset); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_char_parse( - message, - length, - &mut cur_token, - '?' as i32 as libc::c_char, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailmime_encoding_parse( - message, - length, - &mut cur_token, - &mut encoding, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_char_parse( - message, - length, - &mut cur_token, - '?' as i32 as libc::c_char, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - lookfwd_cur_token = cur_token; - body = 0 as *mut libc::c_char; - old_body_len = 0i32 as size_t; - loop { - let mut has_base64_padding: libc::c_int = 0; - end = 0i32; - has_base64_padding = 0i32; - end_encoding = cur_token; - while !(end_encoding >= length) { - if end_encoding.wrapping_add(1i32 as libc::size_t) - < length - { - if *message.offset(end_encoding as isize) - as libc::c_int - == '?' as i32 - && *message.offset( - end_encoding - .wrapping_add(1i32 as libc::size_t) - as isize, - ) - as libc::c_int - == '=' as i32 - { - end = 1i32 - } - } - if 0 != end { - break; - } - end_encoding = end_encoding.wrapping_add(1) - } - copy_len = end_encoding.wrapping_sub(lookfwd_cur_token); - if copy_len > 0i32 as libc::size_t { - if encoding == MAILMIME_ENCODING_B as libc::c_int { - if end_encoding >= 1i32 as libc::size_t { - if *message.offset( - end_encoding - .wrapping_sub(1i32 as libc::size_t) - as isize, - ) - as libc::c_int - == '=' as i32 - { - has_base64_padding = 1i32 - } - } - } - body = realloc( - body as *mut libc::c_void, - old_body_len - .wrapping_add(copy_len) - .wrapping_add(1i32 as libc::size_t), - ) - as *mut libc::c_char; - if body.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13900684162107791171; - break; - } else { - memcpy( - body.offset(old_body_len as isize) - as *mut libc::c_void, - &*message.offset(cur_token as isize) - as *const libc::c_char - as *const libc::c_void, - copy_len, - ); - *body - .offset(old_body_len.wrapping_add(copy_len) - as isize) = '\u{0}' as i32 as libc::c_char; - old_body_len = (old_body_len as libc::size_t) - .wrapping_add(copy_len) - as size_t - as size_t - } - } - cur_token = end_encoding; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"?=\x00" as *const u8 as *const libc::c_char - as *mut libc::c_char, - strlen(b"?=\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 2652804691515851435; - break; - } - if 0 != has_base64_padding { - current_block = 2652804691515851435; - break; - } - lookfwd_cur_token = cur_token; - r = mailimf_fws_parse( - message, - length, - &mut lookfwd_cur_token, - ); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - current_block = 2652804691515851435; - break; - } - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut lookfwd_cur_token, - b"=?\x00" as *const u8 as *const libc::c_char - as *mut libc::c_char, - strlen(b"=?\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 2652804691515851435; - break; - } - r = mailmime_charset_parse( - message, - length, - &mut lookfwd_cur_token, - &mut lookfwd_charset, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 2652804691515851435; - break; - } - r = mailimf_char_parse( - message, - length, - &mut lookfwd_cur_token, - '?' as i32 as libc::c_char, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 2652804691515851435; - break; - } - r = mailmime_encoding_parse( - message, - length, - &mut lookfwd_cur_token, - &mut lookfwd_encoding, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 2652804691515851435; - break; - } - r = mailimf_char_parse( - message, - length, - &mut lookfwd_cur_token, - '?' as i32 as libc::c_char, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 2652804691515851435; - break; - } - if strcasecmp(charset, lookfwd_charset) == 0i32 - && encoding == lookfwd_encoding - { - cur_token = lookfwd_cur_token; - mailmime_charset_free(lookfwd_charset); - lookfwd_charset = 0 as *mut libc::c_char - } else { - /* the next charset is not matched with the current one, - therefore exit the loop to decode the body appended so far */ - current_block = 2652804691515851435; - break; - } - } - match current_block { - 2652804691515851435 => { - if !lookfwd_charset.is_null() { - mailmime_charset_free(lookfwd_charset); - lookfwd_charset = 0 as *mut libc::c_char - } - if body.is_null() { - body = strdup( - b"\x00" as *const u8 as *const libc::c_char, - ); - if body.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13900684162107791171; - } else { - current_block = 16778110326724371720; - } - } else { - current_block = 16778110326724371720; - } - match current_block { - 13900684162107791171 => {} - _ => { - decoded_token = 0i32 as size_t; - decoded_len = 0i32 as size_t; - decoded = 0 as *mut libc::c_char; - match encoding { - 0 => { - r = mailmime_base64_body_parse( - body, - strlen(body), - &mut decoded_token, - &mut decoded, - &mut decoded_len, - ); - if r != MAILIMF_NO_ERROR as libc::c_int - { - res = r; - current_block = - 13900684162107791171; - } else { - current_block = 7337917895049117968; - } - } - 1 => { - r = - mailmime_quoted_printable_body_parse(body, - strlen(body), - &mut decoded_token, - &mut decoded, - &mut decoded_len, - 1i32); - if r != MAILIMF_NO_ERROR as libc::c_int - { - res = r; - current_block = - 13900684162107791171; - } else { - current_block = 7337917895049117968; - } - } - _ => { - current_block = 7337917895049117968; - } - } - match current_block { - 13900684162107791171 => {} - _ => { - text = - malloc(decoded_len.wrapping_add( - 1i32 as libc::size_t, - )) - as *mut libc::c_char; - if text.is_null() { - res = MAILIMF_ERROR_MEMORY - as libc::c_int - } else { - if decoded_len - > 0i32 as libc::size_t - { - memcpy( - text as *mut libc::c_void, - decoded - as *const libc::c_void, - decoded_len, - ); - } - *text - .offset(decoded_len as isize) = - '\u{0}' as i32 as libc::c_char; - if 0 != opening_quote { - r = mailimf_char_parse( - message, - length, - &mut cur_token, - '\"' as i32 as libc::c_char, - ); - if r == MAILIMF_ERROR_PARSE - as libc::c_int - { - missing_closing_quote = 1i32 - } - } - if strcasecmp( - charset, - b"utf8\x00" as *const u8 - as *const libc::c_char, - ) == 0i32 - { - free( - charset - as *mut libc::c_void, - ); - charset = strdup( - b"utf-8\x00" as *const u8 - as *const libc::c_char, - ) - } - ew = mailmime_encoded_word_new( - charset, text, - ); - if ew.is_null() { - res = MAILIMF_ERROR_MEMORY - as libc::c_int - } else { - *result = ew; - *indx = cur_token; - *p_has_fwd = has_fwd; - *p_missing_closing_quote = - missing_closing_quote; - mailmime_decoded_part_free( - decoded, - ); - free(body as *mut libc::c_void); - return MAILIMF_NO_ERROR - as libc::c_int; - } - } - mailmime_decoded_part_free(decoded); - } - } - } - } - } - _ => {} - } - free(body as *mut libc::c_void); - mailmime_encoded_text_free(text); - } - } - } - mailmime_charset_free(charset); - } - } - } - } - } - return res; -} -unsafe fn mailmime_encoding_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut libc::c_int, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut encoding: libc::c_int = 0; - cur_token = *indx; - if cur_token >= length { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - match toupper(*message.offset(cur_token as isize) as libc::c_uchar as libc::c_int) - as libc::c_char as libc::c_int - { - 81 => encoding = MAILMIME_ENCODING_Q as libc::c_int, - 66 => encoding = MAILMIME_ENCODING_B as libc::c_int, - _ => return MAILIMF_ERROR_INVAL as libc::c_int, - } - cur_token = cur_token.wrapping_add(1); - *result = encoding; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} - -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * $Id: mailmime_decode.c,v 1.37 2010/11/16 20:52:28 hoa Exp $ - */ -/* - RFC 2047 : MIME (Multipurpose Internet Mail Extensions) Part Three: - Message Header Extensions for Non-ASCII Text -*/ -unsafe fn mailmime_charset_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut charset: *mut *mut libc::c_char, -) -> libc::c_int { - return mailmime_etoken_parse(message, length, indx, charset); -} -unsafe fn mailmime_etoken_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - return mailimf_custom_string_parse(message, length, indx, result, Some(is_etoken_char)); -} - -unsafe fn is_etoken_char(mut ch: libc::c_char) -> libc::c_int { - let mut uch: libc::c_uchar = ch as libc::c_uchar; - if (uch as libc::c_int) < 31i32 { - return 0i32; - } - match uch as libc::c_int { - 32 | 40 | 41 | 60 | 62 | 64 | 44 | 59 | 58 | 34 | 47 | 91 | 93 | 63 | 61 => return 0i32, - _ => {} - } - return 1i32; -} diff --git a/mmime/src/mailmime/disposition.rs b/mmime/src/mailmime/disposition.rs deleted file mode 100644 index 6b68763dd..000000000 --- a/mmime/src/mailmime/disposition.rs +++ /dev/null @@ -1,583 +0,0 @@ -use libc::{self, toupper}; - -use crate::clist::*; -use crate::mailimf::*; -use crate::mailmime::types::*; -use crate::mailmime::*; -use crate::other::*; - -pub const MAILMIME_DISPOSITION_TYPE_EXTENSION: libc::c_uint = 3; -pub const MAILMIME_DISPOSITION_TYPE_ATTACHMENT: libc::c_uint = 2; -pub const MAILMIME_DISPOSITION_TYPE_INLINE: libc::c_uint = 1; -pub const MAILMIME_DISPOSITION_TYPE_ERROR: libc::c_uint = 0; - -pub unsafe fn mailmime_disposition_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_disposition, -) -> libc::c_int { - let mut current_block: u64; - let mut final_token: size_t = 0; - let mut cur_token: size_t = 0; - let mut dsp_type: *mut mailmime_disposition_type = 0 as *mut mailmime_disposition_type; - let mut list: *mut clist = 0 as *mut clist; - let mut dsp: *mut mailmime_disposition = 0 as *mut mailmime_disposition; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailmime_disposition_type_parse(message, length, &mut cur_token, &mut dsp_type); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - loop { - let mut param: *mut mailmime_disposition_parm = 0 as *mut mailmime_disposition_parm; - final_token = cur_token; - r = mailimf_unstrict_char_parse( - message, - length, - &mut cur_token, - ';' as i32 as libc::c_char, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - param = 0 as *mut mailmime_disposition_parm; - r = mailmime_disposition_parm_parse( - message, - length, - &mut cur_token, - &mut param, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - r = clist_insert_after(list, (*list).last, param as *mut libc::c_void); - if !(r < 0i32) { - continue; - } - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 18290070879695007868; - break; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - cur_token = final_token; - current_block = 652864300344834934; - break; - } else { - res = r; - current_block = 18290070879695007868; - break; - } - } else { - /* do nothing */ - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 652864300344834934; - break; - } - res = r; - current_block = 18290070879695007868; - break; - } - } - match current_block { - 652864300344834934 => { - dsp = mailmime_disposition_new(dsp_type, list); - if dsp.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = dsp; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - _ => {} - } - clist_foreach( - list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailmime_disposition_parm_free)), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - mailmime_disposition_type_free(dsp_type); - } - return res; -} -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * $Id: mailmime_disposition.c,v 1.17 2011/05/03 16:30:22 hoa Exp $ - */ -unsafe fn mailmime_disposition_parm_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_disposition_parm, -) -> libc::c_int { - let mut current_block: u64; - let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; - let mut creation_date: *mut libc::c_char = 0 as *mut libc::c_char; - let mut modification_date: *mut libc::c_char = 0 as *mut libc::c_char; - let mut read_date: *mut libc::c_char = 0 as *mut libc::c_char; - let mut size: size_t = 0; - let mut parameter: *mut mailmime_parameter = 0 as *mut mailmime_parameter; - let mut cur_token: size_t = 0; - let mut dsp_parm: *mut mailmime_disposition_parm = 0 as *mut mailmime_disposition_parm; - let mut type_0: libc::c_int = 0; - let mut guessed_type: libc::c_int = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - filename = 0 as *mut libc::c_char; - creation_date = 0 as *mut libc::c_char; - modification_date = 0 as *mut libc::c_char; - read_date = 0 as *mut libc::c_char; - size = 0i32 as size_t; - parameter = 0 as *mut mailmime_parameter; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - guessed_type = mailmime_disposition_guess_type(message, length, cur_token); - type_0 = MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int; - match guessed_type { - 0 => { - r = mailmime_filename_parm_parse(message, length, &mut cur_token, &mut filename); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 13826291924415791078; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 13826291924415791078; - } else { - /* do nothing */ - res = r; - current_block = 9120900589700563584; - } - } - 1 => { - r = mailmime_creation_date_parm_parse( - message, - length, - &mut cur_token, - &mut creation_date, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 13826291924415791078; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 13826291924415791078; - } else { - /* do nothing */ - res = r; - current_block = 9120900589700563584; - } - } - 2 => { - r = mailmime_modification_date_parm_parse( - message, - length, - &mut cur_token, - &mut modification_date, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 13826291924415791078; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 13826291924415791078; - } else { - /* do nothing */ - res = r; - current_block = 9120900589700563584; - } - } - 3 => { - r = mailmime_read_date_parm_parse(message, length, &mut cur_token, &mut read_date); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 13826291924415791078; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 13826291924415791078; - } else { - /* do nothing */ - res = r; - current_block = 9120900589700563584; - } - } - 4 => { - r = mailmime_size_parm_parse(message, length, &mut cur_token, &mut size); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - current_block = 13826291924415791078; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 13826291924415791078; - } else { - /* do nothing */ - res = r; - current_block = 9120900589700563584; - } - } - _ => { - current_block = 13826291924415791078; - } - } - match current_block { - 9120900589700563584 => {} - _ => { - if type_0 == MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int { - r = mailmime_parameter_parse(message, length, &mut cur_token, &mut parameter); - if r != MAILIMF_NO_ERROR as libc::c_int { - type_0 = guessed_type; - res = r; - current_block = 9120900589700563584; - } else { - current_block = 6721012065216013753; - } - } else { - current_block = 6721012065216013753; - } - match current_block { - 9120900589700563584 => {} - _ => { - dsp_parm = mailmime_disposition_parm_new( - type_0, - filename, - creation_date, - modification_date, - read_date, - size, - parameter, - ); - if dsp_parm.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !filename.is_null() { - mailmime_filename_parm_free(filename); - } - if !creation_date.is_null() { - mailmime_creation_date_parm_free(creation_date); - } - if !modification_date.is_null() { - mailmime_modification_date_parm_free(modification_date); - } - if !read_date.is_null() { - mailmime_read_date_parm_free(read_date); - } - if !parameter.is_null() { - mailmime_parameter_free(parameter); - } - } else { - *result = dsp_parm; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - } - } - return res; -} -unsafe fn mailmime_size_parm_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut size_t, -) -> libc::c_int { - let mut value: uint32_t = 0; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"size\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"size\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_unstrict_char_parse(message, length, &mut cur_token, '=' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_number_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - *result = value as size_t; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_read_date_parm_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"read-date\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"read-date\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_unstrict_char_parse(message, length, &mut cur_token, '=' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailmime_quoted_date_time_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - *result = value; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_quoted_date_time_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - return mailimf_quoted_string_parse(message, length, indx, result); -} -unsafe fn mailmime_modification_date_parm_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"modification-date\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"modification-date\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_unstrict_char_parse(message, length, &mut cur_token, '=' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailmime_quoted_date_time_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - *result = value; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_creation_date_parm_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut cur_token: size_t = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"creation-date\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"creation-date\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_unstrict_char_parse(message, length, &mut cur_token, '=' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailmime_quoted_date_time_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - *result = value; - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_filename_parm_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut r: libc::c_int = 0; - let mut cur_token: size_t = 0; - cur_token = *indx; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"filename\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"filename\x00" as *const u8 as *const libc::c_char), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_unstrict_char_parse(message, length, &mut cur_token, '=' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailmime_value_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *indx = cur_token; - *result = value; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_disposition_guess_type( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: size_t, -) -> libc::c_int { - if indx >= length { - return MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int; - } - match toupper(*message.offset(indx as isize) as libc::c_uchar as libc::c_int) as libc::c_char - as libc::c_int - { - 70 => return MAILMIME_DISPOSITION_PARM_FILENAME as libc::c_int, - 67 => return MAILMIME_DISPOSITION_PARM_CREATION_DATE as libc::c_int, - 77 => return MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE as libc::c_int, - 82 => return MAILMIME_DISPOSITION_PARM_READ_DATE as libc::c_int, - 83 => return MAILMIME_DISPOSITION_PARM_SIZE as libc::c_int, - _ => return MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int, - }; -} - -pub unsafe fn mailmime_disposition_type_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_disposition_type, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut type_0: libc::c_int = 0; - let mut extension: *mut libc::c_char = 0 as *mut libc::c_char; - let mut dsp_type: *mut mailmime_disposition_type = 0 as *mut mailmime_disposition_type; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - type_0 = MAILMIME_DISPOSITION_TYPE_ERROR as libc::c_int; - extension = 0 as *mut libc::c_char; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"inline\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"inline\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_DISPOSITION_TYPE_INLINE as libc::c_int - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"attachment\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"attachment\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int - } - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailmime_extension_token_parse(message, length, &mut cur_token, &mut extension); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_DISPOSITION_TYPE_EXTENSION as libc::c_int - } - } - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - dsp_type = mailmime_disposition_type_new(type_0, extension); - if dsp_type.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !extension.is_null() { - free(extension as *mut libc::c_void); - } - } else { - *result = dsp_type; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - return res; -} diff --git a/mmime/src/mailmime/mod.rs b/mmime/src/mailmime/mod.rs deleted file mode 100644 index d13fe4bdd..000000000 --- a/mmime/src/mailmime/mod.rs +++ /dev/null @@ -1,1143 +0,0 @@ -pub mod content; -pub mod decode; -pub mod disposition; -pub mod types; -pub mod types_helper; -pub(crate) mod write_generic; -pub mod write_mem; - -use libc::toupper; - -use crate::clist::*; -use crate::mailimf::types::*; -use crate::mailimf::*; -use crate::mailmime::decode::*; -use crate::mailmime::disposition::*; -use crate::mailmime::types::*; -use crate::other::*; - -pub const MAILMIME_COMPOSITE_TYPE_EXTENSION: libc::c_uint = 3; -pub const MAILMIME_COMPOSITE_TYPE_MULTIPART: libc::c_uint = 2; -pub const MAILMIME_COMPOSITE_TYPE_MESSAGE: libc::c_uint = 1; -pub const MAILMIME_COMPOSITE_TYPE_ERROR: libc::c_uint = 0; - -pub const MAILMIME_TYPE_COMPOSITE_TYPE: libc::c_uint = 2; -pub const MAILMIME_TYPE_DISCRETE_TYPE: libc::c_uint = 1; -pub const MAILMIME_TYPE_ERROR: libc::c_uint = 0; -pub const FIELD_STATE_L: libc::c_uint = 3; -pub const FIELD_STATE_D: libc::c_uint = 2; -pub const FIELD_STATE_T: libc::c_uint = 1; -pub const FIELD_STATE_START: libc::c_uint = 0; - -pub const MAILMIME_DISCRETE_TYPE_EXTENSION: libc::c_uint = 6; -pub const MAILMIME_DISCRETE_TYPE_APPLICATION: libc::c_uint = 5; -pub const MAILMIME_DISCRETE_TYPE_VIDEO: libc::c_uint = 4; -pub const MAILMIME_DISCRETE_TYPE_AUDIO: libc::c_uint = 3; -pub const MAILMIME_DISCRETE_TYPE_IMAGE: libc::c_uint = 2; -pub const MAILMIME_DISCRETE_TYPE_TEXT: libc::c_uint = 1; -pub const MAILMIME_DISCRETE_TYPE_ERROR: libc::c_uint = 0; - -pub unsafe fn mailmime_content_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_content, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut type_0: *mut mailmime_type = 0 as *mut mailmime_type; - let mut subtype: *mut libc::c_char = 0 as *mut libc::c_char; - let mut parameters_list: *mut clist = 0 as *mut clist; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - mailimf_cfws_parse(message, length, &mut cur_token); - type_0 = 0 as *mut mailmime_type; - r = mailmime_type_parse(message, length, &mut cur_token, &mut type_0); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_char_parse( - message, - length, - &mut cur_token, - '/' as i32 as libc::c_char, - ); - match r { - 0 => { - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r; - current_block = 10242373397628622958; - } else { - r = mailmime_subtype_parse(message, length, &mut cur_token, &mut subtype); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 10242373397628622958; - } else { - current_block = 1109700713171191020; - } - } - } - 1 => { - subtype = strdup(b"unknown\x00" as *const u8 as *const libc::c_char); - current_block = 1109700713171191020; - } - _ => { - res = r; - current_block = 10242373397628622958; - } - } - match current_block { - 1109700713171191020 => { - parameters_list = clist_new(); - if parameters_list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - loop { - let mut final_token: size_t = 0; - let mut parameter: *mut mailmime_parameter = 0 as *mut mailmime_parameter; - final_token = cur_token; - r = mailimf_unstrict_char_parse( - message, - length, - &mut cur_token, - ';' as i32 as libc::c_char, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - cur_token = final_token; - current_block = 12497913735442871383; - break; - } else { - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int - && r != MAILIMF_ERROR_PARSE as libc::c_int - { - res = r; - current_block = 6276274620003476740; - break; - } else { - r = mailmime_parameter_parse( - message, - length, - &mut cur_token, - &mut parameter, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - r = clist_insert_after( - parameters_list, - (*parameters_list).last, - parameter as *mut libc::c_void, - ); - if !(r < 0i32) { - continue; - } - mailmime_parameter_free(parameter); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 5731074241326334034; - break; - } else if r == MAILIMF_ERROR_PARSE as libc::c_int { - cur_token = final_token; - current_block = 12497913735442871383; - break; - } else { - res = r; - current_block = 6276274620003476740; - break; - } - } - } - } - match current_block { - 6276274620003476740 => {} - _ => { - match current_block { - 12497913735442871383 => { - content = - mailmime_content_new(type_0, subtype, parameters_list); - if content.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = content; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - _ => {} - } - clist_foreach( - parameters_list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailmime_parameter_free)), - 0 as *mut libc::c_void, - ); - clist_free(parameters_list); - } - } - } - mailmime_subtype_free(subtype); - } - _ => {} - } - mailmime_type_free(type_0); - } - return res; -} - -pub unsafe fn mailmime_parameter_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_parameter, -) -> libc::c_int { - let mut attribute: *mut libc::c_char = 0 as *mut libc::c_char; - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut parameter: *mut mailmime_parameter = 0 as *mut mailmime_parameter; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - r = mailmime_attribute_parse(message, length, &mut cur_token, &mut attribute); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_unstrict_char_parse( - message, - length, - &mut cur_token, - '=' as i32 as libc::c_char, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - res = r - } else { - r = mailmime_value_parse(message, length, &mut cur_token, &mut value); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - parameter = mailmime_parameter_new(attribute, value); - if parameter.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - mailmime_value_free(value); - } else { - *result = parameter; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - } - mailmime_attribute_free(attribute); - } - return res; -} - -pub unsafe fn mailmime_value_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_atom_parse(message, length, indx, result); - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_quoted_string_parse(message, length, indx, result) - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * $Id: mailmime.c,v 1.29 2011/01/06 00:09:52 hoa Exp $ - */ -/* - RFC 2045 - RFC 2046 - RFC 2047 - RFC 2048 - RFC 2049 - RFC 2231 - RFC 2387 - RFC 2424 - RFC 2557 - - RFC 2183 Content-Disposition - - RFC 1766 Language -*/ -unsafe fn mailmime_attribute_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - return mailmime_token_parse(message, length, indx, result); -} -unsafe fn mailmime_token_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut token: *mut *mut libc::c_char, -) -> libc::c_int { - return mailimf_custom_string_parse(message, length, indx, token, Some(is_token)); -} -unsafe fn is_token(mut ch: libc::c_char) -> libc::c_int { - let mut uch: libc::c_uchar = ch as libc::c_uchar; - if uch as libc::c_int > 0x7fi32 { - return 0i32; - } - if uch as libc::c_int == ' ' as i32 { - return 0i32; - } - if 0 != is_tspecials(ch) { - return 0i32; - } - return 1i32; -} -unsafe fn is_tspecials(mut ch: libc::c_char) -> libc::c_int { - match ch as libc::c_int { - 40 | 41 | 60 | 62 | 64 | 44 | 59 | 58 | 92 | 34 | 47 | 91 | 93 | 63 | 61 => return 1i32, - _ => return 0i32, - }; -} -unsafe fn mailmime_subtype_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - return mailmime_extension_token_parse(message, length, indx, result); -} - -pub unsafe fn mailmime_extension_token_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - return mailmime_token_parse(message, length, indx, result); -} -unsafe fn mailmime_type_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_type, -) -> libc::c_int { - let mut discrete_type: *mut mailmime_discrete_type = 0 as *mut mailmime_discrete_type; - let mut composite_type: *mut mailmime_composite_type = 0 as *mut mailmime_composite_type; - let mut cur_token: size_t = 0; - let mut mime_type: *mut mailmime_type = 0 as *mut mailmime_type; - let mut type_0: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - discrete_type = 0 as *mut mailmime_discrete_type; - composite_type = 0 as *mut mailmime_composite_type; - type_0 = MAILMIME_TYPE_ERROR as libc::c_int; - r = mailmime_composite_type_parse(message, length, &mut cur_token, &mut composite_type); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailmime_discrete_type_parse(message, length, &mut cur_token, &mut discrete_type); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_TYPE_DISCRETE_TYPE as libc::c_int - } - } - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - mime_type = mailmime_type_new(type_0, discrete_type, composite_type); - if mime_type.is_null() { - res = r; - if !discrete_type.is_null() { - mailmime_discrete_type_free(discrete_type); - } - if !composite_type.is_null() { - mailmime_composite_type_free(composite_type); - } - } else { - *result = mime_type; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} -unsafe fn mailmime_discrete_type_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_discrete_type, -) -> libc::c_int { - let mut extension: *mut libc::c_char = 0 as *mut libc::c_char; - let mut type_0: libc::c_int = 0; - let mut discrete_type: *mut mailmime_discrete_type = 0 as *mut mailmime_discrete_type; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - extension = 0 as *mut libc::c_char; - type_0 = MAILMIME_DISCRETE_TYPE_ERROR as libc::c_int; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"text\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"text\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_DISCRETE_TYPE_TEXT as libc::c_int - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"image\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"image\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_DISCRETE_TYPE_IMAGE as libc::c_int - } - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"audio\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"audio\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_DISCRETE_TYPE_AUDIO as libc::c_int - } - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"video\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"video\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_DISCRETE_TYPE_VIDEO as libc::c_int - } - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"application\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"application\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_DISCRETE_TYPE_APPLICATION as libc::c_int - } - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailmime_extension_token_parse(message, length, &mut cur_token, &mut extension); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_DISCRETE_TYPE_EXTENSION as libc::c_int - } - } - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - discrete_type = mailmime_discrete_type_new(type_0, extension); - if discrete_type.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - mailmime_extension_token_free(extension); - } else { - *result = discrete_type; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} -unsafe fn mailmime_composite_type_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_composite_type, -) -> libc::c_int { - let mut extension_token: *mut libc::c_char = 0 as *mut libc::c_char; - let mut type_0: libc::c_int = 0; - let mut ct: *mut mailmime_composite_type = 0 as *mut mailmime_composite_type; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - extension_token = 0 as *mut libc::c_char; - type_0 = MAILMIME_COMPOSITE_TYPE_ERROR as libc::c_int; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"message\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"message\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_COMPOSITE_TYPE_MESSAGE as libc::c_int - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"multipart\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"multipart\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_COMPOSITE_TYPE_MULTIPART as libc::c_int - } - } - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - ct = mailmime_composite_type_new(type_0, extension_token); - if ct.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !extension_token.is_null() { - mailmime_extension_token_free(extension_token); - } - } else { - *result = ct; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} - -pub unsafe fn mailmime_description_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - return mailimf_custom_string_parse(message, length, indx, result, Some(is_text)); -} -unsafe fn is_text(mut ch: libc::c_char) -> libc::c_int { - let mut uch: libc::c_uchar = ch as libc::c_uchar; - if (uch as libc::c_int) < 1i32 { - return 0i32; - } - if uch as libc::c_int == 10i32 || uch as libc::c_int == 13i32 { - return 0i32; - } - return 1i32; -} - -pub unsafe fn mailmime_location_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - return mailimf_custom_string_parse(message, length, indx, result, Some(is_text)); -} - -pub unsafe fn mailmime_encoding_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_mechanism, -) -> libc::c_int { - return mailmime_mechanism_parse(message, length, indx, result); -} -unsafe fn mailmime_mechanism_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_mechanism, -) -> libc::c_int { - let mut token: *mut libc::c_char = 0 as *mut libc::c_char; - let mut type_0: libc::c_int = 0; - let mut mechanism: *mut mailmime_mechanism = 0 as *mut mailmime_mechanism; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - cur_token = *indx; - type_0 = MAILMIME_MECHANISM_ERROR as libc::c_int; - token = 0 as *mut libc::c_char; - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"7bit\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"7bit\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_MECHANISM_7BIT as libc::c_int - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"8bit\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"8bit\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_MECHANISM_8BIT as libc::c_int - } - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"binary\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"binary\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_MECHANISM_BINARY as libc::c_int - } - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"quoted-printable\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"quoted-printable\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_MECHANISM_QUOTED_PRINTABLE as libc::c_int - } - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailimf_token_case_insensitive_len_parse( - message, - length, - &mut cur_token, - b"base64\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - strlen(b"base64\x00" as *const u8 as *const libc::c_char), - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_MECHANISM_BASE64 as libc::c_int - } - } - if r == MAILIMF_ERROR_PARSE as libc::c_int { - r = mailmime_token_parse(message, length, &mut cur_token, &mut token); - if r == MAILIMF_NO_ERROR as libc::c_int { - type_0 = MAILMIME_MECHANISM_TOKEN as libc::c_int - } - } - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - mechanism = mailmime_mechanism_new(type_0, token); - if mechanism.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !token.is_null() { - mailmime_token_free(token); - } - } else { - *result = mechanism; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} - -pub unsafe fn mailmime_field_parse( - mut field: *mut mailimf_optional_field, - mut result: *mut *mut mailmime_field, -) -> libc::c_int { - let mut name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut guessed_type: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - let mut encoding: *mut mailmime_mechanism = 0 as *mut mailmime_mechanism; - let mut id: *mut libc::c_char = 0 as *mut libc::c_char; - let mut description: *mut libc::c_char = 0 as *mut libc::c_char; - let mut version: uint32_t = 0; - let mut mime_field: *mut mailmime_field = 0 as *mut mailmime_field; - let mut language: *mut mailmime_language = 0 as *mut mailmime_language; - let mut disposition: *mut mailmime_disposition = 0 as *mut mailmime_disposition; - let mut location: *mut libc::c_char = 0 as *mut libc::c_char; - let mut res: libc::c_int = 0; - let mut r: libc::c_int = 0; - name = (*field).fld_name; - value = (*field).fld_value; - cur_token = 0i32 as size_t; - content = 0 as *mut mailmime_content; - encoding = 0 as *mut mailmime_mechanism; - id = 0 as *mut libc::c_char; - description = 0 as *mut libc::c_char; - version = 0i32 as uint32_t; - disposition = 0 as *mut mailmime_disposition; - language = 0 as *mut mailmime_language; - location = 0 as *mut libc::c_char; - guessed_type = guess_field_type(name); - match guessed_type { - 1 => { - if strcasecmp( - name, - b"Content-Type\x00" as *const u8 as *const libc::c_char, - ) != 0i32 - { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - let mut cur_token_0: size_t = 0i32 as size_t; - let mut decoded_value: *mut libc::c_char = 0 as *mut libc::c_char; - r = mailmime_encoded_phrase_parse( - b"us-ascii\x00" as *const u8 as *const libc::c_char, - value, - strlen(value), - &mut cur_token_0, - b"utf-8\x00" as *const u8 as *const libc::c_char, - &mut decoded_value, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - cur_token_0 = 0i32 as size_t; - r = mailmime_content_parse(value, strlen(value), &mut cur_token_0, &mut content) - } else { - cur_token_0 = 0i32 as size_t; - r = mailmime_content_parse( - decoded_value, - strlen(decoded_value), - &mut cur_token_0, - &mut content, - ); - free(decoded_value as *mut libc::c_void); - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 2 => { - if strcasecmp( - name, - b"Content-Transfer-Encoding\x00" as *const u8 as *const libc::c_char, - ) != 0i32 - { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - r = mailmime_encoding_parse(value, strlen(value), &mut cur_token, &mut encoding); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 3 => { - if strcasecmp(name, b"Content-ID\x00" as *const u8 as *const libc::c_char) != 0i32 { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - r = mailmime_id_parse(value, strlen(value), &mut cur_token, &mut id); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 4 => { - if strcasecmp( - name, - b"Content-Description\x00" as *const u8 as *const libc::c_char, - ) != 0i32 - { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - r = mailmime_description_parse(value, strlen(value), &mut cur_token, &mut description); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 5 => { - if strcasecmp( - name, - b"MIME-Version\x00" as *const u8 as *const libc::c_char, - ) != 0i32 - { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - r = mailmime_version_parse(value, strlen(value), &mut cur_token, &mut version); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 6 => { - if strcasecmp( - name, - b"Content-Disposition\x00" as *const u8 as *const libc::c_char, - ) != 0i32 - { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - r = mailmime_disposition_parse(value, strlen(value), &mut cur_token, &mut disposition); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 7 => { - if strcasecmp( - name, - b"Content-Language\x00" as *const u8 as *const libc::c_char, - ) != 0i32 - { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - r = mailmime_language_parse(value, strlen(value), &mut cur_token, &mut language); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 8 => { - if strcasecmp( - name, - b"Content-Location\x00" as *const u8 as *const libc::c_char, - ) != 0i32 - { - return MAILIMF_ERROR_PARSE as libc::c_int; - } - r = mailmime_location_parse(value, strlen(value), &mut cur_token, &mut location); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - _ => return MAILIMF_ERROR_PARSE as libc::c_int, - } - mime_field = mailmime_field_new( - guessed_type, - content, - encoding, - id, - description, - version, - disposition, - language, - location, - ); - if mime_field.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - if !location.is_null() { - mailmime_location_free(location); - } - if !language.is_null() { - mailmime_language_free(language); - } - if !content.is_null() { - mailmime_content_free(content); - } - if !encoding.is_null() { - mailmime_encoding_free(encoding); - } - if !id.is_null() { - mailmime_id_free(id); - } - if !description.is_null() { - mailmime_description_free(description); - } - return res; - } else { - *result = mime_field; - return MAILIMF_NO_ERROR as libc::c_int; - }; -} - -pub unsafe fn mailmime_language_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut mailmime_language, -) -> libc::c_int { - let mut current_block: u64; - let mut cur_token: size_t = 0; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - let mut list: *mut clist = 0 as *mut clist; - let mut language: *mut mailmime_language = 0 as *mut mailmime_language; - cur_token = *indx; - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - loop { - let mut atom: *mut libc::c_char = 0 as *mut libc::c_char; - r = mailimf_unstrict_char_parse( - message, - length, - &mut cur_token, - ',' as i32 as libc::c_char, - ); - if r == MAILIMF_NO_ERROR as libc::c_int { - r = mailimf_atom_parse(message, length, &mut cur_token, &mut atom); - if r == MAILIMF_NO_ERROR as libc::c_int { - r = clist_insert_after(list, (*list).last, atom as *mut libc::c_void); - if !(r < 0i32) { - continue; - } - mailimf_atom_free(atom); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 14533943604180559553; - break; - } else { - /* do nothing */ - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 6669252993407410313; - break; - } - res = r; - current_block = 11601180562230609130; - break; - } - } else { - /* do nothing */ - if r == MAILIMF_ERROR_PARSE as libc::c_int { - current_block = 6669252993407410313; - break; - } - res = r; - current_block = 11601180562230609130; - break; - } - } - match current_block { - 11601180562230609130 => {} - _ => { - match current_block { - 6669252993407410313 => { - language = mailmime_language_new(list); - if language.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = language; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - _ => {} - } - clist_foreach( - list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailimf_atom_free)), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - } - } - return res; -} - -pub unsafe fn mailmime_version_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut uint32_t, -) -> libc::c_int { - let mut cur_token: size_t = 0; - let mut hi: uint32_t = 0; - let mut low: uint32_t = 0; - let mut version: uint32_t = 0; - let mut r: libc::c_int = 0; - cur_token = *indx; - r = mailimf_number_parse(message, length, &mut cur_token, &mut hi); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_unstrict_char_parse(message, length, &mut cur_token, '.' as i32 as libc::c_char); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_cfws_parse(message, length, &mut cur_token); - if r != MAILIMF_NO_ERROR as libc::c_int && r != MAILIMF_ERROR_PARSE as libc::c_int { - return r; - } - r = mailimf_number_parse(message, length, &mut cur_token, &mut low); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - version = (hi << 16i32).wrapping_add(low); - *result = version; - *indx = cur_token; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_id_parse( - mut message: *const libc::c_char, - mut length: size_t, - mut indx: *mut size_t, - mut result: *mut *mut libc::c_char, -) -> libc::c_int { - return mailimf_msg_id_parse(message, length, indx, result); -} -unsafe fn guess_field_type(mut name: *mut libc::c_char) -> libc::c_int { - let mut state: libc::c_int = 0; - if *name as libc::c_int == 'M' as i32 { - return MAILMIME_FIELD_VERSION as libc::c_int; - } - if strncasecmp( - name, - b"Content-\x00" as *const u8 as *const libc::c_char, - 8i32 as libc::size_t, - ) != 0i32 - { - return MAILMIME_FIELD_NONE as libc::c_int; - } - name = name.offset(8isize); - state = FIELD_STATE_START as libc::c_int; - loop { - match state { - 0 => { - match toupper(*name as libc::c_uchar as libc::c_int) as libc::c_char as libc::c_int - { - 84 => state = FIELD_STATE_T as libc::c_int, - 73 => return MAILMIME_FIELD_ID as libc::c_int, - 68 => state = FIELD_STATE_D as libc::c_int, - 76 => state = FIELD_STATE_L as libc::c_int, - _ => return MAILMIME_FIELD_NONE as libc::c_int, - } - } - 1 => { - match toupper(*name as libc::c_uchar as libc::c_int) as libc::c_char as libc::c_int - { - 89 => return MAILMIME_FIELD_TYPE as libc::c_int, - 82 => return MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int, - _ => return MAILMIME_FIELD_NONE as libc::c_int, - } - } - 2 => { - match toupper(*name as libc::c_uchar as libc::c_int) as libc::c_char as libc::c_int - { - 69 => return MAILMIME_FIELD_DESCRIPTION as libc::c_int, - 73 => return MAILMIME_FIELD_DISPOSITION as libc::c_int, - _ => return MAILMIME_FIELD_NONE as libc::c_int, - } - } - 3 => { - match toupper(*name as libc::c_uchar as libc::c_int) as libc::c_char as libc::c_int - { - 65 => return MAILMIME_FIELD_LANGUAGE as libc::c_int, - 79 => return MAILMIME_FIELD_LOCATION as libc::c_int, - _ => return MAILMIME_FIELD_NONE as libc::c_int, - } - } - _ => {} - } - name = name.offset(1isize) - } -} - -pub unsafe fn mailmime_fields_parse( - mut fields: *mut mailimf_fields, - mut result: *mut *mut mailmime_fields, -) -> libc::c_int { - let mut current_block: u64; - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - let mut list: *mut clist = 0 as *mut clist; - let mut r: libc::c_int = 0; - let mut res: libc::c_int = 0; - list = clist_new(); - if list.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - cur = (*(*fields).fld_list).first; - loop { - if cur.is_null() { - current_block = 1109700713171191020; - break; - } - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - let mut mime_field: *mut mailmime_field = 0 as *mut mailmime_field; - field = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_field; - if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { - r = mailmime_field_parse((*field).fld_data.fld_optional_field, &mut mime_field); - if r == MAILIMF_NO_ERROR as libc::c_int { - r = clist_insert_after(list, (*list).last, mime_field as *mut libc::c_void); - if r < 0i32 { - mailmime_field_free(mime_field); - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 17592539310030730040; - break; - } - } else if !(r == MAILIMF_ERROR_PARSE as libc::c_int) { - /* do nothing */ - res = r; - current_block = 17592539310030730040; - break; - } - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - match current_block { - 1109700713171191020 => { - if (*list).first.is_null() { - res = MAILIMF_ERROR_PARSE as libc::c_int - } else { - mime_fields = mailmime_fields_new(list); - if mime_fields.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - *result = mime_fields; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - _ => {} - } - clist_foreach( - list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailmime_field_free), - ), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - return res; -} diff --git a/mmime/src/mailmime/types.rs b/mmime/src/mailmime/types.rs deleted file mode 100644 index 7088d3f46..000000000 --- a/mmime/src/mailmime/types.rs +++ /dev/null @@ -1,891 +0,0 @@ -use crate::clist::*; -use crate::mailimf::types::*; -use crate::mmapstring::*; -use crate::other::*; - -pub const MAILMIME_MECHANISM_TOKEN: libc::c_uint = 6; -pub const MAILMIME_MECHANISM_BASE64: libc::c_uint = 5; -pub const MAILMIME_MECHANISM_QUOTED_PRINTABLE: libc::c_uint = 4; -pub const MAILMIME_MECHANISM_BINARY: libc::c_uint = 3; -pub const MAILMIME_MECHANISM_8BIT: libc::c_uint = 2; -pub const MAILMIME_MECHANISM_7BIT: libc::c_uint = 1; -pub const MAILMIME_MECHANISM_ERROR: libc::c_uint = 0; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_composite_type { - pub ct_type: libc::c_int, - pub ct_token: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_content { - pub ct_type: *mut mailmime_type, - pub ct_subtype: *mut libc::c_char, - pub ct_parameters: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_type { - pub tp_type: libc::c_int, - pub tp_data: unnamed, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - pub tp_discrete_type: *mut mailmime_discrete_type, - pub tp_composite_type: *mut mailmime_composite_type, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_discrete_type { - pub dt_type: libc::c_int, - pub dt_extension: *mut libc::c_char, -} -pub type unnamed_0 = libc::c_uint; -pub const MAILMIME_FIELD_LOCATION: unnamed_0 = 8; -pub const MAILMIME_FIELD_LANGUAGE: unnamed_0 = 7; -pub const MAILMIME_FIELD_DISPOSITION: unnamed_0 = 6; -pub const MAILMIME_FIELD_VERSION: unnamed_0 = 5; -pub const MAILMIME_FIELD_DESCRIPTION: unnamed_0 = 4; -pub const MAILMIME_FIELD_ID: unnamed_0 = 3; -pub const MAILMIME_FIELD_TRANSFER_ENCODING: unnamed_0 = 2; -pub const MAILMIME_FIELD_TYPE: unnamed_0 = 1; -pub const MAILMIME_FIELD_NONE: unnamed_0 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_field { - pub fld_type: libc::c_int, - pub fld_data: unnamed_1, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_1 { - pub fld_content: *mut mailmime_content, - pub fld_encoding: *mut mailmime_mechanism, - pub fld_id: *mut libc::c_char, - pub fld_description: *mut libc::c_char, - pub fld_version: uint32_t, - pub fld_disposition: *mut mailmime_disposition, - pub fld_language: *mut mailmime_language, - pub fld_location: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_language { - pub lg_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_disposition { - pub dsp_type: *mut mailmime_disposition_type, - pub dsp_parms: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_disposition_type { - pub dsp_type: libc::c_int, - pub dsp_extension: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_mechanism { - pub enc_type: libc::c_int, - pub enc_token: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_fields { - pub fld_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_parameter { - pub pa_name: *mut libc::c_char, - pub pa_value: *mut libc::c_char, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_disposition_parm { - pub pa_type: libc::c_int, - pub pa_data: unnamed_3, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_3 { - pub pa_filename: *mut libc::c_char, - pub pa_creation_date: *mut libc::c_char, - pub pa_modification_date: *mut libc::c_char, - pub pa_read_date: *mut libc::c_char, - pub pa_size: size_t, - pub pa_parameter: *mut mailmime_parameter, -} -pub const MAILMIME_DISPOSITION_PARM_PARAMETER: unnamed_11 = 5; -pub const MAILMIME_DISPOSITION_PARM_READ_DATE: unnamed_11 = 3; -pub const MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: unnamed_11 = 2; -pub const MAILMIME_DISPOSITION_PARM_CREATION_DATE: unnamed_11 = 1; -pub const MAILMIME_DISPOSITION_PARM_FILENAME: unnamed_11 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_multipart_body { - pub bd_list: *mut clist, -} -pub type unnamed_4 = libc::c_uint; -pub const MAILMIME_DATA_FILE: unnamed_4 = 1; -pub const MAILMIME_DATA_TEXT: unnamed_4 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_data { - pub dt_type: libc::c_int, - pub dt_encoding: libc::c_int, - pub dt_encoded: libc::c_int, - pub dt_data: unnamed_5, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_5 { - pub dt_text: unnamed_6, - pub dt_filename: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_6 { - pub dt_data: *const libc::c_char, - pub dt_length: size_t, -} -pub type unnamed_7 = libc::c_uint; -pub const MAILMIME_MESSAGE: unnamed_7 = 3; -pub const MAILMIME_MULTIPLE: unnamed_7 = 2; -pub const MAILMIME_SINGLE: unnamed_7 = 1; -pub const MAILMIME_NONE: unnamed_7 = 0; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct Mailmime { - pub mm_parent_type: libc::c_int, - pub mm_parent: *mut Mailmime, - pub mm_multipart_pos: *mut clistiter, - pub mm_type: libc::c_int, - pub mm_mime_start: *const libc::c_char, - pub mm_length: size_t, - pub mm_mime_fields: *mut mailmime_fields, - pub mm_content_type: *mut mailmime_content, - pub mm_body: *mut mailmime_data, - pub mm_data: unnamed_8, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_8 { - pub mm_single: *mut mailmime_data, - pub mm_multipart: unnamed_10, - pub mm_message: unnamed_9, -} -/* message */ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_9 { - pub mm_fields: *mut mailimf_fields, - pub mm_msg_mime: *mut Mailmime, -} -/* multi-part */ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_10 { - pub mm_preamble: *mut mailmime_data, - pub mm_epilogue: *mut mailmime_data, - pub mm_mp_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_encoded_word { - pub wd_charset: *mut libc::c_char, - pub wd_text: *mut libc::c_char, -} -pub type unnamed_11 = libc::c_uint; -pub const MAILMIME_DISPOSITION_PARM_SIZE: unnamed_11 = 4; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_section { - pub sec_list: *mut clist, -} - -pub unsafe fn mailmime_attribute_free(mut attribute: *mut libc::c_char) { - mailmime_token_free(attribute); -} - -pub unsafe fn mailmime_token_free(mut token: *mut libc::c_char) { - free(token as *mut libc::c_void); -} -pub unsafe fn mailmime_composite_type_new( - mut ct_type: libc::c_int, - mut ct_token: *mut libc::c_char, -) -> *mut mailmime_composite_type { - let mut ct: *mut mailmime_composite_type = 0 as *mut mailmime_composite_type; - ct = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_composite_type; - if ct.is_null() { - return 0 as *mut mailmime_composite_type; - } - (*ct).ct_type = ct_type; - (*ct).ct_token = ct_token; - return ct; -} - -pub unsafe fn mailmime_composite_type_free(mut ct: *mut mailmime_composite_type) { - if !(*ct).ct_token.is_null() { - mailmime_extension_token_free((*ct).ct_token); - } - free(ct as *mut libc::c_void); -} - -pub unsafe fn mailmime_extension_token_free(mut extension: *mut libc::c_char) { - mailmime_token_free(extension); -} - -pub unsafe fn mailmime_content_new( - mut ct_type: *mut mailmime_type, - mut ct_subtype: *mut libc::c_char, - mut ct_parameters: *mut clist, -) -> *mut mailmime_content { - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - content = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailmime_content; - if content.is_null() { - return 0 as *mut mailmime_content; - } - (*content).ct_type = ct_type; - (*content).ct_subtype = ct_subtype; - (*content).ct_parameters = ct_parameters; - return content; -} - -pub unsafe fn mailmime_content_free(mut content: *mut mailmime_content) { - mailmime_type_free((*content).ct_type); - mailmime_subtype_free((*content).ct_subtype); - if !(*content).ct_parameters.is_null() { - clist_foreach( - (*content).ct_parameters, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailmime_parameter_free), - ), - 0 as *mut libc::c_void, - ); - clist_free((*content).ct_parameters); - } - free(content as *mut libc::c_void); -} - -pub unsafe fn mailmime_parameter_free(mut parameter: *mut mailmime_parameter) { - mailmime_attribute_free((*parameter).pa_name); - mailmime_value_free((*parameter).pa_value); - free(parameter as *mut libc::c_void); -} - -pub unsafe fn mailmime_value_free(mut value: *mut libc::c_char) { - free(value as *mut libc::c_void); -} - -pub unsafe fn mailmime_subtype_free(mut subtype: *mut libc::c_char) { - mailmime_extension_token_free(subtype); -} - -pub unsafe fn mailmime_type_free(mut type_0: *mut mailmime_type) { - match (*type_0).tp_type { - 1 => { - mailmime_discrete_type_free((*type_0).tp_data.tp_discrete_type); - } - 2 => { - mailmime_composite_type_free((*type_0).tp_data.tp_composite_type); - } - _ => {} - } - free(type_0 as *mut libc::c_void); -} - -pub unsafe fn mailmime_discrete_type_free(mut discrete_type: *mut mailmime_discrete_type) { - if !(*discrete_type).dt_extension.is_null() { - mailmime_extension_token_free((*discrete_type).dt_extension); - } - free(discrete_type as *mut libc::c_void); -} - -pub unsafe fn mailmime_description_free(mut description: *mut libc::c_char) { - free(description as *mut libc::c_void); -} - -pub unsafe fn mailmime_location_free(mut location: *mut libc::c_char) { - free(location as *mut libc::c_void); -} - -pub unsafe fn mailmime_discrete_type_new( - mut dt_type: libc::c_int, - mut dt_extension: *mut libc::c_char, -) -> *mut mailmime_discrete_type { - let mut discrete_type: *mut mailmime_discrete_type = 0 as *mut mailmime_discrete_type; - discrete_type = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_discrete_type; - if discrete_type.is_null() { - return 0 as *mut mailmime_discrete_type; - } - (*discrete_type).dt_type = dt_type; - (*discrete_type).dt_extension = dt_extension; - return discrete_type; -} - -pub unsafe fn mailmime_encoding_free(mut encoding: *mut mailmime_mechanism) { - mailmime_mechanism_free(encoding); -} - -pub unsafe fn mailmime_mechanism_free(mut mechanism: *mut mailmime_mechanism) { - if !(*mechanism).enc_token.is_null() { - mailmime_token_free((*mechanism).enc_token); - } - free(mechanism as *mut libc::c_void); -} - -pub unsafe fn mailmime_id_free(mut id: *mut libc::c_char) { - mailimf_msg_id_free(id); -} - -pub unsafe fn mailmime_mechanism_new( - mut enc_type: libc::c_int, - mut enc_token: *mut libc::c_char, -) -> *mut mailmime_mechanism { - let mut mechanism: *mut mailmime_mechanism = 0 as *mut mailmime_mechanism; - mechanism = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_mechanism; - if mechanism.is_null() { - return 0 as *mut mailmime_mechanism; - } - (*mechanism).enc_type = enc_type; - (*mechanism).enc_token = enc_token; - return mechanism; -} - -pub unsafe fn mailmime_parameter_new( - mut pa_name: *mut libc::c_char, - mut pa_value: *mut libc::c_char, -) -> *mut mailmime_parameter { - let mut parameter: *mut mailmime_parameter = 0 as *mut mailmime_parameter; - parameter = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_parameter; - if parameter.is_null() { - return 0 as *mut mailmime_parameter; - } - (*parameter).pa_name = pa_name; - (*parameter).pa_value = pa_value; - return parameter; -} - -pub unsafe fn mailmime_type_new( - mut tp_type: libc::c_int, - mut tp_discrete_type: *mut mailmime_discrete_type, - mut tp_composite_type: *mut mailmime_composite_type, -) -> *mut mailmime_type { - let mut mime_type: *mut mailmime_type = 0 as *mut mailmime_type; - mime_type = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailmime_type; - if mime_type.is_null() { - return 0 as *mut mailmime_type; - } - (*mime_type).tp_type = tp_type; - match tp_type { - 1 => (*mime_type).tp_data.tp_discrete_type = tp_discrete_type, - 2 => (*mime_type).tp_data.tp_composite_type = tp_composite_type, - _ => {} - } - return mime_type; -} - -pub unsafe fn mailmime_language_new(mut lg_list: *mut clist) -> *mut mailmime_language { - let mut lang: *mut mailmime_language = 0 as *mut mailmime_language; - lang = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_language; - if lang.is_null() { - return 0 as *mut mailmime_language; - } - (*lang).lg_list = lg_list; - return lang; -} - -pub unsafe fn mailmime_language_free(mut lang: *mut mailmime_language) { - clist_foreach( - (*lang).lg_list, - ::std::mem::transmute:: ()>, clist_func>(Some( - mailimf_atom_free, - )), - 0 as *mut libc::c_void, - ); - clist_free((*lang).lg_list); - free(lang as *mut libc::c_void); -} -/* -void mailmime_x_token_free(gchar * x_token); -*/ -pub unsafe fn mailmime_field_new( - mut fld_type: libc::c_int, - mut fld_content: *mut mailmime_content, - mut fld_encoding: *mut mailmime_mechanism, - mut fld_id: *mut libc::c_char, - mut fld_description: *mut libc::c_char, - mut fld_version: uint32_t, - mut fld_disposition: *mut mailmime_disposition, - mut fld_language: *mut mailmime_language, - mut fld_location: *mut libc::c_char, -) -> *mut mailmime_field { - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - field = malloc(::std::mem::size_of::() as libc::size_t) as *mut mailmime_field; - if field.is_null() { - return 0 as *mut mailmime_field; - } - (*field).fld_type = fld_type; - match fld_type { - 1 => (*field).fld_data.fld_content = fld_content, - 2 => (*field).fld_data.fld_encoding = fld_encoding, - 3 => (*field).fld_data.fld_id = fld_id, - 4 => (*field).fld_data.fld_description = fld_description, - 5 => (*field).fld_data.fld_version = fld_version, - 6 => (*field).fld_data.fld_disposition = fld_disposition, - 7 => (*field).fld_data.fld_language = fld_language, - 8 => (*field).fld_data.fld_location = fld_location, - _ => {} - } - return field; -} - -pub unsafe fn mailmime_field_free(mut field: *mut mailmime_field) { - match (*field).fld_type { - 1 => { - if !(*field).fld_data.fld_content.is_null() { - mailmime_content_free((*field).fld_data.fld_content); - } - } - 2 => { - if !(*field).fld_data.fld_encoding.is_null() { - mailmime_encoding_free((*field).fld_data.fld_encoding); - } - } - 3 => { - if !(*field).fld_data.fld_id.is_null() { - mailmime_id_free((*field).fld_data.fld_id); - } - } - 4 => { - if !(*field).fld_data.fld_description.is_null() { - mailmime_description_free((*field).fld_data.fld_description); - } - } - 6 => { - if !(*field).fld_data.fld_disposition.is_null() { - mailmime_disposition_free((*field).fld_data.fld_disposition); - } - } - 7 => { - if !(*field).fld_data.fld_language.is_null() { - mailmime_language_free((*field).fld_data.fld_language); - } - } - 8 => { - if !(*field).fld_data.fld_location.is_null() { - mailmime_location_free((*field).fld_data.fld_location); - } - } - _ => {} - } - free(field as *mut libc::c_void); -} - -pub unsafe fn mailmime_disposition_free(mut dsp: *mut mailmime_disposition) { - mailmime_disposition_type_free((*dsp).dsp_type); - clist_foreach( - (*dsp).dsp_parms, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailmime_disposition_parm_free)), - 0 as *mut libc::c_void, - ); - clist_free((*dsp).dsp_parms); - free(dsp as *mut libc::c_void); -} - -pub unsafe fn mailmime_disposition_parm_free(mut dsp_parm: *mut mailmime_disposition_parm) { - match (*dsp_parm).pa_type { - 0 => { - mailmime_filename_parm_free((*dsp_parm).pa_data.pa_filename); - } - 1 => { - mailmime_creation_date_parm_free((*dsp_parm).pa_data.pa_creation_date); - } - 2 => { - mailmime_modification_date_parm_free((*dsp_parm).pa_data.pa_modification_date); - } - 3 => { - mailmime_read_date_parm_free((*dsp_parm).pa_data.pa_read_date); - } - 5 => { - mailmime_parameter_free((*dsp_parm).pa_data.pa_parameter); - } - _ => {} - } - free(dsp_parm as *mut libc::c_void); -} - -pub unsafe fn mailmime_read_date_parm_free(mut date: *mut libc::c_char) { - mailmime_quoted_date_time_free(date); -} - -pub unsafe fn mailmime_quoted_date_time_free(mut date: *mut libc::c_char) { - mailimf_quoted_string_free(date); -} - -pub unsafe fn mailmime_modification_date_parm_free(mut date: *mut libc::c_char) { - mailmime_quoted_date_time_free(date); -} - -pub unsafe fn mailmime_creation_date_parm_free(mut date: *mut libc::c_char) { - mailmime_quoted_date_time_free(date); -} - -pub unsafe fn mailmime_filename_parm_free(mut filename: *mut libc::c_char) { - mailmime_value_free(filename); -} - -pub unsafe fn mailmime_disposition_type_free(mut dsp_type: *mut mailmime_disposition_type) { - if !(*dsp_type).dsp_extension.is_null() { - free((*dsp_type).dsp_extension as *mut libc::c_void); - } - free(dsp_type as *mut libc::c_void); -} - -pub unsafe fn mailmime_fields_new(mut fld_list: *mut clist) -> *mut mailmime_fields { - let mut fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - fields = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailmime_fields; - if fields.is_null() { - return 0 as *mut mailmime_fields; - } - (*fields).fld_list = fld_list; - return fields; -} - -pub unsafe fn mailmime_fields_free(mut fields: *mut mailmime_fields) { - clist_foreach( - (*fields).fld_list, - ::std::mem::transmute:: ()>, clist_func>(Some( - mailmime_field_free, - )), - 0 as *mut libc::c_void, - ); - clist_free((*fields).fld_list); - free(fields as *mut libc::c_void); -} - -pub unsafe fn mailmime_multipart_body_new(mut bd_list: *mut clist) -> *mut mailmime_multipart_body { - let mut mp_body: *mut mailmime_multipart_body = 0 as *mut mailmime_multipart_body; - mp_body = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_multipart_body; - if mp_body.is_null() { - return 0 as *mut mailmime_multipart_body; - } - (*mp_body).bd_list = bd_list; - return mp_body; -} - -pub unsafe fn mailmime_multipart_body_free(mut mp_body: *mut mailmime_multipart_body) { - clist_foreach( - (*mp_body).bd_list, - ::std::mem::transmute:: ()>, clist_func>(Some( - mailimf_body_free, - )), - 0 as *mut libc::c_void, - ); - clist_free((*mp_body).bd_list); - free(mp_body as *mut libc::c_void); -} - -pub unsafe fn mailmime_data_new( - mut dt_type: libc::c_int, - mut dt_encoding: libc::c_int, - mut dt_encoded: libc::c_int, - mut dt_data: *const libc::c_char, - mut dt_length: size_t, - mut dt_filename: *mut libc::c_char, -) -> *mut mailmime_data { - let mut mime_data: *mut mailmime_data = 0 as *mut mailmime_data; - mime_data = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailmime_data; - if mime_data.is_null() { - return 0 as *mut mailmime_data; - } - (*mime_data).dt_type = dt_type; - (*mime_data).dt_encoding = dt_encoding; - (*mime_data).dt_encoded = dt_encoded; - match dt_type { - 0 => { - (*mime_data).dt_data.dt_text.dt_data = dt_data; - (*mime_data).dt_data.dt_text.dt_length = dt_length - } - 1 => (*mime_data).dt_data.dt_filename = dt_filename, - _ => {} - } - return mime_data; -} - -pub unsafe fn mailmime_data_free(mut mime_data: *mut mailmime_data) { - match (*mime_data).dt_type { - 1 => { - free((*mime_data).dt_data.dt_filename as *mut libc::c_void); - } - _ => {} - } - free(mime_data as *mut libc::c_void); -} - -pub unsafe fn mailmime_new( - mut mm_type: libc::c_int, - mut mm_mime_start: *const libc::c_char, - mut mm_length: size_t, - mut mm_mime_fields: *mut mailmime_fields, - mut mm_content_type: *mut mailmime_content, - mut mm_body: *mut mailmime_data, - mut mm_preamble: *mut mailmime_data, - mut mm_epilogue: *mut mailmime_data, - mut mm_mp_list: *mut clist, - mut mm_fields: *mut mailimf_fields, - mut mm_msg_mime: *mut Mailmime, -) -> *mut Mailmime { - let mut mime: *mut Mailmime = 0 as *mut Mailmime; - let mut cur: *mut clistiter = 0 as *mut clistiter; - mime = malloc(::std::mem::size_of::() as libc::size_t) as *mut Mailmime; - if mime.is_null() { - return 0 as *mut Mailmime; - } - (*mime).mm_parent = 0 as *mut Mailmime; - (*mime).mm_parent_type = MAILMIME_NONE as libc::c_int; - (*mime).mm_multipart_pos = 0 as *mut clistiter; - (*mime).mm_type = mm_type; - (*mime).mm_mime_start = mm_mime_start; - (*mime).mm_length = mm_length; - (*mime).mm_mime_fields = mm_mime_fields; - (*mime).mm_content_type = mm_content_type; - (*mime).mm_body = mm_body; - match mm_type { - 1 => (*mime).mm_data.mm_single = mm_body, - 2 => { - (*mime).mm_data.mm_multipart.mm_preamble = mm_preamble; - (*mime).mm_data.mm_multipart.mm_epilogue = mm_epilogue; - (*mime).mm_data.mm_multipart.mm_mp_list = mm_mp_list; - cur = (*mm_mp_list).first; - while !cur.is_null() { - let mut submime: *mut Mailmime = 0 as *mut Mailmime; - submime = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut Mailmime; - (*submime).mm_parent = mime; - (*submime).mm_parent_type = MAILMIME_MULTIPLE as libc::c_int; - (*submime).mm_multipart_pos = cur; - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - } - 3 => { - (*mime).mm_data.mm_message.mm_fields = mm_fields; - (*mime).mm_data.mm_message.mm_msg_mime = mm_msg_mime; - if !mm_msg_mime.is_null() { - (*mm_msg_mime).mm_parent = mime; - (*mm_msg_mime).mm_parent_type = MAILMIME_MESSAGE as libc::c_int - } - } - _ => {} - } - return mime; -} - -pub unsafe fn mailmime_new_simple( - mut mm_type: libc::c_int, - mut mm_mime_fields: *mut mailmime_fields, - mut mm_content_type: *mut mailmime_content, - mut mm_fields: *mut mailimf_fields, - mut mm_msg_mime: *mut Mailmime, -) -> *mut Mailmime { - mailmime_new( - mm_type, - std::ptr::null(), - 0, - mm_mime_fields, - mm_content_type, - std::ptr::null_mut(), - std::ptr::null_mut(), - std::ptr::null_mut(), - std::ptr::null_mut(), - mm_fields, - mm_msg_mime, - ) -} - -pub unsafe fn mailmime_free(mut mime: *mut Mailmime) { - match (*mime).mm_type { - 1 => { - if (*mime).mm_body.is_null() && !(*mime).mm_data.mm_single.is_null() { - mailmime_data_free((*mime).mm_data.mm_single); - } - } - 2 => { - /* do nothing */ - if !(*mime).mm_data.mm_multipart.mm_preamble.is_null() { - mailmime_data_free((*mime).mm_data.mm_multipart.mm_preamble); - } - if !(*mime).mm_data.mm_multipart.mm_epilogue.is_null() { - mailmime_data_free((*mime).mm_data.mm_multipart.mm_epilogue); - } - clist_foreach( - (*mime).mm_data.mm_multipart.mm_mp_list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailmime_free), - ), - 0 as *mut libc::c_void, - ); - clist_free((*mime).mm_data.mm_multipart.mm_mp_list); - } - 3 => { - if !(*mime).mm_data.mm_message.mm_fields.is_null() { - mailimf_fields_free((*mime).mm_data.mm_message.mm_fields); - } - if !(*mime).mm_data.mm_message.mm_msg_mime.is_null() { - mailmime_free((*mime).mm_data.mm_message.mm_msg_mime); - } - } - _ => {} - } - if !(*mime).mm_body.is_null() { - mailmime_data_free((*mime).mm_body); - } - if !(*mime).mm_mime_fields.is_null() { - mailmime_fields_free((*mime).mm_mime_fields); - } - if !(*mime).mm_content_type.is_null() { - mailmime_content_free((*mime).mm_content_type); - } - free(mime as *mut libc::c_void); -} - -pub unsafe fn mailmime_encoded_word_new( - mut wd_charset: *mut libc::c_char, - mut wd_text: *mut libc::c_char, -) -> *mut mailmime_encoded_word { - let mut ew: *mut mailmime_encoded_word = 0 as *mut mailmime_encoded_word; - ew = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_encoded_word; - if ew.is_null() { - return 0 as *mut mailmime_encoded_word; - } - (*ew).wd_charset = wd_charset; - (*ew).wd_text = wd_text; - return ew; -} - -pub unsafe fn mailmime_encoded_word_free(mut ew: *mut mailmime_encoded_word) { - mailmime_charset_free((*ew).wd_charset); - mailmime_encoded_text_free((*ew).wd_text); - free(ew as *mut libc::c_void); -} - -pub unsafe fn mailmime_encoded_text_free(mut text: *mut libc::c_char) { - free(text as *mut libc::c_void); -} - -pub unsafe fn mailmime_charset_free(mut charset: *mut libc::c_char) { - free(charset as *mut libc::c_void); -} - -pub unsafe fn mailmime_disposition_new( - mut dsp_type: *mut mailmime_disposition_type, - mut dsp_parms: *mut clist, -) -> *mut mailmime_disposition { - let mut dsp: *mut mailmime_disposition = 0 as *mut mailmime_disposition; - dsp = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_disposition; - if dsp.is_null() { - return 0 as *mut mailmime_disposition; - } - (*dsp).dsp_type = dsp_type; - (*dsp).dsp_parms = dsp_parms; - return dsp; -} - -pub unsafe fn mailmime_disposition_type_new( - mut dsp_type: libc::c_int, - mut dsp_extension: *mut libc::c_char, -) -> *mut mailmime_disposition_type { - let mut m_dsp_type: *mut mailmime_disposition_type = 0 as *mut mailmime_disposition_type; - m_dsp_type = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_disposition_type; - if m_dsp_type.is_null() { - return 0 as *mut mailmime_disposition_type; - } - (*m_dsp_type).dsp_type = dsp_type; - (*m_dsp_type).dsp_extension = dsp_extension; - return m_dsp_type; -} - -pub unsafe fn mailmime_disposition_parm_new( - mut pa_type: libc::c_int, - mut pa_filename: *mut libc::c_char, - mut pa_creation_date: *mut libc::c_char, - mut pa_modification_date: *mut libc::c_char, - mut pa_read_date: *mut libc::c_char, - mut pa_size: size_t, - mut pa_parameter: *mut mailmime_parameter, -) -> *mut mailmime_disposition_parm { - let mut dsp_parm: *mut mailmime_disposition_parm = 0 as *mut mailmime_disposition_parm; - dsp_parm = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_disposition_parm; - if dsp_parm.is_null() { - return 0 as *mut mailmime_disposition_parm; - } - (*dsp_parm).pa_type = pa_type; - match pa_type { - 0 => (*dsp_parm).pa_data.pa_filename = pa_filename, - 1 => (*dsp_parm).pa_data.pa_creation_date = pa_creation_date, - 2 => (*dsp_parm).pa_data.pa_modification_date = pa_modification_date, - 3 => (*dsp_parm).pa_data.pa_read_date = pa_read_date, - 4 => (*dsp_parm).pa_data.pa_size = pa_size, - 5 => (*dsp_parm).pa_data.pa_parameter = pa_parameter, - _ => {} - } - return dsp_parm; -} - -pub unsafe fn mailmime_section_new(mut sec_list: *mut clist) -> *mut mailmime_section { - let mut section: *mut mailmime_section = 0 as *mut mailmime_section; - section = - malloc(::std::mem::size_of::() as libc::size_t) as *mut mailmime_section; - if section.is_null() { - return 0 as *mut mailmime_section; - } - (*section).sec_list = sec_list; - return section; -} - -pub unsafe fn mailmime_section_free(mut section: *mut mailmime_section) { - clist_foreach( - (*section).sec_list, - ::std::mem::transmute:: ()>, clist_func>( - Some(free), - ), - 0 as *mut libc::c_void, - ); - clist_free((*section).sec_list); - free(section as *mut libc::c_void); -} - -pub unsafe fn mailmime_decoded_part_free(mut part: *mut libc::c_char) { - mmap_string_unref(part); -} diff --git a/mmime/src/mailmime/types_helper.rs b/mmime/src/mailmime/types_helper.rs deleted file mode 100644 index 630c849f6..000000000 --- a/mmime/src/mailmime/types_helper.rs +++ /dev/null @@ -1,1445 +0,0 @@ -use rand::{thread_rng, Rng}; - -use crate::clist::*; -use crate::mailimf::types::*; -use crate::mailmime::types::*; -use crate::mailmime::*; -use crate::other::*; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_single_fields { - pub fld_content: *mut mailmime_content, - pub fld_content_charset: *mut libc::c_char, - pub fld_content_boundary: *mut libc::c_char, - pub fld_content_name: *mut libc::c_char, - pub fld_encoding: *mut mailmime_mechanism, - pub fld_id: *mut libc::c_char, - pub fld_description: *mut libc::c_char, - pub fld_version: uint32_t, - pub fld_disposition: *mut mailmime_disposition, - pub fld_disposition_filename: *mut libc::c_char, - pub fld_disposition_creation_date: *mut libc::c_char, - pub fld_disposition_modification_date: *mut libc::c_char, - pub fld_disposition_read_date: *mut libc::c_char, - pub fld_disposition_size: size_t, - pub fld_language: *mut mailmime_language, - pub fld_location: *mut libc::c_char, -} - -pub unsafe fn mailmime_transfer_encoding_get(mut fields: *mut mailmime_fields) -> libc::c_int { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*fields).fld_list).first; - while !cur.is_null() { - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - field = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailmime_field; - if (*field).fld_type == MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int { - return (*(*field).fld_data.fld_encoding).enc_type; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - return MAILMIME_MECHANISM_8BIT as libc::c_int; -} - -pub unsafe fn mailmime_disposition_new_filename( - mut type_0: libc::c_int, - mut filename: *mut libc::c_char, -) -> *mut mailmime_disposition { - return mailmime_disposition_new_with_data( - type_0, - filename, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - -1i32 as size_t, - ); -} - -pub unsafe fn mailmime_disposition_new_with_data( - mut type_0: libc::c_int, - mut filename: *mut libc::c_char, - mut creation_date: *mut libc::c_char, - mut modification_date: *mut libc::c_char, - mut read_date: *mut libc::c_char, - mut size: size_t, -) -> *mut mailmime_disposition { - let mut current_block: u64; - let mut dsp_type: *mut mailmime_disposition_type = 0 as *mut mailmime_disposition_type; - let mut list: *mut clist = 0 as *mut clist; - let mut r: libc::c_int = 0; - let mut parm: *mut mailmime_disposition_parm = 0 as *mut mailmime_disposition_parm; - let mut dsp: *mut mailmime_disposition = 0 as *mut mailmime_disposition; - dsp_type = mailmime_disposition_type_new(type_0, 0 as *mut libc::c_char); - if !dsp_type.is_null() { - list = clist_new(); - if !list.is_null() { - if !filename.is_null() { - parm = mailmime_disposition_parm_new( - MAILMIME_DISPOSITION_PARM_FILENAME as libc::c_int, - filename, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0i32 as size_t, - 0 as *mut mailmime_parameter, - ); - if parm.is_null() { - current_block = 13210718484351940574; - } else { - r = clist_insert_after(list, (*list).last, parm as *mut libc::c_void); - if r < 0i32 { - mailmime_disposition_parm_free(parm); - current_block = 13210718484351940574; - } else { - current_block = 4166486009154926805; - } - } - } else { - current_block = 4166486009154926805; - } - match current_block { - 4166486009154926805 => { - if !creation_date.is_null() { - parm = mailmime_disposition_parm_new( - MAILMIME_DISPOSITION_PARM_CREATION_DATE as libc::c_int, - 0 as *mut libc::c_char, - creation_date, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0i32 as size_t, - 0 as *mut mailmime_parameter, - ); - if parm.is_null() { - current_block = 13210718484351940574; - } else { - r = clist_insert_after(list, (*list).last, parm as *mut libc::c_void); - if r < 0i32 { - mailmime_disposition_parm_free(parm); - current_block = 13210718484351940574; - } else { - current_block = 12147880666119273379; - } - } - } else { - current_block = 12147880666119273379; - } - match current_block { - 13210718484351940574 => {} - _ => { - if !modification_date.is_null() { - parm = mailmime_disposition_parm_new( - MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE as libc::c_int, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - modification_date, - 0 as *mut libc::c_char, - 0i32 as size_t, - 0 as *mut mailmime_parameter, - ); - if parm.is_null() { - current_block = 13210718484351940574; - } else { - r = clist_insert_after( - list, - (*list).last, - parm as *mut libc::c_void, - ); - if r < 0i32 { - mailmime_disposition_parm_free(parm); - current_block = 13210718484351940574; - } else { - current_block = 13550086250199790493; - } - } - } else { - current_block = 13550086250199790493; - } - match current_block { - 13210718484351940574 => {} - _ => { - if !read_date.is_null() { - parm = mailmime_disposition_parm_new( - MAILMIME_DISPOSITION_PARM_READ_DATE as libc::c_int, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - read_date, - 0i32 as size_t, - 0 as *mut mailmime_parameter, - ); - if parm.is_null() { - current_block = 13210718484351940574; - } else { - r = clist_insert_after( - list, - (*list).last, - parm as *mut libc::c_void, - ); - if r < 0i32 { - mailmime_disposition_parm_free(parm); - current_block = 13210718484351940574; - } else { - current_block = 9520865839495247062; - } - } - } else { - current_block = 9520865839495247062; - } - match current_block { - 13210718484351940574 => {} - _ => { - if size != -1i32 as size_t { - parm = mailmime_disposition_parm_new( - MAILMIME_DISPOSITION_PARM_SIZE as libc::c_int, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - size, - 0 as *mut mailmime_parameter, - ); - if parm.is_null() { - current_block = 13210718484351940574; - } else { - r = clist_insert_after( - list, - (*list).last, - parm as *mut libc::c_void, - ); - if r < 0i32 { - mailmime_disposition_parm_free(parm); - current_block = 13210718484351940574; - } else { - current_block = 12199444798915819164; - } - } - } else { - current_block = 12199444798915819164; - } - match current_block { - 13210718484351940574 => {} - _ => { - dsp = mailmime_disposition_new(dsp_type, list); - return dsp; - } - } - } - } - } - } - } - } - } - _ => {} - } - clist_foreach( - list, - ::std::mem::transmute::< - Option ()>, - clist_func, - >(Some(mailmime_disposition_parm_free)), - 0 as *mut libc::c_void, - ); - clist_free(list); - } - mailmime_disposition_type_free(dsp_type); - } - return 0 as *mut mailmime_disposition; -} - -pub unsafe fn mailmime_fields_new_empty() -> *mut mailmime_fields { - let mut list: *mut clist = 0 as *mut clist; - let mut fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - list = clist_new(); - if !list.is_null() { - fields = mailmime_fields_new(list); - if fields.is_null() { - clist_free(list); - } else { - return fields; - } - } - return 0 as *mut mailmime_fields; -} - -pub unsafe fn mailmime_fields_add( - mut fields: *mut mailmime_fields, - mut field: *mut mailmime_field, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = clist_insert_after( - (*fields).fld_list, - (*(*fields).fld_list).last, - field as *mut libc::c_void, - ); - if r < 0i32 { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_fields_new_with_data( - mut encoding: *mut mailmime_mechanism, - mut id: *mut libc::c_char, - mut description: *mut libc::c_char, - mut disposition: *mut mailmime_disposition, - mut language: *mut mailmime_language, -) -> *mut mailmime_fields { - let mut current_block: u64; - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - let mut fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - let mut r: libc::c_int = 0; - fields = mailmime_fields_new_empty(); - if !fields.is_null() { - if !encoding.is_null() { - field = mailmime_field_new( - MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int, - 0 as *mut mailmime_content, - encoding, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0i32 as uint32_t, - 0 as *mut mailmime_disposition, - 0 as *mut mailmime_language, - 0 as *mut libc::c_char, - ); - if field.is_null() { - current_block = 5039974454013832799; - } else { - r = mailmime_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - mailmime_field_detach(field); - mailmime_field_free(field); - current_block = 5039974454013832799; - } else { - current_block = 7746791466490516765; - } - } - } else { - current_block = 7746791466490516765; - } - match current_block { - 7746791466490516765 => { - if !id.is_null() { - field = mailmime_field_new( - MAILMIME_FIELD_ID as libc::c_int, - 0 as *mut mailmime_content, - 0 as *mut mailmime_mechanism, - id, - 0 as *mut libc::c_char, - 0i32 as uint32_t, - 0 as *mut mailmime_disposition, - 0 as *mut mailmime_language, - 0 as *mut libc::c_char, - ); - if field.is_null() { - current_block = 5039974454013832799; - } else { - r = mailmime_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - mailmime_field_detach(field); - mailmime_field_free(field); - current_block = 5039974454013832799; - } else { - current_block = 13242334135786603907; - } - } - } else { - current_block = 13242334135786603907; - } - match current_block { - 5039974454013832799 => {} - _ => { - if !description.is_null() { - field = mailmime_field_new( - MAILMIME_FIELD_DESCRIPTION as libc::c_int, - 0 as *mut mailmime_content, - 0 as *mut mailmime_mechanism, - 0 as *mut libc::c_char, - description, - 0i32 as uint32_t, - 0 as *mut mailmime_disposition, - 0 as *mut mailmime_language, - 0 as *mut libc::c_char, - ); - if field.is_null() { - current_block = 5039974454013832799; - } else { - r = mailmime_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - mailmime_field_detach(field); - mailmime_field_free(field); - current_block = 5039974454013832799; - } else { - current_block = 15125582407903384992; - } - } - } else { - current_block = 15125582407903384992; - } - match current_block { - 5039974454013832799 => {} - _ => { - if !disposition.is_null() { - field = mailmime_field_new( - MAILMIME_FIELD_DISPOSITION as libc::c_int, - 0 as *mut mailmime_content, - 0 as *mut mailmime_mechanism, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0i32 as uint32_t, - disposition, - 0 as *mut mailmime_language, - 0 as *mut libc::c_char, - ); - if field.is_null() { - current_block = 5039974454013832799; - } else { - r = mailmime_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - mailmime_field_detach(field); - mailmime_field_free(field); - current_block = 5039974454013832799; - } else { - current_block = 9520865839495247062; - } - } - } else { - current_block = 9520865839495247062; - } - match current_block { - 5039974454013832799 => {} - _ => { - if !language.is_null() { - field = mailmime_field_new( - MAILMIME_FIELD_DISPOSITION as libc::c_int, - 0 as *mut mailmime_content, - 0 as *mut mailmime_mechanism, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0i32 as uint32_t, - 0 as *mut mailmime_disposition, - language, - 0 as *mut libc::c_char, - ); - if field.is_null() { - current_block = 5039974454013832799; - } else { - r = mailmime_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - mailmime_field_detach(field); - mailmime_field_free(field); - current_block = 5039974454013832799; - } else { - current_block = 15512526488502093901; - } - } - } else { - current_block = 15512526488502093901; - } - match current_block { - 5039974454013832799 => {} - _ => return fields, - } - } - } - } - } - } - } - } - _ => {} - } - clist_foreach( - (*fields).fld_list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailmime_field_detach), - ), - 0 as *mut libc::c_void, - ); - mailmime_fields_free(fields); - } - return 0 as *mut mailmime_fields; -} -unsafe fn mailmime_field_detach(mut field: *mut mailmime_field) { - match (*field).fld_type { - 1 => (*field).fld_data.fld_content = 0 as *mut mailmime_content, - 2 => (*field).fld_data.fld_encoding = 0 as *mut mailmime_mechanism, - 3 => (*field).fld_data.fld_id = 0 as *mut libc::c_char, - 4 => (*field).fld_data.fld_description = 0 as *mut libc::c_char, - 6 => (*field).fld_data.fld_disposition = 0 as *mut mailmime_disposition, - 7 => (*field).fld_data.fld_language = 0 as *mut mailmime_language, - _ => {} - }; -} - -pub unsafe fn mailmime_fields_new_with_version( - mut encoding: *mut mailmime_mechanism, - mut id: *mut libc::c_char, - mut description: *mut libc::c_char, - mut disposition: *mut mailmime_disposition, - mut language: *mut mailmime_language, -) -> *mut mailmime_fields { - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - let mut fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - let mut r: libc::c_int = 0; - fields = mailmime_fields_new_with_data(encoding, id, description, disposition, language); - if !fields.is_null() { - field = mailmime_field_new( - MAILMIME_FIELD_VERSION as libc::c_int, - 0 as *mut mailmime_content, - 0 as *mut mailmime_mechanism, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - (1i32 << 16i32) as uint32_t, - 0 as *mut mailmime_disposition, - 0 as *mut mailmime_language, - 0 as *mut libc::c_char, - ); - if !field.is_null() { - r = mailmime_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - mailmime_field_detach(field); - mailmime_field_free(field); - } else { - return fields; - } - } - clist_foreach( - (*fields).fld_list, - ::std::mem::transmute:: ()>, clist_func>( - Some(mailmime_field_detach), - ), - 0 as *mut libc::c_void, - ); - mailmime_fields_free(fields); - } - return 0 as *mut mailmime_fields; -} - -pub unsafe fn mailmime_get_content_message() -> *mut mailmime_content { - let mut list: *mut clist = 0 as *mut clist; - let mut composite_type: *mut mailmime_composite_type = 0 as *mut mailmime_composite_type; - let mut mime_type: *mut mailmime_type = 0 as *mut mailmime_type; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - let mut subtype: *mut libc::c_char = 0 as *mut libc::c_char; - composite_type = mailmime_composite_type_new( - MAILMIME_COMPOSITE_TYPE_MESSAGE as libc::c_int, - 0 as *mut libc::c_char, - ); - if !composite_type.is_null() { - mime_type = mailmime_type_new( - MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int, - 0 as *mut mailmime_discrete_type, - composite_type, - ); - if !mime_type.is_null() { - composite_type = 0 as *mut mailmime_composite_type; - list = clist_new(); - if !list.is_null() { - subtype = strdup(b"rfc822\x00" as *const u8 as *const libc::c_char); - if !subtype.is_null() { - content = mailmime_content_new(mime_type, subtype, list); - if content.is_null() { - free(subtype as *mut libc::c_void); - } else { - return content; - } - } - clist_free(list); - } - mailmime_type_free(mime_type); - } - if !composite_type.is_null() { - mailmime_composite_type_free(composite_type); - } - } - return 0 as *mut mailmime_content; -} - -pub unsafe fn mailmime_get_content_text() -> *mut mailmime_content { - let mut list: *mut clist = 0 as *mut clist; - let mut discrete_type: *mut mailmime_discrete_type = 0 as *mut mailmime_discrete_type; - let mut mime_type: *mut mailmime_type = 0 as *mut mailmime_type; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - let mut subtype: *mut libc::c_char = 0 as *mut libc::c_char; - discrete_type = mailmime_discrete_type_new( - MAILMIME_DISCRETE_TYPE_TEXT as libc::c_int, - 0 as *mut libc::c_char, - ); - if !discrete_type.is_null() { - mime_type = mailmime_type_new( - MAILMIME_TYPE_DISCRETE_TYPE as libc::c_int, - discrete_type, - 0 as *mut mailmime_composite_type, - ); - if !mime_type.is_null() { - discrete_type = 0 as *mut mailmime_discrete_type; - list = clist_new(); - if !list.is_null() { - subtype = strdup(b"plain\x00" as *const u8 as *const libc::c_char); - if !subtype.is_null() { - content = mailmime_content_new(mime_type, subtype, list); - if content.is_null() { - free(subtype as *mut libc::c_void); - } else { - return content; - } - } - clist_free(list); - } - mailmime_type_free(mime_type); - } - if !discrete_type.is_null() { - mailmime_discrete_type_free(discrete_type); - } - } - return 0 as *mut mailmime_content; -} -/* struct mailmime_content * mailmime_get_content(char * mime_type); */ -pub unsafe fn mailmime_data_new_data( - mut encoding: libc::c_int, - mut encoded: libc::c_int, - mut data: *const libc::c_char, - mut length: size_t, -) -> *mut mailmime_data { - return mailmime_data_new( - MAILMIME_DATA_TEXT as libc::c_int, - encoding, - encoded, - data, - length, - 0 as *mut libc::c_char, - ); -} - -pub unsafe fn mailmime_data_new_file( - mut encoding: libc::c_int, - mut encoded: libc::c_int, - mut filename: *mut libc::c_char, -) -> *mut mailmime_data { - return mailmime_data_new( - MAILMIME_DATA_FILE as libc::c_int, - encoding, - encoded, - 0 as *const libc::c_char, - 0i32 as size_t, - filename, - ); -} - -pub unsafe fn mailmime_new_message_data(mut msg_mime: *mut Mailmime) -> *mut Mailmime { - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - let mut build_info: *mut Mailmime = 0 as *mut Mailmime; - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - content = mailmime_get_content_message(); - if !content.is_null() { - mime_fields = mailmime_fields_new_with_version( - 0 as *mut mailmime_mechanism, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0 as *mut mailmime_disposition, - 0 as *mut mailmime_language, - ); - if !mime_fields.is_null() { - build_info = mailmime_new( - MAILMIME_MESSAGE as libc::c_int, - 0 as *const libc::c_char, - 0i32 as size_t, - mime_fields, - content, - 0 as *mut mailmime_data, - 0 as *mut mailmime_data, - 0 as *mut mailmime_data, - 0 as *mut clist, - 0 as *mut mailimf_fields, - msg_mime, - ); - if build_info.is_null() { - mailmime_fields_free(mime_fields); - } else { - return build_info; - } - } - mailmime_content_free(content); - } - return 0 as *mut Mailmime; -} - -pub unsafe fn mailmime_new_empty( - mut content: *mut mailmime_content, - mut mime_fields: *mut mailmime_fields, -) -> *mut Mailmime { - let mut current_block: u64; - let mut build_info: *mut Mailmime = 0 as *mut Mailmime; - let mut list: *mut clist = 0 as *mut clist; - let mut r: libc::c_int = 0; - let mut mime_type: libc::c_int = 0; - list = 0 as *mut clist; - match (*(*content).ct_type).tp_type { - 1 => { - mime_type = MAILMIME_SINGLE as libc::c_int; - current_block = 12349973810996921269; - } - 2 => match (*(*(*content).ct_type).tp_data.tp_composite_type).ct_type { - 2 => { - current_block = 5822726848290245908; - match current_block { - 565197971715936940 => { - if strcasecmp( - (*content).ct_subtype, - b"rfc822\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - mime_type = MAILMIME_MESSAGE as libc::c_int - } else { - mime_type = MAILMIME_SINGLE as libc::c_int - } - } - _ => mime_type = MAILMIME_MULTIPLE as libc::c_int, - } - current_block = 12349973810996921269; - } - 1 => { - current_block = 565197971715936940; - match current_block { - 565197971715936940 => { - if strcasecmp( - (*content).ct_subtype, - b"rfc822\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - mime_type = MAILMIME_MESSAGE as libc::c_int - } else { - mime_type = MAILMIME_SINGLE as libc::c_int - } - } - _ => mime_type = MAILMIME_MULTIPLE as libc::c_int, - } - current_block = 12349973810996921269; - } - _ => { - current_block = 13576996419214490990; - } - }, - _ => { - current_block = 13576996419214490990; - } - } - match current_block { - 12349973810996921269 => { - if mime_type == MAILMIME_MULTIPLE as libc::c_int { - let mut attr_name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut attr_value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut param: *mut mailmime_parameter = 0 as *mut mailmime_parameter; - let mut parameters: *mut clist = 0 as *mut clist; - let mut boundary: *mut libc::c_char = 0 as *mut libc::c_char; - list = clist_new(); - if list.is_null() { - current_block = 13576996419214490990; - } else { - attr_name = strdup(b"boundary\x00" as *const u8 as *const libc::c_char); - if attr_name.is_null() { - current_block = 13142422523813476356; - } else { - boundary = mailmime_generate_boundary(); - attr_value = boundary; - if attr_name.is_null() { - free(attr_name as *mut libc::c_void); - current_block = 13142422523813476356; - } else { - param = mailmime_parameter_new(attr_name, attr_value); - if param.is_null() { - free(attr_value as *mut libc::c_void); - free(attr_name as *mut libc::c_void); - current_block = 13142422523813476356; - } else { - if (*content).ct_parameters.is_null() { - parameters = clist_new(); - if parameters.is_null() { - mailmime_parameter_free(param); - current_block = 13142422523813476356; - } else { - current_block = 1836292691772056875; - } - } else { - parameters = (*content).ct_parameters; - current_block = 1836292691772056875; - } - match current_block { - 13142422523813476356 => {} - _ => { - r = clist_insert_after( - parameters, - (*parameters).last, - param as *mut libc::c_void, - ); - if r != 0i32 { - clist_free(parameters); - mailmime_parameter_free(param); - current_block = 13142422523813476356; - } else { - if (*content).ct_parameters.is_null() { - (*content).ct_parameters = parameters - } - current_block = 2543120759711851213; - } - } - } - } - } - } - match current_block { - 2543120759711851213 => {} - _ => { - clist_free(list); - current_block = 13576996419214490990; - } - } - } - } else { - current_block = 2543120759711851213; - } - match current_block { - 13576996419214490990 => {} - _ => { - build_info = mailmime_new( - mime_type, - 0 as *const libc::c_char, - 0i32 as size_t, - mime_fields, - content, - 0 as *mut mailmime_data, - 0 as *mut mailmime_data, - 0 as *mut mailmime_data, - list, - 0 as *mut mailimf_fields, - 0 as *mut Mailmime, - ); - if build_info.is_null() { - clist_free(list); - return 0 as *mut Mailmime; - } - return build_info; - } - } - } - _ => {} - } - return 0 as *mut Mailmime; -} - -pub unsafe fn mailmime_generate_boundary() -> *mut libc::c_char { - let mut rng = thread_rng(); - let value: libc::c_int = rng.gen(); - let now = chrono::Utc::now().timestamp(); - let raw = format!( - "{}_{}_{}", - hex::encode(&now.to_be_bytes()[4..]), - hex::encode(value.to_be_bytes()), - hex::encode(&std::process::id().to_le_bytes()[..2]) - ); - - let c = std::ffi::CString::new(raw).unwrap_or_default(); - strdup(c.as_ptr()) -} - -pub unsafe fn mailmime_new_with_content( - mut content_type: *const libc::c_char, - mut mime_fields: *mut mailmime_fields, - mut result: *mut *mut Mailmime, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - let mut build_info: *mut Mailmime = 0 as *mut Mailmime; - let mut res: libc::c_int = 0; - cur_token = 0i32 as size_t; - r = mailmime_content_parse( - content_type, - strlen(content_type), - &mut cur_token, - &mut content, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r - } else { - build_info = mailmime_new_empty(content, mime_fields); - if build_info.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - mailmime_content_free(content); - } else { - *result = build_info; - return MAILIMF_NO_ERROR as libc::c_int; - } - } - return res; -} - -pub unsafe fn mailmime_set_preamble_file( - mut build_info: *mut Mailmime, - mut filename: *mut libc::c_char, -) -> libc::c_int { - let mut data: *mut mailmime_data = 0 as *mut mailmime_data; - data = mailmime_data_new( - MAILMIME_DATA_FILE as libc::c_int, - MAILMIME_MECHANISM_8BIT as libc::c_int, - 0i32, - 0 as *const libc::c_char, - 0i32 as size_t, - filename, - ); - if data.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - (*build_info).mm_data.mm_multipart.mm_preamble = data; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_set_epilogue_file( - mut build_info: *mut Mailmime, - mut filename: *mut libc::c_char, -) -> libc::c_int { - let mut data: *mut mailmime_data = 0 as *mut mailmime_data; - data = mailmime_data_new( - MAILMIME_DATA_FILE as libc::c_int, - MAILMIME_MECHANISM_8BIT as libc::c_int, - 0i32, - 0 as *const libc::c_char, - 0i32 as size_t, - filename, - ); - if data.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - (*build_info).mm_data.mm_multipart.mm_epilogue = data; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_set_preamble_text( - mut build_info: *mut Mailmime, - mut data_str: *mut libc::c_char, - mut length: size_t, -) -> libc::c_int { - let mut data: *mut mailmime_data = 0 as *mut mailmime_data; - data = mailmime_data_new( - MAILMIME_DATA_TEXT as libc::c_int, - MAILMIME_MECHANISM_8BIT as libc::c_int, - 0i32, - data_str, - length, - 0 as *mut libc::c_char, - ); - if data.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - (*build_info).mm_data.mm_multipart.mm_preamble = data; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_set_epilogue_text( - mut build_info: *mut Mailmime, - mut data_str: *mut libc::c_char, - mut length: size_t, -) -> libc::c_int { - let mut data: *mut mailmime_data = 0 as *mut mailmime_data; - data = mailmime_data_new( - MAILMIME_DATA_TEXT as libc::c_int, - MAILMIME_MECHANISM_8BIT as libc::c_int, - 0i32, - data_str, - length, - 0 as *mut libc::c_char, - ); - if data.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - (*build_info).mm_data.mm_multipart.mm_epilogue = data; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_set_body_file( - mut build_info: *mut Mailmime, - mut filename: *mut libc::c_char, -) -> libc::c_int { - let mut encoding: libc::c_int = 0; - let mut data: *mut mailmime_data = 0 as *mut mailmime_data; - encoding = mailmime_transfer_encoding_get((*build_info).mm_mime_fields); - data = mailmime_data_new( - MAILMIME_DATA_FILE as libc::c_int, - encoding, - 0i32, - 0 as *const libc::c_char, - 0i32 as size_t, - filename, - ); - if data.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - (*build_info).mm_data.mm_single = data; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_set_body_text( - mut build_info: *mut Mailmime, - mut data_str: *mut libc::c_char, - mut length: size_t, -) -> libc::c_int { - let mut encoding: libc::c_int = 0; - let mut data: *mut mailmime_data = 0 as *mut mailmime_data; - encoding = mailmime_transfer_encoding_get((*build_info).mm_mime_fields); - data = mailmime_data_new( - MAILMIME_DATA_TEXT as libc::c_int, - encoding, - 0i32, - data_str, - length, - 0 as *mut libc::c_char, - ); - if data.is_null() { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - (*build_info).mm_data.mm_single = data; - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_add_part( - mut build_info: *mut Mailmime, - mut part: *mut Mailmime, -) -> libc::c_int { - let mut r: libc::c_int = 0; - if (*build_info).mm_type == MAILMIME_MESSAGE as libc::c_int { - (*build_info).mm_data.mm_message.mm_msg_mime = part; - (*part).mm_parent_type = MAILMIME_MESSAGE as libc::c_int; - (*part).mm_parent = build_info - } else if (*build_info).mm_type == MAILMIME_MULTIPLE as libc::c_int { - r = clist_insert_after( - (*build_info).mm_data.mm_multipart.mm_mp_list, - (*(*build_info).mm_data.mm_multipart.mm_mp_list).last, - part as *mut libc::c_void, - ); - if r != 0i32 { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - (*part).mm_parent_type = MAILMIME_MULTIPLE as libc::c_int; - (*part).mm_parent = build_info; - (*part).mm_multipart_pos = (*(*build_info).mm_data.mm_multipart.mm_mp_list).last - } else { - return MAILIMF_ERROR_INVAL as libc::c_int; - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_remove_part(mut mime: *mut Mailmime) { - let mut parent: *mut Mailmime = 0 as *mut Mailmime; - parent = (*mime).mm_parent; - if parent.is_null() { - return; - } - match (*mime).mm_parent_type { - 3 => { - (*mime).mm_parent = 0 as *mut Mailmime; - (*parent).mm_data.mm_message.mm_msg_mime = 0 as *mut Mailmime - } - 2 => { - (*mime).mm_parent = 0 as *mut Mailmime; - clist_delete( - (*parent).mm_data.mm_multipart.mm_mp_list, - (*mime).mm_multipart_pos, - ); - } - _ => {} - }; -} - -pub unsafe fn mailmime_set_imf_fields( - mut build_info: *mut Mailmime, - mut mm_fields: *mut mailimf_fields, -) { - (*build_info).mm_data.mm_message.mm_fields = mm_fields; -} - -pub unsafe fn mailmime_single_fields_init( - mut single_fields: *mut mailmime_single_fields, - mut fld_fields: *mut mailmime_fields, - mut fld_content: *mut mailmime_content, -) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - memset( - single_fields as *mut libc::c_void, - 0i32, - ::std::mem::size_of::() as libc::size_t, - ); - if !fld_content.is_null() { - mailmime_content_single_fields_init(single_fields, fld_content); - } - if fld_fields.is_null() { - return; - } - cur = (*(*fld_fields).fld_list).first; - while !cur.is_null() { - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - field = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailmime_field; - match (*field).fld_type { - 1 => { - mailmime_content_single_fields_init(single_fields, (*field).fld_data.fld_content); - } - 2 => (*single_fields).fld_encoding = (*field).fld_data.fld_encoding, - 3 => (*single_fields).fld_id = (*field).fld_data.fld_id, - 4 => (*single_fields).fld_description = (*field).fld_data.fld_description, - 5 => (*single_fields).fld_version = (*field).fld_data.fld_version, - 6 => { - mailmime_disposition_single_fields_init( - single_fields, - (*field).fld_data.fld_disposition, - ); - } - 7 => (*single_fields).fld_language = (*field).fld_data.fld_language, - 8 => (*single_fields).fld_location = (*field).fld_data.fld_location, - _ => {} - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } -} -unsafe fn mailmime_disposition_single_fields_init( - mut single_fields: *mut mailmime_single_fields, - mut fld_disposition: *mut mailmime_disposition, -) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - (*single_fields).fld_disposition = fld_disposition; - cur = (*(*fld_disposition).dsp_parms).first; - while !cur.is_null() { - let mut param: *mut mailmime_disposition_parm = 0 as *mut mailmime_disposition_parm; - param = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailmime_disposition_parm; - match (*param).pa_type { - 0 => (*single_fields).fld_disposition_filename = (*param).pa_data.pa_filename, - 1 => (*single_fields).fld_disposition_creation_date = (*param).pa_data.pa_creation_date, - 2 => { - (*single_fields).fld_disposition_modification_date = - (*param).pa_data.pa_modification_date - } - 3 => (*single_fields).fld_disposition_read_date = (*param).pa_data.pa_read_date, - 4 => (*single_fields).fld_disposition_size = (*param).pa_data.pa_size, - _ => {} - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } -} -unsafe fn mailmime_content_single_fields_init( - mut single_fields: *mut mailmime_single_fields, - mut fld_content: *mut mailmime_content, -) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - (*single_fields).fld_content = fld_content; - cur = (*(*fld_content).ct_parameters).first; - while !cur.is_null() { - let mut param: *mut mailmime_parameter = 0 as *mut mailmime_parameter; - param = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailmime_parameter; - if strcasecmp( - (*param).pa_name, - b"boundary\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - (*single_fields).fld_content_boundary = (*param).pa_value - } - if strcasecmp( - (*param).pa_name, - b"charset\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - (*single_fields).fld_content_charset = (*param).pa_value - } - if strcasecmp( - (*param).pa_name, - b"name\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - (*single_fields).fld_content_name = (*param).pa_value - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } -} - -pub unsafe fn mailmime_single_fields_new( - mut fld_fields: *mut mailmime_fields, - mut fld_content: *mut mailmime_content, -) -> *mut mailmime_single_fields { - let mut single_fields: *mut mailmime_single_fields = 0 as *mut mailmime_single_fields; - single_fields = malloc(::std::mem::size_of::() as libc::size_t) - as *mut mailmime_single_fields; - if single_fields.is_null() { - return 0 as *mut mailmime_single_fields; - } else { - mailmime_single_fields_init(single_fields, fld_fields, fld_content); - return single_fields; - }; -} - -pub unsafe fn mailmime_single_fields_free(mut single_fields: *mut mailmime_single_fields) { - free(single_fields as *mut libc::c_void); -} - -pub unsafe fn mailmime_smart_add_part( - mut mime: *mut Mailmime, - mut mime_sub: *mut Mailmime, -) -> libc::c_int { - let mut saved_sub: *mut Mailmime = 0 as *mut Mailmime; - let mut mp: *mut Mailmime = 0 as *mut Mailmime; - let mut res: libc::c_int = 0; - let mut r: libc::c_int = 0; - match (*mime).mm_type { - 1 => res = MAILIMF_ERROR_INVAL as libc::c_int, - 2 => { - r = mailmime_add_part(mime, mime_sub); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - return MAILIMF_NO_ERROR as libc::c_int; - } - } - _ => { - /* MAILMIME_MESSAGE */ - if (*mime).mm_data.mm_message.mm_msg_mime.is_null() { - r = mailmime_add_part(mime, mime_sub); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - return MAILIMF_NO_ERROR as libc::c_int; - } - } else { - if (*(*mime).mm_data.mm_message.mm_msg_mime).mm_type - == MAILMIME_MULTIPLE as libc::c_int - { - return mailmime_add_part((*mime).mm_data.mm_message.mm_msg_mime, mime_sub); - } - saved_sub = (*mime).mm_data.mm_message.mm_msg_mime; - mp = mailmime_multiple_new( - b"multipart/mixed\x00" as *const u8 as *const libc::c_char, - ); - if mp.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - mailmime_remove_part(saved_sub); - r = mailmime_add_part(mime, mp); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - mailmime_free(mp); - } else { - r = mailmime_add_part(mp, saved_sub); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - r = mailmime_add_part(mp, mime_sub); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = MAILIMF_ERROR_MEMORY as libc::c_int - } else { - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - mailmime_free(saved_sub); - } - } - } - } - return res; -} - -pub unsafe fn mailmime_multiple_new(mut type_0: *const libc::c_char) -> *mut Mailmime { - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - let mut mp: *mut Mailmime = 0 as *mut Mailmime; - mime_fields = mailmime_fields_new_empty(); - if !mime_fields.is_null() { - content = mailmime_content_new_with_str(type_0); - if !content.is_null() { - mp = mailmime_new_empty(content, mime_fields); - if mp.is_null() { - mailmime_content_free(content); - } else { - return mp; - } - } - mailmime_fields_free(mime_fields); - } - return 0 as *mut Mailmime; -} - -pub unsafe fn mailmime_content_new_with_str(mut str: *const libc::c_char) -> *mut mailmime_content { - let mut r: libc::c_int = 0; - let mut cur_token: size_t = 0; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - cur_token = 0i32 as size_t; - r = mailmime_content_parse(str, strlen(str), &mut cur_token, &mut content); - if r != MAILIMF_NO_ERROR as libc::c_int { - return 0 as *mut mailmime_content; - } - return content; -} - -pub unsafe fn mailmime_smart_remove_part(mut mime: *mut Mailmime) -> libc::c_int { - let mut parent: *mut Mailmime = 0 as *mut Mailmime; - let mut res: libc::c_int = 0; - parent = (*mime).mm_parent; - if parent.is_null() { - res = MAILIMF_ERROR_INVAL as libc::c_int - } else { - match (*mime).mm_type { - 3 => { - if !(*mime).mm_data.mm_message.mm_msg_mime.is_null() { - res = MAILIMF_ERROR_INVAL as libc::c_int - } else { - mailmime_remove_part(mime); - mailmime_free(mime); - return MAILIMF_NO_ERROR as libc::c_int; - } - } - 2 => { - if !((*(*mime).mm_data.mm_multipart.mm_mp_list).first - == (*(*mime).mm_data.mm_multipart.mm_mp_list).last - && (*(*mime).mm_data.mm_multipart.mm_mp_list).last.is_null()) - { - res = MAILIMF_ERROR_INVAL as libc::c_int - } else { - mailmime_remove_part(mime); - mailmime_free(mime); - return MAILIMF_NO_ERROR as libc::c_int; - } - } - 1 => { - mailmime_remove_part(mime); - mailmime_free(mime); - return MAILIMF_NO_ERROR as libc::c_int; - } - _ => return MAILIMF_ERROR_INVAL as libc::c_int, - } - } - return res; -} - -pub unsafe fn mailmime_fields_new_encoding(mut type_0: libc::c_int) -> *mut mailmime_fields { - let mut encoding: *mut mailmime_mechanism = 0 as *mut mailmime_mechanism; - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - encoding = mailmime_mechanism_new(type_0, 0 as *mut libc::c_char); - if !encoding.is_null() { - mime_fields = mailmime_fields_new_with_data( - encoding, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0 as *mut mailmime_disposition, - 0 as *mut mailmime_language, - ); - if mime_fields.is_null() { - mailmime_mechanism_free(encoding); - } else { - return mime_fields; - } - } - return 0 as *mut mailmime_fields; -} - -pub unsafe fn mailmime_fields_new_filename( - mut dsp_type: libc::c_int, - mut filename: *mut libc::c_char, - mut encoding_type: libc::c_int, -) -> *mut mailmime_fields { - let mut dsp: *mut mailmime_disposition = 0 as *mut mailmime_disposition; - let mut encoding: *mut mailmime_mechanism = 0 as *mut mailmime_mechanism; - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - dsp = mailmime_disposition_new_with_data( - dsp_type, - filename, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - -1i32 as size_t, - ); - if !dsp.is_null() { - encoding = mailmime_mechanism_new(encoding_type, 0 as *mut libc::c_char); - if !encoding.is_null() { - mime_fields = mailmime_fields_new_with_data( - encoding, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - dsp, - 0 as *mut mailmime_language, - ); - if mime_fields.is_null() { - mailmime_encoding_free(encoding); - } else { - return mime_fields; - } - } - mailmime_disposition_free(dsp); - } - return 0 as *mut mailmime_fields; -} - -pub unsafe fn mailmime_param_new_with_data( - mut name: *mut libc::c_char, - mut value: *mut libc::c_char, -) -> *mut mailmime_parameter { - let mut param_name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut param_value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut param: *mut mailmime_parameter = 0 as *mut mailmime_parameter; - param_name = strdup(name); - if !param_name.is_null() { - param_value = strdup(value); - if !param_value.is_null() { - param = mailmime_parameter_new(param_name, param_value); - if param.is_null() { - free(param_value as *mut libc::c_void); - } else { - return param; - } - } - free(param_name as *mut libc::c_void); - } - return 0 as *mut mailmime_parameter; -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_generate_boundary() { - let res_c = unsafe { mailmime_generate_boundary() }; - let res = unsafe { std::ffi::CStr::from_ptr(res_c).to_str().unwrap() }; - assert_eq!(res.len(), 22); - - unsafe { free(res_c as *mut _) }; - } -} diff --git a/mmime/src/mailmime/write_generic.rs b/mmime/src/mailmime/write_generic.rs deleted file mode 100644 index cc951e5f2..000000000 --- a/mmime/src/mailmime/write_generic.rs +++ /dev/null @@ -1,1979 +0,0 @@ -use std::ffi::CStr; - -use crate::clist::*; -use crate::mailimf::write_generic::*; -use crate::mailmime::content::*; -use crate::mailmime::types::*; -use crate::mailmime::types_helper::*; -use crate::mailmime::*; -use crate::other::*; - -pub const STATE_INIT: libc::c_uint = 0; -pub const STATE_SPACE_CR: libc::c_uint = 3; -pub const STATE_SPACE: libc::c_uint = 2; -pub const STATE_CR: libc::c_uint = 1; - -pub unsafe fn mailmime_fields_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut fields: *mut mailmime_fields, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*fields).fld_list).first; - while !cur.is_null() { - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - field = (*cur).data as *mut mailmime_field; - r = mailmime_field_write_driver(do_write, data, col, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -unsafe fn mailmime_field_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut field: *mut mailmime_field, -) -> libc::c_int { - let mut r: libc::c_int = 0; - match (*field).fld_type { - 1 => r = mailmime_content_write_driver(do_write, data, col, (*field).fld_data.fld_content), - 2 => { - r = mailmime_encoding_write_driver(do_write, data, col, (*field).fld_data.fld_encoding) - } - 3 => r = mailmime_id_write_driver(do_write, data, col, (*field).fld_data.fld_id), - 4 => { - r = mailmime_description_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_description, - ) - } - 5 => r = mailmime_version_write_driver(do_write, data, col, (*field).fld_data.fld_version), - 6 => { - r = mailmime_disposition_write_driver( - do_write, - data, - col, - (*field).fld_data.fld_disposition, - ) - } - 7 => { - r = mailmime_language_write_driver(do_write, data, col, (*field).fld_data.fld_language) - } - 8 => { - r = mailmime_location_write_driver(do_write, data, col, (*field).fld_data.fld_location) - } - _ => r = MAILIMF_ERROR_INVAL as libc::c_int, - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_location_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut location: *mut libc::c_char, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut len: libc::c_int = strlen(location) as libc::c_int; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Content-Location: \x00" as *const u8 as *const libc::c_char, - 18i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - if *col > 1i32 && *col + len > 78i32 { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - r = mailimf_string_write_driver(do_write, data, col, location, len as size_t); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_language_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut language: *mut mailmime_language, -) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut first: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Content-Language: \x00" as *const u8 as *const libc::c_char, - 18i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - first = 1i32; - cur = (*(*language).lg_list).first; - while !cur.is_null() { - let mut lang: *mut libc::c_char = 0 as *mut libc::c_char; - let mut len: size_t = 0; - lang = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut libc::c_char; - len = strlen(lang); - if 0 == first { - r = mailimf_string_write_driver( - do_write, - data, - col, - b", \x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } else { - first = 0i32 - } - if *col > 1i32 { - if (*col as libc::size_t).wrapping_add(len) > 78i32 as libc::size_t { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - } - r = mailimf_string_write_driver(do_write, data, col, lang, len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_disposition_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut disposition: *mut mailmime_disposition, -) -> libc::c_int { - let mut dsp_type: *mut mailmime_disposition_type = 0 as *mut mailmime_disposition_type; - let mut r: libc::c_int = 0; - let mut cur: *mut clistiter = 0 as *mut clistiter; - dsp_type = (*disposition).dsp_type; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Content-Disposition: \x00" as *const u8 as *const libc::c_char, - 21i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - match (*dsp_type).dsp_type { - 1 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"inline\x00" as *const u8 as *const libc::c_char, - 6i32 as size_t, - ) - } - 2 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"attachment\x00" as *const u8 as *const libc::c_char, - 10i32 as size_t, - ) - } - 3 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - (*dsp_type).dsp_extension, - strlen((*dsp_type).dsp_extension), - ) - } - _ => r = MAILIMF_ERROR_INVAL as libc::c_int, - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = (*(*disposition).dsp_parms).first; - while !cur.is_null() { - let mut param: *mut mailmime_disposition_parm = 0 as *mut mailmime_disposition_parm; - param = (*cur).data as *mut mailmime_disposition_parm; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"; \x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailmime_disposition_param_write_driver(do_write, data, col, param); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_disposition_param_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut param: *mut mailmime_disposition_parm, -) -> libc::c_int { - let mut len: size_t = 0; - let mut r: libc::c_int = 0; - let mut sizestr: *mut libc::c_char = std::ptr::null_mut(); - - match (*param).pa_type { - 0 => { - len = strlen(b"filename=\x00" as *const u8 as *const libc::c_char) - .wrapping_add(strlen((*param).pa_data.pa_filename)) - } - 1 => { - len = strlen(b"creation-date=\x00" as *const u8 as *const libc::c_char) - .wrapping_add(strlen((*param).pa_data.pa_creation_date)) - } - 2 => { - len = strlen(b"modification-date=\x00" as *const u8 as *const libc::c_char) - .wrapping_add(strlen((*param).pa_data.pa_modification_date)) - } - 3 => { - len = strlen(b"read-date=\x00" as *const u8 as *const libc::c_char) - .wrapping_add(strlen((*param).pa_data.pa_read_date)) - } - 4 => { - let value = (*param).pa_data.pa_size as u32; - let raw = format!("{}", value); - let raw_c = std::ffi::CString::new(raw).unwrap_or_default(); - sizestr = strdup(raw_c.as_ptr()); - len = strlen(b"size=\x00" as *const u8 as *const libc::c_char) - .wrapping_add(strlen(sizestr)) - } - 5 => { - len = strlen((*(*param).pa_data.pa_parameter).pa_name) - .wrapping_add(1i32 as libc::size_t) - .wrapping_add(strlen((*(*param).pa_data.pa_parameter).pa_value)) - } - _ => return MAILIMF_ERROR_INVAL as libc::c_int, - } - if *col > 1i32 { - if (*col as libc::size_t).wrapping_add(len) > 78i32 as libc::size_t { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - } - match (*param).pa_type { - 0 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"filename=\x00" as *const u8 as *const libc::c_char, - 9i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_quoted_string_write_driver( - do_write, - data, - col, - (*param).pa_data.pa_filename, - strlen((*param).pa_data.pa_filename), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 1 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"creation-date=\x00" as *const u8 as *const libc::c_char, - 14i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_quoted_string_write_driver( - do_write, - data, - col, - (*param).pa_data.pa_creation_date, - strlen((*param).pa_data.pa_creation_date), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 2 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"modification-date=\x00" as *const u8 as *const libc::c_char, - 18i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_quoted_string_write_driver( - do_write, - data, - col, - (*param).pa_data.pa_modification_date, - strlen((*param).pa_data.pa_modification_date), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 3 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"read-date=\x00" as *const u8 as *const libc::c_char, - 10i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_quoted_string_write_driver( - do_write, - data, - col, - (*param).pa_data.pa_read_date, - strlen((*param).pa_data.pa_read_date), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 4 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"size=\x00" as *const u8 as *const libc::c_char, - 5i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver(do_write, data, col, sizestr, strlen(sizestr)); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - 5 => { - r = mailmime_parameter_write_driver(do_write, data, col, (*param).pa_data.pa_parameter); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - _ => {} - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_parameter_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut param: *mut mailmime_parameter, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - (*param).pa_name, - strlen((*param).pa_name), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"=\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_quoted_string_write_driver( - do_write, - data, - col, - (*param).pa_value, - strlen((*param).pa_value), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_version_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut version: uint32_t, -) -> libc::c_int { - let mut r: libc::c_int = 0; - - r = mailimf_string_write_driver( - do_write, - data, - col, - b"MIME-Version: \x00" as *const u8 as *const libc::c_char, - 14i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - - let raw = format!("{}.{}", (version >> 16) as i32, (version & 0xffff) as i32); - let raw_c = std::ffi::CString::new(raw).unwrap_or_default(); - let mut versionstr = strdup(raw_c.as_ptr()); - r = mailimf_string_write_driver(do_write, data, col, versionstr, strlen(versionstr)); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_description_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut descr: *mut libc::c_char, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Content-Description: \x00" as *const u8 as *const libc::c_char, - 21i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver(do_write, data, col, descr, strlen(descr)); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_id_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut id: *mut libc::c_char, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Content-ID: \x00" as *const u8 as *const libc::c_char, - 12i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"<\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver(do_write, data, col, id, strlen(id)); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b">\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_encoding_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut encoding: *mut mailmime_mechanism, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Content-Transfer-Encoding: \x00" as *const u8 as *const libc::c_char, - 27i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - match (*encoding).enc_type { - 1 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"7bit\x00" as *const u8 as *const libc::c_char, - 4i32 as size_t, - ) - } - 2 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"8bit\x00" as *const u8 as *const libc::c_char, - 4i32 as size_t, - ) - } - 3 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"binary\x00" as *const u8 as *const libc::c_char, - 6i32 as size_t, - ) - } - 4 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"quoted-printable\x00" as *const u8 as *const libc::c_char, - 16i32 as size_t, - ) - } - 5 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"base64\x00" as *const u8 as *const libc::c_char, - 6i32 as size_t, - ) - } - 6 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - (*encoding).enc_token, - strlen((*encoding).enc_token), - ) - } - _ => r = MAILIMF_ERROR_INVAL as libc::c_int, - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_content_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut content: *mut mailmime_content, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"Content-Type: \x00" as *const u8 as *const libc::c_char, - 14i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailmime_content_type_write_driver(do_write, data, col, content); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_content_type_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut content: *mut mailmime_content, -) -> libc::c_int { - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut len: size_t = 0; - let mut r: libc::c_int = 0; - r = mailmime_type_write_driver(do_write, data, col, (*content).ct_type); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"/\x00" as *const u8 as *const libc::c_char, - 1i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - r = mailimf_string_write_driver( - do_write, - data, - col, - (*content).ct_subtype, - strlen((*content).ct_subtype), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - if !(*content).ct_parameters.is_null() { - cur = (*(*content).ct_parameters).first; - while !cur.is_null() { - let mut param: *mut mailmime_parameter = 0 as *mut mailmime_parameter; - param = (*cur).data as *mut mailmime_parameter; - r = mailimf_string_write_driver( - do_write, - data, - col, - b"; \x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - len = strlen((*param).pa_name) - .wrapping_add(1i32 as libc::size_t) - .wrapping_add(strlen((*param).pa_value)); - if *col > 1i32 { - if (*col as libc::size_t).wrapping_add(len) > 78i32 as libc::size_t { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n \x00" as *const u8 as *const libc::c_char, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - } - r = mailmime_parameter_write_driver(do_write, data, col, param); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - } - return MAILIMF_NO_ERROR as libc::c_int; -} -/* -static int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, - struct mailmime_content * content); -*/ -unsafe fn mailmime_type_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut type_0: *mut mailmime_type, -) -> libc::c_int { - let mut r: libc::c_int = 0; - match (*type_0).tp_type { - 1 => { - r = mailmime_discrete_type_write_driver( - do_write, - data, - col, - (*type_0).tp_data.tp_discrete_type, - ) - } - 2 => { - r = mailmime_composite_type_write_driver( - do_write, - data, - col, - (*type_0).tp_data.tp_composite_type, - ) - } - _ => r = MAILIMF_ERROR_INVAL as libc::c_int, - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_composite_type_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut composite_type: *mut mailmime_composite_type, -) -> libc::c_int { - let mut r: libc::c_int = 0; - match (*composite_type).ct_type { - 1 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"message\x00" as *const u8 as *const libc::c_char, - 7i32 as size_t, - ) - } - 2 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"multipart\x00" as *const u8 as *const libc::c_char, - 9i32 as size_t, - ) - } - 3 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - (*composite_type).ct_token, - strlen((*composite_type).ct_token), - ) - } - _ => r = MAILIMF_ERROR_INVAL as libc::c_int, - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -unsafe fn mailmime_discrete_type_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut discrete_type: *mut mailmime_discrete_type, -) -> libc::c_int { - let mut r: libc::c_int = 0; - match (*discrete_type).dt_type { - 1 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"text\x00" as *const u8 as *const libc::c_char, - 4i32 as size_t, - ) - } - 2 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"image\x00" as *const u8 as *const libc::c_char, - 5i32 as size_t, - ) - } - 3 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"audio\x00" as *const u8 as *const libc::c_char, - 5i32 as size_t, - ) - } - 4 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"video\x00" as *const u8 as *const libc::c_char, - 5i32 as size_t, - ) - } - 5 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"application\x00" as *const u8 as *const libc::c_char, - 11i32 as size_t, - ) - } - 6 => { - r = mailimf_string_write_driver( - do_write, - data, - col, - (*discrete_type).dt_extension, - strlen((*discrete_type).dt_extension), - ) - } - _ => r = MAILIMF_ERROR_INVAL as libc::c_int, - } - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -pub unsafe fn mailmime_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut build_info: *mut Mailmime, -) -> libc::c_int { - if !(*build_info).mm_parent.is_null() { - return mailmime_sub_write_driver(do_write, data, col, build_info); - } else { - return mailmime_part_write_driver(do_write, data, col, build_info); - }; -} -/* -static int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, - char * text, size_t size); - -static int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext, - char * text, size_t size); -*/ -unsafe fn mailmime_part_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut build_info: *mut Mailmime, -) -> libc::c_int { - let mut current_block: u64; - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut first: libc::c_int = 0; - let mut r: libc::c_int = 0; - let mut boundary: *mut libc::c_char = 0 as *mut libc::c_char; - let mut istext: libc::c_int = 0; - let mut res: libc::c_int = 0; - istext = 1i32; - boundary = 0 as *mut libc::c_char; - if !(*build_info).mm_content_type.is_null() { - if (*build_info).mm_type == MAILMIME_MULTIPLE as libc::c_int { - boundary = mailmime_extract_boundary((*build_info).mm_content_type); - if boundary.is_null() { - boundary = mailmime_generate_boundary(); - if boundary.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 13530634675565645571; - } else { - current_block = 13586036798005543211; - } - } else { - current_block = 13586036798005543211; - } - } else { - current_block = 13586036798005543211; - } - match current_block { - 13530634675565645571 => {} - _ => { - if (*(*(*build_info).mm_content_type).ct_type).tp_type - == MAILMIME_TYPE_DISCRETE_TYPE as libc::c_int - { - if (*(*(*(*build_info).mm_content_type).ct_type) - .tp_data - .tp_discrete_type) - .dt_type - != MAILMIME_DISCRETE_TYPE_TEXT as libc::c_int - { - istext = 0i32 - } - } - current_block = 8457315219000651999; - } - } - } else { - current_block = 8457315219000651999; - } - match current_block { - 8457315219000651999 => { - match (*build_info).mm_type { - 1 => { - /* 1-part body */ - if !(*build_info).mm_data.mm_single.is_null() { - r = mailmime_data_write_driver( - do_write, - data, - col, - (*build_info).mm_data.mm_single, - istext, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else { - current_block = 7639320476250304355; - } - } else { - current_block = 7639320476250304355; - } - } - 2 => { - /* multi-part */ - /* preamble */ - if !(*build_info).mm_data.mm_multipart.mm_preamble.is_null() { - r = mailmime_data_write_driver( - do_write, - data, - col, - (*build_info).mm_data.mm_multipart.mm_preamble, - 1i32, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else { - current_block = 17500079516916021833; - } - } - } else { - current_block = 17500079516916021833; - } - match current_block { - 16754986508692159943 => {} - _ => { - first = 1i32; - cur = (*(*build_info).mm_data.mm_multipart.mm_mp_list).first; - loop { - if cur.is_null() { - current_block = 3546145585875536353; - break; - } - let mut subpart: *mut Mailmime = 0 as *mut Mailmime; - subpart = (*cur).data as *mut Mailmime; - if 0 == first { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - break; - } - } else { - first = 0i32 - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"--\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - break; - } else if boundary.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 16754986508692159943; - break; - } else { - r = mailimf_string_write_driver( - do_write, - data, - col, - boundary, - strlen(boundary), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - break; - } else { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - break; - } else { - r = mailmime_sub_write_driver( - do_write, data, col, subpart, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - break; - } else { - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - } - } - } - } - match current_block { - 16754986508692159943 => {} - _ => { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"--\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else if boundary.is_null() { - res = MAILIMF_ERROR_MEMORY as libc::c_int; - current_block = 16754986508692159943; - } else { - r = mailimf_string_write_driver( - do_write, - data, - col, - boundary, - strlen(boundary), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"--\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 - as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else if !(*build_info) - .mm_data - .mm_multipart - .mm_epilogue - .is_null() - { - r = mailmime_data_write_driver( - do_write, - data, - col, - (*build_info) - .mm_data - .mm_multipart - .mm_epilogue, - 1i32, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else { - current_block = 7639320476250304355; - } - } else { - current_block = 7639320476250304355; - } - } - } - } - } - } - } - } - } - } - 3 => { - if !(*build_info).mm_data.mm_message.mm_fields.is_null() { - r = mailimf_fields_write_driver( - do_write, - data, - col, - (*build_info).mm_data.mm_message.mm_fields, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else { - current_block = 2798392256336243897; - } - } else { - current_block = 2798392256336243897; - } - match current_block { - 16754986508692159943 => {} - _ => { - if !(*build_info).mm_mime_fields.is_null() { - let mut r_0: libc::c_int = 0; - let mut cur_0: *mut clistiter = 0 as *mut clistiter; - cur_0 = (*(*(*build_info).mm_mime_fields).fld_list).first; - loop { - if cur_0.is_null() { - current_block = 562309032768341766; - break; - } - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - field = (*cur_0).data as *mut mailmime_field; - if (*field).fld_type == MAILMIME_FIELD_VERSION as libc::c_int { - r_0 = - mailmime_field_write_driver(do_write, data, col, field); - if r_0 != MAILIMF_NO_ERROR as libc::c_int { - res = r_0; - current_block = 16754986508692159943; - break; - } - } - cur_0 = if !cur_0.is_null() { - (*cur_0).next - } else { - 0 as *mut clistcell - } - } - } else { - current_block = 562309032768341766; - } - match current_block { - 16754986508692159943 => {} - _ => { - /* encapsuled message */ - if !(*build_info).mm_data.mm_message.mm_msg_mime.is_null() { - r = mailmime_sub_write_driver( - do_write, - data, - col, - (*build_info).mm_data.mm_message.mm_msg_mime, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 16754986508692159943; - } else { - current_block = 7639320476250304355; - } - } else { - current_block = 7639320476250304355; - } - } - } - } - } - } - _ => { - current_block = 7639320476250304355; - } - } - match current_block { - 16754986508692159943 => { - free(boundary as *mut libc::c_void); - } - _ => { - free(boundary as *mut libc::c_void); - return MAILIMF_NO_ERROR as libc::c_int; - } - } - } - _ => {} - } - return res; -} -unsafe fn mailmime_sub_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut build_info: *mut Mailmime, -) -> libc::c_int { - let mut r: libc::c_int = 0; - if !(*build_info).mm_content_type.is_null() { - r = mailmime_content_write_driver(do_write, data, col, (*build_info).mm_content_type); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - if (*build_info).mm_type != MAILMIME_MESSAGE as libc::c_int { - if !(*build_info).mm_mime_fields.is_null() { - r = mailmime_fields_write_driver(do_write, data, col, (*build_info).mm_mime_fields); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - } else if !(*build_info).mm_mime_fields.is_null() { - let mut r_0: libc::c_int = 0; - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*(*(*build_info).mm_mime_fields).fld_list).first; - while !cur.is_null() { - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - field = (*cur).data as *mut mailmime_field; - if (*field).fld_type != MAILMIME_FIELD_VERSION as libc::c_int { - r_0 = mailmime_field_write_driver(do_write, data, col, field); - if r_0 != MAILIMF_NO_ERROR as libc::c_int { - return r_0; - } - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return mailmime_part_write_driver(do_write, data, col, build_info); -} - -pub unsafe fn mailmime_data_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut mime_data: *mut mailmime_data, - mut istext: libc::c_int, -) -> libc::c_int { - let mut current_block: u64 = 0; - let mut fd: libc::c_int = 0; - let mut r: libc::c_int = 0; - let mut text: *mut libc::c_char = 0 as *mut libc::c_char; - - let mut res: libc::c_int = 0; - match (*mime_data).dt_type { - 0 => { - if 0 != (*mime_data).dt_encoded { - r = mailimf_string_write_driver( - do_write, - data, - col, - (*mime_data).dt_data.dt_text.dt_data, - (*mime_data).dt_data.dt_text.dt_length, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } else { - r = mailmime_text_content_write_driver( - do_write, - data, - col, - (*mime_data).dt_encoding, - istext, - (*mime_data).dt_data.dt_text.dt_data, - (*mime_data).dt_data.dt_text.dt_length, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - } - 1 => { - let filename = CStr::from_ptr((*mime_data).dt_data.dt_filename) - .to_string_lossy() - .into_owned(); - if let Ok(file) = std::fs::File::open(filename) { - if let Ok(mut text) = memmap::MmapOptions::new().map_copy(&file) { - if 0 != (*mime_data).dt_encoded { - r = mailimf_string_write_driver( - do_write, - data, - col, - text.as_ptr() as *const _, - text.len(), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 1055471768422549395; - } else { - current_block = 1538046216550696469; - } - } else { - r = mailmime_text_content_write_driver( - do_write, - data, - col, - (*mime_data).dt_encoding, - istext, - text.as_ptr() as *const _, - text.len(), - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - res = r; - current_block = 1055471768422549395; - } else { - current_block = 1538046216550696469; - } - } - match current_block { - 1055471768422549395 => { - current_block = 5221028069996397600; - } - _ => { - current_block = 9853141518545631134; - } - } - } else { - res = MAILIMF_ERROR_FILE as libc::c_int; - current_block = 5221028069996397600; - } - match current_block { - 5221028069996397600 => {} - _ => { - close(fd); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - current_block = 10891380440665537214; - } - } - } else { - res = MAILIMF_ERROR_FILE as libc::c_int; - current_block = 10275258781883576179; - } - match current_block { - 10891380440665537214 => {} - _ => { - current_block = 10275258781883576179; - } - } - match current_block { - 10891380440665537214 => {} - _ => return res, - } - } - _ => {} - } - return MAILIMF_NO_ERROR as libc::c_int; -} -/* ****************************************************************** */ -/* message */ -/* -static int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, - struct mailmime_data * data, - int is_text); -*/ -unsafe fn mailmime_text_content_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut encoding: libc::c_int, - mut istext: libc::c_int, - mut text: *const libc::c_char, - mut size: size_t, -) -> libc::c_int { - match encoding { - 4 => { - return mailmime_quoted_printable_write_driver(do_write, data, col, istext, text, size) - } - 5 => return mailmime_base64_write_driver(do_write, data, col, text, size), - 1 | 2 | 3 | _ => return mailimf_string_write_driver(do_write, data, col, text, size), - }; -} - -pub unsafe fn mailmime_base64_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut text: *const libc::c_char, - mut size: size_t, -) -> libc::c_int { - let mut a: libc::c_int = 0; - let mut b: libc::c_int = 0; - let mut c: libc::c_int = 0; - let mut remains: size_t = 0; - let mut p: *const libc::c_char = 0 as *const libc::c_char; - let mut count: size_t = 0; - let mut ogroup: [libc::c_char; 4] = [0; 4]; - let mut r: libc::c_int = 0; - remains = size; - p = text; - while remains > 0i32 as libc::size_t { - match remains { - 1 => { - a = *p.offset(0isize) as libc::c_uchar as libc::c_int; - b = 0i32; - c = 0i32; - count = 1i32 as size_t - } - 2 => { - a = *p.offset(0isize) as libc::c_uchar as libc::c_int; - b = *p.offset(1isize) as libc::c_uchar as libc::c_int; - c = 0i32; - count = 2i32 as size_t - } - _ => { - a = *p.offset(0isize) as libc::c_uchar as libc::c_int; - b = *p.offset(1isize) as libc::c_uchar as libc::c_int; - c = *p.offset(2isize) as libc::c_uchar as libc::c_int; - count = 3i32 as size_t - } - } - ogroup[0usize] = base64_encoding[(a >> 2i32) as usize]; - ogroup[1usize] = base64_encoding[((a & 3i32) << 4i32 | b >> 4i32) as usize]; - ogroup[2usize] = base64_encoding[((b & 0xfi32) << 2i32 | c >> 6i32) as usize]; - ogroup[3usize] = base64_encoding[(c & 0x3fi32) as usize]; - match count { - 1 => { - ogroup[2usize] = '=' as i32 as libc::c_char; - ogroup[3usize] = '=' as i32 as libc::c_char - } - 2 => ogroup[3usize] = '=' as i32 as libc::c_char, - _ => {} - } - if *col + 4i32 > 76i32 { - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - r = mailimf_string_write_driver(do_write, data, col, ogroup.as_mut_ptr(), 4i32 as size_t); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - remains = (remains as libc::size_t).wrapping_sub(count) as size_t as size_t; - p = p.offset(count as isize) - } - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - return MAILIMF_NO_ERROR as libc::c_int; -} -static mut base64_encoding: [libc::c_char; 65] = [ - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 0, -]; - -pub unsafe fn mailmime_quoted_printable_write_driver( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut istext: libc::c_int, - mut text: *const libc::c_char, - mut size: size_t, -) -> libc::c_int { - let mut i: size_t = 0; - let mut start: *const libc::c_char = 0 as *const libc::c_char; - let mut len: size_t = 0; - let mut r: libc::c_int = 0; - let mut state: libc::c_int = 0; - start = text; - len = 0i32 as size_t; - state = STATE_INIT as libc::c_int; - i = 0i32 as size_t; - while i < size { - let mut ch: libc::c_uchar = 0; - if (*col as libc::size_t).wrapping_add(len) > 72i32 as libc::size_t { - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - start = text.offset(i as isize); - r = mailimf_string_write_driver( - do_write, - data, - col, - b"=\r\n\x00" as *const u8 as *const libc::c_char, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - } - ch = *text.offset(i as isize) as libc::c_uchar; - match state { - 0 => { - let mut current_block_50: u64; - match ch as libc::c_int { - 32 | 9 => { - state = STATE_SPACE as libc::c_int; - len = len.wrapping_add(1); - i = i.wrapping_add(1); - current_block_50 = 3546145585875536353; - } - 13 => { - state = STATE_CR as libc::c_int; - i = i.wrapping_add(1); - current_block_50 = 3546145585875536353; - } - 33 | 34 | 35 | 36 | 64 | 91 | 92 | 93 | 94 | 96 | 123 | 124 | 125 | 126 - | 61 | 63 | 95 => { - /* there is no more 'From' at the beginning of a line */ - current_block_50 = 177397332496894159; - } - 70 => { - current_block_50 = 177397332496894159; - } - _ => { - if 0 != istext && ch as libc::c_int == '\n' as i32 { - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - start = text.offset(i as isize).offset(1isize); - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - i = i.wrapping_add(1) - } else if ch as libc::c_int >= 33i32 && ch as libc::c_int <= 60i32 - || ch as libc::c_int >= 62i32 && ch as libc::c_int <= 126i32 - { - len = len.wrapping_add(1); - i = i.wrapping_add(1) - } else { - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - start = text.offset(i as isize).offset(1isize); - - let raw = format!("={:02X}", (ch as libc::c_int)); - let raw_c = std::ffi::CString::new(raw).unwrap_or_default(); - let mut hexstr = strdup(raw_c.as_ptr()); - r = mailimf_string_write_driver( - do_write, - data, - col, - hexstr, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - i = i.wrapping_add(1) - } - current_block_50 = 3546145585875536353; - } - } - match current_block_50 { - 177397332496894159 => { - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - start = text.offset(i as isize).offset(1isize); - let raw = format!("={:02X}", ch as libc::c_int); - let raw_c = std::ffi::CString::new(raw).unwrap_or_default(); - let mut hexstr = strdup(raw_c.as_ptr()); - r = mailimf_string_write_driver( - do_write, - data, - col, - hexstr, - 3i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - i = i.wrapping_add(1) - } - _ => {} - } - } - 1 => match ch as libc::c_int { - 10 => { - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - start = text.offset(i as isize).offset(1isize); - r = mailimf_string_write_driver( - do_write, - data, - col, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32 as size_t, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - i = i.wrapping_add(1); - state = STATE_INIT as libc::c_int - } - _ => { - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - start = text.offset(i as isize); - let raw = format!("={:02X}", b'\r' as i32); - let raw_c = std::ffi::CString::new(raw).unwrap_or_default(); - let mut hexstr = strdup(raw_c.as_ptr()); - r = mailimf_string_write_driver(do_write, data, col, hexstr, 3i32 as size_t); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - state = STATE_INIT as libc::c_int - } - }, - 2 => match ch as libc::c_int { - 13 => { - state = STATE_SPACE_CR as libc::c_int; - i = i.wrapping_add(1) - } - 10 => { - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - start = text.offset(i as isize).offset(1isize); - let raw = format!( - "={:02X}\r\n", - *text.offset(i.wrapping_sub(1i32 as libc::size_t) as isize) as libc::c_int - ); - let raw_c = std::ffi::CString::new(raw).unwrap_or_default(); - let mut hexstr = strdup(raw_c.as_ptr()); - - r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr)); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - state = STATE_INIT as libc::c_int; - i = i.wrapping_add(1) - } - 32 | 9 => { - len = len.wrapping_add(1); - i = i.wrapping_add(1) - } - _ => state = STATE_INIT as libc::c_int, - }, - 3 => match ch as libc::c_int { - 10 => { - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - start = text.offset(i as isize).offset(1isize); - let raw = format!( - "={:02X}\r\n", - *text.offset(i.wrapping_sub(2i32 as libc::size_t) as isize) as libc::c_int - ); - let raw_c = std::ffi::CString::new(raw).unwrap_or_default(); - let mut hexstr = strdup(raw_c.as_ptr()); - - r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr)); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - state = STATE_INIT as libc::c_int; - i = i.wrapping_add(1) - } - _ => { - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - start = text.offset(i as isize).offset(1isize); - let raw = format!( - "{}={:02X}\r\n", - (*text.offset(i.wrapping_sub(2i32 as libc::size_t) as isize) as u8 as char), - b'\r' as i32 - ); - let raw_c = std::ffi::CString::new(raw).unwrap_or_default(); - let mut hexstr = strdup(raw_c.as_ptr()); - - r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr)); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - state = STATE_INIT as libc::c_int - } - }, - _ => {} - } - } - r = write_remaining(do_write, data, col, &mut start, &mut len); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - return MAILIMF_NO_ERROR as libc::c_int; -} -#[inline] -unsafe fn write_remaining( - mut do_write: Option< - unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int, - >, - mut data: *mut libc::c_void, - mut col: *mut libc::c_int, - mut pstart: *mut *const libc::c_char, - mut plen: *mut size_t, -) -> libc::c_int { - let mut r: libc::c_int = 0; - if *plen > 0i32 as libc::size_t { - r = mailimf_string_write_driver(do_write, data, col, *pstart, *plen); - if r != MAILIMF_NO_ERROR as libc::c_int { - return r; - } - *plen = 0i32 as size_t - } - return MAILIMF_NO_ERROR as libc::c_int; -} diff --git a/mmime/src/mailmime/write_mem.rs b/mmime/src/mailmime/write_mem.rs deleted file mode 100644 index 1cf0bc58d..000000000 --- a/mmime/src/mailmime/write_mem.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::mailmime::types::*; -use crate::mailmime::write_generic::*; -use crate::mmapstring::*; -use crate::other::*; - -unsafe fn do_write( - mut data: *mut libc::c_void, - mut str: *const libc::c_char, - mut length: size_t, -) -> libc::c_int { - let mut f: *mut MMAPString = 0 as *mut MMAPString; - f = data as *mut MMAPString; - if mmap_string_append_len(f, str, length).is_null() { - return 0i32; - } else { - return length as libc::c_int; - }; -} - -pub unsafe fn mailmime_content_write_mem( - mut f: *mut MMAPString, - mut col: *mut libc::c_int, - mut content: *mut mailmime_content, -) -> libc::c_int { - return mailmime_content_write_driver(Some(do_write), f as *mut libc::c_void, col, content); -} - -pub unsafe fn mailmime_content_type_write_mem( - mut f: *mut MMAPString, - mut col: *mut libc::c_int, - mut content: *mut mailmime_content, -) -> libc::c_int { - return mailmime_content_type_write_driver( - Some(do_write), - f as *mut libc::c_void, - col, - content, - ); -} - -pub unsafe fn mailmime_write_mem( - mut f: *mut MMAPString, - mut col: *mut libc::c_int, - mut build_info: *mut Mailmime, -) -> libc::c_int { - return mailmime_write_driver(Some(do_write), f as *mut libc::c_void, col, build_info); -} - -pub unsafe fn mailmime_quoted_printable_write_mem( - mut f: *mut MMAPString, - mut col: *mut libc::c_int, - mut istext: libc::c_int, - mut text: *const libc::c_char, - mut size: size_t, -) -> libc::c_int { - return mailmime_quoted_printable_write_driver( - Some(do_write), - f as *mut libc::c_void, - col, - istext, - text, - size, - ); -} - -pub unsafe fn mailmime_base64_write_mem( - mut f: *mut MMAPString, - mut col: *mut libc::c_int, - mut text: *const libc::c_char, - mut size: size_t, -) -> libc::c_int { - return mailmime_base64_write_driver(Some(do_write), f as *mut libc::c_void, col, text, size); -} - -pub unsafe fn mailmime_data_write_mem( - mut f: *mut MMAPString, - mut col: *mut libc::c_int, - mut data: *mut mailmime_data, - mut istext: libc::c_int, -) -> libc::c_int { - return mailmime_data_write_driver(Some(do_write), f as *mut libc::c_void, col, data, istext); -} diff --git a/mmime/src/mmapstring.rs b/mmime/src/mmapstring.rs deleted file mode 100644 index a3749ac4c..000000000 --- a/mmime/src/mmapstring.rs +++ /dev/null @@ -1,397 +0,0 @@ -use std::sync::Mutex; - -use lazy_static::lazy_static; -use libc; - -use crate::chash::*; -use crate::other::*; - -lazy_static! { - static ref mmapstring_lock: Mutex<()> = Mutex::new(()); -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct MMAPString { - pub str_0: *mut libc::c_char, - pub len: size_t, - pub allocated_len: size_t, - pub fd: libc::c_int, - pub mmapped_size: size_t, -} - -pub const TMPDIR: &'static str = "/tmp"; - -pub unsafe fn mmap_string_new(mut init: *const libc::c_char) -> *mut MMAPString { - let mut string: *mut MMAPString = 0 as *mut MMAPString; - string = mmap_string_sized_new(if !init.is_null() { - strlen(init).wrapping_add(2i32 as libc::size_t) - } else { - 2i32 as libc::size_t - }); - if string.is_null() { - return 0 as *mut MMAPString; - } - if !init.is_null() { - mmap_string_append(string, init); - } - return string; -} - -pub unsafe fn mmap_string_append( - mut string: *mut MMAPString, - mut val: *const libc::c_char, -) -> *mut MMAPString { - return mmap_string_insert_len(string, (*string).len, val, strlen(val)); -} - -pub unsafe fn mmap_string_insert_len( - mut string: *mut MMAPString, - mut pos: size_t, - mut val: *const libc::c_char, - mut len: size_t, -) -> *mut MMAPString { - if mmap_string_maybe_expand(string, len).is_null() { - return 0 as *mut MMAPString; - } - if pos < (*string).len { - memmove( - (*string).str_0.offset(pos as isize).offset(len as isize) as *mut libc::c_void, - (*string).str_0.offset(pos as isize) as *const libc::c_void, - (*string).len.wrapping_sub(pos), - ); - } - memmove( - (*string).str_0.offset(pos as isize) as *mut libc::c_void, - val as *const libc::c_void, - len, - ); - (*string).len = ((*string).len as libc::size_t).wrapping_add(len) as size_t as size_t; - *(*string).str_0.offset((*string).len as isize) = 0i32 as libc::c_char; - return string; -} -unsafe fn mmap_string_maybe_expand( - mut string: *mut MMAPString, - mut len: size_t, -) -> *mut MMAPString { - if (*string).len.wrapping_add(len) >= (*string).allocated_len { - let mut old_size: size_t = 0; - let mut newstring: *mut MMAPString = 0 as *mut MMAPString; - old_size = (*string).allocated_len; - (*string).allocated_len = nearest_power( - 1i32 as size_t, - (*string) - .len - .wrapping_add(len) - .wrapping_add(1i32 as libc::size_t), - ); - newstring = mmap_string_realloc_memory(string); - if newstring.is_null() { - (*string).allocated_len = old_size - } - return newstring; - } - return string; -} -/* Strings. - */ -/* SEB */ -unsafe fn mmap_string_realloc_memory(mut string: *mut MMAPString) -> *mut MMAPString { - let mut tmp: *mut libc::c_char = 0 as *mut libc::c_char; - tmp = realloc( - (*string).str_0 as *mut libc::c_void, - (*string).allocated_len, - ) as *mut libc::c_char; - if tmp.is_null() { - string = 0 as *mut MMAPString - } else { - (*string).str_0 = tmp - } - return string; -} -/* MMAPString */ -#[inline] -unsafe fn nearest_power(mut base: size_t, mut num: size_t) -> size_t { - if num > (-1i32 as size_t).wrapping_div(2i32 as libc::size_t) { - return -1i32 as size_t; - } else { - let mut n: size_t = base; - while n < num { - n <<= 1i32 - } - return n; - }; -} - -pub unsafe fn mmap_string_sized_new(mut dfl_size: size_t) -> *mut MMAPString { - let mut string: *mut MMAPString = 0 as *mut MMAPString; - string = malloc(::std::mem::size_of::() as libc::size_t) as *mut MMAPString; - if string.is_null() { - return 0 as *mut MMAPString; - } - (*string).allocated_len = 0i32 as size_t; - (*string).len = 0i32 as size_t; - (*string).str_0 = 0 as *mut libc::c_char; - (*string).fd = -1i32; - (*string).mmapped_size = 0i32 as size_t; - if mmap_string_maybe_expand( - string, - if dfl_size > 2i32 as libc::size_t { - dfl_size - } else { - 2i32 as libc::size_t - }, - ) - .is_null() - { - free(string as *mut libc::c_void); - return 0 as *mut MMAPString; - } - *(*string).str_0.offset(0isize) = 0i32 as libc::c_char; - return string; -} - -pub unsafe fn mmap_string_new_len( - mut init: *const libc::c_char, - mut len: size_t, -) -> *mut MMAPString { - let mut string: *mut MMAPString = 0 as *mut MMAPString; - if len <= 0i32 as libc::size_t { - return mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - } else { - string = mmap_string_sized_new(len); - if string.is_null() { - return string; - } - if !init.is_null() { - mmap_string_append_len(string, init, len); - } - return string; - }; -} - -pub unsafe fn mmap_string_append_len( - mut string: *mut MMAPString, - mut val: *const libc::c_char, - mut len: size_t, -) -> *mut MMAPString { - return mmap_string_insert_len(string, (*string).len, val, len); -} - -pub unsafe fn mmap_string_free(mut string: *mut MMAPString) { - if string.is_null() { - return; - } - free((*string).str_0 as *mut libc::c_void); - free(string as *mut libc::c_void); -} - -pub unsafe fn mmap_string_assign( - mut string: *mut MMAPString, - mut rval: *const libc::c_char, -) -> *mut MMAPString { - mmap_string_truncate(string, 0i32 as size_t); - if mmap_string_append(string, rval).is_null() { - return 0 as *mut MMAPString; - } - return string; -} - -pub unsafe fn mmap_string_truncate( - mut string: *mut MMAPString, - mut len: size_t, -) -> *mut MMAPString { - (*string).len = if len < (*string).len { - len - } else { - (*string).len - }; - *(*string).str_0.offset((*string).len as isize) = 0i32 as libc::c_char; - return string; -} - -pub unsafe fn mmap_string_set_size( - mut string: *mut MMAPString, - mut len: size_t, -) -> *mut MMAPString { - if len >= (*string).allocated_len { - if mmap_string_maybe_expand(string, len.wrapping_sub((*string).len)).is_null() { - return 0 as *mut MMAPString; - } - } - (*string).len = len; - *(*string).str_0.offset(len as isize) = 0i32 as libc::c_char; - return string; -} - -pub unsafe fn mmap_string_append_c( - mut string: *mut MMAPString, - mut c: libc::c_char, -) -> *mut MMAPString { - return mmap_string_insert_c(string, (*string).len, c); -} - -pub unsafe fn mmap_string_insert_c( - mut string: *mut MMAPString, - mut pos: size_t, - mut c: libc::c_char, -) -> *mut MMAPString { - if mmap_string_maybe_expand(string, 1i32 as size_t).is_null() { - return 0 as *mut MMAPString; - } - if pos < (*string).len { - memmove( - (*string).str_0.offset(pos as isize).offset(1isize) as *mut libc::c_void, - (*string).str_0.offset(pos as isize) as *const libc::c_void, - (*string).len.wrapping_sub(pos), - ); - } - *(*string).str_0.offset(pos as isize) = c; - (*string).len = - ((*string).len as libc::size_t).wrapping_add(1i32 as libc::size_t) as size_t as size_t; - *(*string).str_0.offset((*string).len as isize) = 0i32 as libc::c_char; - return string; -} - -pub unsafe fn mmap_string_prepend( - mut string: *mut MMAPString, - mut val: *const libc::c_char, -) -> *mut MMAPString { - return mmap_string_insert_len(string, 0i32 as size_t, val, strlen(val)); -} - -pub unsafe fn mmap_string_prepend_c( - mut string: *mut MMAPString, - mut c: libc::c_char, -) -> *mut MMAPString { - return mmap_string_insert_c(string, 0i32 as size_t, c); -} - -pub unsafe fn mmap_string_prepend_len( - mut string: *mut MMAPString, - mut val: *const libc::c_char, - mut len: size_t, -) -> *mut MMAPString { - return mmap_string_insert_len(string, 0i32 as size_t, val, len); -} - -pub unsafe fn mmap_string_insert( - mut string: *mut MMAPString, - mut pos: size_t, - mut val: *const libc::c_char, -) -> *mut MMAPString { - return mmap_string_insert_len(string, pos, val, strlen(val)); -} - -pub unsafe fn mmap_string_erase( - mut string: *mut MMAPString, - mut pos: size_t, - mut len: size_t, -) -> *mut MMAPString { - if pos.wrapping_add(len) < (*string).len { - memmove( - (*string).str_0.offset(pos as isize) as *mut libc::c_void, - (*string).str_0.offset(pos as isize).offset(len as isize) as *const libc::c_void, - (*string).len.wrapping_sub(pos.wrapping_add(len)), - ); - } - (*string).len = ((*string).len as libc::size_t).wrapping_sub(len) as size_t as size_t; - *(*string).str_0.offset((*string).len as isize) = 0i32 as libc::c_char; - return string; -} - -pub unsafe fn mmap_string_set_ceil(mut ceil: size_t) { - mmap_string_ceil = ceil; -} -static mut mmap_string_ceil: size_t = (8i32 * 1024i32 * 1024i32) as size_t; - -pub unsafe fn mmap_string_ref(mut string: *mut MMAPString) -> libc::c_int { - let mut ht: *mut chash = 0 as *mut chash; - let mut r: libc::c_int = 0; - let mut key: chashdatum = chashdatum { - data: 0 as *mut libc::c_void, - len: 0, - }; - let mut data: chashdatum = chashdatum { - data: 0 as *mut libc::c_void, - len: 0, - }; - mmapstring_lock.lock().unwrap(); - if mmapstring_hashtable.is_null() { - mmapstring_hashtable_init(); - } - ht = mmapstring_hashtable; - if ht.is_null() { - return -1i32; - } - key.data = &mut (*string).str_0 as *mut *mut libc::c_char as *mut libc::c_void; - key.len = ::std::mem::size_of::<*mut libc::c_char>() as libc::size_t as libc::c_uint; - data.data = string as *mut libc::c_void; - data.len = 0i32 as libc::c_uint; - r = chash_set( - mmapstring_hashtable, - &mut key, - &mut data, - 0 as *mut chashdatum, - ); - - if r < 0i32 { - return r; - } - return 0i32; -} - -static mut mmapstring_hashtable: *mut chash = 0 as *const chash as *mut chash; -unsafe fn mmapstring_hashtable_init() { - mmapstring_hashtable = chash_new(13i32 as libc::c_uint, 1i32); -} - -pub unsafe fn mmap_string_unref(mut str: *mut libc::c_char) -> libc::c_int { - let mut string: *mut MMAPString = 0 as *mut MMAPString; - let mut ht: *mut chash = 0 as *mut chash; - let mut key: chashdatum = chashdatum { - data: 0 as *mut libc::c_void, - len: 0, - }; - let mut data: chashdatum = chashdatum { - data: 0 as *mut libc::c_void, - len: 0, - }; - let mut r: libc::c_int = 0; - if str.is_null() { - return -1i32; - } - mmapstring_lock.lock().unwrap(); - ht = mmapstring_hashtable; - if ht.is_null() { - return -1i32; - } - key.data = &mut str as *mut *mut libc::c_char as *mut libc::c_void; - key.len = ::std::mem::size_of::<*mut libc::c_char>() as libc::size_t as libc::c_uint; - r = chash_get(ht, &mut key, &mut data); - if r < 0i32 { - string = 0 as *mut MMAPString - } else { - string = data.data as *mut MMAPString - } - if !string.is_null() { - chash_delete(ht, &mut key, 0 as *mut chashdatum); - if chash_count(ht) == 0i32 as libc::c_uint { - chash_free(ht); - mmapstring_hashtable = 0 as *mut chash - } - } - if !string.is_null() { - mmap_string_free(string); - return 0i32; - } else { - return -1i32; - }; -} -#[inline] -unsafe fn chash_count(mut hash: *mut chash) -> libc::c_uint { - return (*hash).count; -} - -pub unsafe fn mmapstring_init_lock() {} -pub unsafe fn mmapstring_uninit_lock() {} diff --git a/mmime/src/other.rs b/mmime/src/other.rs deleted file mode 100644 index 08d9162a5..000000000 --- a/mmime/src/other.rs +++ /dev/null @@ -1,1728 +0,0 @@ -use chrono::{Datelike, Local, TimeZone, Timelike}; - -use crate::clist::*; -use crate::mailimf::types::*; -use crate::mailimf::types_helper::*; -use crate::mailmime::types::*; -use crate::mailmime::types_helper::*; - -pub(crate) use libc::{ - calloc, close, free, isalpha, isdigit, malloc, memcmp, memcpy, memmove, memset, realloc, - strcpy, strlen, strncmp, strncpy, strnlen, -}; - -pub(crate) unsafe fn strcasecmp(s1: *const libc::c_char, s2: *const libc::c_char) -> libc::c_int { - if s1.is_null() || s2.is_null() { - return 1; - } - - let s1 = std::ffi::CStr::from_ptr(s1) - .to_string_lossy() - .to_lowercase(); - let s2 = std::ffi::CStr::from_ptr(s2) - .to_string_lossy() - .to_lowercase(); - if s1 == s2 { - 0 - } else { - 1 - } -} - -pub(crate) unsafe fn strncasecmp( - s1: *const libc::c_char, - s2: *const libc::c_char, - n: libc::size_t, -) -> libc::c_int { - if s1.is_null() || s2.is_null() { - return 1; - } - - // s1 and s2 might not be null terminated. - - let s1_slice = - std::slice::from_raw_parts(s1 as *const u8, strnlen(s1 as *const libc::c_char, n)); - let s2_slice = - std::slice::from_raw_parts(s2 as *const u8, strnlen(s2 as *const libc::c_char, n)); - - let s1 = std::ffi::CStr::from_bytes_with_nul_unchecked(s1_slice) - .to_string_lossy() - .to_lowercase(); - let s2 = std::ffi::CStr::from_bytes_with_nul_unchecked(s2_slice) - .to_string_lossy() - .to_lowercase(); - - if s1 == s2 { - 0 - } else { - 1 - } -} - -pub(crate) unsafe fn strdup(s: *const libc::c_char) -> *mut libc::c_char { - let slen = libc::strlen(s); - let result = libc::malloc(slen + 1); - if result.is_null() { - return std::ptr::null_mut(); - } - - libc::memcpy(result, s as *const _, slen + 1); - result as *mut _ -} - -pub(crate) type size_t = libc::size_t; -pub(crate) type uint32_t = libc::c_uint; - -pub const MAIL_ERROR_SSL: libc::c_uint = 58; -pub const MAIL_ERROR_FOLDER: libc::c_uint = 57; -pub const MAIL_ERROR_UNABLE: libc::c_uint = 56; -pub const MAIL_ERROR_SYSTEM: libc::c_uint = 55; -pub const MAIL_ERROR_COMMAND: libc::c_uint = 54; -pub const MAIL_ERROR_SEND: libc::c_uint = 53; -pub const MAIL_ERROR_CHAR_ENCODING_FAILED: libc::c_uint = 52; -pub const MAIL_ERROR_SUBJECT_NOT_FOUND: libc::c_uint = 51; -/* 50 */ -pub const MAIL_ERROR_PROGRAM_ERROR: libc::c_uint = 50; -pub const MAIL_ERROR_NO_PERMISSION: libc::c_uint = 49; -pub const MAIL_ERROR_COMMAND_NOT_SUPPORTED: libc::c_uint = 48; -pub const MAIL_ERROR_NO_APOP: libc::c_uint = 47; -pub const MAIL_ERROR_READONLY: libc::c_uint = 46; -pub const MAIL_ERROR_FATAL: libc::c_uint = 45; -pub const MAIL_ERROR_CLOSE: libc::c_uint = 44; -pub const MAIL_ERROR_CAPABILITY: libc::c_uint = 43; -pub const MAIL_ERROR_PROTOCOL: libc::c_uint = 42; -/* misc errors */ -pub const MAIL_ERROR_MISC: libc::c_uint = 41; -/* 40 */ -pub const MAIL_ERROR_EXPUNGE: libc::c_uint = 40; -pub const MAIL_ERROR_NO_TLS: libc::c_uint = 39; -pub const MAIL_ERROR_CACHE_MISS: libc::c_uint = 38; -pub const MAIL_ERROR_STARTTLS: libc::c_uint = 37; -pub const MAIL_ERROR_MOVE: libc::c_uint = 36; -pub const MAIL_ERROR_FOLDER_NOT_FOUND: libc::c_uint = 35; -pub const MAIL_ERROR_REMOVE: libc::c_uint = 34; -pub const MAIL_ERROR_PART_NOT_FOUND: libc::c_uint = 33; -pub const MAIL_ERROR_INVAL: libc::c_uint = 32; -pub const MAIL_ERROR_PARSE: libc::c_uint = 31; -/* 30 */ -pub const MAIL_ERROR_MSG_NOT_FOUND: libc::c_uint = 30; -pub const MAIL_ERROR_DISKSPACE: libc::c_uint = 29; -pub const MAIL_ERROR_SEARCH: libc::c_uint = 28; -pub const MAIL_ERROR_STORE: libc::c_uint = 27; -pub const MAIL_ERROR_FETCH: libc::c_uint = 26; -pub const MAIL_ERROR_COPY: libc::c_uint = 25; -pub const MAIL_ERROR_APPEND: libc::c_uint = 24; -pub const MAIL_ERROR_LSUB: libc::c_uint = 23; -pub const MAIL_ERROR_LIST: libc::c_uint = 22; -pub const MAIL_ERROR_UNSUBSCRIBE: libc::c_uint = 21; -/* 20 */ -pub const MAIL_ERROR_SUBSCRIBE: libc::c_uint = 20; -pub const MAIL_ERROR_STATUS: libc::c_uint = 19; -pub const MAIL_ERROR_MEMORY: libc::c_uint = 18; -pub const MAIL_ERROR_SELECT: libc::c_uint = 17; -pub const MAIL_ERROR_EXAMINE: libc::c_uint = 16; -pub const MAIL_ERROR_CHECK: libc::c_uint = 15; -pub const MAIL_ERROR_RENAME: libc::c_uint = 14; -pub const MAIL_ERROR_NOOP: libc::c_uint = 13; -pub const MAIL_ERROR_LOGOUT: libc::c_uint = 12; -pub const MAIL_ERROR_DELETE: libc::c_uint = 11; -/* 10 */ -pub const MAIL_ERROR_CREATE: libc::c_uint = 10; -pub const MAIL_ERROR_LOGIN: libc::c_uint = 9; -pub const MAIL_ERROR_STREAM: libc::c_uint = 8; -pub const MAIL_ERROR_FILE: libc::c_uint = 7; -pub const MAIL_ERROR_BAD_STATE: libc::c_uint = 6; -pub const MAIL_ERROR_CONNECT: libc::c_uint = 5; -pub const MAIL_ERROR_UNKNOWN: libc::c_uint = 4; -pub const MAIL_ERROR_NOT_IMPLEMENTED: libc::c_uint = 3; -pub const MAIL_NO_ERROR_NON_AUTHENTICATED: libc::c_uint = 2; -pub const MAIL_NO_ERROR_AUTHENTICATED: libc::c_uint = 1; -pub const MAIL_NO_ERROR: libc::c_uint = 0; - -pub const MAILIMF_ERROR_FILE: libc::c_uint = 4; -pub const MAILIMF_ERROR_INVAL: libc::c_uint = 3; -pub const MAILIMF_ERROR_MEMORY: libc::c_uint = 2; -pub const MAILIMF_ERROR_PARSE: libc::c_uint = 1; -pub const MAILIMF_NO_ERROR: libc::c_uint = 0; - -pub unsafe fn mailprivacy_prepare_mime(mut mime: *mut Mailmime) { - let mut cur: *mut clistiter = 0 as *mut clistiter; - match (*mime).mm_type { - 1 => { - if !(*mime).mm_data.mm_single.is_null() { - prepare_mime_single(mime); - } - } - 2 => { - cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; - while !cur.is_null() { - let mut child: *mut Mailmime = 0 as *mut Mailmime; - child = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut Mailmime; - mailprivacy_prepare_mime(child); - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - } - 3 => { - if !(*mime).mm_data.mm_message.mm_msg_mime.is_null() { - mailprivacy_prepare_mime((*mime).mm_data.mm_message.mm_msg_mime); - } - } - _ => {} - }; -} - -unsafe fn prepare_mime_single(mut mime: *mut Mailmime) { - let mut single_fields: mailmime_single_fields = mailmime_single_fields { - fld_content: 0 as *mut mailmime_content, - fld_content_charset: 0 as *mut libc::c_char, - fld_content_boundary: 0 as *mut libc::c_char, - fld_content_name: 0 as *mut libc::c_char, - fld_encoding: 0 as *mut mailmime_mechanism, - fld_id: 0 as *mut libc::c_char, - fld_description: 0 as *mut libc::c_char, - fld_version: 0, - fld_disposition: 0 as *mut mailmime_disposition, - fld_disposition_filename: 0 as *mut libc::c_char, - fld_disposition_creation_date: 0 as *mut libc::c_char, - fld_disposition_modification_date: 0 as *mut libc::c_char, - fld_disposition_read_date: 0 as *mut libc::c_char, - fld_disposition_size: 0, - fld_language: 0 as *mut mailmime_language, - fld_location: 0 as *mut libc::c_char, - }; - let mut encoding: libc::c_int = 0; - let mut r: libc::c_int = 0; - if !(*mime).mm_mime_fields.is_null() { - mailmime_single_fields_init( - &mut single_fields, - (*mime).mm_mime_fields, - (*mime).mm_content_type, - ); - if !single_fields.fld_encoding.is_null() { - encoding = (*single_fields.fld_encoding).enc_type; - match encoding { - 2 | 1 | 3 => { - (*single_fields.fld_encoding).enc_type = - MAILMIME_MECHANISM_QUOTED_PRINTABLE as libc::c_int - } - _ => {} - } - } else { - let mut mechanism: *mut mailmime_mechanism = 0 as *mut mailmime_mechanism; - let mut field: *mut mailmime_field = 0 as *mut mailmime_field; - mechanism = mailmime_mechanism_new( - MAILMIME_MECHANISM_QUOTED_PRINTABLE as libc::c_int, - 0 as *mut libc::c_char, - ); - if mechanism.is_null() { - return; - } - field = mailmime_field_new( - MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int, - 0 as *mut mailmime_content, - mechanism, - 0 as *mut libc::c_char, - 0 as *mut libc::c_char, - 0i32 as uint32_t, - 0 as *mut mailmime_disposition, - 0 as *mut mailmime_language, - 0 as *mut libc::c_char, - ); - if field.is_null() { - mailmime_mechanism_free(mechanism); - return; - } - r = clist_insert_after( - (*(*mime).mm_mime_fields).fld_list, - (*(*(*mime).mm_mime_fields).fld_list).last, - field as *mut libc::c_void, - ); - if r < 0i32 { - mailmime_field_free(field); - return; - } - } - } - if (*mime).mm_type == MAILMIME_SINGLE as libc::c_int { - match (*(*mime).mm_data.mm_single).dt_encoding { - 2 | 1 | 3 => { - (*(*mime).mm_data.mm_single).dt_encoding = - MAILMIME_MECHANISM_QUOTED_PRINTABLE as libc::c_int; - (*(*mime).mm_data.mm_single).dt_encoded = 0i32 - } - _ => {} - } - }; -} - -pub unsafe fn mailmime_substitute( - mut old_mime: *mut Mailmime, - mut new_mime: *mut Mailmime, -) -> libc::c_int { - let mut parent: *mut Mailmime = 0 as *mut Mailmime; - parent = (*old_mime).mm_parent; - if parent.is_null() { - return MAIL_ERROR_INVAL as libc::c_int; - } - if (*old_mime).mm_parent_type == MAILMIME_MESSAGE as libc::c_int { - (*parent).mm_data.mm_message.mm_msg_mime = new_mime - } else { - (*(*old_mime).mm_multipart_pos).data = new_mime as *mut libc::c_void - } - (*new_mime).mm_parent = parent; - (*new_mime).mm_parent_type = (*old_mime).mm_parent_type; - (*old_mime).mm_parent = 0 as *mut Mailmime; - (*old_mime).mm_parent_type = MAILMIME_NONE as libc::c_int; - return MAIL_NO_ERROR as libc::c_int; -} - -/* - mailimf_address_list_new_empty creates an empty list of addresses -*/ -pub unsafe fn mailimf_address_list_new_empty() -> *mut mailimf_address_list { - let mut list: *mut clist = 0 as *mut clist; - let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; - list = clist_new(); - if list.is_null() { - return 0 as *mut mailimf_address_list; - } - addr_list = mailimf_address_list_new(list); - if addr_list.is_null() { - return 0 as *mut mailimf_address_list; - } - return addr_list; -} - -/* - mailimf_mailbox_list_new_empty creates an empty list of mailboxes -*/ -pub unsafe fn mailimf_mailbox_list_new_empty() -> *mut mailimf_mailbox_list { - let mut list: *mut clist = 0 as *mut clist; - let mut mb_list: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list; - list = clist_new(); - if list.is_null() { - return 0 as *mut mailimf_mailbox_list; - } - mb_list = mailimf_mailbox_list_new(list); - if mb_list.is_null() { - return 0 as *mut mailimf_mailbox_list; - } - return mb_list; -} - -/* - mailimf_mailbox_list_add adds a mailbox to the list of mailboxes - - @return MAILIMF_NO_ERROR will be returned on success, - other code will be returned otherwise -*/ -pub unsafe fn mailimf_mailbox_list_add( - mut mailbox_list: *mut mailimf_mailbox_list, - mut mb: *mut mailimf_mailbox, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = clist_insert_after( - (*mailbox_list).mb_list, - (*(*mailbox_list).mb_list).last, - mb as *mut libc::c_void, - ); - if r < 0i32 { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -/* - mailimf_address_list_add adds a mailbox to the list of addresses - - @return MAILIMF_NO_ERROR will be returned on success, - other code will be returned otherwise -*/ -pub unsafe fn mailimf_address_list_add( - mut address_list: *mut mailimf_address_list, - mut addr: *mut mailimf_address, -) -> libc::c_int { - let mut r: libc::c_int = 0; - r = clist_insert_after( - (*address_list).ad_list, - (*(*address_list).ad_list).last, - addr as *mut libc::c_void, - ); - if r < 0i32 { - return MAILIMF_ERROR_MEMORY as libc::c_int; - } - return MAILIMF_NO_ERROR as libc::c_int; -} - -/* - mailimf_fields_new_with_data_all creates a new mailimf_fields - structure with a set of fields - - if you don't want a given field in the set to be added in the list - of fields, you can give NULL as argument - - @param message_id sould be allocated with malloc() - @param subject should be allocated with malloc() - @param in_reply_to each elements of this list should be allocated - with malloc() - @param references each elements of this list should be allocated - with malloc() - - @return MAILIMF_NO_ERROR will be returned on success, - other code will be returned otherwise -*/ -pub unsafe fn mailimf_fields_new_with_data_all( - mut date: *mut mailimf_date_time, - mut from: *mut mailimf_mailbox_list, - mut sender: *mut mailimf_mailbox, - mut reply_to: *mut mailimf_address_list, - mut to: *mut mailimf_address_list, - mut cc: *mut mailimf_address_list, - mut bcc: *mut mailimf_address_list, - mut message_id: *mut libc::c_char, - mut in_reply_to: *mut clist, - mut references: *mut clist, - mut subject: *mut libc::c_char, -) -> *mut mailimf_fields { - let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields; - let mut r: libc::c_int = 0; - fields = mailimf_fields_new_empty(); - if !fields.is_null() { - r = mailimf_fields_add_data( - fields, - date, - from, - sender, - reply_to, - to, - cc, - bcc, - message_id, - in_reply_to, - references, - subject, - ); - if r != MAILIMF_NO_ERROR as libc::c_int { - mailimf_fields_free(fields); - } else { - return fields; - } - } - return 0 as *mut mailimf_fields; -} - -/* - mailimf_fields_add_data adds a set of fields in the - given mailimf_fields structure. - - if you don't want a given field in the set to be added in the list - of fields, you can give NULL as argument - - @param msg_id sould be allocated with malloc() - @param subject should be allocated with malloc() - @param in_reply_to each elements of this list should be allocated - with malloc() - @param references each elements of this list should be allocated - with malloc() - - @return MAILIMF_NO_ERROR will be returned on success, - other code will be returned otherwise -*/ -pub unsafe fn mailimf_fields_add_data( - mut fields: *mut mailimf_fields, - mut date: *mut mailimf_date_time, - mut from: *mut mailimf_mailbox_list, - mut sender: *mut mailimf_mailbox, - mut reply_to: *mut mailimf_address_list, - mut to: *mut mailimf_address_list, - mut cc: *mut mailimf_address_list, - mut bcc: *mut mailimf_address_list, - mut msg_id: *mut libc::c_char, - mut in_reply_to: *mut clist, - mut references: *mut clist, - mut subject: *mut libc::c_char, -) -> libc::c_int { - let mut current_block: u64; - let mut imf_date: *mut mailimf_orig_date = 0 as *mut mailimf_orig_date; - let mut imf_from: *mut mailimf_from = 0 as *mut mailimf_from; - let mut imf_sender: *mut mailimf_sender = 0 as *mut mailimf_sender; - let mut imf_reply_to: *mut mailimf_reply_to = 0 as *mut mailimf_reply_to; - let mut imf_to: *mut mailimf_to = 0 as *mut mailimf_to; - let mut imf_cc: *mut mailimf_cc = 0 as *mut mailimf_cc; - let mut imf_bcc: *mut mailimf_bcc = 0 as *mut mailimf_bcc; - let mut imf_msg_id: *mut mailimf_message_id = 0 as *mut mailimf_message_id; - let mut imf_references: *mut mailimf_references = 0 as *mut mailimf_references; - let mut imf_in_reply_to: *mut mailimf_in_reply_to = 0 as *mut mailimf_in_reply_to; - let mut imf_subject: *mut mailimf_subject = 0 as *mut mailimf_subject; - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - let mut r: libc::c_int = 0; - imf_date = 0 as *mut mailimf_orig_date; - imf_from = 0 as *mut mailimf_from; - imf_sender = 0 as *mut mailimf_sender; - imf_reply_to = 0 as *mut mailimf_reply_to; - imf_to = 0 as *mut mailimf_to; - imf_cc = 0 as *mut mailimf_cc; - imf_bcc = 0 as *mut mailimf_bcc; - imf_msg_id = 0 as *mut mailimf_message_id; - imf_references = 0 as *mut mailimf_references; - imf_in_reply_to = 0 as *mut mailimf_in_reply_to; - imf_subject = 0 as *mut mailimf_subject; - field = 0 as *mut mailimf_field; - if !date.is_null() { - imf_date = mailimf_orig_date_new(date); - if imf_date.is_null() { - current_block = 16539016819803454162; - } else { - field = mailimf_field_new( - MAILIMF_FIELD_ORIG_DATE as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - imf_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_reply_to, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - 0 as *mut mailimf_optional_field, - ); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() { - current_block = 16539016819803454162; - } else { - r = mailimf_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 13813460800808168376; - } else { - current_block = 2719512138335094285; - } - } - } - } else { - current_block = 2719512138335094285; - } - match current_block { - 2719512138335094285 => { - if !from.is_null() { - imf_from = mailimf_from_new(from); - if imf_from.is_null() { - current_block = 13813460800808168376; - } else { - field = mailimf_field_new( - MAILIMF_FIELD_FROM as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_orig_date, - imf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_reply_to, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - 0 as *mut mailimf_optional_field, - ); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() { - current_block = 16539016819803454162; - } else { - r = mailimf_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 13813460800808168376; - } else { - current_block = 3275366147856559585; - } - } - } - } else { - current_block = 3275366147856559585; - } - match current_block { - 13813460800808168376 => {} - 16539016819803454162 => {} - _ => { - if !sender.is_null() { - imf_sender = mailimf_sender_new(sender); - if imf_sender.is_null() { - current_block = 16539016819803454162; - } else { - field = mailimf_field_new( - MAILIMF_FIELD_SENDER as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - imf_sender, - 0 as *mut mailimf_reply_to, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - 0 as *mut mailimf_optional_field, - ); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() { - current_block = 16539016819803454162; - } else { - r = mailimf_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 13813460800808168376; - } else { - current_block = 15090052786889560393; - } - } - } - } else { - current_block = 15090052786889560393; - } - match current_block { - 16539016819803454162 => {} - 13813460800808168376 => {} - _ => { - if !reply_to.is_null() { - imf_reply_to = mailimf_reply_to_new(reply_to); - if imf_reply_to.is_null() { - current_block = 16539016819803454162; - } else { - field = mailimf_field_new( - MAILIMF_FIELD_REPLY_TO as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - imf_reply_to, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - 0 as *mut mailimf_optional_field, - ); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() { - current_block = 16539016819803454162; - } else { - r = mailimf_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 13813460800808168376; - } else { - current_block = 10150597327160359210; - } - } - } - } else { - current_block = 10150597327160359210; - } - match current_block { - 16539016819803454162 => {} - 13813460800808168376 => {} - _ => { - if !to.is_null() { - imf_to = mailimf_to_new(to); - if imf_to.is_null() { - current_block = 16539016819803454162; - } else { - field = mailimf_field_new( - MAILIMF_FIELD_TO as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_reply_to, - imf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - 0 as *mut mailimf_optional_field, - ); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() { - current_block = 16539016819803454162; - } else { - r = mailimf_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 13813460800808168376; - } else { - current_block = 17233182392562552756; - } - } - } - } else { - current_block = 17233182392562552756; - } - match current_block { - 16539016819803454162 => {} - 13813460800808168376 => {} - _ => { - if !cc.is_null() { - imf_cc = mailimf_cc_new(cc); - if imf_cc.is_null() { - current_block = 16539016819803454162; - } else { - field = mailimf_field_new( - MAILIMF_FIELD_CC as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_reply_to, - 0 as *mut mailimf_to, - imf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - 0 as *mut mailimf_optional_field, - ); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() { - current_block = 16539016819803454162; - } else { - r = mailimf_fields_add(fields, field); - if r != MAILIMF_NO_ERROR as libc::c_int { - current_block = 13813460800808168376; - } else { - current_block = 12930649117290160518; - } - } - } - } else { - current_block = 12930649117290160518; - } - match current_block { - 16539016819803454162 => {} - 13813460800808168376 => {} - _ => { - if !bcc.is_null() { - imf_bcc = mailimf_bcc_new(bcc); - if imf_bcc.is_null() { - current_block = 16539016819803454162; - } else { - field = mailimf_field_new( - MAILIMF_FIELD_BCC as libc::c_int, - 0 as *mut mailimf_return, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - 0 as *mut mailimf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_orig_date, - 0 as *mut mailimf_from, - 0 as *mut mailimf_sender, - 0 as *mut mailimf_reply_to, - 0 as *mut mailimf_to, - 0 as *mut mailimf_cc, - imf_bcc, - 0 as *mut mailimf_message_id, - 0 as *mut mailimf_in_reply_to, - 0 as *mut mailimf_references, - 0 as *mut mailimf_subject, - 0 as *mut mailimf_comments, - 0 as *mut mailimf_keywords, - 0 as *mut mailimf_optional_field, - ); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() { - current_block = - 16539016819803454162; - } else { - r = mailimf_fields_add( - fields, field, - ); - if r != MAILIMF_NO_ERROR - as libc::c_int - { - current_block = - 13813460800808168376; - } else { - current_block = - 7858101417678297991; - } - } - } - } else { - current_block = 7858101417678297991; - } - match current_block { - 16539016819803454162 => {} - 13813460800808168376 => {} - _ => { - if !msg_id.is_null() { - imf_msg_id = - mailimf_message_id_new(msg_id); - if imf_msg_id.is_null() { - current_block = - 16539016819803454162; - } else { - field = - mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID - as - libc::c_int, - 0 - as - *mut mailimf_return, - 0 - as - *mut mailimf_orig_date, - 0 - as - *mut mailimf_from, - 0 - as - *mut mailimf_sender, - 0 - as - *mut mailimf_to, - 0 - as - *mut mailimf_cc, - 0 - as - *mut mailimf_bcc, - 0 - as - *mut mailimf_message_id, - 0 - as - *mut mailimf_orig_date, - 0 - as - *mut mailimf_from, - 0 - as - *mut mailimf_sender, - 0 - as - *mut mailimf_reply_to, - 0 - as - *mut mailimf_to, - 0 - as - *mut mailimf_cc, - 0 - as - *mut mailimf_bcc, - imf_msg_id, - 0 - as - *mut mailimf_in_reply_to, - 0 - as - *mut mailimf_references, - 0 - as - *mut mailimf_subject, - 0 - as - *mut mailimf_comments, - 0 - as - *mut mailimf_keywords, - 0 - as - *mut mailimf_optional_field); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() { - current_block = - 16539016819803454162; - } else { - r = mailimf_fields_add( - fields, field, - ); - if r != MAILIMF_NO_ERROR - as libc::c_int - { - current_block - = - 13813460800808168376; - } else { - current_block - = - 15514718523126015390; - } - } - } - } else { - current_block = - 15514718523126015390; - } - match current_block { - 13813460800808168376 => {} - 16539016819803454162 => {} - _ => { - if !in_reply_to.is_null() { - imf_in_reply_to = - mailimf_in_reply_to_new( - in_reply_to, - ); - if imf_in_reply_to.is_null() - { - current_block - = - 16539016819803454162; - } else { - field - = - mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO - as - libc::c_int, - 0 - as - *mut mailimf_return, - 0 - as - *mut mailimf_orig_date, - 0 - as - *mut mailimf_from, - 0 - as - *mut mailimf_sender, - 0 - as - *mut mailimf_to, - 0 - as - *mut mailimf_cc, - 0 - as - *mut mailimf_bcc, - 0 - as - *mut mailimf_message_id, - 0 - as - *mut mailimf_orig_date, - 0 - as - *mut mailimf_from, - 0 - as - *mut mailimf_sender, - 0 - as - *mut mailimf_reply_to, - 0 - as - *mut mailimf_to, - 0 - as - *mut mailimf_cc, - 0 - as - *mut mailimf_bcc, - 0 - as - *mut mailimf_message_id, - imf_in_reply_to, - 0 - as - *mut mailimf_references, - 0 - as - *mut mailimf_subject, - 0 - as - *mut mailimf_comments, - 0 - as - *mut mailimf_keywords, - 0 - as - *mut mailimf_optional_field); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() { - current_block - = - 16539016819803454162; - } else { - r - = - mailimf_fields_add(fields, - field); - if r - != - MAILIMF_NO_ERROR - as - libc::c_int - { - current_block - = - 13813460800808168376; - } else { - current_block - = - 15587532755333643506; - } - } - } - } else { - current_block = - 15587532755333643506; - } - match current_block { - 13813460800808168376 => {} - 16539016819803454162 => {} - _ => { - if !references.is_null() - { - imf_references - = - mailimf_references_new(references); - if imf_references - .is_null() - { - current_block - = - 16539016819803454162; - } else { - field - = - mailimf_field_new(MAILIMF_FIELD_REFERENCES - as - libc::c_int, - 0 - as - *mut mailimf_return, - 0 - as - *mut mailimf_orig_date, - 0 - as - *mut mailimf_from, - 0 - as - *mut mailimf_sender, - 0 - as - *mut mailimf_to, - 0 - as - *mut mailimf_cc, - 0 - as - *mut mailimf_bcc, - 0 - as - *mut mailimf_message_id, - 0 - as - *mut mailimf_orig_date, - 0 - as - *mut mailimf_from, - 0 - as - *mut mailimf_sender, - 0 - as - *mut mailimf_reply_to, - 0 - as - *mut mailimf_to, - 0 - as - *mut mailimf_cc, - 0 - as - *mut mailimf_bcc, - 0 - as - *mut mailimf_message_id, - 0 - as - *mut mailimf_in_reply_to, - imf_references, - 0 - as - *mut mailimf_subject, - 0 - as - *mut mailimf_comments, - 0 - as - *mut mailimf_keywords, - 0 - as - *mut mailimf_optional_field); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field - .is_null() - { - current_block - = - 16539016819803454162; - } else { - r - = - mailimf_fields_add(fields, - field); - if r - != - MAILIMF_NO_ERROR - as - libc::c_int - { - current_block - = - 13813460800808168376; - } else { - current_block - = - 7301440000599063274; - } - } - } - } else { - current_block - = - 7301440000599063274; - } - match current_block - { - 13813460800808168376 - => - { - } - 16539016819803454162 - => - { - } - _ - => - { - if !subject.is_null() - { - imf_subject - = - mailimf_subject_new(subject); - if imf_subject.is_null() - { - current_block - = - 16539016819803454162; - } else { - field - = - mailimf_field_new(MAILIMF_FIELD_SUBJECT - as - libc::c_int, - 0 - as - *mut mailimf_return, - 0 - as - *mut mailimf_orig_date, - 0 - as - *mut mailimf_from, - 0 - as - *mut mailimf_sender, - 0 - as - *mut mailimf_to, - 0 - as - *mut mailimf_cc, - 0 - as - *mut mailimf_bcc, - 0 - as - *mut mailimf_message_id, - 0 - as - *mut mailimf_orig_date, - 0 - as - *mut mailimf_from, - 0 - as - *mut mailimf_sender, - 0 - as - *mut mailimf_reply_to, - 0 - as - *mut mailimf_to, - 0 - as - *mut mailimf_cc, - 0 - as - *mut mailimf_bcc, - 0 - as - *mut mailimf_message_id, - 0 - as - *mut mailimf_in_reply_to, - 0 - as - *mut mailimf_references, - imf_subject, - 0 - as - *mut mailimf_comments, - 0 - as - *mut mailimf_keywords, - 0 - as - *mut mailimf_optional_field); - /* return-path */ - /* resent date */ - /* resent from */ - /* resent sender */ - /* resent to */ - /* resent cc */ - /* resent bcc */ - /* resent msg id */ - /* date */ - /* from */ - /* sender */ - /* reply-to */ - /* to */ - /* cc */ - /* bcc */ - /* message id */ - /* in reply to */ - /* references */ - /* subject */ - /* comments */ - /* keywords */ - /* optional field */ - if field.is_null() - { - current_block - = - 16539016819803454162; - } else { - r - = - mailimf_fields_add(fields, - field); - if r - != - MAILIMF_NO_ERROR - as - libc::c_int - { - current_block - = - 13813460800808168376; - } else { - current_block - = - 10153752038087260855; - } - } - } - } else { - current_block - = - 10153752038087260855; - } - match current_block - { - 13813460800808168376 - => - { - } - 16539016819803454162 - => - { - } - _ - => - { - return MAILIMF_NO_ERROR - as - libc::c_int - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - _ => {} - } - match current_block { - 13813460800808168376 => { - if !field.is_null() { - detach_field(field); - mailimf_field_free(field); - } - } - _ => {} - } - detach_free_fields( - imf_date, - imf_from, - imf_sender, - imf_reply_to, - imf_to, - imf_cc, - imf_bcc, - imf_msg_id, - imf_in_reply_to, - imf_references, - imf_subject, - ); - return MAILIMF_ERROR_MEMORY as libc::c_int; -} - -unsafe fn detach_free_fields( - mut date: *mut mailimf_orig_date, - mut from: *mut mailimf_from, - mut sender: *mut mailimf_sender, - mut reply_to: *mut mailimf_reply_to, - mut to: *mut mailimf_to, - mut cc: *mut mailimf_cc, - mut bcc: *mut mailimf_bcc, - mut msg_id: *mut mailimf_message_id, - mut in_reply_to: *mut mailimf_in_reply_to, - mut references: *mut mailimf_references, - mut subject: *mut mailimf_subject, -) { - detach_free_common_fields(date, from, sender, to, cc, bcc, msg_id); - if !reply_to.is_null() { - (*reply_to).rt_addr_list = 0 as *mut mailimf_address_list; - mailimf_reply_to_free(reply_to); - } - if !in_reply_to.is_null() { - (*in_reply_to).mid_list = 0 as *mut clist; - mailimf_in_reply_to_free(in_reply_to); - } - if !references.is_null() { - (*references).mid_list = 0 as *mut clist; - mailimf_references_free(references); - } - if !subject.is_null() { - (*subject).sbj_value = 0 as *mut libc::c_char; - mailimf_subject_free(subject); - }; -} - -unsafe fn detach_field(mut field: *mut mailimf_field) { - (*field).fld_type = MAILIMF_FIELD_NONE as libc::c_int; - mailimf_field_free(field); -} - -unsafe fn detach_free_common_fields( - mut imf_date: *mut mailimf_orig_date, - mut imf_from: *mut mailimf_from, - mut imf_sender: *mut mailimf_sender, - mut imf_to: *mut mailimf_to, - mut imf_cc: *mut mailimf_cc, - mut imf_bcc: *mut mailimf_bcc, - mut imf_msg_id: *mut mailimf_message_id, -) { - if !imf_date.is_null() { - (*imf_date).dt_date_time = 0 as *mut mailimf_date_time; - mailimf_orig_date_free(imf_date); - } - if !imf_from.is_null() { - (*imf_from).frm_mb_list = 0 as *mut mailimf_mailbox_list; - mailimf_from_free(imf_from); - } - if !imf_sender.is_null() { - (*imf_sender).snd_mb = 0 as *mut mailimf_mailbox; - mailimf_sender_free(imf_sender); - } - if !imf_to.is_null() { - (*imf_to).to_addr_list = 0 as *mut mailimf_address_list; - mailimf_to_free(imf_to); - } - if !imf_cc.is_null() { - (*imf_cc).cc_addr_list = 0 as *mut mailimf_address_list; - mailimf_to_free(imf_to); - } - if !imf_bcc.is_null() { - (*imf_bcc).bcc_addr_list = 0 as *mut mailimf_address_list; - mailimf_bcc_free(imf_bcc); - } - if !imf_msg_id.is_null() { - (*imf_msg_id).mid_value = 0 as *mut libc::c_char; - mailimf_message_id_free(imf_msg_id); - }; -} - -pub fn mailimf_get_date(t: i64) -> *mut mailimf_date_time { - let lt = Local.timestamp(t, 0); - - let off = (lt.offset().local_minus_utc() / (60 * 60)) * 100; - - unsafe { - mailimf_date_time_new( - lt.day() as libc::c_int, - lt.month() as libc::c_int, - lt.year() as libc::c_int, - lt.hour() as libc::c_int, - lt.minute() as libc::c_int, - lt.second() as libc::c_int, - off, - ) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use chrono::Utc; - use std::ffi::CString; - - #[test] - fn test_strcasecmp() { - assert_eq!(0, unsafe { - strcasecmp( - CString::new("hello").unwrap().as_ptr(), - CString::new("Hello").unwrap().as_ptr(), - ) - }); - } - - #[test] - fn test_strncasecmp() { - assert_eq!(0, unsafe { - strncasecmp( - CString::new("helloworld").unwrap().as_ptr(), - CString::new("Helloward").unwrap().as_ptr(), - 4, - ) - }); - - assert_eq!(0, unsafe { - strncasecmp( - CString::new("hell").unwrap().as_ptr(), - CString::new("Hell").unwrap().as_ptr(), - 100_000_000, - ) - }); - } - - #[test] - fn test_get_date() { - let now_utc = Utc::now(); - - let now_local = Local.from_utc_datetime(&now_utc.naive_local()); - let t_local = now_local.timestamp(); - - let converted = unsafe { *mailimf_get_date(t_local as i64) }; - - assert_eq!(converted.dt_day as u32, now_local.day()); - assert_eq!(converted.dt_month as u32, now_local.month()); - assert_eq!(converted.dt_year, now_local.year()); - assert_eq!(converted.dt_hour as u32, now_local.hour()); - assert_eq!(converted.dt_min as u32, now_local.minute()); - assert_eq!(converted.dt_sec as u32, now_local.second()); - assert_eq!( - converted.dt_zone, - (now_local.offset().local_minus_utc() / (60 * 60)) * 100 - ); - } -} diff --git a/src/aheader.rs b/src/aheader.rs index 47e374aef..b608932e3 100644 --- a/src/aheader.rs +++ b/src/aheader.rs @@ -3,12 +3,9 @@ //! Parse and create [Autocrypt-headers](https://autocrypt.org/en/latest/level1.html#the-autocrypt-header). use std::collections::BTreeMap; -use std::ffi::CStr; use std::str::FromStr; use std::{fmt, str}; -use mmime::mailimf::types::*; - use crate::constants::*; use crate::contact::*; use crate::key::*; @@ -68,45 +65,21 @@ impl Aheader { } } - pub fn from_imffields(wanted_from: &str, header: *const mailimf_fields) -> Option { - if header.is_null() { - return None; - } + pub fn from_imffields( + wanted_from: &str, + headers: &[mailparse::MailHeader<'_>], + ) -> Option { + use mailparse::MailHeaderMap; - let mut fine_header = None; - let mut cur = unsafe { (*(*header).fld_list).first }; - - while !cur.is_null() { - let field = unsafe { (*cur).data as *mut mailimf_field }; - if !field.is_null() - && unsafe { (*field).fld_type } == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int - { - let optional_field = unsafe { (*field).fld_data.fld_optional_field }; - if !optional_field.is_null() - && unsafe { !(*optional_field).fld_name.is_null() } - && unsafe { CStr::from_ptr((*optional_field).fld_name).to_string_lossy() } - == "Autocrypt" - { - let value = - unsafe { CStr::from_ptr((*optional_field).fld_value).to_string_lossy() }; - - if let Ok(test) = Self::from_str(&value) { - if addr_cmp(&test.addr, wanted_from) { - if fine_header.is_none() { - fine_header = Some(test); - } else { - // TODO: figure out what kind of error case this is - return None; - } - } - } + if let Ok(Some(value)) = headers.get_first_value("Autocrypt") { + if let Ok(test) = Self::from_str(&value) { + if addr_cmp(&test.addr, wanted_from) { + return Some(test); } } - - cur = unsafe { (*cur).next }; } - fine_header + None } } diff --git a/src/chat.rs b/src/chat.rs index 0a35742d8..dedb2b0e6 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -11,12 +11,12 @@ use crate::config::*; use crate::constants::*; use crate::contact::*; use crate::context::Context; -use crate::dc_mimeparser::SystemMessage; use crate::dc_tools::*; use crate::error::Error; use crate::events::Event; use crate::job::*; use crate::message::{self, InvalidMsgId, Message, MessageState, MsgId}; +use crate::mimeparser::SystemMessage; use crate::param::*; use crate::sql::{self, Sql}; use crate::stock::StockMessage; diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs deleted file mode 100644 index 5f9f94890..000000000 --- a/src/dc_mimeparser.rs +++ /dev/null @@ -1,1239 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::ffi::{CStr, CString}; -use std::ptr; - -use charset::Charset; -use deltachat_derive::{FromSql, ToSql}; -use libc::{strcmp, strlen, strncmp}; -use mmime::mailimf::types::*; -use mmime::mailimf::*; -use mmime::mailmime::content::*; -use mmime::mailmime::disposition::*; -use mmime::mailmime::types::*; -use mmime::mailmime::*; -use mmime::other::*; - -use crate::blob::BlobObject; -use crate::constants::Viewtype; -use crate::contact::*; -use crate::context::Context; -use crate::dc_simplify::*; -use crate::dc_strencode::*; -use crate::dc_tools::*; -use crate::e2ee; -use crate::error::Error; -use crate::location; -use crate::param::*; -use crate::stock::StockMessage; -use crate::wrapmime; - -#[derive(Debug)] -pub struct MimeParser<'a, 'b> { - pub context: &'a Context, - pub parts: Vec, - mail: Option>, - pub mimeroot: *mut Mailmime, - pub header: HashMap, - pub header_root: *mut mailimf_fields, - pub header_protected: *mut mailimf_fields, - pub subject: Option, - pub is_send_by_messenger: bool, - pub decrypting_failed: bool, - pub encrypted: bool, - pub signatures: HashSet, - pub gossipped_addr: HashSet, - pub is_forwarded: bool, - pub reports: Vec<*mut Mailmime>, - pub is_system_message: SystemMessage, - pub location_kml: Option, - pub message_kml: Option, -} - -#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql)] -#[repr(i32)] -pub enum SystemMessage { - Unknown = 0, - GroupNameChanged = 2, - GroupImageChanged = 3, - MemberAddedToGroup = 4, - MemberRemovedFromGroup = 5, - AutocryptSetupMessage = 6, - SecurejoinMessage = 7, - LocationStreamingEnabled = 8, - LocationOnly = 9, -} - -impl Default for SystemMessage { - fn default() -> Self { - SystemMessage::Unknown - } -} - -const DC_MIMETYPE_MP_ALTERNATIVE: i32 = 10; -const DC_MIMETYPE_MP_RELATED: i32 = 20; -const DC_MIMETYPE_MP_MIXED: i32 = 30; -const DC_MIMETYPE_MP_NOT_DECRYPTABLE: i32 = 40; -const DC_MIMETYPE_MP_REPORT: i32 = 45; -const DC_MIMETYPE_MP_SIGNED: i32 = 46; -const DC_MIMETYPE_MP_OTHER: i32 = 50; -const DC_MIMETYPE_TEXT_PLAIN: i32 = 60; -const DC_MIMETYPE_TEXT_HTML: i32 = 70; -const DC_MIMETYPE_IMAGE: i32 = 80; -const DC_MIMETYPE_AUDIO: i32 = 90; -const DC_MIMETYPE_VIDEO: i32 = 100; -const DC_MIMETYPE_FILE: i32 = 110; -const DC_MIMETYPE_AC_SETUP_FILE: i32 = 111; - -impl<'a, 'b> MimeParser<'a, 'b> { - pub fn new(context: &'a Context) -> Self { - MimeParser { - parts: Vec::new(), - mail: None, - mimeroot: std::ptr::null_mut(), - header: Default::default(), - header_root: std::ptr::null_mut(), - header_protected: std::ptr::null_mut(), - subject: None, - is_send_by_messenger: false, - decrypting_failed: false, - encrypted: false, - signatures: Default::default(), - gossipped_addr: Default::default(), - is_forwarded: false, - context, - reports: Vec::new(), - is_system_message: SystemMessage::Unknown, - location_kml: None, - message_kml: None, - } - } - - pub fn parse(&mut self, body: &'b [u8]) -> Result<(), Error> { - let mut index = 0; - - self.mail = Some(mailparse::parse_mail(body).unwrap()); - - // TODO: decrypt - // match e2ee::try_decrypt(self.context, self.mimeroot) { - // Ok((encrypted, signatures, gossipped_addr)) => { - // self.encrypted = encrypted; - // self.signatures = signatures; - // self.gossipped_addr = gossipped_addr; - // } - // Err(err) => { - // // continue with the current, still encrypted, mime tree. - // // unencrypted parts will be replaced by an error message - // // that is added as "the message" to the chat then. - // // - // // if we just return here, the header is missing - // // and the caller cannot display the message - // // and try to assign the message to a chat - // warn!(self.context, "decryption failed: {}", err); - // } - // } - - self.parse_mime_recursive(None); - - if let Some(field) = self.lookup_field("Subject") { - self.subject = Some(field.get_value().unwrap()); - } - - if self.lookup_field("Chat-Version").is_some() { - self.is_send_by_messenger = true - } - - if self.lookup_field("Autocrypt-Setup-Message").is_some() { - let has_setup_file = self - .parts - .iter() - .any(|p| p.mimetype == DC_MIMETYPE_AC_SETUP_FILE); - - if has_setup_file { - self.is_system_message = SystemMessage::AutocryptSetupMessage; - - // TODO: replace the following code with this - // once drain_filter stabilizes. - // - // See https://doc.rust-lang.org/std/vec/struct.Vec.html#method.drain_filter - // and https://github.com/rust-lang/rust/issues/43244 - // - // mimeparser - // .parts - // .drain_filter(|part| part.int_mimetype != 111) - // .for_each(|part| dc_mimepart_unref(part)); - - let mut i = 0; - while i != self.parts.len() { - if self.parts[i].mimetype != 111 { - self.parts.remove(i); - } else { - i += 1; - } - } - } - } else if let Some(optional_field) = self.lookup_field("Chat-Content") { - let value = optional_field.get_value(); - if value.is_ok() && value.as_ref().unwrap() == "location-streaming-enabled" { - self.is_system_message = SystemMessage::LocationStreamingEnabled; - } - } - if self.lookup_field("Chat-Group-Image").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]; - if imgpart.typ == Viewtype::Image { - imgpart.is_meta = true; - } - } - } - if self.is_send_by_messenger && self.parts.len() == 2 { - let need_drop = { - let textpart = &self.parts[0]; - let filepart = &self.parts[1]; - textpart.typ == Viewtype::Text - && (filepart.typ == Viewtype::Image - || filepart.typ == Viewtype::Gif - || filepart.typ == Viewtype::Sticker - || filepart.typ == Viewtype::Audio - || filepart.typ == Viewtype::Voice - || filepart.typ == Viewtype::Video - || filepart.typ == Viewtype::File) - && !filepart.is_meta - }; - - if need_drop { - let mut filepart = self.parts.swap_remove(1); - - // insert new one - filepart.msg = self.parts[0].msg.as_ref().map(|s| s.to_string()); - - // forget the one we use now - self.parts[0].msg = None; - - // swap new with old - std::mem::replace(&mut self.parts[0], filepart); - } - } - if let Some(ref subject) = self.subject { - let mut prepend_subject: libc::c_int = 1i32; - if !self.decrypting_failed { - let colon = subject.find(':'); - if colon == Some(2) - || colon == Some(3) - || self.is_send_by_messenger - || subject.contains("Chat:") - { - prepend_subject = 0i32 - } - } - if 0 != prepend_subject { - let subj = if let Some(n) = subject.find('[') { - &subject[0..n] - } else { - subject - } - .trim(); - - if !subj.is_empty() { - for part in self.parts.iter_mut() { - if part.typ == Viewtype::Text { - let new_txt = format!( - "{} – {}", - subj, - part.msg.as_ref().expect("missing msg part") - ); - part.msg = Some(new_txt); - break; - } - } - } - } - } - if self.is_forwarded { - for part in self.parts.iter_mut() { - part.param.set_int(Param::Forwarded, 1); - } - } - if self.parts.len() == 1 { - if self.parts[0].typ == Viewtype::Audio { - if self.lookup_field("Chat-Voice-Message").is_some() { - let part_mut = &mut self.parts[0]; - part_mut.typ = Viewtype::Voice; - } - } - if self.parts[0].typ == Viewtype::Image { - if let Some(content_type) = self.lookup_field("Chat-Content") { - let value = content_type.get_value(); - if value.is_ok() && value.as_ref().unwrap() == "sticker" { - let part_mut = &mut self.parts[0]; - part_mut.typ = Viewtype::Sticker; - } - } - } - let part = &self.parts[0]; - if part.typ == Viewtype::Audio - || part.typ == Viewtype::Voice - || part.typ == Viewtype::Video - { - if let Some(field_0) = self.lookup_field("Chat-Duration") { - let duration_ms = field_0.get_value().unwrap().parse().unwrap_or_default(); - if duration_ms > 0 && duration_ms < 24 * 60 * 60 * 1000 { - let part_mut = &mut self.parts[0]; - part_mut.param.set_int(Param::Duration, duration_ms); - } - } - } - } - if !self.decrypting_failed { - if let Some(dn_field) = self.lookup_field("Chat-Disposition-Notification-To") { - if self.get_last_nonmeta().is_some() { - let addrs = mailparse::addrparse(&dn_field.get_value().unwrap()).unwrap(); - - if let Some(dn_to_addr) = addrs.first() { - if let Some(from_field) = self.lookup_field("From") { - let value = from_field.get_value().unwrap(); - let from_addrs = mailparse::addrparse(&value).unwrap(); - if let Some(from_addr) = from_addrs.first() { - if from_addr == dn_to_addr { - if let Some(part_4) = self.get_last_nonmeta_mut() { - part_4.param.set_int(Param::WantsMdn, 1); - } - } - } - } - } - } - } - } - - /* Cleanup - and try to create at least an empty part if there are no parts yet */ - if self.get_last_nonmeta().is_none() && self.reports.is_empty() { - let mut part_5 = Part::default(); - part_5.typ = Viewtype::Text; - part_5.msg = Some("".into()); - - if let Some(ref subject) = self.subject { - if !self.is_send_by_messenger { - part_5.msg = Some(subject.to_string()) - } - } - self.parts.push(part_5); - } - Ok(()) - } - - pub fn get_last_nonmeta(&self) -> Option<&Part> { - self.parts.iter().rev().find(|part| !part.is_meta) - } - - pub fn get_last_nonmeta_mut(&mut self) -> Option<&mut Part> { - self.parts.iter_mut().rev().find(|part| !part.is_meta) - } - - /* the following functions can be used only after a call to parse() */ - - pub fn lookup_field(&self, field_name: &str) -> Option<&'b mailparse::MailHeader<'_>> { - if let Some(ref mail) = self.mail { - return mail - .headers - .iter() - .find(|header| header.get_key().unwrap() == field_name); - } - None - } - - fn parse_mime_recursive(&mut self, omail: Option>) -> bool { - let mail = omail - .as_ref() - .unwrap_or_else(|| self.mail.as_ref().unwrap()); - - println!("ctype {:?}", mail.ctype); - - if mail.ctype.params.get("protected-headers").is_some() { - if mail.subparts.is_empty() && mail.ctype.mimetype == "text/rfc822-headers" { - info!( - self.context, - "Protected headers found in text/rfc822-headers attachment: Will be ignored.", - ); - return false; - } - - if self.header_protected.is_null() { - // use the most outer protected header - this is typically - // created in sync with the normal, unprotected header - - if let Some(part) = mail.subparts.first() { - let raw = part.get_body_raw().unwrap(); - if let Ok((protected_headers, _)) = mailparse::parse_headers(&raw) { - drop(mail); // I have won against the borrow checker!!!!11 - hash_header(&mut self.header, &protected_headers); - } else { - warn!(self.context, "Protected headers parsing error.",); - } - } - } else { - info!( - self.context, - "Protected headers found in MIME header: Will be ignored as we already found an outer one." - ); - } - } - - let mail = omail - .as_ref() - .unwrap_or_else(|| self.mail.as_ref().unwrap()); - - // single = multipart/* only one - // multiple = multipart/* multiple - // message = text/rfc822 - - if mail.ctype.mimetype == "text/rfc822" { - // if self.header_root.is_null() { - // self.header_root = (*mime).mm_data.mm_message.mm_fields; - // hash_header(&mut self.header, self.header_root); - // } - // if (*mime).mm_data.mm_message.mm_msg_mime.is_null() { - // return false; - // } - - let raw = mail.get_body_raw().unwrap(); - let mail = mailparse::parse_mail(&raw).unwrap(); - - return self.parse_mime_recursive(Some(mail)); - } - - if mail.subparts.len() > 1 { - return self.handle_multiple(omail); - } - - if mail.subparts.len() == 1 { - return self.add_single_part_if_known(omail); - } - false - } - - fn handle_multiple(&mut self, omail: Option>) -> bool { - // let mut any_part_added = false; - // match mailmime_get_mime_type(mime) { - // /* Most times, mutlipart/alternative contains true alternatives - // as text/plain and text/html. If we find a multipart/mixed - // inside mutlipart/alternative, we use this (happens eg in - // apple mail: "plaintext" as an alternative to "html+PDF attachment") */ - // (DC_MIMETYPE_MP_ALTERNATIVE, _, _) => { - // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - // if mailmime_get_mime_type(cur_data as *mut _).0 == DC_MIMETYPE_MP_MIXED { - // any_part_added = self.parse_mime_recursive(cur_data as *mut _); - // break; - // } - // } - // if !any_part_added { - // /* search for text/plain and add this */ - // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - // if mailmime_get_mime_type(cur_data as *mut _).0 == DC_MIMETYPE_TEXT_PLAIN { - // any_part_added = self.parse_mime_recursive(cur_data as *mut _); - // break; - // } - // } - // } - // if !any_part_added { - // /* `text/plain` not found - use the first part */ - // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - // if self.parse_mime_recursive(cur_data as *mut _) { - // any_part_added = true; - // break; - // } - // } - // } - // } - // (DC_MIMETYPE_MP_RELATED, _, _) => { - // /* add the "root part" - the other parts may be referenced which is - // not interesting for us (eg. embedded images) we assume he "root part" - // being the first one, which may not be always true ... - // however, most times it seems okay. */ - // let cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; - // if !cur.is_null() { - // any_part_added = self.parse_mime_recursive((*cur).data as *mut Mailmime); - // } - // } - // (DC_MIMETYPE_MP_NOT_DECRYPTABLE, _, _) => { - // let mut part = Part::default(); - // part.typ = Viewtype::Text; - // let msg_body = self.context.stock_str(StockMessage::CantDecryptMsgBody); - - // let txt = format!("[{}]", msg_body); - // part.msg_raw = Some(txt.clone()); - // part.msg = Some(txt); - - // self.parts.push(part); - // any_part_added = true; - // self.decrypting_failed = true; - // } - // (DC_MIMETYPE_MP_SIGNED, _, _) => { - // /* RFC 1847: "The multipart/signed content type - // contains exactly two body parts. The first body - // part is the body part over which the digital signature was created [...] - // The second body part contains the control information necessary to - // verify the digital signature." We simpliy take the first body part and - // skip the rest. (see - // https://k9mail.github.io/2016/11/24/OpenPGP-Considerations-Part-I.html - // for background information why we use encrypted+signed) */ - // let cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; - // if !cur.is_null() { - // any_part_added = self.parse_mime_recursive((*cur).data as *mut _); - // } - // } - // (DC_MIMETYPE_MP_REPORT, _, _) => { - // /* RFC 6522: the first part is for humans, the second for machines */ - // if (*(*mime).mm_data.mm_multipart.mm_mp_list).count >= 2 { - // let report_type = mailmime_find_ct_parameter(mime, "report-type"); - // if !report_type.is_null() - // && !(*report_type).pa_value.is_null() - // && &to_string_lossy((*report_type).pa_value) == "disposition-notification" - // { - // self.reports.push(mime); - // } else { - // /* eg. `report-type=delivery-status`; - // maybe we should show them as a little error icon */ - // if !(*(*mime).mm_data.mm_multipart.mm_mp_list).first.is_null() { - // any_part_added = self.parse_mime_recursive( - // (*(*(*mime).mm_data.mm_multipart.mm_mp_list).first).data as *mut _, - // ); - // } - // } - // } - // } - // _ => { - // /* eg. DC_MIMETYPE_MP_MIXED - add all parts (in fact, - // AddSinglePartIfKnown() later check if the parts are really supported) - // HACK: the following lines are a hack for clients who use - // multipart/mixed instead of multipart/alternative for - // combined text/html messages (eg. Stock Android "Mail" does so). - // So, if we detect such a message below, we skip the HTML - // part. However, not sure, if there are useful situations to use - // plain+html in multipart/mixed - if so, we should disable the hack. */ - // let mut skip_part = ptr::null_mut(); - // let mut html_part = ptr::null_mut(); - // let mut plain_cnt = 0; - // let mut html_cnt = 0; - - // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - // match mailmime_get_mime_type(cur_data as *mut _) { - // (DC_MIMETYPE_TEXT_PLAIN, _, _) => { - // plain_cnt += 1; - // } - // (DC_MIMETYPE_TEXT_HTML, _, _) => { - // html_part = cur_data as *mut Mailmime; - // html_cnt += 1; - // } - // _ => {} - // } - // } - // if plain_cnt == 1 && html_cnt == 1 { - // warn!( - // self.context, - // "HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted." - // ); - // skip_part = html_part; - // } - - // for cur_data in (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() { - // if cur_data as *mut _ != skip_part { - // if self.parse_mime_recursive(cur_data as *mut _) { - // any_part_added = true; - // } - // } - // } - // } - // } - - // any_part_added - // unimplemented!() - false - } - - fn add_single_part_if_known(&mut self, omail: Option>) -> bool { - false - // unimplemented!() - // // return true if a part was added - // let (mime_type, msg_type, raw_mime) = mailmime_get_mime_type(mime); - - // let mime_data = (*mime).mm_data.mm_single; - // if (*mime_data).dt_type != MAILMIME_DATA_TEXT as libc::c_int - // /* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */ - // || (*mime_data).dt_data.dt_text.dt_data.is_null() - // || (*mime_data).dt_data.dt_text.dt_length <= 0 - // { - // return false; - // } - - // let mut decoded_data = match wrapmime::mailmime_transfer_decode(mime) { - // Ok(decoded_data) => decoded_data, - // Err(_) => { - // // Note that it's not always an error - might be no data - // return false; - // } - // }; - - // let old_part_count = self.parts.len(); - - // /* regard `Content-Transfer-Encoding:` */ - // let mut desired_filename = String::default(); - // match mime_type { - // DC_MIMETYPE_TEXT_PLAIN | DC_MIMETYPE_TEXT_HTML => { - // /* get from `Content-Type: text/...; charset=utf-8`; must not be free()'d */ - // let charset = mailmime_content_charset_get((*mime).mm_content_type); - // if !charset.is_null() - // && strcmp(charset, b"utf-8\x00" as *const u8 as *const libc::c_char) != 0i32 - // && strcmp(charset, b"UTF-8\x00" as *const u8 as *const libc::c_char) != 0i32 - // { - // if let Some(encoding) = - // Charset::for_label(CStr::from_ptr(charset).to_string_lossy().as_bytes()) - // { - // let (res, _, _) = encoding.decode(&decoded_data); - // if res.is_empty() { - // /* no error - but nothing to add */ - // return false; - // } - // decoded_data = res.as_bytes().to_vec() - // } else { - // warn!( - // self.context, - // "Cannot convert {} bytes from \"{}\" to \"utf-8\".", - // decoded_data.len(), - // to_string_lossy(charset), - // ); - // } - // } - // /* check header directly as is_send_by_messenger is not yet set up */ - // let is_msgrmsg = self.lookup_field(mail, "Chat-Version").is_some(); - - // let mut simplifier = Simplify::new(); - // let simplified_txt = if decoded_data.is_empty() { - // "".into() - // } else { - // let input = std::string::String::from_utf8_lossy(&decoded_data); - // let is_html = mime_type == 70; - - // simplifier.simplify(&input, is_html, is_msgrmsg) - // }; - // if !simplified_txt.is_empty() { - // let mut part = Part::default(); - // part.typ = Viewtype::Text; - // part.mimetype = mime_type; - // part.msg = Some(simplified_txt); - // part.msg_raw = - // Some(std::string::String::from_utf8_lossy(&decoded_data).to_string()); - // self.do_add_single_part(part); - // } - - // if simplifier.is_forwarded { - // self.is_forwarded = true; - // } - // } - // DC_MIMETYPE_IMAGE - // | DC_MIMETYPE_AUDIO - // | DC_MIMETYPE_VIDEO - // | DC_MIMETYPE_FILE - // | DC_MIMETYPE_AC_SETUP_FILE => { - // /* try to get file name from - // `Content-Disposition: ... filename*=...` - // or `Content-Disposition: ... filename*0*=... filename*1*=... filename*2*=...` - // or `Content-Disposition: ... filename=...` */ - // let mut filename_parts = String::new(); - - // for cur1 in (*(*(*mime).mm_mime_fields).fld_list).into_iter() { - // let field = cur1 as *mut mailmime_field; - // if !field.is_null() - // && (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int - // && !(*field).fld_data.fld_disposition.is_null() - // { - // let file_disposition: *mut mailmime_disposition = - // (*field).fld_data.fld_disposition; - // if !file_disposition.is_null() { - // for cur2 in (*(*file_disposition).dsp_parms).into_iter() { - // let dsp_param = cur2 as *mut mailmime_disposition_parm; - // if !dsp_param.is_null() { - // if (*dsp_param).pa_type - // == MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int - // && !(*dsp_param).pa_data.pa_parameter.is_null() - // && !(*(*dsp_param).pa_data.pa_parameter).pa_name.is_null() - // && strncmp( - // (*(*dsp_param).pa_data.pa_parameter).pa_name, - // b"filename*\x00" as *const u8 as *const libc::c_char, - // 9, - // ) == 0i32 - // { - // // we assume the filename*?* parts are in order, not seen anything else yet - // filename_parts += &to_string_lossy( - // (*(*dsp_param).pa_data.pa_parameter).pa_value, - // ); - // } else if (*dsp_param).pa_type - // == MAILMIME_DISPOSITION_PARM_FILENAME as libc::c_int - // { - // // might be a wrongly encoded filename - // let s = to_string_lossy((*dsp_param).pa_data.pa_filename); - // // this is used only if the parts buffer stays empty - // desired_filename = dc_decode_header_words(&s) - // } - // } - // } - // } - // break; - // } - // } - // if !filename_parts.is_empty() { - // desired_filename = dc_decode_ext_header(filename_parts.as_bytes()).into_owned(); - // } - // if desired_filename.is_empty() { - // let param = mailmime_find_ct_parameter(mime, "name"); - // if !param.is_null() - // && !(*param).pa_value.is_null() - // && 0 != *(*param).pa_value.offset(0isize) as libc::c_int - // { - // // might be a wrongly encoded filename - // desired_filename = to_string_lossy((*param).pa_value); - // } - // } - // /* if there is still no filename, guess one */ - // if desired_filename.is_empty() { - // if !(*mime).mm_content_type.is_null() - // && !(*(*mime).mm_content_type).ct_subtype.is_null() - // { - // desired_filename = format!( - // "file.{}", - // to_string_lossy((*(*mime).mm_content_type).ct_subtype) - // ); - // } else { - // return false; - // } - // } - // self.do_add_single_file_part( - // msg_type, - // mime_type, - // raw_mime.as_ref(), - // &decoded_data, - // &desired_filename, - // ); - // } - // _ => {} - // } - // /* add object? (we do not add all objects, eg. signatures etc. are ignored) */ - // self.parts.len() > old_part_count - } - - unsafe fn do_add_single_file_part( - &mut self, - msg_type: Viewtype, - mime_type: libc::c_int, - raw_mime: Option<&String>, - decoded_data: &[u8], - filename: &str, - ) { - 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 parsed = location::Kml::parse(self.context, decoded_data) - .map_err(|err| { - warn!(self.context, "failed to parse kml part: {}", err); - }) - .ok(); - 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 {}", 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; - part.bytes = decoded_data.len() as libc::c_int; - part.param.set(Param::File, blob.as_name()); - if let Some(raw_mime) = raw_mime { - part.param.set(Param::MimeType, raw_mime); - } - - if mime_type == DC_MIMETYPE_IMAGE { - if let Ok((width, height)) = dc_get_filemeta(decoded_data) { - part.param.set_int(Param::Width, width as i32); - part.param.set_int(Param::Height, height as i32); - } - } - self.do_add_single_part(part); - } - - fn do_add_single_part(&mut self, mut part: Part) { - 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); - } - - pub fn is_mailinglist_message(&self) -> bool { - if self.lookup_field("List-Id").is_some() { - return true; - } - - if let Some(precedence) = self.lookup_field("Precedence") { - if precedence.get_value().unwrap() == "list" - || precedence.get_value().unwrap() == "bulk" - { - return true; - } - } - - false - } - - pub unsafe fn sender_equals_recipient(&self) -> bool { - if self.header_root.is_null() { - return false; - } - - let mut sender_equals_recipient = false; - let mut fld_from: *const mailimf_from = ptr::null(); - - /* get From: and check there is exactly one sender */ - let fld = wrapmime::mailimf_find_field(self.header_root, MAILIMF_FIELD_FROM as libc::c_int); - if !(fld.is_null() - || { - fld_from = (*fld).fld_data.fld_from; - fld_from.is_null() - } - || (*fld_from).frm_mb_list.is_null() - || (*(*fld_from).frm_mb_list).mb_list.is_null() - || (*(*(*fld_from).frm_mb_list).mb_list).count != 1i32) - { - let mb = (if !(*(*(*fld_from).frm_mb_list).mb_list).first.is_null() { - (*(*(*(*fld_from).frm_mb_list).mb_list).first).data - } else { - ptr::null_mut() - }) as *mut mailimf_mailbox; - - if !mb.is_null() { - let from_addr = to_string_lossy((*mb).mb_addr_spec); - let from_addr_norm = addr_normalize(&from_addr); - let recipients = wrapmime::mailimf_get_recipients(self.header_root); - if recipients.len() == 1 && recipients.contains(from_addr_norm) { - sender_equals_recipient = true; - } - } - } - - sender_equals_recipient - } - - pub fn repl_msg_by_error(&mut self, error_msg: impl AsRef) { - if self.parts.is_empty() { - return; - } - - let part = &mut self.parts[0]; - part.typ = Viewtype::Text; - part.msg = Some(format!("[{}]", error_msg.as_ref())); - self.parts.truncate(1); - - assert_eq!(self.parts.len(), 1); - } - - pub fn get_rfc724_mid(&mut self) -> Option { - // get Message-ID from header - if let Some(field) = self.lookup_field("Message-ID") { - return field.get_value().ok(); - } - None - } -} - -impl<'a, 'b> Drop for MimeParser<'a, 'b> { - fn drop(&mut self) { - if !self.header_protected.is_null() { - unsafe { mailimf_fields_free(self.header_protected) }; - } - if !self.mimeroot.is_null() { - unsafe { mailmime_free(self.mimeroot) }; - } - } -} - -#[derive(Default, Debug, Clone)] -pub struct Part { - pub typ: Viewtype, - pub is_meta: bool, - pub mimetype: i32, - pub msg: Option, - pub msg_raw: Option, - pub bytes: i32, - pub param: Params, -} - -fn hash_header(out: &mut HashMap, fields: &[mailparse::MailHeader<'_>]) { - for field in fields { - if let Ok(key) = field.get_key() { - if !out.contains_key(&key) || // key already exists, only overwrite known types (protected headers) - key.starts_with("Chat-") - { - // TODO: only overwrite known fields - out.insert(key, field.get_value().unwrap()); - } - } - } -} - -unsafe fn mailmime_get_mime_type(mime: *mut Mailmime) -> (libc::c_int, Viewtype, Option) { - let c = (*mime).mm_content_type; - - let unknown_type = (0, Viewtype::Unknown, None); - - if c.is_null() || (*c).ct_type.is_null() { - return unknown_type; - } - - match (*(*c).ct_type).tp_type as libc::c_uint { - MAILMIME_TYPE_DISCRETE_TYPE => match (*(*(*c).ct_type).tp_data.tp_discrete_type).dt_type - as libc::c_uint - { - MAILMIME_DISCRETE_TYPE_TEXT => { - if !mailmime_is_attachment_disposition(mime) { - if strcmp( - (*c).ct_subtype, - b"plain\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - return (DC_MIMETYPE_TEXT_PLAIN, Viewtype::Text, None); - } else if strcmp( - (*c).ct_subtype, - b"html\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - return (DC_MIMETYPE_TEXT_HTML, Viewtype::Text, None); - } - } - - let raw_mime = reconcat_mime(Some("text"), to_opt_string_lossy((*c).ct_subtype)); - (DC_MIMETYPE_FILE, Viewtype::File, Some(raw_mime)) - } - MAILMIME_DISCRETE_TYPE_IMAGE => { - let subtype = to_opt_string_lossy((*c).ct_subtype); - let msg_type = match subtype.as_ref().map(|x| x.as_str()) { - Some("gif") => Viewtype::Gif, - Some("svg+xml") => { - let raw_mime = - reconcat_mime(Some("image"), to_opt_string_lossy((*c).ct_subtype)); - return (DC_MIMETYPE_FILE, Viewtype::File, Some(raw_mime)); - } - _ => Viewtype::Image, - }; - - let raw_mime = reconcat_mime(Some("image"), subtype); - (DC_MIMETYPE_IMAGE, msg_type, Some(raw_mime)) - } - MAILMIME_DISCRETE_TYPE_AUDIO => { - let raw_mime = reconcat_mime(Some("audio"), to_opt_string_lossy((*c).ct_subtype)); - (DC_MIMETYPE_AUDIO, Viewtype::Audio, Some(raw_mime)) - } - MAILMIME_DISCRETE_TYPE_VIDEO => { - let raw_mime = reconcat_mime(Some("video"), to_opt_string_lossy((*c).ct_subtype)); - (DC_MIMETYPE_VIDEO, Viewtype::Video, Some(raw_mime)) - } - _ => { - if (*(*(*c).ct_type).tp_data.tp_discrete_type).dt_type - == MAILMIME_DISCRETE_TYPE_APPLICATION as libc::c_int - && strcmp( - (*c).ct_subtype, - b"autocrypt-setup\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - let raw_mime = reconcat_mime(None, to_opt_string_lossy((*c).ct_subtype)); - return (DC_MIMETYPE_AC_SETUP_FILE, Viewtype::File, Some(raw_mime)); - } - - let raw_mime = reconcat_mime( - to_opt_string_lossy((*(*(*c).ct_type).tp_data.tp_discrete_type).dt_extension) - .as_ref() - .map(|x| x.as_str()), - to_opt_string_lossy((*c).ct_subtype), - ); - - (DC_MIMETYPE_FILE, Viewtype::File, Some(raw_mime)) - } - }, - MAILMIME_TYPE_COMPOSITE_TYPE => { - if (*(*(*c).ct_type).tp_data.tp_composite_type).ct_type - == MAILMIME_COMPOSITE_TYPE_MULTIPART as libc::c_int - { - let subtype = to_opt_string_lossy((*c).ct_subtype); - - let mime_type = match subtype.as_ref().map(|x| x.as_str()) { - Some("alternative") => DC_MIMETYPE_MP_ALTERNATIVE, - Some("related") => DC_MIMETYPE_MP_RELATED, - Some("encrypted") => { - // maybe try_decrypt failed to decrypt - // or it wasn't in proper Autocrypt format - DC_MIMETYPE_MP_NOT_DECRYPTABLE - } - Some("signed") => DC_MIMETYPE_MP_SIGNED, - Some("mixed") => DC_MIMETYPE_MP_MIXED, - Some("report") => DC_MIMETYPE_MP_REPORT, - _ => DC_MIMETYPE_MP_OTHER, - }; - - (mime_type, Viewtype::Unknown, None) - } else { - if (*(*(*c).ct_type).tp_data.tp_composite_type).ct_type - == MAILMIME_COMPOSITE_TYPE_MESSAGE as libc::c_int - { - // Enacapsulated messages, see https://www.w3.org/Protocols/rfc1341/7_3_Message.html - // Also used as part "message/disposition-notification" of "multipart/report", which, however, will - // be handled separatedly. - // I've not seen any messages using this, so we do not attach these parts (maybe they're used to attach replies, - // which are unwanted at all). - // For now, we skip these parts at all; if desired, we could return DC_MIMETYPE_FILE/DC_MSG_FILE - // for selected and known subparts. - } - - unknown_type - } - } - _ => unknown_type, - } -} - -fn reconcat_mime(typ: Option<&str>, subtype: Option) -> String { - let typ = typ.unwrap_or("application"); - let subtype = subtype.unwrap_or("octet-stream".to_string()); - - format!("{}/{}", typ, subtype) -} - -unsafe fn mailmime_is_attachment_disposition(mime: *mut Mailmime) -> bool { - if (*mime).mm_mime_fields.is_null() { - return false; - } - - for cur in (*(*(*mime).mm_mime_fields).fld_list).into_iter() { - let field = cur as *mut mailmime_field; - if !field.is_null() - && (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int - && !(*field).fld_data.fld_disposition.is_null() - { - if !(*(*field).fld_data.fld_disposition).dsp_type.is_null() - && (*(*(*field).fld_data.fld_disposition).dsp_type).dsp_type - == MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int - { - return true; - } - } - } - - false -} - -/* low-level-tools for working with mailmime structures directly */ -pub unsafe fn mailmime_find_ct_parameter( - mime: *mut Mailmime, - name: &str, -) -> *mut mailmime_parameter { - if mime.is_null() - || (*mime).mm_content_type.is_null() - || (*(*mime).mm_content_type).ct_parameters.is_null() - { - return ptr::null_mut(); - } - - for cur in (*(*(*mime).mm_content_type).ct_parameters).into_iter() { - let param = cur as *mut mailmime_parameter; - if !param.is_null() && !(*param).pa_name.is_null() { - if &to_string_lossy((*param).pa_name) == name { - return param; - } - } - } - - ptr::null_mut() -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::test_utils::*; - use proptest::prelude::*; - use std::ffi::CStr; - - #[test] - fn test_mailmime_parse() { - unsafe { - let txt: *const libc::c_char = - b"FieldA: ValueA\nFieldB: ValueB\n\x00" as *const u8 as *const libc::c_char; - let mut mime: *mut Mailmime = ptr::null_mut(); - let mut dummy = 0; - let res = mailmime_parse(txt, strlen(txt), &mut dummy, &mut mime); - assert_eq!(res, MAIL_NO_ERROR as libc::c_int); - assert!(!mime.is_null()); - - let fields: *mut mailimf_fields = wrapmime::mailmime_find_mailimf_fields(mime); - assert!(!fields.is_null()); - - let mut of_a: *mut mailimf_optional_field = wrapmime::mailimf_find_optional_field( - fields, - b"fielda\x00" as *const u8 as *const libc::c_char, - ); - - assert!(!of_a.is_null()); - assert!(!(*of_a).fld_value.is_null()); - assert_eq!( - CStr::from_ptr((*of_a).fld_name as *const libc::c_char) - .to_str() - .unwrap(), - "FieldA", - ); - assert_eq!( - CStr::from_ptr((*of_a).fld_value as *const libc::c_char) - .to_str() - .unwrap(), - "ValueA", - ); - - of_a = wrapmime::mailimf_find_optional_field( - fields, - b"FIELDA\x00" as *const u8 as *const libc::c_char, - ); - - assert!(!of_a.is_null()); - assert!(!(*of_a).fld_value.is_null()); - assert_eq!( - CStr::from_ptr((*of_a).fld_name as *const libc::c_char) - .to_str() - .unwrap(), - "FieldA", - ); - assert_eq!( - CStr::from_ptr((*of_a).fld_value as *const libc::c_char) - .to_str() - .unwrap(), - "ValueA", - ); - - let of_b: *mut mailimf_optional_field = wrapmime::mailimf_find_optional_field( - fields, - b"FieldB\x00" as *const u8 as *const libc::c_char, - ); - - assert!(!of_b.is_null()); - assert!(!(*of_b).fld_value.is_null()); - assert_eq!( - CStr::from_ptr((*of_b).fld_value as *const libc::c_char) - .to_str() - .unwrap(), - "ValueB", - ); - - mailmime_free(mime); - } - } - - #[test] - fn test_dc_mimeparser_crash() { - let context = dummy_context(); - let raw = include_bytes!("../test-data/message/issue_523.txt"); - let mut mimeparser = MimeParser::new(&context.ctx); - unsafe { - mimeparser.parse(&raw[..]).unwrap(); - }; - assert_eq!(mimeparser.subject, None); - assert_eq!(mimeparser.parts.len(), 1); - } - - proptest! { - #[ignore] - #[test] - fn test_dc_mailmime_parse_crash_fuzzy(data in "[!-~\t ]{2000,}") { - let context = dummy_context(); - let mut mimeparser = MimeParser::new(&context.ctx); - - // parsing should always succeed - // but the returned header will normally be empty on random data - assert!(unsafe {mimeparser.parse(data.as_bytes()).is_ok()}); - assert!(mimeparser.header.is_empty()); - } - } - - #[test] - fn test_get_rfc724_mid_exists() { - let context = dummy_context(); - let raw = include_bytes!("../test-data/message/mail_with_message_id.txt"); - let mut mimeparser = MimeParser::new(&context.ctx); - unsafe { mimeparser.parse(&raw[..]).unwrap() }; - assert_eq!( - mimeparser.get_rfc724_mid(), - Some("2dfdbde7@example.org".into()) - ); - } - - #[test] - fn test_get_rfc724_mid_not_exists() { - let context = dummy_context(); - let raw = include_bytes!("../test-data/message/issue_523.txt"); - let mut mimeparser = MimeParser::new(&context.ctx); - unsafe { mimeparser.parse(&raw[..]).unwrap() }; - assert_eq!(mimeparser.get_rfc724_mid(), None); - } - - #[test] - fn test_mimeparser_with_context() { - unsafe { - let context = dummy_context(); - let raw = b"From: hello\nContent-Type: multipart/mixed; boundary=\"==break==\";\nSubject: outer-subject\nX-Special-A: special-a\nFoo: Bar\nChat-Version: 0.0\n\n--==break==\nContent-Type: text/plain; protected-headers=\"v1\";\nSubject: inner-subject\nX-Special-B: special-b\nFoo: Xy\nChat-Version: 1.0\n\ntest1\n\n--==break==--\n\n\x00"; - let mut mimeparser = MimeParser::new(&context.ctx); - mimeparser.parse(&raw[..]).unwrap(); - - assert_eq!(mimeparser.subject, Some("inner-subject".into())); - - let of = mimeparser - .lookup_field("X-Special-A") - .unwrap() - .get_value() - .unwrap(); - assert_eq!(&of, "special-a"); - - let of = mimeparser.lookup_field("Foo").unwrap().get_value().unwrap(); - assert_eq!(&of, "Bar"); - - let of = mimeparser - .lookup_field("Chat-Version") - .unwrap() - .get_value() - .unwrap(); - assert_eq!(&of, "1.0"); - assert_eq!(mimeparser.parts.len(), 1); - } - } -} diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 3168cd3e5..76e73ed8a 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -1,13 +1,4 @@ -use std::ptr; - use itertools::join; -use libc::strcmp; -use mmime::clist::*; -use mmime::mailimf::types::*; -use mmime::mailmime::content::*; -use mmime::mailmime::types::*; -use mmime::mailmime::*; -use mmime::other::*; use sha2::{Digest, Sha256}; use num_traits::FromPrimitive; @@ -18,7 +9,6 @@ use crate::config::Config; use crate::constants::*; use crate::contact::*; use crate::context::Context; -use crate::dc_mimeparser::*; use crate::dc_strencode::*; use crate::dc_tools::*; use crate::error::Result; @@ -26,12 +16,12 @@ use crate::events::Event; use crate::job::*; use crate::location; use crate::message::{self, MessageState, MsgId}; +use crate::mimeparser::*; use crate::param::*; use crate::peerstate::*; use crate::securejoin::handle_securejoin_handshake; use crate::sql; use crate::stock::StockMessage; -use crate::wrapmime; #[derive(Debug, PartialEq, Eq)] enum CreateEvent { @@ -40,7 +30,7 @@ enum CreateEvent { } /// Receive a message and add it to the database. -pub unsafe fn dc_receive_imf( +pub fn dc_receive_imf( context: &Context, imf_raw: &[u8], server_folder: impl AsRef, @@ -63,9 +53,12 @@ pub unsafe fn dc_receive_imf( // we use mailmime_parse() through dc_mimeparser (both call mailimf_struct_multiple_parse() // somewhen, I did not found out anything that speaks against this approach yet) - let mut mime_parser = MimeParser::new(context); - if let Err(err) = mime_parser.parse(imf_raw) { + let mime_parser = MimeParser::from_bytes(context, imf_raw); + let mut mime_parser = if let Err(err) = mime_parser { warn!(context, "dc_receive_imf parse error: {}", err); + return; + } else { + mime_parser.unwrap() }; if mime_parser.header.is_empty() { @@ -77,7 +70,7 @@ pub unsafe fn dc_receive_imf( // the function returns the number of created messages in the database let mut incoming = 1; let mut incoming_origin = Origin::Unknown; - let mut to_self = 0; + let mut to_self = false; let mut from_id = 0u32; let mut from_id_blocked = 0; let mut to_id = 0u32; @@ -122,60 +115,54 @@ pub unsafe fn dc_receive_imf( } }; - if let Some(field) = mime_parser.lookup_field("Date") { - if let Ok(value) = field.get_value() { - // is not yet checked against bad times! we do this later if we have the database information. - // sent_timestamp = dc_timestamp_from_date((*orig_date).dt_date_time) - // TODO - } + if let Some(value) = mime_parser.lookup_field("Date") { + // is not yet checked against bad times! we do this later if we have the database information. + // sent_timestamp = dc_timestamp_from_date((*orig_date).dt_date_time) + // TODO } // 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) = mime_parser.lookup_field("From") { - if let Ok(fld_from) = field.get_value() { - let mut check_self = 0; - // let mut from_list = Vec::with_capacity(16); - // dc_add_or_lookup_contacts_by_mailbox_list( - // context, - // (*fld_from).frm_mb_list, - // Origin::IncomingUnknownFrom, - // &mut from_list, - // &mut check_self, - // ); - // if 0 != check_self { - // incoming = 0; - // if mime_parser.sender_equals_recipient() { - // from_id = DC_CONTACT_ID_SELF; - // } - // } else if !from_list.is_empty() { - // // if there is no from given, from_id stays 0 which is just fine. These messages - // // are very rare, however, we have to add them to the database (they go to the - // // "deaddrop" chat) to avoid a re-download from the server. See also [**] - // from_id = from_list[0]; - // incoming_origin = Contact::get_origin_by_id(context, from_id, &mut from_id_blocked) - // } + if let Some(field_from) = mime_parser.lookup_field("From") { + let mut check_self = false; + let mut from_list = Vec::with_capacity(16); + dc_add_or_lookup_contacts_by_address_list( + context, + &field_from, + Origin::IncomingUnknownFrom, + &mut from_list, + &mut check_self, + ); + if check_self { + incoming = 0; + if mime_parser.sender_equals_recipient() { + from_id = DC_CONTACT_ID_SELF; + } + } else if !from_list.is_empty() { + // if there is no from given, from_id stays 0 which is just fine. These messages + // are very rare, however, we have to add them to the database (they go to the + // "deaddrop" chat) to avoid a re-download from the server. See also [**] + from_id = from_list[0]; + incoming_origin = Contact::get_origin_by_id(context, from_id, &mut from_id_blocked) } } // 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 Ok(fld_to) = field.get_value() { - // dc_add_or_lookup_contacts_by_address_list( - // context, - // (*fld_to).to_addr_list, - // if 0 == incoming { - // Origin::OutgoingTo - // } else if incoming_origin.is_verified() { - // Origin::IncomingTo - // } else { - // Origin::IncomingUnknownTo - // }, - // &mut to_ids, - // &mut to_self, - // ); - } + dc_add_or_lookup_contacts_by_address_list( + context, + &field, + if 0 == incoming { + Origin::OutgoingTo + } else if incoming_origin.is_verified() { + Origin::IncomingTo + } else { + Origin::IncomingUnknownTo + }, + &mut to_ids, + &mut to_self, + ); } // Add parts @@ -243,17 +230,13 @@ pub unsafe fn dc_receive_imf( } } - if !mime_parser.reports.is_empty() { - handle_reports( - context, - &mime_parser, - from_id, - sent_timestamp, - &mut rr_event_to_send, - &server_folder, - server_uid, - ); - } + mime_parser.handle_reports( + from_id, + sent_timestamp, + &mut rr_event_to_send, + &server_folder, + server_uid, + ); if mime_parser.location_kml.is_some() || mime_parser.message_kml.is_some() { save_locations( @@ -292,7 +275,7 @@ pub unsafe fn dc_receive_imf( ); } -unsafe fn add_parts( +fn add_parts( context: &Context, mut mime_parser: &mut MimeParser, imf_raw: &[u8], @@ -310,7 +293,7 @@ unsafe fn add_parts( to_id: &mut u32, flags: u32, needs_delete_job: &mut bool, - to_self: i32, + to_self: bool, insert_msg_id: &mut MsgId, created_db_entries: &mut Vec<(usize, MsgId)>, create_event_to_send: &mut Option, @@ -326,22 +309,20 @@ unsafe 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(field) = mime_parser.lookup_field("Cc") { - if let Ok(fld_cc) = field.get_value() { - // dc_add_or_lookup_contacts_by_address_list( - // context, - // (*fld_cc).cc_addr_list, - // if 0 == incoming { - // Origin::OutgoingCc - // } else if incoming_origin.is_verified() { - // Origin::IncomingCc - // } else { - // Origin::IncomingUnknownCc - // }, - // to_ids, - // std::ptr::null_mut(), - // ); - } + if let Some(fld_cc) = mime_parser.lookup_field("Cc") { + dc_add_or_lookup_contacts_by_address_list( + context, + fld_cc, + if 0 == incoming { + Origin::OutgoingCc + } else if incoming_origin.is_verified() { + Origin::IncomingCc + } else { + Origin::IncomingUnknownCc + }, + to_ids, + &mut false, + ); } // check, if the mail is already in our database - if so, just update the folder/uid @@ -393,7 +374,7 @@ unsafe 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 let Some(_) = mime_parser.lookup_field("Secure-Join") { // avoid discarding by show_emails setting msgrmsg = 1; *chat_id = 0; @@ -567,7 +548,7 @@ unsafe fn add_parts( } } if *chat_id == 0 { - if to_ids.is_empty() && 0 != to_self { + if to_ids.is_empty() && to_self { // from_id==to_id==DC_CONTACT_ID_SELF - this is a self-sent messages, // maybe an Autocrypt Setup Messag let (id, bl) = @@ -605,16 +586,12 @@ unsafe 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(field) = mime_parser.lookup_field("In-Reply-To") { - if let Ok(raw) = field.get_value() { - mime_in_reply_to = raw; - } + if let Some(raw) = mime_parser.lookup_field("In-Reply-To") { + mime_in_reply_to = raw.clone(); } - if let Some(field) = mime_parser.lookup_field("References") { - if let Ok(raw) = field.get_value() { - mime_references = raw; - } + if let Some(raw) = mime_parser.lookup_field("References") { + mime_references = raw.clone(); } // fine, so far. now, split the message into simple parts usable as "short messages" @@ -722,137 +699,6 @@ unsafe fn add_parts( Ok(()) } -// Handle reports (mainly MDNs) -unsafe fn handle_reports( - context: &Context, - mime_parser: &MimeParser, - from_id: u32, - sent_timestamp: i64, - rr_event_to_send: &mut Vec<(u32, MsgId)>, - server_folder: impl AsRef, - server_uid: u32, -) { - let mdns_enabled = context.get_config_bool(Config::MdnsEnabled); - - for report_root in &mime_parser.reports { - let report_root = *report_root; - let mut mdn_consumed = 0; - let report_type = mailmime_find_ct_parameter(report_root, "report-type"); - - if report_root.is_null() || report_type.is_null() || (*report_type).pa_value.is_null() { - continue; - } - - // the first part is for humans, the second for machines - if strcmp( - (*report_type).pa_value, - b"disposition-notification\x00" as *const u8 as *const libc::c_char, - ) == 0 - && (*(*report_root).mm_data.mm_multipart.mm_mp_list).count >= 2 - { - // to get a clear functionality, do not show incoming MDNs if the options is disabled - if mdns_enabled { - let report_data = (if !if !(*(*report_root).mm_data.mm_multipart.mm_mp_list) - .first - .is_null() - { - (*(*(*report_root).mm_data.mm_multipart.mm_mp_list).first).next - } else { - ptr::null_mut() - } - .is_null() - { - (*if !(*(*report_root).mm_data.mm_multipart.mm_mp_list) - .first - .is_null() - { - (*(*(*report_root).mm_data.mm_multipart.mm_mp_list).first).next - } else { - ptr::null_mut() - }) - .data - } else { - ptr::null_mut() - }) as *mut Mailmime; - - if !report_data.is_null() - && (*(*(*report_data).mm_content_type).ct_type).tp_type - == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int - && (*(*(*(*report_data).mm_content_type).ct_type) - .tp_data - .tp_composite_type) - .ct_type - == MAILMIME_COMPOSITE_TYPE_MESSAGE as libc::c_int - && strcmp( - (*(*report_data).mm_content_type).ct_subtype, - b"disposition-notification\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - if let Ok(report_body) = wrapmime::mailmime_transfer_decode(report_data) { - let mut report_parsed = std::ptr::null_mut(); - let mut dummy = 0; - - if mailmime_parse( - report_body.as_ptr() as *const _, - report_body.len(), - &mut dummy, - &mut report_parsed, - ) == MAIL_NO_ERROR as libc::c_int - && !report_parsed.is_null() - { - let report_fields = - wrapmime::mailmime_find_mailimf_fields(report_parsed); - if !report_fields.is_null() { - let of_disposition = wrapmime::mailimf_find_optional_field( - report_fields, - b"Disposition\x00" as *const u8 as *const libc::c_char, - ); - let of_org_msgid = wrapmime::mailimf_find_optional_field( - report_fields, - b"Original-Message-ID\x00" as *const u8 as *const libc::c_char, - ); - if !of_disposition.is_null() - && !(*of_disposition).fld_value.is_null() - && !of_org_msgid.is_null() - && !(*of_org_msgid).fld_value.is_null() - { - if let Ok(rfc724_mid) = - wrapmime::parse_message_id(std::slice::from_raw_parts( - (*of_org_msgid).fld_value as *const u8, - libc::strlen((*of_org_msgid).fld_value), - )) - { - if let Some((chat_id, msg_id)) = message::mdn_from_ext( - context, - from_id, - &rfc724_mid, - sent_timestamp, - ) { - rr_event_to_send.push((chat_id, msg_id)); - mdn_consumed = 1; - } - } - } - } - mailmime_free(report_parsed); - } - } - } - } - - if mime_parser.is_send_by_messenger || 0 != mdn_consumed { - let mut param = Params::new(); - param.set(Param::ServerFolder, server_folder.as_ref()); - param.set_int(Param::ServerUid, server_uid as i32); - if mime_parser.is_send_by_messenger && context.get_config_bool(Config::MvboxMove) { - param.set_int(Param::AlsoMove, 1); - } - job_add(context, Action::MarkseenMdnOnImap, 0, param, 0); - } - } - } -} - fn save_locations( context: &Context, mime_parser: &MimeParser, @@ -906,15 +752,15 @@ fn save_locations( } } -unsafe fn calc_timestamps( +fn calc_timestamps( context: &Context, chat_id: u32, from_id: u32, message_timestamp: i64, is_fresh_msg: libc::c_int, - sort_timestamp: *mut i64, - sent_timestamp: *mut i64, - rcvd_timestamp: *mut i64, + sort_timestamp: &mut i64, + sent_timestamp: &mut i64, + rcvd_timestamp: &mut i64, ) { *rcvd_timestamp = time(); *sent_timestamp = message_timestamp; @@ -953,7 +799,7 @@ unsafe fn calc_timestamps( /// /// So when the function returns, the caller has the group id matching the current state of the group. #[allow(non_snake_case)] -unsafe fn create_or_lookup_group( +fn create_or_lookup_group( context: &Context, mime_parser: &mut MimeParser, allow_creation: libc::c_int, @@ -982,7 +828,7 @@ unsafe fn create_or_lookup_group( chat_id: u32, chat_id_blocked: Blocked| { if !ret_chat_id.is_null() { - *ret_chat_id = chat_id; + unsafe { *ret_chat_id = chat_id }; } *ret_chat_id_blocked = if 0 != chat_id { chat_id_blocked @@ -998,32 +844,24 @@ unsafe fn create_or_lookup_group( set_better_msg(mime_parser, &better_msg); if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-ID") { - grpid = optional_field.get_value().unwrap_or_default(); + grpid = optional_field.clone(); } if grpid.is_empty() { - if let Some(field) = mime_parser.lookup_field("Message-ID") { - if let Ok(value) = field.get_value() { - // if let Some(extracted_grpid) = - // dc_extract_grpid_from_rfc724_mid(&to_string_lossy((*fld_message_id).mid_value)) - // { - // grpid = extracted_grpid.to_string(); - // } else { - // grpid = "".to_string(); - // } + if let Some(value) = mime_parser.lookup_field("Message-ID") { + if let Some(extracted_grpid) = dc_extract_grpid_from_rfc724_mid(&value) { + grpid = extracted_grpid.to_string(); + } else { + grpid = "".to_string(); } } if grpid.is_empty() { - if let Some(field) = mime_parser.lookup_field("In-Reply-To") { - if let Ok(value) = field.get_value() { - grpid = value; - } + if let Some(value) = mime_parser.lookup_field("In-Reply-To") { + grpid = value.clone(); } if grpid.is_empty() { - if let Some(field) = mime_parser.lookup_field("References") { - if let Ok(value) = field.get_value() { - grpid = value; - } + if let Some(value) = mime_parser.lookup_field("References") { + grpid = value.clone(); } if grpid.is_empty() { @@ -1044,11 +882,14 @@ unsafe fn create_or_lookup_group( } } - if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Name") { - grpname = Some(dc_decode_header_words(&optional_field.get_value().unwrap())); + if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Name").cloned() { + grpname = Some(optional_field); } - if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Member-Removed") { - X_MrRemoveFromGrp = optional_field.get_value().ok(); + let field = mime_parser + .lookup_field("Chat-Group-Member-Removed") + .cloned(); + if let Some(optional_field) = field { + 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()) == from_id as u32) as libc::c_int; @@ -1063,11 +904,12 @@ unsafe fn create_or_lookup_group( from_id as u32, ) } else { - if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Member-Added") { - X_MrAddToGrp = optional_field.get_value().ok(); + let field = mime_parser.lookup_field("Chat-Group-Member-Added").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") { - X_MrGrpImageChanged = optional_field.get_value().unwrap(); + if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Image").cloned() { + X_MrGrpImageChanged = optional_field; } better_msg = context.stock_system_msg( StockMessage::MsgAddMember, @@ -1081,7 +923,7 @@ unsafe fn create_or_lookup_group( X_MrGrpNameChanged = 1; better_msg = context.stock_system_msg( StockMessage::MsgGrpName, - &field.unwrap().get_value().unwrap(), + &field.unwrap(), if let Some(ref name) = grpname { name } else { @@ -1089,12 +931,13 @@ unsafe fn create_or_lookup_group( }, from_id as u32, ); - drop(field); + mime_parser.is_system_message = SystemMessage::GroupNameChanged; } else { - if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Image") { + if let Some(optional_field) = mime_parser.lookup_field("Chat-Group-Image").cloned() + { // fld_value is a pointer somewhere into mime_parser, must not be freed - X_MrGrpImageChanged = optional_field.get_value().unwrap(); + X_MrGrpImageChanged = optional_field; mime_parser.is_system_message = SystemMessage::GroupImageChanged; better_msg = context.stock_system_msg( if X_MrGrpImageChanged == "0" { @@ -1324,7 +1167,7 @@ unsafe fn create_or_lookup_group( } /// Handle groups for received messages -unsafe fn create_or_lookup_adhoc_group( +fn create_or_lookup_adhoc_group( context: &Context, mime_parser: &MimeParser, allow_creation: libc::c_int, @@ -1344,7 +1187,7 @@ unsafe fn create_or_lookup_adhoc_group( chat_id: u32, chat_id_blocked: Blocked| { if !ret_chat_id.is_null() { - *ret_chat_id = chat_id; + unsafe { *ret_chat_id = chat_id }; } *ret_chat_id_blocked = chat_id_blocked; }; @@ -1681,42 +1524,30 @@ fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimeParser) -> `In-Reply-To`/`References:` (to support non-Delta-Clients) */ if let Some(field) = mime_parser.lookup_field("In-Reply-To") { - if let Ok(value) = field.get_value() { - // if !fld_in_reply_to.is_null() { - // if is_known_rfc724_mid_in_list( - // context, - // (*(*field).fld_data.fld_in_reply_to).mid_list, - // ) { - // return 1; - // } - // } + if is_known_rfc724_mid_in_list(context, &field) { + return 1; } } if let Some(field) = mime_parser.lookup_field("References") { - if let Ok(value) = field.get_value() { - // if !fld_references.is_null() - // && is_known_rfc724_mid_in_list( - // context, - // (*(*field).fld_data.fld_references).mid_list, - // ) - // { - // return 1; - // } + if is_known_rfc724_mid_in_list(context, &field) { + return 1; } } 0 } -unsafe fn is_known_rfc724_mid_in_list(context: &Context, mid_list: *const clist) -> bool { - if mid_list.is_null() { +fn is_known_rfc724_mid_in_list(context: &Context, mid_list: &String) -> bool { + if mid_list.is_empty() { return false; } - for data in &*mid_list { - if is_known_rfc724_mid(context, data.cast()) != 0 { - return true; + if let Ok(ids) = mailparse::addrparse(mid_list.as_str()) { + for id in ids.iter() { + if is_known_rfc724_mid(context, id) { + return true; + } } } @@ -1724,10 +1555,8 @@ unsafe fn is_known_rfc724_mid_in_list(context: &Context, mid_list: *const clist) } /// Check if a message is a reply to a known message (messenger or non-messenger). -fn is_known_rfc724_mid(context: &Context, rfc724_mid: *const libc::c_char) -> libc::c_int { - if rfc724_mid.is_null() { - return 0; - } +fn is_known_rfc724_mid(context: &Context, rfc724_mid: &mailparse::MailAddr) -> bool { + let addr = extract_single_from_addr(rfc724_mid); context .sql .exists( @@ -1735,116 +1564,92 @@ fn is_known_rfc724_mid(context: &Context, rfc724_mid: *const libc::c_char) -> li LEFT JOIN chats c ON m.chat_id=c.id \ WHERE m.rfc724_mid=? \ AND m.chat_id>9 AND c.blocked=0;", - params![to_string_lossy(rfc724_mid)], + params![addr], ) - .unwrap_or_default() as libc::c_int + .unwrap_or_default() } -unsafe fn dc_is_reply_to_messenger_message( - context: &Context, - mime_parser: &MimeParser, -) -> libc::c_int { +fn dc_is_reply_to_messenger_message(context: &Context, mime_parser: &MimeParser) -> libc::c_int { /* 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 - 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 - no check for the Chat-* headers (function is only called if it is no messenger message itself) */ - if let Some(field) = mime_parser.lookup_field("In-Reply-To") { - if let Ok(value) = field.get_value() { - // if 0 != is_msgrmsg_rfc724_mid_in_list( - // context, - // (*(*field).fld_data.fld_in_reply_to).mid_list, - // ) { - // return 1; - // } + if let Some(value) = mime_parser.lookup_field("In-Reply-To") { + if is_msgrmsg_rfc724_mid_in_list(context, &value) { + return 1; } } - if let Some(field) = mime_parser.lookup_field("References") { - if let Ok(value) = field.get_value() { - // if 0 != is_msgrmsg_rfc724_mid_in_list( - // context, - // (*(*field).fld_data.fld_references).mid_list, - // ) { - // return 1; - // } + if let Some(value) = mime_parser.lookup_field("References") { + if is_msgrmsg_rfc724_mid_in_list(context, &value) { + return 1; } } 0 } -unsafe fn is_msgrmsg_rfc724_mid_in_list(context: &Context, mid_list: *const clist) -> libc::c_int { - if !mid_list.is_null() { - let mut cur: *mut clistiter = (*mid_list).first; - while !cur.is_null() { - if 0 != is_msgrmsg_rfc724_mid( - context, - &to_string_lossy((*cur).data as *const libc::c_char), - ) { - return 1; - } - cur = if !cur.is_null() { - (*cur).next - } else { - ptr::null_mut() +fn is_msgrmsg_rfc724_mid_in_list(context: &Context, mid_list: &String) -> bool { + if let Ok(ids) = mailparse::addrparse(mid_list.as_str()) { + for id in ids.iter() { + if is_msgrmsg_rfc724_mid(context, id) { + return true; } } } - 0 + false +} + +fn extract_single_from_addr(addr: &mailparse::MailAddr) -> &String { + match addr { + mailparse::MailAddr::Group(infos) => &infos.addrs[0].addr, + mailparse::MailAddr::Single(info) => &info.addr, + } } /// Check if a message is a reply to any messenger message. -fn is_msgrmsg_rfc724_mid(context: &Context, rfc724_mid: &str) -> libc::c_int { - if rfc724_mid.is_empty() { - return 0; - } +fn is_msgrmsg_rfc724_mid(context: &Context, rfc724_mid: &mailparse::MailAddr) -> bool { + let addr = extract_single_from_addr(rfc724_mid); context .sql .exists( "SELECT id FROM msgs WHERE rfc724_mid=? AND msgrmsg!=0 AND chat_id>9;", - params![rfc724_mid], + params![addr], ) - .unwrap_or_default() as libc::c_int + .unwrap_or_default() } -unsafe fn dc_add_or_lookup_contacts_by_address_list( +fn dc_add_or_lookup_contacts_by_address_list( context: &Context, - adr_list: *const mailimf_address_list, + addr_list_raw: &str, origin: Origin, ids: &mut Vec, - check_self: *mut libc::c_int, + check_self: &mut bool, ) { - if adr_list.is_null() { + let addrs = mailparse::addrparse(addr_list_raw); + if addrs.is_err() { return; } - let mut cur: *mut clistiter = (*(*adr_list).ad_list).first; - while !cur.is_null() { - let adr: *mut mailimf_address = (if !cur.is_null() { - (*cur).data - } else { - ptr::null_mut() - }) as *mut mailimf_address; - if !adr.is_null() { - if (*adr).ad_type == MAILIMF_ADDRESS_MAILBOX as libc::c_int { - let mb: *mut mailimf_mailbox = (*adr).ad_data.ad_mailbox; - if !mb.is_null() { + for addr in addrs.unwrap().iter() { + match addr { + mailparse::MailAddr::Single(info) => { + add_or_lookup_contact_by_addr( + context, + &info.display_name, + &info.addr, + origin, + ids, + check_self, + ); + } + mailparse::MailAddr::Group(infos) => { + for info in &infos.addrs { add_or_lookup_contact_by_addr( context, - (*mb).mb_display_name, - (*mb).mb_addr_spec, - origin, - ids, - check_self, - ); - } - } else if (*adr).ad_type == MAILIMF_ADDRESS_GROUP as libc::c_int { - let group: *mut mailimf_group = (*adr).ad_data.ad_group; - if !group.is_null() && !(*group).grp_mb_list.is_null() { - dc_add_or_lookup_contacts_by_mailbox_list( - context, - (*group).grp_mb_list, + &info.display_name, + &info.addr, origin, ids, check_self, @@ -1852,93 +1657,42 @@ unsafe fn dc_add_or_lookup_contacts_by_address_list( } } } - cur = if !cur.is_null() { - (*cur).next - } else { - ptr::null_mut() - } - } -} - -unsafe fn dc_add_or_lookup_contacts_by_mailbox_list( - context: &Context, - mb_list: *const mailimf_mailbox_list, - origin: Origin, - ids: &mut Vec, - check_self: *mut libc::c_int, -) { - if mb_list.is_null() { - return; - } - let mut cur: *mut clistiter = (*(*mb_list).mb_list).first; - while !cur.is_null() { - let mb: *mut mailimf_mailbox = (if !cur.is_null() { - (*cur).data - } else { - ptr::null_mut() - }) as *mut mailimf_mailbox; - if !mb.is_null() { - add_or_lookup_contact_by_addr( - context, - (*mb).mb_display_name, - (*mb).mb_addr_spec, - origin, - ids, - check_self, - ); - } - cur = if !cur.is_null() { - (*cur).next - } else { - ptr::null_mut() - } } } /// Add contacts to database on receiving messages. -unsafe fn add_or_lookup_contact_by_addr( +fn add_or_lookup_contact_by_addr( context: &Context, - display_name_enc: *const libc::c_char, - addr_spec: *const libc::c_char, + display_name: &Option, + addr: &String, origin: Origin, ids: &mut Vec, - mut check_self: *mut libc::c_int, + check_self: &mut bool, ) { - /* is addr_spec equal to SELF? */ - let mut dummy: libc::c_int = 0; - if check_self.is_null() { - check_self = &mut dummy - } - if addr_spec.is_null() { - return; - } - *check_self = 0; + // is addr_spec equal to SELF? let self_addr = context .get_config(Config::ConfiguredAddr) .unwrap_or_default(); - if addr_cmp(self_addr, to_string_lossy(addr_spec)) { - *check_self = 1; + if addr_cmp(self_addr, addr) { + *check_self = true; } - if 0 != *check_self { + if *check_self { return; } - /* add addr_spec if missing, update otherwise */ - let mut display_name_dec = "".to_string(); - if !display_name_enc.is_null() { - let tmp = dc_decode_header_words(&to_string_lossy(display_name_enc)); - display_name_dec = normalize_name(&tmp); - } - /*can be NULL*/ - let row_id = Contact::add_or_lookup( - context, - display_name_dec, - to_string_lossy(addr_spec), - origin, - ) - .map(|(id, _)| id) - .unwrap_or_default(); + + // add addr_spec if missing, update otherwise + let display_name_normalized = display_name + .as_ref() + .map(normalize_name) + .unwrap_or_default(); + + // can be NULL + let row_id = Contact::add_or_lookup(context, display_name_normalized, addr, origin) + .map(|(id, _)| id) + .unwrap_or_default(); + if 0 != row_id && !ids.contains(&row_id) { ids.push(row_id); }; diff --git a/src/dc_strencode.rs b/src/dc_strencode.rs index 91f49f375..7f6eb1413 100644 --- a/src/dc_strencode.rs +++ b/src/dc_strencode.rs @@ -5,8 +5,6 @@ use std::ptr; use charset::Charset; use libc::free; -use mmime::mailmime::decode::mailmime_encoded_phrase_parse; -use mmime::other::*; use percent_encoding::{percent_decode, utf8_percent_encode, AsciiSet, CONTROLS}; use crate::dc_tools::*; @@ -68,31 +66,6 @@ fn quote_word(word: &[u8]) -> String { * Encode/decode header words, RFC 2047 ******************************************************************************/ -pub(crate) fn dc_decode_header_words(input: &str) -> String { - static FROM_ENCODING: &[u8] = b"iso-8859-1\x00"; - static TO_ENCODING: &[u8] = b"utf-8\x00"; - let mut out = ptr::null_mut(); - let mut cur_token = 0; - let input_c = CString::yolo(input); - unsafe { - let r = mailmime_encoded_phrase_parse( - FROM_ENCODING.as_ptr().cast(), - input_c.as_ptr(), - input.len(), - &mut cur_token, - TO_ENCODING.as_ptr().cast(), - &mut out, - ); - if r as u32 != MAILIMF_NO_ERROR || out.is_null() { - input.to_string() - } else { - let res = to_string_lossy(out); - free(out.cast()); - res - } - } -} - pub fn dc_needs_ext_header(to_check: impl AsRef) -> bool { let to_check = to_check.as_ref(); @@ -156,33 +129,6 @@ pub fn dc_decode_ext_header(to_decode: &[u8]) -> Cow { mod tests { use super::*; - #[test] - fn test_dc_decode_header_words() { - assert_eq!( - dc_decode_header_words("=?utf-8?B?dGVzdMOkw7bDvC50eHQ=?="), - std::string::String::from_utf8(b"test\xc3\xa4\xc3\xb6\xc3\xbc.txt".to_vec()).unwrap(), - ); - - assert_eq!(dc_decode_header_words("just ascii test"), "just ascii test"); - - assert_eq!(dc_encode_header_words("abcdef"), "abcdef"); - - let r = dc_encode_header_words( - std::string::String::from_utf8(b"test\xc3\xa4\xc3\xb6\xc3\xbc.txt".to_vec()).unwrap(), - ); - assert!(r.starts_with("=?utf-8")); - - assert_eq!( - dc_decode_header_words(&r), - std::string::String::from_utf8(b"test\xc3\xa4\xc3\xb6\xc3\xbc.txt".to_vec()).unwrap(), - ); - - assert_eq!( - dc_decode_header_words("=?ISO-8859-1?Q?attachment=3B=0D=0A_filename=3D?= =?ISO-8859-1?Q?=22test=E4=F6=FC=2Etxt=22=3B=0D=0A_size=3D39?="), - std::string::String::from_utf8(b"attachment;\r\n filename=\"test\xc3\xa4\xc3\xb6\xc3\xbc.txt\";\r\n size=39".to_vec()).unwrap(), - ); - } - #[test] fn test_dc_encode_ext_header() { let buf1 = dc_encode_ext_header("Björn Petersen"); @@ -239,13 +185,5 @@ mod tests { // make sure this never panics let _decoded = dc_decode_ext_header(&buf); } - - #[test] - fn test_dc_header_roundtrip(input: String) { - let encoded = dc_encode_header_words(&input); - let decoded = dc_decode_header_words(&encoded); - - assert_eq!(input, decoded); - } } } diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 255e73a2a..87db1b882 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -11,8 +11,6 @@ use std::{fmt, fs, ptr}; use chrono::{Local, TimeZone}; use libc::{memcpy, strlen}; -use mmime::clist::*; -use mmime::mailimf::types::*; use rand::{thread_rng, Rng}; use crate::context::Context; @@ -74,36 +72,12 @@ pub(crate) fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Co } } -pub(crate) fn dc_str_from_clist(list: *const clist, delimiter: &str) -> String { - let mut res = String::new(); - - if !list.is_null() { - for rfc724_mid in unsafe { (*list).into_iter() } { - if !res.is_empty() { - res += delimiter; - } - res += &to_string_lossy(rfc724_mid as *const libc::c_char); - } - } - res -} - -pub(crate) fn dc_str_to_clist(str: &str, delimiter: &str) -> *mut clist { - unsafe { - let list: *mut clist = clist_new(); - for cur in str.split(&delimiter) { - clist_insert_after(list, (*list).last, cur.strdup().cast()); - } - list - } -} - -/* the colors must fulfill some criterions as: -- contrast to black and to white -- work as a text-color -- being noticeable on a typical map -- harmonize together while being different enough -(therefore, we cannot just use random rgb colors :) */ +/// the colors must fulfill some criterions as: +/// - contrast to black and to white +/// - work as a text-color +/// - being noticeable on a typical map +/// - harmonize together while being different enough +/// (therefore, we cannot just use random rgb colors :) const COLORS: [u32; 16] = [ 0xe56555, 0xf28c48, 0x8e85ee, 0x76c84d, 0x5bb6cc, 0x549cdd, 0xd25c99, 0xb37800, 0xf23030, 0x39b249, 0xbb243b, 0x964078, 0x66874f, 0x308ab9, 0x127ed0, 0xbe450c, @@ -124,30 +98,30 @@ pub(crate) fn dc_str_to_color(s: impl AsRef) -> u32 { /* date/time tools */ /* the result is UTC or DC_INVALID_TIMESTAMP */ -pub(crate) fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 { - assert!(!date_time.is_null()); - let dt = unsafe { *date_time }; +// pub(crate) fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 { +// assert!(!date_time.is_null()); +// let dt = { *date_time }; - let sec = dt.dt_sec; - let min = dt.dt_min; - let hour = dt.dt_hour; - let day = dt.dt_day; - let month = dt.dt_month; - let year = dt.dt_year; +// let sec = dt.dt_sec; +// let min = dt.dt_min; +// let hour = dt.dt_hour; +// let day = dt.dt_day; +// let month = dt.dt_month; +// let year = dt.dt_year; - let ts = chrono::NaiveDateTime::new( - chrono::NaiveDate::from_ymd(year, month as u32, day as u32), - chrono::NaiveTime::from_hms(hour as u32, min as u32, sec as u32), - ); +// let ts = chrono::NaiveDateTime::new( +// chrono::NaiveDate::from_ymd(year, month as u32, day as u32), +// chrono::NaiveTime::from_hms(hour as u32, min as u32, sec as u32), +// ); - let (zone_hour, zone_min) = if dt.dt_zone >= 0 { - (dt.dt_zone / 100, dt.dt_zone % 100) - } else { - (-(-dt.dt_zone / 100), -(-dt.dt_zone % 100)) - }; +// let (zone_hour, zone_min) = if dt.dt_zone >= 0 { +// (dt.dt_zone / 100, dt.dt_zone % 100) +// } else { +// (-(-dt.dt_zone / 100), -(-dt.dt_zone % 100)) +// }; - ts.timestamp() - (zone_hour * 3600 + zone_min * 60) as i64 -} +// ts.timestamp() - (zone_hour * 3600 + zone_min * 60) as i64 +// } /* ****************************************************************************** * date/time tools @@ -318,22 +292,6 @@ pub(crate) fn dc_extract_grpid_from_rfc724_mid(mid: &str) -> Option<&str> { None } -pub(crate) fn dc_extract_grpid_from_rfc724_mid_list(list: *const clist) -> *mut libc::c_char { - if !list.is_null() { - unsafe { - for cur in (*list).into_iter() { - let mid = to_string_lossy(cur as *const libc::c_char); - - if let Some(grpid) = dc_extract_grpid_from_rfc724_mid(&mid) { - return grpid.strdup(); - } - } - } - } - - ptr::null_mut() -} - pub(crate) fn dc_ensure_no_slash_safe(path: &str) -> &str { if path.ends_with('/') || path.ends_with('\\') { return &path[..path.len() - 1]; @@ -1009,44 +967,6 @@ mod tests { ); } - /* calls free() for each item content */ - unsafe fn clist_free_content(haystack: *const clist) { - let mut iter = (*haystack).first; - - while !iter.is_null() { - free((*iter).data); - (*iter).data = ptr::null_mut(); - iter = if !iter.is_null() { - (*iter).next - } else { - ptr::null_mut() - } - } - } - - #[test] - fn test_dc_str_to_clist_1() { - unsafe { - let list = dc_str_to_clist("", " "); - assert_eq!((*list).count, 1); - clist_free_content(list); - clist_free(list); - } - } - - #[test] - fn test_dc_str_to_clist_4() { - unsafe { - let list: *mut clist = dc_str_to_clist("foo bar test", " "); - assert_eq!((*list).count, 3); - let str = dc_str_from_clist(list, " "); - assert_eq!(str, "foo bar test"); - - clist_free_content(list); - clist_free(list); - } - } - #[test] fn test_dc_create_id() { let buf = dc_create_id(); diff --git a/src/e2ee.rs b/src/e2ee.rs index 76e611a39..4f2898715 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -1,28 +1,12 @@ //! End-to-end encryption support. use std::collections::HashSet; -use std::ptr; -use std::str::FromStr; -use libc::strlen; -use mmime::clist::*; -use mmime::mailimf::types::*; -use mmime::mailimf::types_helper::*; -use mmime::mailimf::*; -use mmime::mailmime::content::*; -use mmime::mailmime::types::*; -use mmime::mailmime::types_helper::*; -use mmime::mailmime::write_mem::*; -use mmime::mailmime::*; -use mmime::mailprivacy_prepare_mime; -use mmime::mmapstring::*; -use mmime::{mailmime_substitute, MAILIMF_NO_ERROR, MAIL_NO_ERROR}; use num_traits::FromPrimitive; use crate::aheader::*; use crate::config::Config; use crate::context::Context; -use crate::dc_tools::*; use crate::error::*; use crate::key::*; use crate::keyring::*; @@ -31,7 +15,6 @@ use crate::peerstate::*; use crate::pgp; use crate::securejoin::handle_degrade_event; use crate::wrapmime; -use crate::wrapmime::*; // standard mime-version header aka b"Version: 1\r\n\x00" static mut VERSION_CONTENT: [libc::c_char; 13] = @@ -77,203 +60,203 @@ impl EncryptHelper { e2ee_guaranteed: bool, min_verified: PeerstateVerifiedStatus, do_gossip: bool, - mut in_out_message: *mut Mailmime, - imffields_unprotected: *mut mailimf_fields, - ) -> Result { - // libEtPan's pgp_encrypt_mime() takes the parent as the new root. - // We just expect the root as being given to this function. - ensure!( - !in_out_message.is_null() && unsafe { (*in_out_message).mm_parent.is_null() }, - "corrupted inputs" - ); + mut in_out_message: lettre_email::Email, + imffields_unprotected: Vec, + ) -> Result { + unimplemented!() + // // libEtPan's pgp_encrypt_mime() takes the parent as the new root. + // // We just expect the root as being given to this function. + // ensure!( + // !in_out_message.is_null() && { (*in_out_message).mm_parent.is_null() }, + // "corrupted inputs" + // ); - if !(self.prefer_encrypt == EncryptPreference::Mutual || e2ee_guaranteed) { - return Ok(false); - } + // if !(self.prefer_encrypt == EncryptPreference::Mutual || e2ee_guaranteed) { + // return Ok(false); + // } - let context = &factory.context; - let mut keyring = Keyring::default(); - let mut gossip_headers: Vec = Vec::with_capacity(factory.recipients_addr.len()); + // let context = &factory.context; + // let mut keyring = Keyring::default(); + // let mut gossip_headers: Vec = Vec::with_capacity(factory.recipients_addr.len()); - // determine if we can and should encrypt - for recipient_addr in factory.recipients_addr.iter() { - if recipient_addr == &self.addr { - continue; - } - let peerstate = match Peerstate::from_addr(context, &context.sql, recipient_addr) { - Some(peerstate) => peerstate, - None => { - let msg = format!("peerstate for {} missing, cannot encrypt", recipient_addr); - if e2ee_guaranteed { - return Err(format_err!("{}", msg)); - } else { - info!(context, "{}", msg); - return Ok(false); - } - } - }; + // // determine if we can and should encrypt + // for recipient_addr in factory.recipients_addr.iter() { + // if recipient_addr == &self.addr { + // continue; + // } + // let peerstate = match Peerstate::from_addr(context, &context.sql, recipient_addr) { + // Some(peerstate) => peerstate, + // None => { + // let msg = format!("peerstate for {} missing, cannot encrypt", recipient_addr); + // if e2ee_guaranteed { + // return Err(format_err!("{}", msg)); + // } else { + // info!(context, "{}", msg); + // return Ok(false); + // } + // } + // }; - if peerstate.prefer_encrypt != EncryptPreference::Mutual && !e2ee_guaranteed { - info!(context, "peerstate for {} is no-encrypt", recipient_addr); - return Ok(false); - } + // if peerstate.prefer_encrypt != EncryptPreference::Mutual && !e2ee_guaranteed { + // info!(context, "peerstate for {} is no-encrypt", recipient_addr); + // return Ok(false); + // } - if let Some(key) = peerstate.peek_key(min_verified) { - keyring.add_owned(key.clone()); - if do_gossip { - if let Some(header) = peerstate.render_gossip_header(min_verified) { - gossip_headers.push(header.to_string()); - } - } - } else { - bail!( - "proper enc-key for {} missing, cannot encrypt", - recipient_addr - ); - } - } + // if let Some(key) = peerstate.peek_key(min_verified) { + // keyring.add_owned(key.clone()); + // if do_gossip { + // if let Some(header) = peerstate.render_gossip_header(min_verified) { + // gossip_headers.push(header.to_string()); + // } + // } + // } else { + // bail!( + // "proper enc-key for {} missing, cannot encrypt", + // recipient_addr + // ); + // } + // } - let sign_key = { - keyring.add_ref(&self.public_key); - let key = Key::from_self_private(context, self.addr.clone(), &context.sql); - ensure!(key.is_some(), "no own private key found"); + // let sign_key = { + // keyring.add_ref(&self.public_key); + // let key = Key::from_self_private(context, self.addr.clone(), &context.sql); + // ensure!(key.is_some(), "no own private key found"); - key - }; + // key + // }; - // encrypt message - unsafe { - mailprivacy_prepare_mime(in_out_message); - let mut part_to_encrypt = (*in_out_message).mm_data.mm_message.mm_msg_mime; - (*part_to_encrypt).mm_parent = ptr::null_mut(); - let imffields_encrypted = mailimf_fields_new_empty(); + // // encrypt message + // { + // mailprivacy_prepare_mime(in_out_message); + // let mut part_to_encrypt = (*in_out_message).mm_data.mm_message.mm_msg_mime; + // (*part_to_encrypt).mm_parent = ptr::null_mut(); + // let imffields_encrypted = mailimf_fields_new_empty(); - // mailmime_new_message_data() calls mailmime_fields_new_with_version() - // which would add the unwanted MIME-Version:-header - let message_to_encrypt = mailmime_new_simple( - MAILMIME_MESSAGE as libc::c_int, - mailmime_fields_new_empty(), - mailmime_get_content_message(), - imffields_encrypted, - part_to_encrypt, - ); + // // mailmime_new_message_data() calls mailmime_fields_new_with_version() + // // which would add the unwanted MIME-Version:-header + // let message_to_encrypt = mailmime_new_simple( + // MAILMIME_MESSAGE as libc::c_int, + // mailmime_fields_new_empty(), + // mailmime_get_content_message(), + // imffields_encrypted, + // part_to_encrypt, + // ); - for header in &gossip_headers { - wrapmime::new_custom_field(imffields_encrypted, "Autocrypt-Gossip", &header) - } + // for header in &gossip_headers { + // wrapmime::new_custom_field(imffields_encrypted, "Autocrypt-Gossip", &header) + // } - // memoryhole headers: move some headers into encrypted part - // XXX note we can't use clist's into_iter() because the loop body also removes items - let mut cur = (*(*imffields_unprotected).fld_list).first; - while !cur.is_null() { - let field = (*cur).data as *mut mailimf_field; - let mut move_to_encrypted = false; + // // memoryhole headers: move some headers into encrypted part + // // XXX note we can't use clist's into_iter() because the loop body also removes items + // let mut cur = (*(*imffields_unprotected).fld_list).first; + // while !cur.is_null() { + // let field = (*cur).data as *mut mailimf_field; + // let mut move_to_encrypted = false; - if !field.is_null() { - if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { - move_to_encrypted = true; - } else if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { - let opt_field = (*field).fld_data.fld_optional_field; - if !opt_field.is_null() && !(*opt_field).fld_name.is_null() { - let fld_name = to_string_lossy((*opt_field).fld_name); - if fld_name.starts_with("Secure-Join") - || (fld_name.starts_with("Chat-") && fld_name != "Chat-Version") - { - move_to_encrypted = true; - } - } - } - } + // if !field.is_null() { + // if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { + // move_to_encrypted = true; + // } else if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { + // let opt_field = (*field).fld_data.fld_optional_field; + // if !opt_field.is_null() && !(*opt_field).fld_name.is_null() { + // let fld_name = to_string_lossy((*opt_field).fld_name); + // if fld_name.starts_with("Secure-Join") + // || (fld_name.starts_with("Chat-") && fld_name != "Chat-Version") + // { + // move_to_encrypted = true; + // } + // } + // } + // } - if move_to_encrypted { - mailimf_fields_add(imffields_encrypted, field); - cur = clist_delete((*imffields_unprotected).fld_list, cur); - } else { - cur = (*cur).next; - } - } + // if move_to_encrypted { + // mailimf_fields_add(imffields_encrypted, field); + // cur = clist_delete((*imffields_unprotected).fld_list, cur); + // } else { + // cur = (*cur).next; + // } + // } - let subject = mailimf_subject_new("...".strdup()); - mailimf_fields_add(imffields_unprotected, mailimf_field_new_subject(subject)); + // let subject = mailimf_subject_new("...".strdup()); + // mailimf_fields_add(imffields_unprotected, mailimf_field_new_subject(subject)); - wrapmime::append_ct_param( - (*part_to_encrypt).mm_content_type, - "protected-headers", - "v1", - )?; - let plain = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - let mut col = 0; - mailmime_write_mem(plain, &mut col, message_to_encrypt); - mailmime_free(message_to_encrypt); + // wrapmime::append_ct_param( + // (*part_to_encrypt).mm_content_type, + // "protected-headers", + // "v1", + // )?; + // let plain = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); + // let mut col = 0; + // mailmime_write_mem(plain, &mut col, message_to_encrypt); + // mailmime_free(message_to_encrypt); - ensure!( - !(*plain).str_0.is_null() && (*plain).len > 0, - "could not write/allocate" - ); + // ensure!( + // !(*plain).str_0.is_null() && (*plain).len > 0, + // "could not write/allocate" + // ); - let ctext = pgp::pk_encrypt( - std::slice::from_raw_parts((*plain).str_0 as *const u8, (*plain).len), - &keyring, - sign_key.as_ref(), - ); - mmap_string_free(plain); + // let ctext = pgp::pk_encrypt( + // std::slice::from_raw_parts((*plain).str_0 as *const u8, (*plain).len), + // &keyring, + // sign_key.as_ref(), + // ); + // mmap_string_free(plain); - let ctext_v = ctext?; + // let ctext_v = ctext?; - // create MIME-structure that will contain the encrypted text - let mut encrypted_part = new_data_part( - ptr::null_mut(), - 0 as libc::size_t, - "multipart/encrypted", - MAILMIME_MECHANISM_BASE64, - )?; - let content = (*encrypted_part).mm_content_type; - wrapmime::append_ct_param(content, "protocol", "application/pgp-encrypted")?; + // // create MIME-structure that will contain the encrypted text + // let mut encrypted_part = new_data_part( + // ptr::null_mut(), + // 0 as libc::size_t, + // "multipart/encrypted", + // MAILMIME_MECHANISM_BASE64, + // )?; + // let content = (*encrypted_part).mm_content_type; + // wrapmime::append_ct_param(content, "protocol", "application/pgp-encrypted")?; - let version_mime = new_data_part( - VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void, - strlen(VERSION_CONTENT.as_mut_ptr()), - "application/pgp-encrypted", - MAILMIME_MECHANISM_7BIT, - )?; - mailmime_smart_add_part(encrypted_part, version_mime); + // let version_mime = new_data_part( + // VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void, + // strlen(VERSION_CONTENT.as_mut_ptr()), + // "application/pgp-encrypted", + // MAILMIME_MECHANISM_7BIT, + // )?; + // mailmime_smart_add_part(encrypted_part, version_mime); - // we assume that ctext_v is not dropped until the end - // of this if-scope - let ctext_part = new_data_part( - ctext_v.as_ptr() as *mut libc::c_void, - ctext_v.len(), - "application/octet-stream", - MAILMIME_MECHANISM_7BIT, - )?; + // // we assume that ctext_v is not dropped until the end + // // of this if-scope + // let ctext_part = new_data_part( + // ctext_v.as_ptr() as *mut libc::c_void, + // ctext_v.len(), + // "application/octet-stream", + // MAILMIME_MECHANISM_7BIT, + // )?; - mailmime_smart_add_part(encrypted_part, ctext_part); - (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; - (*encrypted_part).mm_parent = in_out_message; - let gossiped = !&gossip_headers.is_empty(); - factory.finalize_mime_message(in_out_message, true, gossiped)?; + // mailmime_smart_add_part(encrypted_part, ctext_part); + // (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; + // (*encrypted_part).mm_parent = in_out_message; + // let gossiped = !&gossip_headers.is_empty(); + // factory.finalize_mime_message(in_out_message, true, gossiped)?; - Ok(true) - } + // Ok(true) + // } } } pub fn try_decrypt( context: &Context, - in_out_message: *mut Mailmime, -) -> Result<(bool, HashSet, HashSet)> { - // just a pointer into mailmime structure, must not be freed - let imffields = mailmime_find_mailimf_fields(in_out_message); - ensure!( - !in_out_message.is_null() && !imffields.is_null(), - "corrupt invalid mime inputs" - ); + mail: &mailparse::ParsedMail<'_>, +) -> Result<(Option>, HashSet, HashSet)> { + use mailparse::MailHeaderMap; - let from = wrapmime::get_field_from(imffields)?; - let message_time = wrapmime::get_field_date(imffields)?; + let from = mail.headers.get_first_value("From")?.unwrap_or_default(); + let message_time = mail + .headers + .get_first_value("Date")? + .and_then(|v| v.parse().ok()) + .unwrap_or_default(); let mut peerstate = None; - let autocryptheader = Aheader::from_imffields(&from, imffields); + let autocryptheader = Aheader::from_imffields(&from, &mail.headers); if message_time > 0 { peerstate = Peerstate::from_addr(context, &context.sql, &from); @@ -282,9 +265,7 @@ pub fn try_decrypt( if let Some(ref header) = autocryptheader { peerstate.apply_header(&header, message_time); peerstate.save_to_db(&context.sql, false)?; - } else if message_time > peerstate.last_seen_autocrypt - && !contains_report(in_out_message) - { + } else if message_time > peerstate.last_seen_autocrypt && !contains_report(mail) { peerstate.degrade_encryption(message_time); peerstate.save_to_db(&context.sql, false)?; } @@ -297,10 +278,9 @@ pub fn try_decrypt( /* possibly perform decryption */ let mut private_keyring = Keyring::default(); let mut public_keyring_for_validate = Keyring::default(); - let mut encrypted = false; - let mut signatures = HashSet::default(); + let mut out_mail = None; let mut gossipped_addr = HashSet::default(); - + let mut signatures = HashSet::default(); let self_addr = context.get_config(Config::ConfiguredAddr); if let Some(self_addr) = self_addr { @@ -320,61 +300,60 @@ pub fn try_decrypt( } } - let mut gossip_headers = ptr::null_mut(); - encrypted = decrypt_if_autocrypt_message( + out_mail = decrypt_if_autocrypt_message( context, - in_out_message, + mail, &private_keyring, &public_keyring_for_validate, &mut signatures, - &mut gossip_headers, )?; - if !gossip_headers.is_null() { - gossipped_addr = - update_gossip_peerstates(context, message_time, imffields, gossip_headers)?; - unsafe { mailimf_fields_free(gossip_headers) }; - } + + // TODO: + // if !gossip_headers.is_empty() { + // gossipped_addr = + // update_gossip_peerstates(context, message_time, imffields, gossip_headers)?; + // } } } - Ok((encrypted, signatures, gossipped_addr)) + Ok((out_mail, signatures, gossipped_addr)) } -fn new_data_part( - data: *mut libc::c_void, - data_bytes: libc::size_t, - content_type: &str, - default_encoding: u32, -) -> Result<*mut Mailmime> { - let content = new_content_type(&content_type)?; - let mut encoding = ptr::null_mut(); - if wrapmime::content_type_needs_encoding(content) { - encoding = unsafe { mailmime_mechanism_new(default_encoding as i32, ptr::null_mut()) }; - ensure!(!encoding.is_null(), "failed to create encoding"); - } - let mime_fields = { - unsafe { - mailmime_fields_new_with_data( - encoding, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ) - } - }; - ensure!(!mime_fields.is_null(), "internal mime error"); - - let mime = unsafe { mailmime_new_empty(content, mime_fields) }; - ensure!(!mime.is_null(), "internal mime error"); - - if unsafe { (*mime).mm_type } == MAILMIME_SINGLE as libc::c_int { - if !data.is_null() && data_bytes > 0 { - unsafe { mailmime_set_body_text(mime, data as *mut libc::c_char, data_bytes) }; - } - } - - Ok(mime) -} +// fn new_data_part( +// data: *mut libc::c_void, +// data_bytes: libc::size_t, +// content_type: &str, +// default_encoding: u32, +// ) -> Result<*mut Mailmime> { +// let content = new_content_type(&content_type)?; +// let mut encoding = ptr::null_mut(); +// if wrapmime::content_type_needs_encoding(content) { +// encoding = { mailmime_mechanism_new(default_encoding as i32, ptr::null_mut()) }; +// ensure!(!encoding.is_null(), "failed to create encoding"); +// } +// let mime_fields = { +// { +// mailmime_fields_new_with_data( +// encoding, +// ptr::null_mut(), +// ptr::null_mut(), +// ptr::null_mut(), +// ptr::null_mut(), +// ) +// } +// }; +// ensure!(!mime_fields.is_null(), "internal mime error"); +// +// let mime = { mailmime_new_empty(content, mime_fields) }; +// ensure!(!mime.is_null(), "internal mime error"); +// +// if { (*mime).mm_type } == MAILMIME_SINGLE as libc::c_int { +// if !data.is_null() && data_bytes > 0 { +// { mailmime_set_body_text(mime, data as *mut libc::c_char, data_bytes) }; +// } +// } +// +// Ok(mime) +// } /// Load public key from database or generate a new one. /// @@ -423,204 +402,158 @@ fn load_or_generate_self_public_key(context: &Context, self_addr: impl AsRef Result> { +// // XXX split the parsing from the modification part +// let mut recipients: Option> = None; +// let mut gossipped_addr: HashSet = Default::default(); + +// for cur_data in { (*(*gossip_headers).fld_list).into_iter() } { +// let field = cur_data as *mut mailimf_field; +// if field.is_null() { +// continue; +// } + +// let field = { *field }; + +// if field.fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { +// let optional_field = { field.fld_data.fld_optional_field }; +// if optional_field.is_null() { +// continue; +// } + +// let optional_field = { *optional_field }; +// if !optional_field.fld_name.is_null() +// && to_string_lossy(optional_field.fld_name) == "Autocrypt-Gossip" +// { +// let value = to_string_lossy(optional_field.fld_value); +// let gossip_header = Aheader::from_str(&value); + +// if let Ok(ref header) = gossip_header { +// if recipients.is_none() { +// recipients = Some(mailimf_get_recipients(imffields)); +// } +// if recipients.as_ref().unwrap().contains(&header.addr) { +// let mut peerstate = +// Peerstate::from_addr(context, &context.sql, &header.addr); +// if let Some(ref mut peerstate) = peerstate { +// peerstate.apply_gossip(header, message_time); +// peerstate.save_to_db(&context.sql, false)?; +// } else { +// let p = Peerstate::from_gossip(context, header, message_time); +// p.save_to_db(&context.sql, true)?; +// peerstate = Some(p); +// } +// if let Some(peerstate) = peerstate { +// if peerstate.degrade_event.is_some() { +// handle_degrade_event(context, &peerstate)?; +// } +// } + +// gossipped_addr.insert(header.addr.clone()); +// } else { +// info!( +// context, +// "Ignoring gossipped \"{}\" as the address is not in To/Cc list.", +// &header.addr, +// ); +// } +// } +// } +// } +// } + +// Ok(gossipped_addr) +// } + +fn decrypt_if_autocrypt_message<'a>( context: &Context, - message_time: i64, - imffields: *mut mailimf_fields, - gossip_headers: *const mailimf_fields, -) -> Result> { - // XXX split the parsing from the modification part - let mut recipients: Option> = None; - let mut gossipped_addr: HashSet = Default::default(); - - for cur_data in unsafe { (*(*gossip_headers).fld_list).into_iter() } { - let field = cur_data as *mut mailimf_field; - if field.is_null() { - continue; - } - - let field = unsafe { *field }; - - if field.fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { - let optional_field = unsafe { field.fld_data.fld_optional_field }; - if optional_field.is_null() { - continue; - } - - let optional_field = unsafe { *optional_field }; - if !optional_field.fld_name.is_null() - && to_string_lossy(optional_field.fld_name) == "Autocrypt-Gossip" - { - let value = to_string_lossy(optional_field.fld_value); - let gossip_header = Aheader::from_str(&value); - - if let Ok(ref header) = gossip_header { - if recipients.is_none() { - recipients = Some(mailimf_get_recipients(imffields)); - } - if recipients.as_ref().unwrap().contains(&header.addr) { - let mut peerstate = - Peerstate::from_addr(context, &context.sql, &header.addr); - if let Some(ref mut peerstate) = peerstate { - peerstate.apply_gossip(header, message_time); - peerstate.save_to_db(&context.sql, false)?; - } else { - let p = Peerstate::from_gossip(context, header, message_time); - p.save_to_db(&context.sql, true)?; - peerstate = Some(p); - } - if let Some(peerstate) = peerstate { - if peerstate.degrade_event.is_some() { - handle_degrade_event(context, &peerstate)?; - } - } - - gossipped_addr.insert(header.addr.clone()); - } else { - info!( - context, - "Ignoring gossipped \"{}\" as the address is not in To/Cc list.", - &header.addr, - ); - } - } - } - } - } - - Ok(gossipped_addr) -} - -fn decrypt_if_autocrypt_message( - context: &Context, - mime_undetermined: *mut Mailmime, + mail: &mailparse::ParsedMail<'a>, private_keyring: &Keyring, public_keyring_for_validate: &Keyring, ret_valid_signatures: &mut HashSet, - ret_gossip_headers: *mut *mut mailimf_fields, -) -> Result { - /* The returned bool is true if we detected an Autocrypt-encrypted - message and successfully decrypted it. Decryption then modifies the - passed in mime structure in place. The returned bool is false - if it was not an Autocrypt message. +) -> Result>> { + // The returned bool is true if we detected an Autocrypt-encrypted + // message and successfully decrypted it. Decryption then modifies the + // passed in mime structure in place. The returned bool is false + // if it was not an Autocrypt message. + // + // Errors are returned for failures related to decryption of AC-messages. - Errors are returned for failures related to decryption of AC-messages. - */ - ensure!(!mime_undetermined.is_null(), "Invalid mime reference"); - - let (mime, encrypted_data_part) = match wrapmime::get_autocrypt_mime(mime_undetermined) { + let encrypted_data_part = match wrapmime::get_autocrypt_mime(mail) { Err(_) => { // not a proper autocrypt message, abort and ignore - return Ok(false); + return Ok(None); } Ok(res) => res, }; - let decrypted_mime = decrypt_part( + let decrypted = decrypt_part( context, encrypted_data_part, private_keyring, public_keyring_for_validate, ret_valid_signatures, )?; - // decrypted_mime is a dangling pointer which we now put into mailmime's Ownership - unsafe { - mailmime_substitute(mime, decrypted_mime); - mailmime_free(mime); - } // finally, let's also return gossip headers // XXX better return parsed headers so that upstream // does not need to dive into mmime-stuff again. - unsafe { - if (*ret_gossip_headers).is_null() && !ret_valid_signatures.is_empty() { - let mut dummy: libc::size_t = 0; - let mut test: *mut mailimf_fields = ptr::null_mut(); - if mailimf_envelope_and_optional_fields_parse( - (*decrypted_mime).mm_mime_start, - (*decrypted_mime).mm_length, - &mut dummy, - &mut test, - ) == MAILIMF_NO_ERROR as libc::c_int - && !test.is_null() - { - *ret_gossip_headers = test; - } - } - } + // { + // if (*ret_gossip_headers).is_null() && !ret_valid_signatures.is_empty() { + // let mut dummy: libc::size_t = 0; + // let mut test: *mut mailimf_fields = ptr::null_mut(); + // if mailimf_envelope_and_optional_fields_parse( + // (*decrypted_mime).mm_mime_start, + // (*decrypted_mime).mm_length, + // &mut dummy, + // &mut test, + // ) == MAILIMF_NO_ERROR as libc::c_int + // && !test.is_null() + // { + // *ret_gossip_headers = test; + // } + // } + // } - Ok(true) + Ok(decrypted) } +/// Returns Ok(None) if nothing encrypted was found. fn decrypt_part( _context: &Context, - mime: *mut Mailmime, + mail: &mailparse::ParsedMail<'_>, private_keyring: &Keyring, public_keyring_for_validate: &Keyring, ret_valid_signatures: &mut HashSet, -) -> Result<*mut Mailmime> { - let mime_data: *mut mailmime_data; - let mut mime_transfer_encoding = MAILMIME_MECHANISM_BINARY as libc::c_int; +) -> Result>> { + ensure!( + wrapmime::has_decryptable_data(mail), + "No decryptable data found" + ); - unsafe { - mime_data = (*mime).mm_data.mm_single; - } - if !wrapmime::has_decryptable_data(mime_data) { - return Ok(ptr::null_mut()); - } - - if let Some(enc) = wrapmime::get_mime_transfer_encoding(mime) { - mime_transfer_encoding = enc; - } - - let data: Vec = wrapmime::decode_dt_data(mime_data, mime_transfer_encoding)?; - - let mut ret_decrypted_mime = ptr::null_mut(); + let data = mail.get_body_raw()?; if has_decrypted_pgp_armor(&data) { // we should only have one decryption happening ensure!(ret_valid_signatures.is_empty(), "corrupt signatures"); - let plain = match pgp::pk_decrypt( + let plain = pgp::pk_decrypt( &data, &private_keyring, &public_keyring_for_validate, Some(ret_valid_signatures), - ) { - Ok(plain) => { - ensure!(!ret_valid_signatures.is_empty(), "no valid signatures"); - plain - } - Err(err) => bail!("could not decrypt: {}", err), - }; - let plain_bytes = plain.len(); - let plain_buf = plain.as_ptr() as *const libc::c_char; + )?; - let mut index = 0; - let mut decrypted_mime = ptr::null_mut(); - if unsafe { - mailmime_parse( - plain_buf as *const _, - plain_bytes, - &mut index, - &mut decrypted_mime, - ) - } != MAIL_NO_ERROR as libc::c_int - || decrypted_mime.is_null() - { - if !decrypted_mime.is_null() { - unsafe { mailmime_free(decrypted_mime) }; - } - } else { - // decrypted_mime points into `plain`. - // FIXME(@dignifiedquire): this still leaks memory I believe, as mailmime_free - // does not free the underlying buffer. But for now we have to live with it - std::mem::forget(plain); - ret_decrypted_mime = decrypted_mime; - } + ensure!(!ret_valid_signatures.is_empty(), "no valid signatures"); + return Ok(Some(plain)); } - Ok(ret_decrypted_mime) + Ok(None) } fn has_decrypted_pgp_armor(input: &[u8]) -> bool { @@ -644,36 +577,8 @@ fn has_decrypted_pgp_armor(input: &[u8]) -> bool { /// However, Delta Chat itself has no problem with encrypted multipart/report /// parts and MUAs should be encouraged to encrpyt multipart/reports as well so /// that we could use the normal Autocrypt processing. -fn contains_report(mime: *mut Mailmime) -> bool { - assert!(!mime.is_null()); - let mime = unsafe { *mime }; - - if mime.mm_type == MAILMIME_MULTIPLE as libc::c_int { - let tp_type = unsafe { (*(*mime.mm_content_type).ct_type).tp_type }; - let ct_type = - unsafe { (*(*(*mime.mm_content_type).ct_type).tp_data.tp_composite_type).ct_type }; - - if tp_type == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int - && ct_type == MAILMIME_COMPOSITE_TYPE_MULTIPART as libc::c_int - && to_string_lossy(unsafe { (*mime.mm_content_type).ct_subtype }) == "report" - { - return true; - } - - for cur_data in unsafe { (*(*mime.mm_mime_fields).fld_list).into_iter() } { - if contains_report(cur_data as *mut Mailmime) { - return true; - } - } - } else if mime.mm_type == MAILMIME_MESSAGE as libc::c_int { - let m = unsafe { mime.mm_data.mm_message.mm_msg_mime }; - - if contains_report(m) { - return true; - } - } - - false +fn contains_report(mail: &mailparse::ParsedMail<'_>) -> bool { + mail.ctype.mimetype == "multipart/report" } /// Ensures a private key exists for the configured user. @@ -699,7 +604,6 @@ pub fn ensure_secret_key_exists(context: &Context) -> Result { #[cfg(test)] mod tests { use super::*; - use libc::free; use crate::test_utils::*; @@ -720,46 +624,46 @@ mod tests { } } - #[test] - fn test_mailmime_parse() { - let plain = b"Chat-Disposition-Notification-To: holger@deltachat.de -Chat-Group-ID: CovhGgau8M- -Chat-Group-Name: Delta Chat Dev -Subject: =?utf-8?Q?Chat=3A?= Delta Chat =?utf-8?Q?Dev=3A?= sidenote for - =?utf-8?Q?all=3A?= rust core master ... -Content-Type: text/plain; charset=\"utf-8\"; protected-headers=\"v1\" -Content-Transfer-Encoding: quoted-printable + // #[test] + // fn test_mailmime_parse() { + // let plain = b"Chat-Disposition-Notification-To: holger@deltachat.de + // Chat-Group-ID: CovhGgau8M- + // Chat-Group-Name: Delta Chat Dev + // Subject: =?utf-8?Q?Chat=3A?= Delta Chat =?utf-8?Q?Dev=3A?= sidenote for + // =?utf-8?Q?all=3A?= rust core master ... + // Content-Type: text/plain; charset=\"utf-8\"; protected-headers=\"v1\" + // Content-Transfer-Encoding: quoted-printable -sidenote for all: rust core master is broken currently ... so dont recomm= -end to try to run with desktop or ios unless you are ready to hunt bugs + // sidenote for all: rust core master is broken currently ... so dont recomm= + // end to try to run with desktop or ios unless you are ready to hunt bugs --- =20 -Sent with my Delta Chat Messenger: https://delta.chat"; - let plain_bytes = plain.len(); - let plain_buf = plain.as_ptr() as *const libc::c_char; + // -- =20 + // Sent with my Delta Chat Messenger: https://delta.chat"; + // let plain_bytes = plain.len(); + // let plain_buf = plain.as_ptr() as *const libc::c_char; - let mut index = 0; - let mut decrypted_mime = std::ptr::null_mut(); + // let mut index = 0; + // let mut decrypted_mime = std::ptr::null_mut(); - let res = unsafe { - mailmime_parse( - plain_buf as *const _, - plain_bytes, - &mut index, - &mut decrypted_mime, - ) - }; - unsafe { - let msg1 = (*decrypted_mime).mm_data.mm_message.mm_msg_mime; - let data = mailmime_transfer_decode(msg1).unwrap(); - println!("{:?}", String::from_utf8_lossy(&data)); - } + // let res = { + // mailmime_parse( + // plain_buf as *const _, + // plain_bytes, + // &mut index, + // &mut decrypted_mime, + // ) + // }; + // { + // let msg1 = (*decrypted_mime).mm_data.mm_message.mm_msg_mime; + // let data = mailmime_transfer_decode(msg1).unwrap(); + // println!("{:?}", String::from_utf8_lossy(&data)); + // } - assert_eq!(res, 0); - assert!(!decrypted_mime.is_null()); + // assert_eq!(res, 0); + // assert!(!decrypted_mime.is_null()); - unsafe { free(decrypted_mime as *mut _) }; - } + // { free(decrypted_mime as *mut _) }; + // } mod load_or_generate_self_public_key { use super::*; diff --git a/src/error.rs b/src/error.rs index b1e8419d5..d1e4d35aa 100644 --- a/src/error.rs +++ b/src/error.rs @@ -28,6 +28,8 @@ pub enum Error { InvalidMsgId, #[fail(display = "Watch folder not found {:?}", _0)] WatchFolderNotFound(String), + #[fail(display = "Inalid Email: {:?}", _0)] + MailParseError(mailparse::MailParseError), } pub type Result = std::result::Result; @@ -98,6 +100,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: mailparse::MailParseError) -> Error { + Error::MailParseError(err) + } +} + #[macro_export] macro_rules! bail { ($e:expr) => { diff --git a/src/imap.rs b/src/imap.rs index 49f12b460..43f7d89cb 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -825,9 +825,7 @@ impl Imap { if !is_deleted && msg.body().is_some() { let body = msg.body().unwrap_or_default(); - unsafe { - dc_receive_imf(context, &body, folder.as_ref(), server_uid, flags as u32); - } + dc_receive_imf(context, &body, folder.as_ref(), server_uid, flags as u32); } } diff --git a/src/imex.rs b/src/imex.rs index 816db76f1..dc2e25965 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -12,7 +12,6 @@ use crate::config::Config; use crate::configure::*; use crate::constants::*; use crate::context::Context; -use crate::dc_mimeparser::SystemMessage; use crate::dc_tools::*; use crate::e2ee; use crate::error::*; @@ -20,6 +19,7 @@ use crate::events::Event; use crate::job::*; use crate::key::*; use crate::message::{Message, MsgId}; +use crate::mimeparser::SystemMessage; use crate::param::*; use crate::pgp; use crate::sql::{self, Sql}; diff --git a/src/job.rs b/src/job.rs index dd4e66561..87bea8054 100644 --- a/src/job.rs +++ b/src/job.rs @@ -608,7 +608,7 @@ pub fn job_send_msg(context: &Context, msg_id: MsgId) -> Result<(), Error> { mimefactory.msg.try_calc_and_set_dimensions(context).ok(); /* create message */ - if let Err(msg) = unsafe { mimefactory.render() } { + if let Err(msg) = mimefactory.render() { let e = msg.to_string(); message::set_msg_failed(context, msg_id, Some(e)); return Err(msg); @@ -867,7 +867,7 @@ fn suspend_smtp_thread(context: &Context, suspend: bool) { fn send_mdn(context: &Context, msg_id: MsgId) -> Result<(), Error> { let mut mimefactory = MimeFactory::load_mdn(context, msg_id)?; - unsafe { mimefactory.render()? }; + mimefactory.render()?; add_smtp_job(context, Action::SendMdn, &mut mimefactory)?; Ok(()) @@ -880,12 +880,7 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &MimeFactory) -> "no recipients for smtp job set" ); let mut param = Params::new(); - let bytes = unsafe { - std::slice::from_raw_parts( - (*mimefactory.out).str_0 as *const u8, - (*mimefactory.out).len, - ) - }; + let bytes = &mimefactory.out; let blob = BlobObject::create(context, &mimefactory.rfc724_mid, bytes)?; let recipients = mimefactory.recipients_addr.join("\x1e"); param.set(Param::File, blob.as_name()); diff --git a/src/lib.rs b/src/lib.rs index 64c39353a..9f75b5303 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,7 @@ mod login_param; pub mod lot; pub mod message; mod mimefactory; +pub mod mimeparser; pub mod oauth2; mod param; pub mod peerstate; @@ -63,14 +64,13 @@ pub mod stock; mod token; #[macro_use] mod wrapmime; +mod dehtml; pub mod dc_array; -pub mod dc_mimeparser; pub mod dc_receive_imf; mod dc_simplify; mod dc_strencode; pub mod dc_tools; -mod dehtml; #[cfg(test)] mod test_utils; diff --git a/src/location.rs b/src/location.rs index f9375b0cd..357349d89 100644 --- a/src/location.rs +++ b/src/location.rs @@ -8,12 +8,12 @@ use crate::chat; use crate::config::Config; use crate::constants::*; use crate::context::*; -use crate::dc_mimeparser::SystemMessage; use crate::dc_tools::*; use crate::error::Error; use crate::events::Event; use crate::job::*; use crate::message::{Message, MsgId}; +use crate::mimeparser::SystemMessage; use crate::param::*; use crate::sql; use crate::stock::StockMessage; diff --git a/src/message.rs b/src/message.rs index dccb500ac..329b9c209 100644 --- a/src/message.rs +++ b/src/message.rs @@ -7,12 +7,12 @@ use crate::chat::{self, Chat}; use crate::constants::*; use crate::contact::*; use crate::context::*; -use crate::dc_mimeparser::SystemMessage; use crate::dc_tools::*; use crate::error::Error; use crate::events::Event; use crate::job::*; use crate::lot::{Lot, LotState, Meaning}; +use crate::mimeparser::SystemMessage; use crate::param::*; use crate::pgp::*; use crate::sql; diff --git a/src/mimefactory.rs b/src/mimefactory.rs index cf56c42f8..83e6d7fe2 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -1,22 +1,12 @@ use std::ptr; use chrono::TimeZone; -use mmime::clist::*; -use mmime::mailimf::types::*; -use mmime::mailimf::types_helper::*; -use mmime::mailmime::disposition::*; -use mmime::mailmime::types::*; -use mmime::mailmime::types_helper::*; -use mmime::mailmime::write_mem::*; -use mmime::mmapstring::*; -use mmime::other::*; use crate::chat::{self, Chat}; use crate::config::Config; use crate::constants::*; use crate::contact::*; use crate::context::{get_version_str, Context}; -use crate::dc_mimeparser::SystemMessage; use crate::dc_strencode::*; use crate::dc_tools::*; use crate::e2ee::*; @@ -24,6 +14,7 @@ use crate::error::Error; use crate::location; use crate::message::MsgId; use crate::message::{self, Message}; +use crate::mimeparser::SystemMessage; use crate::param::*; use crate::stock::StockMessage; use crate::wrapmime; @@ -51,7 +42,7 @@ pub struct MimeFactory<'a> { pub in_reply_to: String, pub references: String, pub req_mdn: bool, - pub out: *mut MMAPString, + pub out: Vec, pub out_encrypted: bool, pub out_gossiped: bool, pub out_last_added_location_id: u32, @@ -79,7 +70,7 @@ impl<'a> MimeFactory<'a> { in_reply_to: String::default(), references: String::default(), req_mdn: false, - out: ptr::null_mut(), + out: Vec::new(), out_encrypted: false, out_gossiped: false, out_last_added_location_id: 0, @@ -89,19 +80,19 @@ impl<'a> MimeFactory<'a> { pub fn finalize_mime_message( &mut self, - message: *mut Mailmime, + message: &mut lettre_email::Email, encrypted: bool, gossiped: bool, ) -> Result<(), Error> { - unsafe { - assert!(self.out.is_null()); // guard against double-calls - self.out = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - let mut col: libc::c_int = 0; - ensure_eq!( - mailmime_write_mem(self.out, &mut col, message), - 0, - "mem-error" - ); + { + // assert!(self.out.is_null()); // guard against double-calls + // self.out = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); + // let mut col: libc::c_int = 0; + // ensure_eq!( + // mailmime_write_mem(self.out, &mut col, message), + // 0, + // "mem-error" + // ); } self.out_encrypted = encrypted; self.out_gossiped = encrypted && gossiped; @@ -142,519 +133,519 @@ impl<'a> MimeFactory<'a> { * Render a basic email ******************************************************************************/ // XXX restrict unsafe to parts, introduce wrapmime helpers where appropriate - pub unsafe fn render(&mut self) -> Result<(), Error> { - if self.loaded == Loaded::Nothing || !self.out.is_null() { + pub fn render(&mut self) -> Result<(), Error> { + if self.loaded == Loaded::Nothing || !self.out.is_empty() { bail!("Invalid use of mimefactory-object."); } let context = &self.context; - let from = wrapmime::new_mailbox_list(&self.from_displayname, &self.from_addr); + unimplemented!(); + // let from = wrapmime::new_mailbox_list(&self.from_displayname, &self.from_addr); - let to = mailimf_address_list_new_empty(); - let name_iter = self.recipients_names.iter(); - let addr_iter = self.recipients_addr.iter(); - for (name, addr) in name_iter.zip(addr_iter) { - mailimf_address_list_add( - to, - mailimf_address_new( - MAILIMF_ADDRESS_MAILBOX as libc::c_int, - mailimf_mailbox_new( - if !name.is_empty() { - dc_encode_header_words(&name).strdup() - } else { - ptr::null_mut() - }, - addr.strdup(), - ), - ptr::null_mut(), - ), - ); - } - let references_list = if !self.references.is_empty() { - dc_str_to_clist(&self.references, " ") - } else { - ptr::null_mut() - }; - let in_reply_to_list = if !self.in_reply_to.is_empty() { - dc_str_to_clist(&self.in_reply_to, " ") - } else { - ptr::null_mut() - }; + // let to = mailimf_address_list_new_empty(); + // let name_iter = self.recipients_names.iter(); + // let addr_iter = self.recipients_addr.iter(); + // for (name, addr) in name_iter.zip(addr_iter) { + // mailimf_address_list_add( + // to, + // mailimf_address_new( + // MAILIMF_ADDRESS_MAILBOX as libc::c_int, + // mailimf_mailbox_new( + // if !name.is_empty() { + // dc_encode_header_words(&name).strdup() + // } else { + // ptr::null_mut() + // }, + // addr.strdup(), + // ), + // ptr::null_mut(), + // ), + // ); + // } + // let references_list = if !self.references.is_empty() { + // dc_str_to_clist(&self.references, " ") + // } else { + // ptr::null_mut() + // }; + // let in_reply_to_list = if !self.in_reply_to.is_empty() { + // dc_str_to_clist(&self.in_reply_to, " ") + // } else { + // ptr::null_mut() + // }; - let imf_fields = mailimf_fields_new_with_data_all( - mailimf_get_date(self.timestamp as i64), - from, - ptr::null_mut(), - ptr::null_mut(), - to, - ptr::null_mut(), - ptr::null_mut(), - self.rfc724_mid.strdup(), - in_reply_to_list, - references_list, - ptr::null_mut(), - ); + // let imf_fields = mailimf_fields_new_with_data_all( + // mailimf_get_date(self.timestamp as i64), + // from, + // ptr::null_mut(), + // ptr::null_mut(), + // to, + // ptr::null_mut(), + // ptr::null_mut(), + // self.rfc724_mid.strdup(), + // in_reply_to_list, + // references_list, + // ptr::null_mut(), + // ); - let os_name = &self.context.os_name; - let os_part = os_name - .as_ref() - .map(|s| format!("/{}", s)) - .unwrap_or_default(); - let version = get_version_str(); - let headerval = format!("Delta Chat Core {}{}", version, os_part); + // let os_name = &self.context.os_name; + // let os_part = os_name + // .as_ref() + // .map(|s| format!("/{}", s)) + // .unwrap_or_default(); + // let version = get_version_str(); + // let headerval = format!("Delta Chat Core {}{}", version, os_part); - /* Add a X-Mailer header. - This is only informational for debugging and may be removed in the release. - We do not rely on this header as it may be removed by MTAs. */ - wrapmime::new_custom_field(imf_fields, "X-Mailer", &headerval); - wrapmime::new_custom_field(imf_fields, "Chat-Version", "1.0"); - if self.req_mdn { - /* we use "Chat-Disposition-Notification-To" - because replies to "Disposition-Notification-To" are weird in many cases - eg. are just freetext and/or do not follow any standard. */ - wrapmime::new_custom_field( - imf_fields, - "Chat-Disposition-Notification-To", - &self.from_addr, - ); - } + // /* Add a X-Mailer header. + // This is only informational for debugging and may be removed in the release. + // We do not rely on this header as it may be removed by MTAs. */ + // wrapmime::new_custom_field(imf_fields, "X-Mailer", &headerval); + // wrapmime::new_custom_field(imf_fields, "Chat-Version", "1.0"); + // if self.req_mdn { + // /* we use "Chat-Disposition-Notification-To" + // because replies to "Disposition-Notification-To" are weird in many cases + // eg. are just freetext and/or do not follow any standard. */ + // wrapmime::new_custom_field( + // imf_fields, + // "Chat-Disposition-Notification-To", + // &self.from_addr, + // ); + // } - let cleanup = |message: *mut Mailmime| { - if !message.is_null() { - mailmime_free(message); - } - }; - let message = mailmime_new_message_data(0 as *mut Mailmime); - ensure!(!message.is_null(), "could not create mime message data"); + // let cleanup = |message: *mut Mailmime| { + // if !message.is_null() { + // mailmime_free(message); + // } + // }; + // let message = mailmime_new_message_data(0 as *mut Mailmime); + // ensure!(!message.is_null(), "could not create mime message data"); - mailmime_set_imf_fields(message, imf_fields); + // mailmime_set_imf_fields(message, imf_fields); - // 1=add Autocrypt-header (needed eg. for handshaking), 2=no Autocrypte-header (used for MDN) - let mut e2ee_guaranteed = false; - let mut min_verified = crate::peerstate::PeerstateVerifiedStatus::Unverified; - let mut do_gossip = false; - let mut grpimage = None; - let force_plaintext: libc::c_int; - let subject_str = match self.loaded { - Loaded::Message => { - /* Render a normal message - *********************************************************************/ - let chat = self.chat.as_ref().unwrap(); - let mut meta_part: *mut Mailmime = ptr::null_mut(); - let mut placeholdertext = None; + // // 1=add Autocrypt-header (needed eg. for handshaking), 2=no Autocrypte-header (used for MDN) + // let mut e2ee_guaranteed = false; + // let mut min_verified = crate::peerstate::PeerstateVerifiedStatus::Unverified; + // let mut do_gossip = false; + // let mut grpimage = None; + // let force_plaintext: libc::c_int; + // let subject_str = match self.loaded { + // Loaded::Message => { + // /* Render a normal message + // *********************************************************************/ + // let chat = self.chat.as_ref().unwrap(); + // let mut meta_part: *mut Mailmime = ptr::null_mut(); + // let mut placeholdertext = None; - if chat.typ == Chattype::VerifiedGroup { - wrapmime::new_custom_field(imf_fields, "Chat-Verified", "1"); - force_plaintext = 0; - e2ee_guaranteed = true; - min_verified = crate::peerstate::PeerstateVerifiedStatus::BidirectVerified; - } else { - force_plaintext = self - .msg - .param - .get_int(Param::ForcePlaintext) - .unwrap_or_default(); - if force_plaintext == 0 { - e2ee_guaranteed = self - .msg - .param - .get_int(Param::GuaranteeE2ee) - .unwrap_or_default() - != 0; - } - } + // if chat.typ == Chattype::VerifiedGroup { + // wrapmime::new_custom_field(imf_fields, "Chat-Verified", "1"); + // force_plaintext = 0; + // e2ee_guaranteed = true; + // min_verified = crate::peerstate::PeerstateVerifiedStatus::BidirectVerified; + // } else { + // force_plaintext = self + // .msg + // .param + // .get_int(Param::ForcePlaintext) + // .unwrap_or_default(); + // if force_plaintext == 0 { + // e2ee_guaranteed = self + // .msg + // .param + // .get_int(Param::GuaranteeE2ee) + // .unwrap_or_default() + // != 0; + // } + // } - /* beside key- and member-changes, force re-gossip every 48 hours */ - if chat.gossiped_timestamp == 0 - || (chat.gossiped_timestamp + (2 * 24 * 60 * 60)) < time() - { - do_gossip = true - } + // /* beside key- and member-changes, force re-gossip every 48 hours */ + // if chat.gossiped_timestamp == 0 + // || (chat.gossiped_timestamp + (2 * 24 * 60 * 60)) < time() + // { + // do_gossip = true + // } - /* build header etc. */ - let command = self.msg.param.get_cmd(); - if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { - wrapmime::new_custom_field(imf_fields, "Chat-Group-ID", &chat.grpid); + // /* build header etc. */ + // let command = self.msg.param.get_cmd(); + // if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { + // wrapmime::new_custom_field(imf_fields, "Chat-Group-ID", &chat.grpid); - let encoded = dc_encode_header_words(&chat.name); - wrapmime::new_custom_field(imf_fields, "Chat-Group-Name", &encoded); + // let encoded = dc_encode_header_words(&chat.name); + // wrapmime::new_custom_field(imf_fields, "Chat-Group-Name", &encoded); - match command { - SystemMessage::MemberRemovedFromGroup => { - let email_to_remove = - self.msg.param.get(Param::Arg).unwrap_or_default(); - if !email_to_remove.is_empty() { - wrapmime::new_custom_field( - imf_fields, - "Chat-Group-Member-Removed", - &email_to_remove, - ); - } - } - SystemMessage::MemberAddedToGroup => { - let msg = &self.msg; - do_gossip = true; - let email_to_add = msg.param.get(Param::Arg).unwrap_or_default(); - if !email_to_add.is_empty() { - wrapmime::new_custom_field( - imf_fields, - "Chat-Group-Member-Added", - &email_to_add, - ); - grpimage = chat.param.get(Param::ProfileImage); - } - if 0 != msg.param.get_int(Param::Arg2).unwrap_or_default() & 0x1 { - info!( - context, - "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", - "vg-member-added", - ); - wrapmime::new_custom_field( - imf_fields, - "Secure-Join", - "vg-member-added", - ); - } - } - SystemMessage::GroupNameChanged => { - let msg = &self.msg; - let value_to_add = msg.param.get(Param::Arg).unwrap_or_default(); + // match command { + // SystemMessage::MemberRemovedFromGroup => { + // let email_to_remove = + // self.msg.param.get(Param::Arg).unwrap_or_default(); + // if !email_to_remove.is_empty() { + // wrapmime::new_custom_field( + // imf_fields, + // "Chat-Group-Member-Removed", + // &email_to_remove, + // ); + // } + // } + // SystemMessage::MemberAddedToGroup => { + // let msg = &self.msg; + // do_gossip = true; + // let email_to_add = msg.param.get(Param::Arg).unwrap_or_default(); + // if !email_to_add.is_empty() { + // wrapmime::new_custom_field( + // imf_fields, + // "Chat-Group-Member-Added", + // &email_to_add, + // ); + // grpimage = chat.param.get(Param::ProfileImage); + // } + // if 0 != msg.param.get_int(Param::Arg2).unwrap_or_default() & 0x1 { + // info!( + // context, + // "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", + // "vg-member-added", + // ); + // wrapmime::new_custom_field( + // imf_fields, + // "Secure-Join", + // "vg-member-added", + // ); + // } + // } + // SystemMessage::GroupNameChanged => { + // let msg = &self.msg; + // let value_to_add = msg.param.get(Param::Arg).unwrap_or_default(); - wrapmime::new_custom_field( - imf_fields, - "Chat-Group-Name-Changed", - &value_to_add, - ); - } - SystemMessage::GroupImageChanged => { - let msg = &self.msg; - grpimage = msg.param.get(Param::Arg); - if grpimage.is_none() { - wrapmime::new_custom_field(imf_fields, "Chat-Group-Image", "0"); - } - } - _ => {} - } - } + // wrapmime::new_custom_field( + // imf_fields, + // "Chat-Group-Name-Changed", + // &value_to_add, + // ); + // } + // SystemMessage::GroupImageChanged => { + // let msg = &self.msg; + // grpimage = msg.param.get(Param::Arg); + // if grpimage.is_none() { + // wrapmime::new_custom_field(imf_fields, "Chat-Group-Image", "0"); + // } + // } + // _ => {} + // } + // } - match command { - SystemMessage::LocationStreamingEnabled => { - wrapmime::new_custom_field( - imf_fields, - "Chat-Content", - "location-streaming-enabled", - ); - } - SystemMessage::AutocryptSetupMessage => { - wrapmime::new_custom_field(imf_fields, "Autocrypt-Setup-Message", "v1"); - placeholdertext = Some( - self.context - .stock_str(StockMessage::AcSetupMsgBody) - .to_string(), - ); - } - SystemMessage::SecurejoinMessage => { - let msg = &self.msg; - let step = msg.param.get(Param::Arg).unwrap_or_default(); - if !step.is_empty() { - info!( - context, - "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", - step, - ); - wrapmime::new_custom_field(imf_fields, "Secure-Join", &step); - let param2 = msg.param.get(Param::Arg2).unwrap_or_default(); - if !param2.is_empty() { - wrapmime::new_custom_field( - imf_fields, - if step == "vg-request-with-auth" - || step == "vc-request-with-auth" - { - "Secure-Join-Auth" - } else { - "Secure-Join-Invitenumber" - }, - param2, - ) - } - let fingerprint = msg.param.get(Param::Arg3).unwrap_or_default(); - if !fingerprint.is_empty() { - wrapmime::new_custom_field( - imf_fields, - "Secure-Join-Fingerprint", - &fingerprint, - ); - } - if let Some(id) = msg.param.get(Param::Arg4) { - wrapmime::new_custom_field(imf_fields, "Secure-Join-Group", &id); - }; - } - } - _ => {} - } + // match command { + // SystemMessage::LocationStreamingEnabled => { + // wrapmime::new_custom_field( + // imf_fields, + // "Chat-Content", + // "location-streaming-enabled", + // ); + // } + // SystemMessage::AutocryptSetupMessage => { + // wrapmime::new_custom_field(imf_fields, "Autocrypt-Setup-Message", "v1"); + // placeholdertext = Some( + // self.context + // .stock_str(StockMessage::AcSetupMsgBody) + // .to_string(), + // ); + // } + // SystemMessage::SecurejoinMessage => { + // let msg = &self.msg; + // let step = msg.param.get(Param::Arg).unwrap_or_default(); + // if !step.is_empty() { + // info!( + // context, + // "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", + // step, + // ); + // wrapmime::new_custom_field(imf_fields, "Secure-Join", &step); + // let param2 = msg.param.get(Param::Arg2).unwrap_or_default(); + // if !param2.is_empty() { + // wrapmime::new_custom_field( + // imf_fields, + // if step == "vg-request-with-auth" + // || step == "vc-request-with-auth" + // { + // "Secure-Join-Auth" + // } else { + // "Secure-Join-Invitenumber" + // }, + // param2, + // ) + // } + // let fingerprint = msg.param.get(Param::Arg3).unwrap_or_default(); + // if !fingerprint.is_empty() { + // wrapmime::new_custom_field( + // imf_fields, + // "Secure-Join-Fingerprint", + // &fingerprint, + // ); + // } + // if let Some(id) = msg.param.get(Param::Arg4) { + // wrapmime::new_custom_field(imf_fields, "Secure-Join-Group", &id); + // }; + // } + // } + // _ => {} + // } - if let Some(grpimage) = grpimage { - info!(self.context, "setting group image '{}'", grpimage); - let mut meta = Message::default(); - meta.type_0 = Viewtype::Image; - meta.param.set(Param::File, grpimage); + // if let Some(grpimage) = grpimage { + // info!(self.context, "setting group image '{}'", grpimage); + // let mut meta = Message::default(); + // meta.type_0 = Viewtype::Image; + // meta.param.set(Param::File, grpimage); - let res = build_body_file(context, &meta, "group-image")?; - meta_part = res.0; - let filename_as_sent = res.1; - if !meta_part.is_null() { - wrapmime::new_custom_field( - imf_fields, - "Chat-Group-Image", - &filename_as_sent, - ) - } - } + // let res = build_body_file(context, &meta, "group-image")?; + // meta_part = res.0; + // let filename_as_sent = res.1; + // if !meta_part.is_null() { + // wrapmime::new_custom_field( + // imf_fields, + // "Chat-Group-Image", + // &filename_as_sent, + // ) + // } + // } - if self.msg.type_0 == Viewtype::Sticker { - wrapmime::new_custom_field(imf_fields, "Chat-Content", "sticker"); - } + // if self.msg.type_0 == Viewtype::Sticker { + // wrapmime::new_custom_field(imf_fields, "Chat-Content", "sticker"); + // } - if self.msg.type_0 == Viewtype::Voice - || self.msg.type_0 == Viewtype::Audio - || self.msg.type_0 == Viewtype::Video - { - if self.msg.type_0 == Viewtype::Voice { - wrapmime::new_custom_field(imf_fields, "Chat-Voice-Message", "1"); - } - let duration_ms = self.msg.param.get_int(Param::Duration).unwrap_or_default(); - if duration_ms > 0 { - let dur = duration_ms.to_string(); - wrapmime::new_custom_field(imf_fields, "Chat-Duration", &dur); - } - } + // if self.msg.type_0 == Viewtype::Voice + // || self.msg.type_0 == Viewtype::Audio + // || self.msg.type_0 == Viewtype::Video + // { + // if self.msg.type_0 == Viewtype::Voice { + // wrapmime::new_custom_field(imf_fields, "Chat-Voice-Message", "1"); + // } + // let duration_ms = self.msg.param.get_int(Param::Duration).unwrap_or_default(); + // if duration_ms > 0 { + // let dur = duration_ms.to_string(); + // wrapmime::new_custom_field(imf_fields, "Chat-Duration", &dur); + // } + // } - /* add text part - we even add empty text and force a MIME-multipart-message as: - - some Apps have problems with Non-text in the main part (eg. "Mail" from stock Android) - - we can add "forward hints" this way - - it looks better */ - let afwd_email = self.msg.param.exists(Param::Forwarded); - let fwdhint = if afwd_email { - Some( - "---------- Forwarded message ----------\r\nFrom: Delta Chat\r\n\r\n" - .to_string(), - ) - } else { - None - }; + // /* add text part - we even add empty text and force a MIME-multipart-message as: + // - some Apps have problems with Non-text in the main part (eg. "Mail" from stock Android) + // - we can add "forward hints" this way + // - it looks better */ + // let afwd_email = self.msg.param.exists(Param::Forwarded); + // let fwdhint = if afwd_email { + // Some( + // "---------- Forwarded message ----------\r\nFrom: Delta Chat\r\n\r\n" + // .to_string(), + // ) + // } else { + // None + // }; - let final_text = { - if let Some(ref text) = placeholdertext { - text - } else if let Some(ref text) = self.msg.text { - text - } else { - "" - } - }; + // let final_text = { + // if let Some(ref text) = placeholdertext { + // text + // } else if let Some(ref text) = self.msg.text { + // text + // } else { + // "" + // } + // }; - let footer = &self.selfstatus; - let message_text = format!( - "{}{}{}{}{}", - fwdhint.unwrap_or_default(), - &final_text, - if !final_text.is_empty() && !footer.is_empty() { - "\r\n\r\n" - } else { - "" - }, - if !footer.is_empty() { "-- \r\n" } else { "" }, - footer - ); - let text_part = wrapmime::build_body_text(&message_text)?; - mailmime_smart_add_part(message, text_part); + // let footer = &self.selfstatus; + // let message_text = format!( + // "{}{}{}{}{}", + // fwdhint.unwrap_or_default(), + // &final_text, + // if !final_text.is_empty() && !footer.is_empty() { + // "\r\n\r\n" + // } else { + // "" + // }, + // if !footer.is_empty() { "-- \r\n" } else { "" }, + // footer + // ); + // let text_part = wrapmime::build_body_text(&message_text)?; + // mailmime_smart_add_part(message, text_part); - /* add attachment part */ - if chat::msgtype_has_file(self.msg.type_0) { - if !is_file_size_okay(context, &self.msg) { - cleanup(message); - bail!( - "Message exceeds the recommended {} MB.", - 24 * 1024 * 1024 / 4 * 3 / 1000 / 1000, - ); - } else { - let (file_part, _) = build_body_file(context, &self.msg, "")?; - mailmime_smart_add_part(message, file_part); - } - } - if !meta_part.is_null() { - mailmime_smart_add_part(message, meta_part); - } + // /* add attachment part */ + // if chat::msgtype_has_file(self.msg.type_0) { + // if !is_file_size_okay(context, &self.msg) { + // cleanup(message); + // bail!( + // "Message exceeds the recommended {} MB.", + // 24 * 1024 * 1024 / 4 * 3 / 1000 / 1000, + // ); + // } else { + // let (file_part, _) = build_body_file(context, &self.msg, "")?; + // mailmime_smart_add_part(message, file_part); + // } + // } + // if !meta_part.is_null() { + // mailmime_smart_add_part(message, meta_part); + // } - if self.msg.param.exists(Param::SetLatitude) { - let param = &self.msg.param; - let kml_file = location::get_message_kml( - self.msg.timestamp_sort, - param.get_float(Param::SetLatitude).unwrap_or_default(), - param.get_float(Param::SetLongitude).unwrap_or_default(), - ); - wrapmime::add_filename_part( - message, - "message.kml", - "application/vnd.google-earth.kml+xml", - &kml_file, - )?; - } + // if self.msg.param.exists(Param::SetLatitude) { + // let param = &self.msg.param; + // let kml_file = location::get_message_kml( + // self.msg.timestamp_sort, + // param.get_float(Param::SetLatitude).unwrap_or_default(), + // param.get_float(Param::SetLongitude).unwrap_or_default(), + // ); + // wrapmime::add_filename_part( + // message, + // "message.kml", + // "application/vnd.google-earth.kml+xml", + // &kml_file, + // )?; + // } - if location::is_sending_locations_to_chat(context, self.msg.chat_id) { - match location::get_kml(context, self.msg.chat_id) { - Ok((kml_content, last_added_location_id)) => { - wrapmime::add_filename_part( - message, - "location.kml", - "application/vnd.google-earth.kml+xml", - &kml_content, - )?; - if !self.msg.param.exists(Param::SetLatitude) { - // otherwise, the independent location is already filed - self.out_last_added_location_id = last_added_location_id; - } - } - Err(err) => { - warn!(context, "mimefactory: could not get location: {}", err); - } - } - } - get_subject(context, self.chat.as_ref(), &mut self.msg, afwd_email) - } - Loaded::MDN => { - /* Render a MDN - *********************************************************************/ - /* RFC 6522, this also requires the `report-type` parameter which is equal - to the MIME subtype of the second body part of the multipart/report */ - let multipart = mailmime_multiple_new( - b"multipart/report\x00" as *const u8 as *const libc::c_char, - ); - wrapmime::append_ct_param( - (*multipart).mm_content_type, - "report-type", - "disposition-notification", - )?; + // if location::is_sending_locations_to_chat(context, self.msg.chat_id) { + // match location::get_kml(context, self.msg.chat_id) { + // Ok((kml_content, last_added_location_id)) => { + // wrapmime::add_filename_part( + // message, + // "location.kml", + // "application/vnd.google-earth.kml+xml", + // &kml_content, + // )?; + // if !self.msg.param.exists(Param::SetLatitude) { + // // otherwise, the independent location is already filed + // self.out_last_added_location_id = last_added_location_id; + // } + // } + // Err(err) => { + // warn!(context, "mimefactory: could not get location: {}", err); + // } + // } + // } + // get_subject(context, self.chat.as_ref(), &mut self.msg, afwd_email) + // } + // Loaded::MDN => { + // /* Render a MDN + // *********************************************************************/ + // /* RFC 6522, this also requires the `report-type` parameter which is equal + // to the MIME subtype of the second body part of the multipart/report */ + // let multipart = mailmime_multiple_new( + // b"multipart/report\x00" as *const u8 as *const libc::c_char, + // ); + // wrapmime::append_ct_param( + // (*multipart).mm_content_type, + // "report-type", + // "disposition-notification", + // )?; - mailmime_add_part(message, multipart); + // mailmime_add_part(message, multipart); - /* first body part: always human-readable, always REQUIRED by RFC 6522 */ - let p1 = if 0 - != self - .msg - .param - .get_int(Param::GuaranteeE2ee) - .unwrap_or_default() - { - self.context - .stock_str(StockMessage::EncryptedMsg) - .into_owned() - } else { - self.msg.get_summarytext(context, 32) - }; - let p2 = self - .context - .stock_string_repl_str(StockMessage::ReadRcptMailBody, p1); - let message_text = format!("{}\r\n", p2); - let human_mime_part = wrapmime::build_body_text(&message_text)?; - mailmime_add_part(multipart, human_mime_part); + // /* first body part: always human-readable, always REQUIRED by RFC 6522 */ + // let p1 = if 0 + // != self + // .msg + // .param + // .get_int(Param::GuaranteeE2ee) + // .unwrap_or_default() + // { + // self.context + // .stock_str(StockMessage::EncryptedMsg) + // .into_owned() + // } else { + // self.msg.get_summarytext(context, 32) + // }; + // let p2 = self + // .context + // .stock_string_repl_str(StockMessage::ReadRcptMailBody, p1); + // let message_text = format!("{}\r\n", p2); + // let human_mime_part = wrapmime::build_body_text(&message_text)?; + // mailmime_add_part(multipart, human_mime_part); - /* second body part: machine-readable, always REQUIRED by RFC 6522 */ - let version = get_version_str(); - let message_text2 = format!( - "Reporting-UA: Delta Chat {}\r\nOriginal-Recipient: rfc822;{}\r\nFinal-Recipient: rfc822;{}\r\nOriginal-Message-ID: <{}>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n", - version, - self.from_addr, - self.from_addr, - self.msg.rfc724_mid - ); + // /* second body part: machine-readable, always REQUIRED by RFC 6522 */ + // let version = get_version_str(); + // let message_text2 = format!( + // "Reporting-UA: Delta Chat {}\r\nOriginal-Recipient: rfc822;{}\r\nFinal-Recipient: rfc822;{}\r\nOriginal-Message-ID: <{}>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n", + // version, + // self.from_addr, + // self.from_addr, + // self.msg.rfc724_mid + // ); - let content_type_0 = - wrapmime::new_content_type("message/disposition-notification")?; - let mime_fields_0: *mut mailmime_fields = - mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int); - let mach_mime_part: *mut Mailmime = - mailmime_new_empty(content_type_0, mime_fields_0); - wrapmime::set_body_text(mach_mime_part, &message_text2)?; - mailmime_add_part(multipart, mach_mime_part); - force_plaintext = DC_FP_NO_AUTOCRYPT_HEADER; - /* currently, we do not send MDNs encrypted: - - in a multi-device-setup that is not set up properly, MDNs would disturb the communication as they - are send automatically which may lead to spreading outdated Autocrypt headers. - - they do not carry any information but the Message-ID - - this save some KB - - in older versions, we did not encrypt messages to ourself when they to to SMTP - however, if these messages - are forwarded for any reasons (eg. gmail always forwards to IMAP), we have no chance to decrypt them; - this issue is fixed with 0.9.4 */ - let e = self.context.stock_str(StockMessage::ReadRcpt); - format!("Chat: {}", e).to_string() - } - _ => { - cleanup(message); - bail!("No message loaded."); - } - }; + // let content_type_0 = + // wrapmime::new_content_type("message/disposition-notification")?; + // let mime_fields_0: *mut mailmime_fields = + // mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int); + // let mach_mime_part: *mut Mailmime = + // mailmime_new_empty(content_type_0, mime_fields_0); + // wrapmime::set_body_text(mach_mime_part, &message_text2)?; + // mailmime_add_part(multipart, mach_mime_part); + // force_plaintext = DC_FP_NO_AUTOCRYPT_HEADER; + // /* currently, we do not send MDNs encrypted: + // - in a multi-device-setup that is not set up properly, MDNs would disturb the communication as they + // are send automatically which may lead to spreading outdated Autocrypt headers. + // - they do not carry any information but the Message-ID + // - this save some KB + // - in older versions, we did not encrypt messages to ourself when they to to SMTP - however, if these messages + // are forwarded for any reasons (eg. gmail always forwards to IMAP), we have no chance to decrypt them; + // this issue is fixed with 0.9.4 */ + // let e = self.context.stock_str(StockMessage::ReadRcpt); + // format!("Chat: {}", e).to_string() + // } + // _ => { + // cleanup(message); + // bail!("No message loaded."); + // } + // }; - /* Create the mime message - *************************************************************************/ + // /* Create the mime message + // *************************************************************************/ + // mailimf_fields_add( + // imf_fields, + // mailimf_field_new( + // MAILIMF_FIELD_SUBJECT as libc::c_int, + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // mailimf_subject_new(dc_encode_header_words(subject_str).strdup()), + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ), + // ); - mailimf_fields_add( - imf_fields, - mailimf_field_new( - MAILIMF_FIELD_SUBJECT as libc::c_int, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - mailimf_subject_new(dc_encode_header_words(subject_str).strdup()), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ), - ); + // /*just a pointer into mailmime structure, must not be freed*/ + // let imffields_unprotected = wrapmime::mailmime_find_mailimf_fields(message); + // ensure!( + // !imffields_unprotected.is_null(), + // "could not find mime fields" + // ); - /*just a pointer into mailmime structure, must not be freed*/ - let imffields_unprotected = wrapmime::mailmime_find_mailimf_fields(message); - ensure!( - !imffields_unprotected.is_null(), - "could not find mime fields" - ); - - let mut encrypt_helper = EncryptHelper::new(&context)?; - if force_plaintext != DC_FP_NO_AUTOCRYPT_HEADER { - // unless determined otherwise we add Autocrypt header - let aheader = encrypt_helper.get_aheader().to_string(); - wrapmime::new_custom_field(imffields_unprotected, "Autocrypt", &aheader); - } - let finalized = if force_plaintext == 0 { - encrypt_helper.try_encrypt( - self, - e2ee_guaranteed, - min_verified, - do_gossip, - message, - imffields_unprotected, - )? - } else { - false - }; - if !finalized { - self.finalize_mime_message(message, false, false)?; - } - cleanup(message); + // let mut encrypt_helper = EncryptHelper::new(&context)?; + // if force_plaintext != DC_FP_NO_AUTOCRYPT_HEADER { + // // unless determined otherwise we add Autocrypt header + // let aheader = encrypt_helper.get_aheader().to_string(); + // wrapmime::new_custom_field(imffields_unprotected, "Autocrypt", &aheader); + // } + // let finalized = if force_plaintext == 0 { + // encrypt_helper.try_encrypt( + // self, + // e2ee_guaranteed, + // min_verified, + // do_gossip, + // message, + // imffields_unprotected, + // )? + // } else { + // false + // }; + // if !finalized { + // self.finalize_mime_message(message, false, false)?; + // } + // cleanup(message); Ok(()) } @@ -753,16 +744,6 @@ impl<'a> MimeFactory<'a> { } } -impl<'a> Drop for MimeFactory<'a> { - fn drop(&mut self) { - unsafe { - if !self.out.is_null() { - mmap_string_free(self.out); - } - } - } -} - fn get_subject( context: &Context, chat: Option<&Chat>, @@ -790,109 +771,108 @@ fn get_subject( } } -#[allow(non_snake_case)] -fn build_body_file( - context: &Context, - msg: &Message, - base_name: &str, -) -> Result<(*mut Mailmime, String), Error> { - let blob = msg - .param - .get_blob(Param::File, context, true)? - .ok_or_else(|| format_err!("msg has no filename"))?; - let suffix = blob.suffix().unwrap_or("dat"); +// fn build_body_file( +// context: &Context, +// msg: &Message, +// base_name: &str, +// ) -> Result<(*mut Mailmime, String), Error> { +// let blob = msg +// .param +// .get_blob(Param::File, context, true)? +// .ok_or_else(|| format_err!("msg has no filename"))?; +// let suffix = blob.suffix().unwrap_or("dat"); - // Get file name to use for sending. For privacy purposes, we do - // not transfer the original filenames eg. for images; these names - // are normally not needed and contain timestamps, running numbers - // etc. - let filename_to_send: String = match msg.type_0 { - Viewtype::Voice => chrono::Utc - .timestamp(msg.timestamp_sort as i64, 0) - .format(&format!("voice-message_%Y-%m-%d_%H-%M-%S.{}", &suffix)) - .to_string(), - Viewtype::Image | Viewtype::Gif => format!( - "{}.{}", - if base_name.is_empty() { - "image" - } else { - base_name - }, - &suffix, - ), - Viewtype::Video => format!("video.{}", &suffix), - _ => blob.as_file_name().to_string(), - }; +// // Get file name to use for sending. For privacy purposes, we do +// // not transfer the original filenames eg. for images; these names +// // are normally not needed and contain timestamps, running numbers +// // etc. +// let filename_to_send: String = match msg.type_0 { +// Viewtype::Voice => chrono::Utc +// .timestamp(msg.timestamp_sort as i64, 0) +// .format(&format!("voice-message_%Y-%m-%d_%H-%M-%S.{}", &suffix)) +// .to_string(), +// Viewtype::Image | Viewtype::Gif => format!( +// "{}.{}", +// if base_name.is_empty() { +// "image" +// } else { +// base_name +// }, +// &suffix, +// ), +// Viewtype::Video => format!("video.{}", &suffix), +// _ => blob.as_file_name().to_string(), +// }; - /* check mimetype */ - let mimetype = match msg.param.get(Param::MimeType) { - Some(mtype) => mtype, - None => { - if let Some(res) = message::guess_msgtype_from_suffix(blob.as_rel_path()) { - res.1 - } else { - "application/octet-stream" - } - } - }; +// /* check mimetype */ +// let mimetype = match msg.param.get(Param::MimeType) { +// Some(mtype) => mtype, +// None => { +// if let Some(res) = message::guess_msgtype_from_suffix(blob.as_rel_path()) { +// res.1 +// } else { +// "application/octet-stream" +// } +// } +// }; - let needs_ext = dc_needs_ext_header(&filename_to_send); +// let needs_ext = dc_needs_ext_header(&filename_to_send); - unsafe { - /* create mime part, for Content-Disposition, see RFC 2183. - `Content-Disposition: attachment` seems not to make a difference to `Content-Disposition: inline` at least on tested Thunderbird and Gma'l in 2017. - But I've heard about problems with inline and outl'k, so we just use the attachment-type until we run into other problems ... */ - let mime_fields = mailmime_fields_new_filename( - MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int, - if needs_ext { - ptr::null_mut() - } else { - filename_to_send.strdup() - }, - MAILMIME_MECHANISM_BASE64 as libc::c_int, - ); - if needs_ext { - for cur_data in (*(*mime_fields).fld_list).into_iter() { - let field: *mut mailmime_field = cur_data as *mut _; - if (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int - && !(*field).fld_data.fld_disposition.is_null() - { - let file_disposition = (*field).fld_data.fld_disposition; - if !file_disposition.is_null() { - let parm = mailmime_disposition_parm_new( - MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - 0 as libc::size_t, - mailmime_parameter_new( - strdup(b"filename*\x00" as *const u8 as *const libc::c_char), - dc_encode_ext_header(&filename_to_send).strdup(), - ), - ); - if !parm.is_null() { - clist_insert_after( - (*file_disposition).dsp_parms, - (*(*file_disposition).dsp_parms).last, - parm as *mut libc::c_void, - ); - } - } - break; - } - } - } - let content = wrapmime::new_content_type(&mimetype)?; - let filename_encoded = dc_encode_header_words(&filename_to_send); - wrapmime::append_ct_param(content, "name", &filename_encoded)?; +// { +// /* create mime part, for Content-Disposition, see RFC 2183. +// `Content-Disposition: attachment` seems not to make a difference to `Content-Disposition: inline` at least on tested Thunderbird and Gma'l in 2017. +// But I've heard about problems with inline and outl'k, so we just use the attachment-type until we run into other problems ... */ +// let mime_fields = mailmime_fields_new_filename( +// MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int, +// if needs_ext { +// ptr::null_mut() +// } else { +// filename_to_send.strdup() +// }, +// MAILMIME_MECHANISM_BASE64 as libc::c_int, +// ); +// if needs_ext { +// for cur_data in (*(*mime_fields).fld_list).into_iter() { +// let field: *mut mailmime_field = cur_data as *mut _; +// if (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int +// && !(*field).fld_data.fld_disposition.is_null() +// { +// let file_disposition = (*field).fld_data.fld_disposition; +// if !file_disposition.is_null() { +// let parm = mailmime_disposition_parm_new( +// MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int, +// ptr::null_mut(), +// ptr::null_mut(), +// ptr::null_mut(), +// ptr::null_mut(), +// 0 as libc::size_t, +// mailmime_parameter_new( +// strdup(b"filename*\x00" as *const u8 as *const libc::c_char), +// dc_encode_ext_header(&filename_to_send).strdup(), +// ), +// ); +// if !parm.is_null() { +// clist_insert_after( +// (*file_disposition).dsp_parms, +// (*(*file_disposition).dsp_parms).last, +// parm as *mut libc::c_void, +// ); +// } +// } +// break; +// } +// } +// } +// let content = wrapmime::new_content_type(&mimetype)?; +// let filename_encoded = dc_encode_header_words(&filename_to_send); +// wrapmime::append_ct_param(content, "name", &filename_encoded)?; - let mime_sub = mailmime_new_empty(content, mime_fields); - let abs_path = blob.to_abs_path().to_c_string()?; - mailmime_set_body_file(mime_sub, dc_strdup(abs_path.as_ptr())); - Ok((mime_sub, filename_to_send)) - } -} +// let mime_sub = mailmime_new_empty(content, mime_fields); +// let abs_path = blob.to_abs_path().to_c_string()?; +// mailmime_set_body_file(mime_sub, dc_strdup(abs_path.as_ptr())); +// Ok((mime_sub, filename_to_send)) +// } +// } pub(crate) fn vec_contains_lowercase(vec: &[String], part: &str) -> bool { let partlc = part.to_lowercase(); diff --git a/src/mimeparser.rs b/src/mimeparser.rs new file mode 100644 index 000000000..c55633a08 --- /dev/null +++ b/src/mimeparser.rs @@ -0,0 +1,1053 @@ +use std::collections::{HashMap, HashSet}; + +use deltachat_derive::{FromSql, ToSql}; + +use crate::blob::BlobObject; +use crate::config::Config; +use crate::constants::Viewtype; +use crate::contact::*; +use crate::context::Context; +use crate::dc_simplify::*; +use crate::dc_tools::*; +use crate::e2ee; +use crate::error::Result; +use crate::job::{job_add, Action}; +use crate::location; +use crate::message; +use crate::message::MsgId; +use crate::param::*; +use crate::stock::StockMessage; +use crate::wrapmime; + +#[derive(Debug)] +pub struct MimeParser<'a> { + pub context: &'a Context, + pub parts: Vec, + pub header: HashMap, + pub subject: Option, + pub is_send_by_messenger: bool, + pub decrypting_failed: bool, + pub encrypted: bool, + pub signatures: HashSet, + pub gossipped_addr: HashSet, + pub is_forwarded: bool, + pub is_system_message: SystemMessage, + pub location_kml: Option, + pub message_kml: Option, + reports: Vec, + parsed_header_protected: bool, + mdns_enabled: bool, +} + +#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql)] +#[repr(i32)] +pub enum SystemMessage { + Unknown = 0, + GroupNameChanged = 2, + GroupImageChanged = 3, + MemberAddedToGroup = 4, + MemberRemovedFromGroup = 5, + AutocryptSetupMessage = 6, + SecurejoinMessage = 7, + LocationStreamingEnabled = 8, + LocationOnly = 9, +} + +impl Default for SystemMessage { + fn default() -> Self { + SystemMessage::Unknown + } +} + +const DC_MIMETYPE_MP_ALTERNATIVE: i32 = 10; +const DC_MIMETYPE_MP_RELATED: i32 = 20; +const DC_MIMETYPE_MP_MIXED: i32 = 30; +const DC_MIMETYPE_MP_NOT_DECRYPTABLE: i32 = 40; +const DC_MIMETYPE_MP_REPORT: i32 = 45; +const DC_MIMETYPE_MP_SIGNED: i32 = 46; +const DC_MIMETYPE_MP_OTHER: i32 = 50; +const DC_MIMETYPE_TEXT_PLAIN: i32 = 60; +const DC_MIMETYPE_TEXT_HTML: i32 = 70; +const DC_MIMETYPE_IMAGE: i32 = 80; +const DC_MIMETYPE_AUDIO: i32 = 90; +const DC_MIMETYPE_VIDEO: i32 = 100; +const DC_MIMETYPE_FILE: i32 = 110; +const DC_MIMETYPE_AC_SETUP_FILE: i32 = 111; + +impl<'a> MimeParser<'a> { + pub fn from_bytes(context: &'a Context, body: &[u8]) -> Result { + let mail = mailparse::parse_mail(body)?; + let mdns_enabled = context.get_config_bool(Config::MdnsEnabled); + + let mut parser = MimeParser { + parts: Vec::new(), + header: Default::default(), + parsed_header_protected: false, + subject: None, + is_send_by_messenger: false, + decrypting_failed: false, + encrypted: false, + signatures: Default::default(), + gossipped_addr: Default::default(), + is_forwarded: false, + context, + reports: Vec::new(), + is_system_message: SystemMessage::Unknown, + location_kml: None, + message_kml: None, + mdns_enabled, + }; + + let mail_raw; + let mail = match e2ee::try_decrypt(parser.context, &mail) { + Ok((raw, signatures, gossipped_addr)) => { + parser.encrypted = raw.is_some(); + parser.signatures = signatures; + parser.gossipped_addr = gossipped_addr; + if let Some(raw) = raw { + mail_raw = raw; + mailparse::parse_mail(&mail_raw)? + } else { + mail + } + } + Err(err) => { + // continue with the current, still encrypted, mime tree. + // unencrypted parts will be replaced by an error message + // that is added as "the message" to the chat then. + // + // if we just return here, the header is missing + // and the caller cannot display the message + // and try to assign the message to a chat + warn!(parser.context, "decryption failed: {}", err); + mail + } + }; + + parser.hash_header(&mail.headers); + parser.parse_mime_recursive(&mail)?; + parser.parse_headers()?; + + Ok(parser) + } + + fn parse_headers(&mut self) -> Result<()> { + if let Some(field) = self.lookup_field("Subject") { + self.subject = Some(field.clone()); + } + + if let Some(_) = self.lookup_field("Chat-Version") { + self.is_send_by_messenger = true + } + + if let Some(_) = self.lookup_field("Autocrypt-Setup-Message") { + let has_setup_file = self + .parts + .iter() + .any(|p| p.mimetype == DC_MIMETYPE_AC_SETUP_FILE); + + if has_setup_file { + self.is_system_message = SystemMessage::AutocryptSetupMessage; + + // TODO: replace the following code with this + // once drain_filter stabilizes. + // + // See https://doc.rust-lang.org/std/vec/struct.Vec.html#method.drain_filter + // and https://github.com/rust-lang/rust/issues/43244 + // + // mimeparser + // .parts + // .drain_filter(|part| part.int_mimetype != 111) + // .for_each(|part| dc_mimepart_unref(part)); + + let mut i = 0; + while i != self.parts.len() { + if self.parts[i].mimetype != 111 { + self.parts.remove(i); + } else { + i += 1; + } + } + } + } else if let Some(value) = self.lookup_field("Chat-Content") { + if value == "location-streaming-enabled" { + self.is_system_message = SystemMessage::LocationStreamingEnabled; + } + } + if let Some(_) = self.lookup_field("Chat-Group-Image") { + if !self.parts.is_empty() { + let textpart = &self.parts[0]; + if textpart.typ == Viewtype::Text && self.parts.len() >= 2 { + let imgpart = &mut self.parts[1]; + if imgpart.typ == Viewtype::Image { + imgpart.is_meta = true; + } + } + } + } + if self.is_send_by_messenger && self.parts.len() == 2 { + let need_drop = { + let textpart = &self.parts[0]; + let filepart = &self.parts[1]; + textpart.typ == Viewtype::Text + && (filepart.typ == Viewtype::Image + || filepart.typ == Viewtype::Gif + || filepart.typ == Viewtype::Sticker + || filepart.typ == Viewtype::Audio + || filepart.typ == Viewtype::Voice + || filepart.typ == Viewtype::Video + || filepart.typ == Viewtype::File) + && !filepart.is_meta + }; + + if need_drop { + let mut filepart = self.parts.swap_remove(1); + + // insert new one + filepart.msg = self.parts[0].msg.as_ref().map(|s| s.to_string()); + + // forget the one we use now + self.parts[0].msg = None; + + // swap new with old + std::mem::replace(&mut self.parts[0], filepart); + } + } + if let Some(ref subject) = self.subject { + let mut prepend_subject: libc::c_int = 1i32; + if !self.decrypting_failed { + let colon = subject.find(':'); + if colon == Some(2) + || colon == Some(3) + || self.is_send_by_messenger + || subject.contains("Chat:") + { + prepend_subject = 0i32 + } + } + if 0 != prepend_subject { + let subj = if let Some(n) = subject.find('[') { + &subject[0..n] + } else { + subject + } + .trim(); + + if !subj.is_empty() { + for part in self.parts.iter_mut() { + if part.typ == Viewtype::Text { + let new_txt = format!( + "{} – {}", + subj, + part.msg.as_ref().expect("missing msg part") + ); + part.msg = Some(new_txt); + break; + } + } + } + } + } + if self.is_forwarded { + for part in self.parts.iter_mut() { + part.param.set_int(Param::Forwarded, 1); + } + } + if self.parts.len() == 1 { + if self.parts[0].typ == Viewtype::Audio { + if let Some(_) = self.lookup_field("Chat-Voice-Message") { + 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 value == "sticker" { + let part_mut = &mut self.parts[0]; + part_mut.typ = Viewtype::Sticker; + } + } + } + let part = &self.parts[0]; + if part.typ == Viewtype::Audio + || part.typ == Viewtype::Voice + || part.typ == Viewtype::Video + { + if let Some(field_0) = self.lookup_field("Chat-Duration") { + 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]; + part_mut.param.set_int(Param::Duration, duration_ms); + } + } + } + } + if !self.decrypting_failed { + if let Some(dn_field) = self.lookup_field("Chat-Disposition-Notification-To") { + 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") { + let value = from_field; + let from_addrs = mailparse::addrparse(&value).unwrap(); + if let Some(from_addr) = from_addrs.first() { + if from_addr == dn_to_addr { + if let Some(part_4) = self.get_last_nonmeta_mut() { + part_4.param.set_int(Param::WantsMdn, 1); + } + } + } + } + } + } + } + } + + /* Cleanup - and try to create at least an empty part if there are no parts yet */ + if self.get_last_nonmeta().is_none() && self.reports.is_empty() { + let mut part_5 = Part::default(); + part_5.typ = Viewtype::Text; + part_5.msg = Some("".into()); + + if let Some(ref subject) = self.subject { + if !self.is_send_by_messenger { + part_5.msg = Some(subject.to_string()) + } + } + self.parts.push(part_5); + } + + Ok(()) + } + + pub fn get_last_nonmeta(&self) -> Option<&Part> { + self.parts.iter().rev().find(|part| !part.is_meta) + } + + pub fn get_last_nonmeta_mut(&mut self) -> Option<&mut Part> { + self.parts.iter_mut().rev().find(|part| !part.is_meta) + } + + pub fn lookup_field(&self, field_name: &str) -> Option<&String> { + self.header.get(&field_name.to_lowercase()) + } + + fn parse_mime_recursive(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result { + if mail.ctype.params.get("protected-headers").is_some() { + if mail.ctype.mimetype == "text/rfc822-headers" { + info!( + self.context, + "Protected headers found in text/rfc822-headers attachment: Will be ignored.", + ); + return Ok(false); + } + + if !self.parsed_header_protected { + // use the most outer protected header - this is typically + // created in sync with the normal, unprotected header + + self.parsed_header_protected = true; + self.hash_header(&mail.headers); + } else { + info!( + self.context, + "Protected headers found in MIME header: Will be ignored as we already found an outer one." + ); + } + } + + // multiple = multipart/ or message/ + enum MimeS { + Multiple, + Single, + Message, + } + + let mimetype = mail.ctype.mimetype.to_lowercase(); + + let m = if mimetype.starts_with("multipart") { + if mail.ctype.params.get("boundary").is_some() { + MimeS::Multiple + } else { + MimeS::Single + } + } else if mimetype.starts_with("message") { + if mimetype == "message/rfc822" { + MimeS::Message + } else { + MimeS::Single + } + } else { + MimeS::Single + }; + + match m { + MimeS::Multiple => self.handle_multiple(mail), + MimeS::Message => { + let raw = mail.get_body_raw()?; + if raw.is_empty() { + return Ok(false); + } + let mail = mailparse::parse_mail(&raw).unwrap(); + + self.parse_mime_recursive(&mail) + } + MimeS::Single => self.add_single_part_if_known(mail), + } + } + + fn handle_multiple(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result { + let mut any_part_added = false; + match mailmime_get_mime_type(mail) { + /* Most times, mutlipart/alternative contains true alternatives + as text/plain and text/html. If we find a multipart/mixed + inside mutlipart/alternative, we use this (happens eg in + apple mail: "plaintext" as an alternative to "html+PDF attachment") */ + (DC_MIMETYPE_MP_ALTERNATIVE, _) => { + for cur_data in &mail.subparts { + if mailmime_get_mime_type(cur_data).0 == DC_MIMETYPE_MP_MIXED { + any_part_added = self.parse_mime_recursive(cur_data)?; + break; + } + } + if !any_part_added { + /* search for text/plain and add this */ + for cur_data in &mail.subparts { + if mailmime_get_mime_type(cur_data).0 == DC_MIMETYPE_TEXT_PLAIN { + any_part_added = self.parse_mime_recursive(cur_data)?; + break; + } + } + } + if !any_part_added { + /* `text/plain` not found - use the first part */ + for cur_part in &mail.subparts { + if self.parse_mime_recursive(cur_part)? { + any_part_added = true; + break; + } + } + } + } + (DC_MIMETYPE_MP_RELATED, _) => { + /* add the "root part" - the other parts may be referenced which is + not interesting for us (eg. embedded images) we assume he "root part" + being the first one, which may not be always true ... + however, most times it seems okay. */ + if let Some(first) = mail.subparts.iter().next() { + any_part_added = self.parse_mime_recursive(first)?; + } + } + (DC_MIMETYPE_MP_NOT_DECRYPTABLE, _) => { + let mut part = Part::default(); + part.typ = Viewtype::Text; + let msg_body = self.context.stock_str(StockMessage::CantDecryptMsgBody); + + let txt = format!("[{}]", msg_body); + part.msg_raw = Some(txt.clone()); + part.msg = Some(txt); + + self.parts.push(part); + any_part_added = true; + self.decrypting_failed = true; + } + (DC_MIMETYPE_MP_SIGNED, _) => { + /* RFC 1847: "The multipart/signed content type + contains exactly two body parts. The first body + part is the body part over which the digital signature was created [...] + The second body part contains the control information necessary to + verify the digital signature." We simpliy take the first body part and + skip the rest. (see + https://k9mail.github.io/2016/11/24/OpenPGP-Considerations-Part-I.html + for background information why we use encrypted+signed) */ + if let Some(first) = mail.subparts.iter().next() { + any_part_added = self.parse_mime_recursive(mail)?; + } + } + (DC_MIMETYPE_MP_REPORT, _) => { + /* RFC 6522: the first part is for humans, the second for machines */ + if mail.subparts.len() >= 2 { + let ct = mail.get_content_disposition()?; + if let Some(report_type) = ct.params.get("report-type") { + if report_type == "disposition-notification" { + if let Some(report) = self.process_report(mail)? { + self.reports.push(report); + } + } else { + /* eg. `report-type=delivery-status`; + maybe we should show them as a little error icon */ + if let Some(first) = mail.subparts.iter().next() { + any_part_added = self.parse_mime_recursive(mail)?; + } + } + } + } + } + _ => { + /* eg. DC_MIMETYPE_MP_MIXED - add all parts (in fact, + AddSinglePartIfKnown() later check if the parts are really supported) + HACK: the following lines are a hack for clients who use + multipart/mixed instead of multipart/alternative for + combined text/html messages (eg. Stock Android "Mail" does so). + So, if we detect such a message below, we skip the HTML + part. However, not sure, if there are useful situations to use + plain+html in multipart/mixed - if so, we should disable the hack. */ + let mut skip_part = -1; + let mut html_part = -1; + let mut plain_cnt = 0; + let mut html_cnt = 0; + + for (i, cur_data) in mail.subparts.iter().enumerate() { + match mailmime_get_mime_type(cur_data) { + (DC_MIMETYPE_TEXT_PLAIN, _) => { + plain_cnt += 1; + } + (DC_MIMETYPE_TEXT_HTML, _) => { + html_part = i as isize; + html_cnt += 1; + } + _ => {} + } + } + if plain_cnt == 1 && html_cnt == 1 { + warn!( + self.context, + "HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted." + ); + skip_part = html_part; + } + + for (i, cur_data) in mail.subparts.iter().enumerate() { + if i as isize != skip_part { + if self.parse_mime_recursive(cur_data)? { + any_part_added = true; + } + } + } + } + } + + Ok(any_part_added) + } + + fn add_single_part_if_known(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result { + // return true if a part was added + let (mime_type, msg_type) = mailmime_get_mime_type(mail); + let raw_mime = mail.ctype.mimetype.to_lowercase(); + + if !raw_mime.starts_with("text") { + // MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing + return Ok(false); + } + + let old_part_count = self.parts.len(); + + // regard `Content-Transfer-Encoding:` + match mime_type { + DC_MIMETYPE_TEXT_PLAIN | DC_MIMETYPE_TEXT_HTML => { + let decoded_data = match mail.get_body() { + Ok(decoded_data) => decoded_data, + Err(err) => { + warn!(self.context, "Invalid body parsed {:?}", err); + // Note that it's not always an error - might be no data + return Ok(false); + } + }; + + // check header directly as is_send_by_messenger is not yet set up + let is_msgrmsg = self.lookup_field("Chat-Version").is_some(); + + let mut simplifier = Simplify::new(); + let simplified_txt = if decoded_data.is_empty() { + "".into() + } else { + let is_html = mime_type == DC_MIMETYPE_TEXT_HTML; + simplifier.simplify(&decoded_data, is_html, is_msgrmsg) + }; + + if !simplified_txt.is_empty() { + let mut part = Part::default(); + part.typ = Viewtype::Text; + part.mimetype = mime_type; + part.msg = Some(simplified_txt); + part.msg_raw = Some(decoded_data); + self.do_add_single_part(part); + } + + if simplifier.is_forwarded { + self.is_forwarded = true; + } + } + DC_MIMETYPE_IMAGE + | DC_MIMETYPE_AUDIO + | DC_MIMETYPE_VIDEO + | DC_MIMETYPE_FILE + | DC_MIMETYPE_AC_SETUP_FILE => { + // try to get file name from + // `Content-Disposition: ... filename*=...` + // or `Content-Disposition: ... filename*0*=... filename*1*=... filename*2*=...` + // or `Content-Disposition: ... filename=...` + + let ct = mail.get_content_disposition()?; + let mut desired_filename = ct + .params + .iter() + .filter(|(key, _value)| key.starts_with("filename")) + .fold(String::new(), |mut acc, (_key, value)| { + acc += value; + acc + }); + + if desired_filename.is_empty() { + if let Some(param) = ct.params.get("name") { + // might be a wrongly encoded filename + desired_filename = param.to_string(); + } + } + + // if there is still no filename, guess one + if desired_filename.is_empty() { + if let Some(subtype) = mail.ctype.mimetype.split('/').skip(1).next() { + desired_filename = format!("file.{}", subtype,); + } else { + return Ok(false); + } + } + self.do_add_single_file_part( + msg_type, + mime_type, + &raw_mime, + &mail.get_body_raw()?, + &desired_filename, + ); + } + _ => {} + } + + // add object? (we do not add all objects, eg. signatures etc. are ignored) + Ok(self.parts.len() > old_part_count) + } + + fn do_add_single_file_part( + &mut self, + msg_type: Viewtype, + mime_type: libc::c_int, + raw_mime: &String, + decoded_data: &[u8], + filename: &str, + ) { + 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 parsed = location::Kml::parse(self.context, decoded_data) + .map_err(|err| { + warn!(self.context, "failed to parse kml part: {}", err); + }) + .ok(); + 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 {}", 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; + part.bytes = decoded_data.len() as libc::c_int; + part.param.set(Param::File, blob.as_name()); + part.param.set(Param::MimeType, raw_mime); + + if mime_type == DC_MIMETYPE_IMAGE { + if let Ok((width, height)) = dc_get_filemeta(decoded_data) { + part.param.set_int(Param::Width, width as i32); + part.param.set_int(Param::Height, height as i32); + } + } + self.do_add_single_part(part); + } + + fn do_add_single_part(&mut self, mut part: Part) { + 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); + } + + pub fn is_mailinglist_message(&self) -> bool { + if let Some(_) = self.lookup_field("List-Id") { + return true; + } + + if let Some(precedence) = self.lookup_field("Precedence") { + if precedence == "list" || precedence == "bulk" { + return true; + } + } + + false + } + + 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 Ok(addrs) = mailparse::addrparse(field) { + if addrs.len() != 1 { + return false; + } + if let mailparse::MailAddr::Single(ref info) = addrs[0] { + let from_addr_norm = addr_normalize(&info.addr); + let recipients = wrapmime::mailimf_get_recipients(&self.header); + if recipients.len() == 1 && recipients.contains(from_addr_norm) { + return true; + } + } + } + } + false + } + + pub fn repl_msg_by_error(&mut self, error_msg: impl AsRef) { + if self.parts.is_empty() { + return; + } + + let part = &mut self.parts[0]; + part.typ = Viewtype::Text; + part.msg = Some(format!("[{}]", error_msg.as_ref())); + self.parts.truncate(1); + + assert_eq!(self.parts.len(), 1); + } + + pub fn get_rfc724_mid(&self) -> Option { + // get Message-ID from header + if let Some(field) = self.lookup_field("Message-ID") { + return parse_message_id(field); + } + None + } + + fn hash_header(&mut self, fields: &[mailparse::MailHeader<'_>]) { + for field in fields { + if let Ok(key) = field.get_key() { + // lowercasing all headers is technically not correct, but makes things work better + let key = key.to_lowercase(); + if !self.header.contains_key(&key) || // key already exists, only overwrite known types (protected headers) + is_known(&key) || key.starts_with("chat-") + { + if let Ok(value) = field.get_value() { + self.header.insert(key, value); + } + } + } + } + } + + fn process_report(&self, report: &mailparse::ParsedMail<'_>) -> Result> { + use mailparse::MailHeaderMap; + + let ct = report.get_content_disposition()?; + let report_type = ct.params.get("report-type"); + if report_type.is_none() { + return Ok(None); + } + let report_type = report_type.unwrap(); + if report_type != "disposition-notification" || report.subparts.len() < 2 { + // the first part is for humans, the second for machines + return Ok(None); + } + + // to get a clear functionality, do not show incoming MDNs if the options is disabled + if !self.mdns_enabled { + return Ok(None); + } + // 1. get content + let raw = report.subparts[1].get_body_raw()?; + let report_details = mailparse::parse_mail(&raw)?; + + // 2. parse as mailheaders + let report_body = report_details.get_body_raw()?; + let (report_fields, _) = mailparse::parse_headers(&report_body)?; + + // 3. retrieve information + + // must be present + if let Some(disposition) = report_fields.get_first_value("Disposition").ok().flatten() { + if let Some(original_message_id) = report_fields + .get_first_value("Original-Message-ID") + .ok() + .flatten() + .and_then(|v| parse_message_id(&v)) + { + return Ok(Some(Report { + original_message_id, + })); + } + } + + Ok(None) + } + + // Handle reports (mainly MDNs) + pub fn handle_reports( + &self, + from_id: u32, + sent_timestamp: i64, + rr_event_to_send: &mut Vec<(u32, MsgId)>, + server_folder: impl AsRef, + server_uid: u32, + ) { + for report in &self.reports { + let mut mdn_consumed = false; + + if let Some((chat_id, msg_id)) = message::mdn_from_ext( + self.context, + from_id, + &report.original_message_id, + sent_timestamp, + ) { + rr_event_to_send.push((chat_id, msg_id)); + mdn_consumed = true; + } + + if self.is_send_by_messenger || mdn_consumed { + let mut param = Params::new(); + param.set(Param::ServerFolder, server_folder.as_ref()); + param.set_int(Param::ServerUid, server_uid as i32); + if self.is_send_by_messenger && self.context.get_config_bool(Config::MvboxMove) { + param.set_int(Param::AlsoMove, 1); + } + job_add(self.context, Action::MarkseenMdnOnImap, 0, param, 0); + } + } + } +} + +#[derive(Debug)] +struct Report { + original_message_id: String, +} + +fn parse_message_id(field: &str) -> Option { + if let Ok(addrs) = mailparse::addrparse(field) { + // Assume the message id is a single id in the form of + if let mailparse::MailAddr::Single(mailparse::SingleInfo { ref addr, .. }) = addrs[0] { + return Some(addr.clone()); + } + } + None +} + +fn is_known(key: &str) -> bool { + match key { + "return-path" | "date" | "from" | "sender" | "reply-to" | "to" | "cc" | "bcc" + | "message-id" | "in-reply-to" | "references" | "subject" => true, + _ => false, + } +} + +#[derive(Default, Debug, Clone)] +pub struct Part { + pub typ: Viewtype, + pub is_meta: bool, + pub mimetype: i32, + pub msg: Option, + pub msg_raw: Option, + pub bytes: i32, + pub param: Params, +} + +fn mailmime_get_mime_type(mail: &mailparse::ParsedMail<'_>) -> (libc::c_int, Viewtype) { + let unknown_type = (0, Viewtype::Unknown); + + let mimetype = mail.ctype.mimetype.to_lowercase(); + let mut parts = mimetype.split('/'); + let typ = parts.next().expect("invalid mimetype"); + let subtype = parts.next().unwrap_or_default(); + + match typ { + "text" => { + if !mailmime_is_attachment_disposition(mail) { + if subtype == "plain" { + return (DC_MIMETYPE_TEXT_PLAIN, Viewtype::Text); + } + if subtype == "html" { + return (DC_MIMETYPE_TEXT_HTML, Viewtype::Text); + } + } + + (DC_MIMETYPE_FILE, Viewtype::File) + } + "image" => { + let msg_type = match subtype { + "gif" => Viewtype::Gif, + "svg+xml" => { + return (DC_MIMETYPE_FILE, Viewtype::File); + } + _ => Viewtype::Image, + }; + + (DC_MIMETYPE_IMAGE, msg_type) + } + "audio" => (DC_MIMETYPE_AUDIO, Viewtype::Audio), + "video" => (DC_MIMETYPE_VIDEO, Viewtype::Video), + "multipart" => { + let mime_type = match subtype { + "alternative" => DC_MIMETYPE_MP_ALTERNATIVE, + "related" => DC_MIMETYPE_MP_RELATED, + "encrypted" => { + // maybe try_decrypt failed to decrypt + // or it wasn't in proper Autocrypt format + DC_MIMETYPE_MP_NOT_DECRYPTABLE + } + "signed" => DC_MIMETYPE_MP_SIGNED, + "mixed" => DC_MIMETYPE_MP_MIXED, + "report" => DC_MIMETYPE_MP_REPORT, + _ => DC_MIMETYPE_MP_OTHER, + }; + + (mime_type, Viewtype::Unknown) + } + "message" => { + // Enacapsulated messages, see https://www.w3.org/Protocols/rfc1341/7_3_Message.html + // Also used as part "message/disposition-notification" of "multipart/report", which, however, will + // be handled separatedly. + // I've not seen any messages using this, so we do not attach these parts (maybe they're used to attach replies, + // which are unwanted at all). + // For now, we skip these parts at all; if desired, we could return DC_MIMETYPE_FILE/DC_MSG_FILE + // for selected and known subparts. + unknown_type + } + "application" => { + if subtype == "autocrypt-setup" { + return (DC_MIMETYPE_AC_SETUP_FILE, Viewtype::File); + } + + (DC_MIMETYPE_FILE, Viewtype::File) + } + _ => unknown_type, + } +} + +fn mailmime_is_attachment_disposition(mail: &mailparse::ParsedMail<'_>) -> bool { + if let Some(ct) = mail.ctype.params.get("Content-Disposition") { + return ct.to_lowercase().starts_with("attachment"); + } + + false +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test_utils::*; + use proptest::prelude::*; + + #[test] + fn test_dc_mimeparser_crash() { + let context = dummy_context(); + let raw = include_bytes!("../test-data/message/issue_523.txt"); + let mimeparser = MimeParser::from_bytes(&context.ctx, &raw[..]).unwrap(); + + assert_eq!(mimeparser.subject, None); + assert_eq!(mimeparser.parts.len(), 1); + } + + proptest! { + #[ignore] + #[test] + fn test_dc_mailmime_parse_crash_fuzzy(data in "[!-~\t ]{2000,}") { + let context = dummy_context(); + // parsing should error out for all these random strings + assert!( + MimeParser::from_bytes(&context.ctx, data.as_bytes()).is_err() + ); + } + } + + #[test] + fn test_get_rfc724_mid_exists() { + let context = dummy_context(); + let raw = include_bytes!("../test-data/message/mail_with_message_id.txt"); + let mimeparser = MimeParser::from_bytes(&context.ctx, &raw[..]).unwrap(); + + assert_eq!( + mimeparser.get_rfc724_mid(), + Some("2dfdbde7@example.org".into()) + ); + } + + #[test] + fn test_get_rfc724_mid_not_exists() { + let context = dummy_context(); + let raw = include_bytes!("../test-data/message/issue_523.txt"); + let mimeparser = MimeParser::from_bytes(&context.ctx, &raw[..]).unwrap(); + assert_eq!(mimeparser.get_rfc724_mid(), None); + } + + #[test] + fn test_mimeparser_with_context() { + let context = dummy_context(); + 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\ + \n\ + --==break==\n\ + Content-Type: text/plain; protected-headers=\"v1\";\n\ + Subject: inner-subject\n\ + X-Special-B: special-b\n\ + Foo: Xy\n\ + Chat-Version: 1.0\n\ + \n\ + test1\n\ + \n\ + --==break==--\n\ + \n\ + \x00"; + let mimeparser = MimeParser::from_bytes(&context.ctx, &raw[..]).unwrap(); + + assert_eq!(mimeparser.subject, Some("inner-subject".into())); + + let of = mimeparser.lookup_field("X-Special-A").unwrap(); + assert_eq!(of, "special-a"); + + let of = mimeparser.lookup_field("Foo").unwrap(); + assert_eq!(of, "Bar"); + + let of = mimeparser.lookup_field("Chat-Version").unwrap(); + assert_eq!(of, "1.0"); + assert_eq!(mimeparser.parts.len(), 1); + } +} diff --git a/src/param.rs b/src/param.rs index 908ba7923..8fc0891fc 100644 --- a/src/param.rs +++ b/src/param.rs @@ -7,8 +7,8 @@ use num_traits::FromPrimitive; use crate::blob::{BlobError, BlobObject}; use crate::context::Context; -use crate::dc_mimeparser::SystemMessage; use crate::error; +use crate::mimeparser::SystemMessage; /// Available param keys. #[derive(PartialEq, Eq, Debug, Clone, Copy, Hash, PartialOrd, Ord, FromPrimitive)] diff --git a/src/securejoin.rs b/src/securejoin.rs index 59ba70e46..b22bb4fde 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -8,13 +8,13 @@ use crate::config::*; use crate::constants::*; use crate::contact::*; use crate::context::Context; -use crate::dc_mimeparser::*; use crate::e2ee::*; use crate::error::Error; use crate::events::Event; use crate::key::*; use crate::lot::LotState; use crate::message::Message; +use crate::mimeparser::*; use crate::param::*; use crate::peerstate::*; use crate::qr::check_qr; diff --git a/src/wrapmime.rs b/src/wrapmime.rs index c8cc7fda3..51d0c3928 100644 --- a/src/wrapmime.rs +++ b/src/wrapmime.rs @@ -1,289 +1,79 @@ -use std::collections::HashSet; -use std::ffi::CString; -use std::ptr; +use std::collections::{HashMap, HashSet}; + +use mailparse::ParsedMail; use crate::contact::addr_normalize; -use crate::dc_strencode::*; -use crate::dc_tools::*; use crate::error::Error; -use mmime::clist::*; -// use mmime::display::*; -use mmime::mailimf::mailimf_msg_id_parse; -use mmime::mailimf::types::*; -use mmime::mailimf::types_helper::*; -use mmime::mailmime::content::*; -use mmime::mailmime::disposition::*; -use mmime::mailmime::types::*; -use mmime::mailmime::types_helper::*; -use mmime::mailmime::*; -use mmime::mmapstring::*; -use mmime::other::*; - -#[macro_export] -macro_rules! clist_append { - ($clist:expr, $item:expr) => { - if clist_insert_after( - $clist as *mut clist, - (*$clist).last, - $item as *mut libc::c_void, - ) != 0 - { - bail!("could not allocate or append list item"); - } - }; -} /************************************** * mime parsing API **************************************/ -pub fn get_ct_subtype(mime: *mut Mailmime) -> Option { - unsafe { - let ct: *mut mailmime_content = (*mime).mm_content_type; - - if !ct.is_null() && !(*ct).ct_subtype.is_null() { - Some(to_string_lossy((*ct).ct_subtype)) - } else { - None - } - } -} - pub fn parse_message_id(message_id: &[u8]) -> Result { - let mut dummy = 0; - let mut rfc724_mid_c = std::ptr::null_mut(); - if unsafe { - mailimf_msg_id_parse( - message_id.as_ptr() as *const libc::c_char, - message_id.len(), - &mut dummy, - &mut rfc724_mid_c, - ) - } == MAIL_NO_ERROR as libc::c_int - && !rfc724_mid_c.is_null() - { - let res = to_string_lossy(rfc724_mid_c); - unsafe { libc::free(rfc724_mid_c.cast()) }; - Ok(res) - } else { - bail!( - "could not parse message_id: {}", - String::from_utf8_lossy(message_id) - ); + let value = std::str::from_utf8(message_id)?; + let addrs = mailparse::addrparse(value) + .map_err(|err| format_err!("failed to parse message id {:?}", err))?; + + if let Some(info) = addrs.extract_single_info() { + return Ok(info.addr); } + + bail!( + "could not parse message_id: {}", + String::from_utf8_lossy(message_id) + ); } -pub fn get_autocrypt_mime( - mime_undetermined: *mut Mailmime, -) -> Result<(*mut Mailmime, *mut Mailmime), Error> { - /* return Result with two mime pointers: +/// Returns a reference to the encrypted payload and validates the autocrypt structure. +pub fn get_autocrypt_mime<'a, 'b>(mail: &'a ParsedMail<'b>) -> Result<&'a ParsedMail<'b>, Error> { + ensure!( + mail.ctype.mimetype == "multipart/encrypted", + "Not a multipart/encrypted message" + ); + ensure!( + mail.subparts.len() == 2, + "Invalid Autocrypt Level 1 Mime Parts" + ); - First mime pointer is to the multipart-mime message - (which is replaced with a decrypted version later) + ensure!( + mail.subparts[0].ctype.mimetype == "application/pgp-encrypted", + "Invalid Autocrypt Level 1 version part" + ); - Second one is to the encrypted payload. - For non-autocrypt message an Error is returned. - */ - unsafe { - ensure!( - (*mime_undetermined).mm_type == MAILMIME_MESSAGE as libc::c_int, - "Not a root mime message" - ); - let mime = (*mime_undetermined).mm_data.mm_message.mm_msg_mime; + ensure!( + mail.subparts[1].ctype.mimetype == "application/octetstream", + "Invalid Autocrypt Level 1 encrypted part" + ); - ensure!( - (*mime).mm_type == MAILMIME_MULTIPLE as libc::c_int - && "encrypted" == get_ct_subtype(mime).unwrap_or_default(), - "Not a multipart/encrypted message" - ); - let parts: Vec<_> = (*(*mime).mm_data.mm_multipart.mm_mp_list) - .into_iter() - .map(|c| c as *mut Mailmime) - .collect(); - ensure!(parts.len() == 2, "Invalid Autocrypt Level 1 Mime Parts"); - // XXX ensure protocol-parameter "application/pgp-encrypted") - // XXX ensure wrapmime::get_content_type(parts[1])) == "application/octetstream" - // a proper OpenPGP multipart/encrypted Autocrypt Level 1 message - // https://tools.ietf.org/html/rfc3156.html#section-4 - Ok((mime, parts[1])) - } + Ok(&mail.subparts[1]) } -pub fn has_decryptable_data(mime_data: *mut mailmime_data) -> bool { - /* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */ - unsafe { - (*mime_data).dt_type == MAILMIME_DATA_TEXT as libc::c_int - && !(*mime_data).dt_data.dt_text.dt_data.is_null() - && (*mime_data).dt_data.dt_text.dt_length > 0 - } +pub fn has_decryptable_data(mail: &ParsedMail<'_>) -> bool { + false + // /* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */ + // { + // (*mime_data).dt_type == MAILMIME_DATA_TEXT as libc::c_int + // && !(*mime_data).dt_data.dt_text.dt_data.is_null() + // && (*mime_data).dt_data.dt_text.dt_length > 0 + // } } -pub fn get_field_from(imffields: *mut mailimf_fields) -> Result { - let field = mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int); - if !field.is_null() && unsafe { !(*field).fld_data.fld_from.is_null() } { - let mb_list = unsafe { (*(*field).fld_data.fld_from).frm_mb_list }; - if let Some(addr) = mailimf_find_first_addr(mb_list) { - return Ok(addr); - } - } - bail!("not From field found"); -} - -pub fn get_field_date(imffields: *mut mailimf_fields) -> Result { - let field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int); - let mut message_time = 0; - - if !field.is_null() && unsafe { !(*field).fld_data.fld_orig_date.is_null() } { - let orig_date = unsafe { (*field).fld_data.fld_orig_date }; - - if !orig_date.is_null() { - let dt = unsafe { (*orig_date).dt_date_time }; - message_time = dc_timestamp_from_date(dt); - if message_time != 0 && message_time > time() { - message_time = time() - } - } - } - - Ok(message_time) -} - -fn mailimf_get_recipients_add_addr(recipients: &mut HashSet, mb: *mut mailimf_mailbox) { - if !mb.is_null() { - let addr = to_string_lossy(unsafe { (*mb).mb_addr_spec }); - let addr_norm = addr_normalize(&addr); - recipients.insert(addr_norm.into()); - } -} - -/*the result is a pointer to mime, must not be freed*/ -pub fn mailimf_find_field( - header: *mut mailimf_fields, - wanted_fld_type: libc::c_int, -) -> *mut mailimf_field { - if header.is_null() { - return ptr::null_mut(); - } - - let header = unsafe { (*header) }; - if header.fld_list.is_null() { - return ptr::null_mut(); - } - - for cur in unsafe { &(*header.fld_list) } { - let field = cur as *mut mailimf_field; - if !field.is_null() { - if unsafe { (*field).fld_type } == wanted_fld_type { - return field; - } - } - } - - ptr::null_mut() -} - -/*the result is a pointer to mime, must not be freed*/ -pub fn mailmime_find_mailimf_fields(mime: *mut Mailmime) -> *mut mailimf_fields { - if mime.is_null() { - return ptr::null_mut(); - } - - match unsafe { (*mime).mm_type as _ } { - MAILMIME_MULTIPLE => { - for cur_data in unsafe { (*(*mime).mm_data.mm_multipart.mm_mp_list).into_iter() } { - let header = mailmime_find_mailimf_fields(cur_data as *mut _); - if !header.is_null() { - return header; - } - } - } - MAILMIME_MESSAGE => return unsafe { (*mime).mm_data.mm_message.mm_fields }, - _ => {} - } - - ptr::null_mut() -} - -pub unsafe fn mailimf_find_optional_field( - header: *mut mailimf_fields, - wanted_fld_name: *const libc::c_char, -) -> *mut mailimf_optional_field { - if header.is_null() || (*header).fld_list.is_null() { - return ptr::null_mut(); - } - for cur_data in (*(*header).fld_list).into_iter() { - let field: *mut mailimf_field = cur_data as *mut _; - - if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { - let optional_field: *mut mailimf_optional_field = (*field).fld_data.fld_optional_field; - if !optional_field.is_null() - && !(*optional_field).fld_name.is_null() - && !(*optional_field).fld_value.is_null() - && strcasecmp((*optional_field).fld_name, wanted_fld_name) == 0i32 - { - return optional_field; - } - } - } - - ptr::null_mut() -} - -pub fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet { - /* returned addresses are normalized. */ +// returned addresses are normalized. +pub fn mailimf_get_recipients(headers: &HashMap) -> HashSet { let mut recipients: HashSet = Default::default(); - for cur in unsafe { (*(*imffields).fld_list).into_iter() } { - let fld = cur as *mut mailimf_field; - - let fld_to: *mut mailimf_to; - let fld_cc: *mut mailimf_cc; - - let mut addr_list: *mut mailimf_address_list = ptr::null_mut(); - if fld.is_null() { - continue; - } - - let fld = unsafe { *fld }; - - // TODO match on enums /rtn - match fld.fld_type { - 13 => { - fld_to = unsafe { fld.fld_data.fld_to }; - if !fld_to.is_null() { - addr_list = unsafe { (*fld_to).to_addr_list }; - } - } - 14 => { - fld_cc = unsafe { fld.fld_data.fld_cc }; - if !fld_cc.is_null() { - addr_list = unsafe { (*fld_cc).cc_addr_list }; - } - } - _ => {} - } - - if !addr_list.is_null() { - for cur2 in unsafe { &(*(*addr_list).ad_list) } { - let adr = cur2 as *mut mailimf_address; - - if adr.is_null() { - continue; - } - let adr = unsafe { *adr }; - - if adr.ad_type == MAILIMF_ADDRESS_MAILBOX as libc::c_int { - mailimf_get_recipients_add_addr(&mut recipients, unsafe { - adr.ad_data.ad_mailbox - }); - } else if adr.ad_type == MAILIMF_ADDRESS_GROUP as libc::c_int { - let group = unsafe { adr.ad_data.ad_group }; - if !group.is_null() && unsafe { !(*group).grp_mb_list.is_null() } { - for cur3 in unsafe { &(*(*(*group).grp_mb_list).mb_list) } { - mailimf_get_recipients_add_addr( - &mut recipients, - cur3 as *mut mailimf_mailbox, - ); + for (hkey, hvalue) in headers.iter() { + if hkey == "to" || hkey == "cc" { + if let Ok(addrs) = mailparse::addrparse(hvalue) { + for addr in addrs.iter() { + match addr { + mailparse::MailAddr::Single(ref info) => { + recipients.insert(addr_normalize(&info.addr).into()); + } + mailparse::MailAddr::Group(ref infos) => { + for info in &infos.addrs { + recipients.insert(addr_normalize(&info.addr).into()); + } } } } @@ -294,258 +84,154 @@ pub fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet recipients } -pub fn mailmime_transfer_decode(mime: *mut Mailmime) -> Result, Error> { - ensure!(!mime.is_null(), "invalid inputs"); - - let mime_transfer_encoding = - get_mime_transfer_encoding(mime).unwrap_or(MAILMIME_MECHANISM_BINARY as i32); - - let mime_data = unsafe { (*mime).mm_data.mm_single }; - - decode_dt_data(mime_data, mime_transfer_encoding) -} - -pub fn get_mime_transfer_encoding(mime: *mut Mailmime) -> Option { - unsafe { - let mm_mime_fields = (*mime).mm_mime_fields; - if !mm_mime_fields.is_null() { - for cur_data in (*(*mm_mime_fields).fld_list).into_iter() { - let field: *mut mailmime_field = cur_data as *mut _; - if (*field).fld_type == MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int - && !(*field).fld_data.fld_encoding.is_null() - { - return Some((*(*field).fld_data.fld_encoding).enc_type); - } - } - } - } - None -} - -pub fn decode_dt_data( - mime_data: *mut mailmime_data, - mime_transfer_encoding: libc::c_int, -) -> Result, Error> { - // Decode data according to mime_transfer_encoding - // returns Ok with a (decoded_data,decoded_data_bytes) pointer - // where the caller must make sure to free it. - // It may return Ok(ptr::null_mut(), 0) - if mime_transfer_encoding == MAILMIME_MECHANISM_7BIT as libc::c_int - || mime_transfer_encoding == MAILMIME_MECHANISM_8BIT as libc::c_int - || mime_transfer_encoding == MAILMIME_MECHANISM_BINARY as libc::c_int - { - let decoded_data = unsafe { (*mime_data).dt_data.dt_text.dt_data }; - let decoded_data_bytes = unsafe { (*mime_data).dt_data.dt_text.dt_length }; - - if decoded_data.is_null() || decoded_data_bytes == 0 { - bail!("No data to decode found"); - } else { - let result = unsafe { - std::slice::from_raw_parts(decoded_data as *const u8, decoded_data_bytes) - }; - return Ok(result.to_vec()); - } - } - // unsafe { display_mime_data(mime_data) }; - - let mut current_index = 0; - let mut transfer_decoding_buffer = ptr::null_mut(); - let mut decoded_data_bytes = 0; - - let r = unsafe { - mailmime_part_parse( - (*mime_data).dt_data.dt_text.dt_data, - (*mime_data).dt_data.dt_text.dt_length, - &mut current_index, - mime_transfer_encoding, - &mut transfer_decoding_buffer, - &mut decoded_data_bytes, - ) - }; - - if r == MAILIMF_NO_ERROR as libc::c_int - && !transfer_decoding_buffer.is_null() - && decoded_data_bytes > 0 - { - let result = unsafe { - std::slice::from_raw_parts(transfer_decoding_buffer as *const u8, decoded_data_bytes) - } - .to_vec(); - // we return a fresh vec and transfer_decoding_buffer is not used or passed anywhere - // so it's safe to free it right away, as mailman_part_parse has - // allocated it fresh. - unsafe { mmap_string_unref(transfer_decoding_buffer) }; - - return Ok(result); - } - - Err(format_err!("Failed to to decode")) -} - -pub fn mailimf_find_first_addr(mb_list: *const mailimf_mailbox_list) -> Option { - if mb_list.is_null() { - return None; - } - - for cur in unsafe { (*(*mb_list).mb_list).into_iter() } { - let mb = cur as *mut mailimf_mailbox; - if !mb.is_null() && !unsafe { (*mb).mb_addr_spec.is_null() } { - let addr = unsafe { to_string_lossy((*mb).mb_addr_spec) }; - return Some(addr_normalize(&addr).to_string()); - } - } - - None -} - /************************************** * mime creation API **************************************/ -pub fn add_filename_part( - message: *mut Mailmime, - basename: &str, - mime_type: &str, - file_content: &str, -) -> Result<(), Error> { - let mime_type_c = CString::new(mime_type.to_string()).expect("failed to create CString"); - unsafe { - let content_type = mailmime_content_new_with_str(mime_type_c.as_ptr()); - let mime_fields = mailmime_fields_new_filename( - MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int, - basename.strdup(), - MAILMIME_MECHANISM_8BIT as libc::c_int, - ); - let file_mime_part = mailmime_new_empty(content_type, mime_fields); - set_body_text(file_mime_part, file_content)?; - mailmime_smart_add_part(message, file_mime_part); - } - Ok(()) -} +// pub fn add_filename_part( +// message: *mut Mailmime, +// basename: &str, +// mime_type: &str, +// file_content: &str, +// ) -> Result<(), Error> { +// let mime_type_c = CString::new(mime_type.to_string()).expect("failed to create CString"); +// { +// let content_type = mailmime_content_new_with_str(mime_type_c.as_ptr()); +// let mime_fields = mailmime_fields_new_filename( +// MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int, +// basename.strdup(), +// MAILMIME_MECHANISM_8BIT as libc::c_int, +// ); +// let file_mime_part = mailmime_new_empty(content_type, mime_fields); +// set_body_text(file_mime_part, file_content)?; +// mailmime_smart_add_part(message, file_mime_part); +// } +// Ok(()) +// } -pub fn new_custom_field(fields: *mut mailimf_fields, name: &str, value: &str) { - unsafe { - let field = mailimf_field_new_custom(name.strdup(), value.strdup()); - let res = mailimf_fields_add(fields, field); - assert!( - res as u32 == MAILIMF_NO_ERROR, - "could not create mailimf field" - ); - } -} +// pub fn new_custom_field(fields: *mut mailimf_fields, name: &str, value: &str) { +// { +// let field = mailimf_field_new_custom(name.strdup(), value.strdup()); +// let res = mailimf_fields_add(fields, field); +// assert!( +// res as u32 == MAILIMF_NO_ERROR, +// "could not create mailimf field" +// ); +// } +// } -pub fn build_body_text(text: &str) -> Result<*mut Mailmime, Error> { - let mime_fields: *mut mailmime_fields; - let message_part: *mut Mailmime; +// pub fn build_body_text(text: &str) -> Result<*mut Mailmime, Error> { +// let mime_fields: *mut mailmime_fields; +// let message_part: *mut Mailmime; - let content = new_content_type("text/plain")?; - append_ct_param(content, "charset", "utf-8")?; +// let content = new_content_type("text/plain")?; +// append_ct_param(content, "charset", "utf-8")?; - unsafe { - mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int); - message_part = mailmime_new_empty(content, mime_fields); - } - set_body_text(message_part, text)?; +// { +// mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int); +// message_part = mailmime_new_empty(content, mime_fields); +// } +// set_body_text(message_part, text)?; - Ok(message_part) -} +// Ok(message_part) +// } -pub fn append_ct_param( - content: *mut mailmime_content, - name: &str, - value: &str, -) -> Result<(), Error> { - unsafe { - let name_c = CString::new(name).unwrap_or_default(); - let value_c = CString::new(value).unwrap_or_default(); +// pub fn append_ct_param( +// content: *mut mailmime_content, +// name: &str, +// value: &str, +// ) -> Result<(), Error> { +// { +// let name_c = CString::new(name).unwrap_or_default(); +// let value_c = CString::new(value).unwrap_or_default(); - clist_append!( - (*content).ct_parameters, - mailmime_param_new_with_data( - name_c.as_ptr() as *const u8 as *const libc::c_char as *mut libc::c_char, - value_c.as_ptr() as *const u8 as *const libc::c_char as *mut libc::c_char - ) - ); - } - Ok(()) -} +// clist_append!( +// (*content).ct_parameters, +// mailmime_param_new_with_data( +// name_c.as_ptr() as *const u8 as *const libc::c_char as *mut libc::c_char, +// value_c.as_ptr() as *const u8 as *const libc::c_char as *mut libc::c_char +// ) +// ); +// } +// Ok(()) +// } -pub fn new_content_type(content_type: &str) -> Result<*mut mailmime_content, Error> { - let ct = CString::new(content_type).unwrap_or_default(); - let content: *mut mailmime_content; - // mailmime_content_new_with_str only parses but does not retain/own ct - unsafe { - content = mailmime_content_new_with_str(ct.as_ptr()); - } - ensure!(!content.is_null(), "mailimf failed to allocate"); - Ok(content) -} +// pub fn new_content_type(content_type: &str) -> Result<*mut mailmime_content, Error> { +// let ct = CString::new(content_type).unwrap_or_default(); +// let content: *mut mailmime_content; +// // mailmime_content_new_with_str only parses but does not retain/own ct +// { +// content = mailmime_content_new_with_str(ct.as_ptr()); +// } +// ensure!(!content.is_null(), "mailimf failed to allocate"); +// Ok(content) +// } -pub fn set_body_text(part: *mut Mailmime, text: &str) -> Result<(), Error> { - use libc::strlen; - unsafe { - let text_c = text.strdup(); - if 0 != mailmime_set_body_text(part, text_c, strlen(text_c)) { - bail!("could not set body text on mime-structure"); - } - } - Ok(()) -} +// pub fn set_body_text(part: *mut Mailmime, text: &str) -> Result<(), Error> { +// use libc::strlen; +// { +// let text_c = text.strdup(); +// if 0 != mailmime_set_body_text(part, text_c, strlen(text_c)) { +// bail!("could not set body text on mime-structure"); +// } +// } +// Ok(()) +// } -pub fn content_type_needs_encoding(content: *const mailmime_content) -> bool { - unsafe { - if (*(*content).ct_type).tp_type == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int { - let composite = (*(*content).ct_type).tp_data.tp_composite_type; - match (*composite).ct_type as u32 { - MAILMIME_COMPOSITE_TYPE_MESSAGE => { - to_string_lossy((*content).ct_subtype) != "rfc822" - } - MAILMIME_COMPOSITE_TYPE_MULTIPART => false, - _ => false, - } - } else { - true - } - } -} +// pub fn content_type_needs_encoding(content: *const mailmime_content) -> bool { +// { +// if (*(*content).ct_type).tp_type == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int { +// let composite = (*(*content).ct_type).tp_data.tp_composite_type; +// match (*composite).ct_type as u32 { +// MAILMIME_COMPOSITE_TYPE_MESSAGE => { +// to_string_lossy((*content).ct_subtype) != "rfc822" +// } +// MAILMIME_COMPOSITE_TYPE_MULTIPART => false, +// _ => false, +// } +// } else { +// true +// } +// } +// } -pub fn new_mailbox_list(displayname: &str, addr: &str) -> *mut mailimf_mailbox_list { - let mbox: *mut mailimf_mailbox_list = unsafe { mailimf_mailbox_list_new_empty() }; - unsafe { - mailimf_mailbox_list_add( - mbox, - mailimf_mailbox_new( - if !displayname.is_empty() { - dc_encode_header_words(&displayname).strdup() - } else { - ptr::null_mut() - }, - addr.strdup(), - ), - ); - } - mbox -} +// pub fn new_mailbox_list(displayname: &str, addr: &str) -> *mut mailimf_mailbox_list { +// let mbox: *mut mailimf_mailbox_list = { mailimf_mailbox_list_new_empty() }; +// { +// mailimf_mailbox_list_add( +// mbox, +// mailimf_mailbox_new( +// if !displayname.is_empty() { +// dc_encode_header_words(&displayname).strdup() +// } else { +// ptr::null_mut() +// }, +// addr.strdup(), +// ), +// ); +// } +// mbox +// } #[cfg(test)] mod tests { use super::*; - #[test] - fn test_needs_encoding() { - assert!(content_type_needs_encoding( - new_content_type("text/plain").unwrap() - )); - assert!(content_type_needs_encoding( - new_content_type("application/octect-stream").unwrap() - )); - assert!(!content_type_needs_encoding( - new_content_type("multipart/encrypted").unwrap() - )); - assert!(content_type_needs_encoding( - new_content_type("application/pgp-encrypted").unwrap() - )); - } + // #[test] + // fn test_needs_encoding() { + // assert!(content_type_needs_encoding( + // new_content_type("text/plain").unwrap() + // )); + // assert!(content_type_needs_encoding( + // new_content_type("application/octect-stream").unwrap() + // )); + // assert!(!content_type_needs_encoding( + // new_content_type("multipart/encrypted").unwrap() + // )); + // assert!(content_type_needs_encoding( + // new_content_type("application/pgp-encrypted").unwrap() + // )); + // } #[test] fn test_parse_message_id() { From 47197aa495fa8c32df80e8f8f5d571cfba7f8bbb Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 01:09:47 +0100 Subject: [PATCH 04/20] Implement message generation using lettre_email --- Cargo.lock | 1 + Cargo.toml | 1 + src/dc_receive_imf.rs | 1 - src/e2ee.rs | 322 +++++----- src/error.rs | 18 +- src/message.rs | 2 +- src/mimefactory.rs | 1313 +++++++++++++++++++++-------------------- src/mimeparser.rs | 4 +- src/wrapmime.rs | 10 - 9 files changed, 844 insertions(+), 828 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 383cf3e49..aeb2b4fb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -641,6 +641,7 @@ dependencies = [ "lettre_email 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "mailparse 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index c85dfccfd..7fa9f7d1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ rustls = "0.16.0" webpki-roots = "0.18.0" webpki = "0.21.0" mailparse = "0.10.1" +mime = "0.3.14" [dev-dependencies] tempfile = "3.0" diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 76e73ed8a..b014377e8 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -9,7 +9,6 @@ use crate::config::Config; use crate::constants::*; use crate::contact::*; use crate::context::Context; -use crate::dc_strencode::*; use crate::dc_tools::*; use crate::error::Result; use crate::events::Event; diff --git a/src/e2ee.rs b/src/e2ee.rs index 4f2898715..d510a623c 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -54,191 +54,184 @@ impl EncryptHelper { Aheader::new(addr, pk, self.prefer_encrypt) } + /// Determines if we can and should encrypt. + pub fn should_encrypt( + &self, + context: &Context, + e2ee_guaranteed: bool, + peerstates: &[(Option, &str)], + ) -> Result { + if !(self.prefer_encrypt == EncryptPreference::Mutual || e2ee_guaranteed) { + return Ok(false); + } + + for (peerstate, addr) in peerstates { + match peerstate { + Some(peerstate) => { + if peerstate.prefer_encrypt != EncryptPreference::Mutual && !e2ee_guaranteed { + info!(context, "peerstate for {:?} is no-encrypt", addr); + return Ok(false); + } + } + None => { + let msg = format!("peerstate for {:?} missing, cannot encrypt", addr); + if e2ee_guaranteed { + return Err(format_err!("{}", msg)); + } else { + info!(context, "{}", msg); + return Ok(false); + } + } + } + } + + Ok(true) + } + + /// Tries to encrypt the passed in `mail`. pub fn try_encrypt( &mut self, factory: &mut MimeFactory, e2ee_guaranteed: bool, min_verified: PeerstateVerifiedStatus, do_gossip: bool, - mut in_out_message: lettre_email::Email, + mut mail: lettre_email::Email, imffields_unprotected: Vec, - ) -> Result { - unimplemented!() - // // libEtPan's pgp_encrypt_mime() takes the parent as the new root. - // // We just expect the root as being given to this function. - // ensure!( - // !in_out_message.is_null() && { (*in_out_message).mm_parent.is_null() }, - // "corrupted inputs" - // ); + peerstates: &[(Option, &str)], + ) -> Result<(lettre_email::Email, bool)> { + let context = &factory.context; + let mut keyring = Keyring::default(); + let mut gossip_headers: Vec = Vec::with_capacity(factory.recipients_addr.len()); - // if !(self.prefer_encrypt == EncryptPreference::Mutual || e2ee_guaranteed) { - // return Ok(false); - // } + for (peerstate, addr) in peerstates + .iter() + .filter_map(|(state, addr)| state.as_ref().map(|s| (s, addr))) + { + if let Some(key) = peerstate.peek_key(min_verified) { + keyring.add_owned(key.clone()); + if do_gossip { + if let Some(header) = peerstate.render_gossip_header(min_verified) { + gossip_headers.push(header.to_string()); + } + } + } else { + bail!("proper enc-key for {} missing, cannot encrypt", addr); + } + } - // let context = &factory.context; - // let mut keyring = Keyring::default(); - // let mut gossip_headers: Vec = Vec::with_capacity(factory.recipients_addr.len()); + // libEtPan's pgp_encrypt_mime() takes the parent as the new root. + // We just expect the root as being given to this function. + let sign_key = { + keyring.add_ref(&self.public_key); + let key = Key::from_self_private(context, self.addr.clone(), &context.sql); + ensure!(key.is_some(), "no own private key found"); - // // determine if we can and should encrypt - // for recipient_addr in factory.recipients_addr.iter() { - // if recipient_addr == &self.addr { - // continue; - // } - // let peerstate = match Peerstate::from_addr(context, &context.sql, recipient_addr) { - // Some(peerstate) => peerstate, - // None => { - // let msg = format!("peerstate for {} missing, cannot encrypt", recipient_addr); - // if e2ee_guaranteed { - // return Err(format_err!("{}", msg)); - // } else { - // info!(context, "{}", msg); - // return Ok(false); - // } - // } - // }; + key + }; - // if peerstate.prefer_encrypt != EncryptPreference::Mutual && !e2ee_guaranteed { - // info!(context, "peerstate for {} is no-encrypt", recipient_addr); - // return Ok(false); - // } + // encrypt message + use lettre_email::{EmailBuilder, MimeMessage, PartBuilder}; - // if let Some(key) = peerstate.peek_key(min_verified) { - // keyring.add_owned(key.clone()); - // if do_gossip { - // if let Some(header) = peerstate.render_gossip_header(min_verified) { - // gossip_headers.push(header.to_string()); - // } - // } - // } else { - // bail!( - // "proper enc-key for {} missing, cannot encrypt", - // recipient_addr - // ); - // } - // } + // let mut part_to_encrypt: lettre::SendableEmail = mail.into().to_string()?.into_bytes(); - // let sign_key = { - // keyring.add_ref(&self.public_key); - // let key = Key::from_self_private(context, self.addr.clone(), &context.sql); - // ensure!(key.is_some(), "no own private key found"); + let mut mail_to_encrypt = EmailBuilder::new(); - // key - // }; + for header in &gossip_headers { + mail_to_encrypt = mail_to_encrypt.header(("Autocrypt-Gossip", header)); + } - // // encrypt message - // { - // mailprivacy_prepare_mime(in_out_message); - // let mut part_to_encrypt = (*in_out_message).mm_data.mm_message.mm_msg_mime; - // (*part_to_encrypt).mm_parent = ptr::null_mut(); - // let imffields_encrypted = mailimf_fields_new_empty(); + // memoryhole headers: move some headers into encrypted part - // // mailmime_new_message_data() calls mailmime_fields_new_with_version() - // // which would add the unwanted MIME-Version:-header - // let message_to_encrypt = mailmime_new_simple( - // MAILMIME_MESSAGE as libc::c_int, - // mailmime_fields_new_empty(), - // mailmime_get_content_message(), - // imffields_encrypted, - // part_to_encrypt, - // ); + // while !cur.is_null() { + // let field = (*cur).data as *mut mailimf_field; + // let mut move_to_encrypted = false; - // for header in &gossip_headers { - // wrapmime::new_custom_field(imffields_encrypted, "Autocrypt-Gossip", &header) - // } - - // // memoryhole headers: move some headers into encrypted part - // // XXX note we can't use clist's into_iter() because the loop body also removes items - // let mut cur = (*(*imffields_unprotected).fld_list).first; - // while !cur.is_null() { - // let field = (*cur).data as *mut mailimf_field; - // let mut move_to_encrypted = false; - - // if !field.is_null() { - // if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { - // move_to_encrypted = true; - // } else if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { - // let opt_field = (*field).fld_data.fld_optional_field; - // if !opt_field.is_null() && !(*opt_field).fld_name.is_null() { - // let fld_name = to_string_lossy((*opt_field).fld_name); - // if fld_name.starts_with("Secure-Join") - // || (fld_name.starts_with("Chat-") && fld_name != "Chat-Version") - // { - // move_to_encrypted = true; - // } + // if !field.is_null() { + // if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { + // move_to_encrypted = true; + // } else if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { + // let opt_field = (*field).fld_data.fld_optional_field; + // if !opt_field.is_null() && !(*opt_field).fld_name.is_null() { + // let fld_name = to_string_lossy((*opt_field).fld_name); + // if fld_name.starts_with("Secure-Join") + // || (fld_name.starts_with("Chat-") && fld_name != "Chat-Version") + // { + // move_to_encrypted = true; // } // } // } - - // if move_to_encrypted { - // mailimf_fields_add(imffields_encrypted, field); - // cur = clist_delete((*imffields_unprotected).fld_list, cur); - // } else { - // cur = (*cur).next; - // } // } - // let subject = mailimf_subject_new("...".strdup()); - // mailimf_fields_add(imffields_unprotected, mailimf_field_new_subject(subject)); - - // wrapmime::append_ct_param( - // (*part_to_encrypt).mm_content_type, - // "protected-headers", - // "v1", - // )?; - // let plain = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - // let mut col = 0; - // mailmime_write_mem(plain, &mut col, message_to_encrypt); - // mailmime_free(message_to_encrypt); - - // ensure!( - // !(*plain).str_0.is_null() && (*plain).len > 0, - // "could not write/allocate" - // ); - - // let ctext = pgp::pk_encrypt( - // std::slice::from_raw_parts((*plain).str_0 as *const u8, (*plain).len), - // &keyring, - // sign_key.as_ref(), - // ); - // mmap_string_free(plain); - - // let ctext_v = ctext?; - - // // create MIME-structure that will contain the encrypted text - // let mut encrypted_part = new_data_part( - // ptr::null_mut(), - // 0 as libc::size_t, - // "multipart/encrypted", - // MAILMIME_MECHANISM_BASE64, - // )?; - // let content = (*encrypted_part).mm_content_type; - // wrapmime::append_ct_param(content, "protocol", "application/pgp-encrypted")?; - - // let version_mime = new_data_part( - // VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void, - // strlen(VERSION_CONTENT.as_mut_ptr()), - // "application/pgp-encrypted", - // MAILMIME_MECHANISM_7BIT, - // )?; - // mailmime_smart_add_part(encrypted_part, version_mime); - - // // we assume that ctext_v is not dropped until the end - // // of this if-scope - // let ctext_part = new_data_part( - // ctext_v.as_ptr() as *mut libc::c_void, - // ctext_v.len(), - // "application/octet-stream", - // MAILMIME_MECHANISM_7BIT, - // )?; - - // mailmime_smart_add_part(encrypted_part, ctext_part); - // (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; - // (*encrypted_part).mm_parent = in_out_message; - // let gossiped = !&gossip_headers.is_empty(); - // factory.finalize_mime_message(in_out_message, true, gossiped)?; - - // Ok(true) + // if move_to_encrypted { + // mailimf_fields_add(imffields_encrypted, field); + // cur = clist_delete((*imffields_unprotected).fld_list, cur); + // } else { + // cur = (*cur).next; + // } // } + + // let subject = mailimf_subject_new("...".strdup()); + // mailimf_fields_add(imffields_unprotected, mailimf_field_new_subject(subject)); + + // wrapmime::append_ct_param( + // (*part_to_encrypt).mm_content_type, + // "protected-headers", + // "v1", + // )?; + // let plain = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); + // let mut col = 0; + // mailmime_write_mem(plain, &mut col, message_to_encrypt); + // mailmime_free(message_to_encrypt); + + // ensure!( + // !(*plain).str_0.is_null() && (*plain).len > 0, + // "could not write/allocate" + // ); + + // let ctext = pgp::pk_encrypt( + // std::slice::from_raw_parts((*plain).str_0 as *const u8, (*plain).len), + // &keyring, + // sign_key.as_ref(), + // ); + // mmap_string_free(plain); + + // let ctext_v = ctext?; + + // // create MIME-structure that will contain the encrypted text + // let mut encrypted_part = new_data_part( + // ptr::null_mut(), + // 0 as libc::size_t, + // "multipart/encrypted", + // MAILMIME_MECHANISM_BASE64, + // )?; + // let content = (*encrypted_part).mm_content_type; + // wrapmime::append_ct_param(content, "protocol", "application/pgp-encrypted")?; + + // let version_mime = new_data_part( + // VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void, + // strlen(VERSION_CONTENT.as_mut_ptr()), + // "application/pgp-encrypted", + // MAILMIME_MECHANISM_7BIT, + // )?; + // mailmime_smart_add_part(encrypted_part, version_mime); + + // // we assume that ctext_v is not dropped until the end + // // of this if-scope + // let ctext_part = new_data_part( + // ctext_v.as_ptr() as *mut libc::c_void, + // ctext_v.len(), + // "application/octet-stream", + // MAILMIME_MECHANISM_7BIT, + // )?; + + // mailmime_smart_add_part(encrypted_part, ctext_part); + // (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; + // (*encrypted_part).mm_parent = in_out_message; + + // let gossiped = !&gossip_headers.is_empty(); + // factory.finalize_mime_message(true, gossiped)?; + + Ok((mail_to_encrypt.build()?, true)) } } @@ -531,11 +524,6 @@ fn decrypt_part( public_keyring_for_validate: &Keyring, ret_valid_signatures: &mut HashSet, ) -> Result>> { - ensure!( - wrapmime::has_decryptable_data(mail), - "No decryptable data found" - ); - let data = mail.get_body_raw()?; if has_decrypted_pgp_armor(&data) { diff --git a/src/error.rs b/src/error.rs index d1e4d35aa..816ba186e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -29,7 +29,11 @@ pub enum Error { #[fail(display = "Watch folder not found {:?}", _0)] WatchFolderNotFound(String), #[fail(display = "Inalid Email: {:?}", _0)] - MailParseError(mailparse::MailParseError), + MailParseError(#[cause] mailparse::MailParseError), + #[fail(display = "Building invalid Email: {:?}", _0)] + LettreError(#[cause] lettre_email::error::Error), + #[fail(display = "FromStr error: {:?}", _0)] + FromStr(#[cause] mime::FromStrError), } pub type Result = std::result::Result; @@ -106,6 +110,18 @@ impl From for Error { } } +impl From for Error { + fn from(err: lettre_email::error::Error) -> Error { + Error::LettreError(err) + } +} + +impl From for Error { + fn from(err: mime::FromStrError) -> Error { + Error::FromStr(err) + } +} + #[macro_export] macro_rules! bail { ($e:expr) => { diff --git a/src/message.rs b/src/message.rs index 329b9c209..09918a55d 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1013,7 +1013,7 @@ pub fn star_msgs(context: &Context, msg_ids: &[MsgId], star: bool) -> bool { pub fn get_summarytext_by_raw( viewtype: Viewtype, text: Option>, - param: &mut Params, + param: &Params, approx_characters: usize, context: &Context, ) -> String { diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 83e6d7fe2..1b36ce2f7 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -1,6 +1,6 @@ -use std::ptr; - use chrono::TimeZone; +use lettre::Envelope; +use lettre_email::{Address, Header, MimeMessage, MimeMultipartType, PartBuilder}; use crate::chat::{self, Chat}; use crate::config::Config; @@ -16,8 +16,8 @@ use crate::message::MsgId; use crate::message::{self, Message}; use crate::mimeparser::SystemMessage; use crate::param::*; +use crate::peerstate::{Peerstate, PeerstateVerifiedStatus}; use crate::stock::StockMessage; -use crate::wrapmime; #[derive(Clone, Copy, Eq, PartialEq)] pub enum Loaded { @@ -43,6 +43,7 @@ pub struct MimeFactory<'a> { pub references: String, pub req_mdn: bool, pub out: Vec, + pub envelope: Option, pub out_encrypted: bool, pub out_gossiped: bool, pub out_last_added_location_id: u32, @@ -50,7 +51,7 @@ pub struct MimeFactory<'a> { } impl<'a> MimeFactory<'a> { - fn new(context: &'a Context, msg: Message) -> Self { + fn from_message(context: &'a Context, msg: Message) -> Self { MimeFactory { from_addr: context .get_config(Config::ConfiguredAddr) @@ -71,6 +72,7 @@ impl<'a> MimeFactory<'a> { references: String::default(), req_mdn: false, out: Vec::new(), + envelope: None, out_encrypted: false, out_gossiped: false, out_last_added_location_id: 0, @@ -78,36 +80,22 @@ impl<'a> MimeFactory<'a> { } } - pub fn finalize_mime_message( - &mut self, - message: &mut lettre_email::Email, - encrypted: bool, - gossiped: bool, - ) -> Result<(), Error> { - { - // assert!(self.out.is_null()); // guard against double-calls - // self.out = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - // let mut col: libc::c_int = 0; - // ensure_eq!( - // mailmime_write_mem(self.out, &mut col, message), - // 0, - // "mem-error" - // ); - } + pub fn finalize_mime_message(&mut self, encrypted: bool, gossiped: bool) -> Result<(), Error> { self.out_encrypted = encrypted; self.out_gossiped = encrypted && gossiped; Ok(()) } - pub fn load_mdn(context: &'a Context, msg_id: MsgId) -> Result { - if !context.get_config_bool(Config::MdnsEnabled) { - // MDNs not enabled - check this is late, in the job. the - // user may have changed its choice while offline ... - bail!("MDNs meanwhile disabled") - } + pub fn load_mdn(context: &'a Context, msg_id: MsgId) -> Result { + // MDNs not enabled - check this is late, in the job. the + // user may have changed its choice while offline ... + ensure!( + context.get_config_bool(Config::MdnsEnabled), + "MDNs meanwhile disabled" + ); let msg = Message::load_from_db(context, msg_id)?; - let mut factory = MimeFactory::new(context, msg); + let mut factory = MimeFactory::from_message(context, msg); let contact = Contact::load_from_db(factory.context, factory.msg.from_id)?; // Do not send MDNs trash etc.; chats.blocked is already checked by the caller @@ -132,527 +120,616 @@ impl<'a> MimeFactory<'a> { /******************************************************************************* * Render a basic email ******************************************************************************/ - // XXX restrict unsafe to parts, introduce wrapmime helpers where appropriate - pub fn render(&mut self) -> Result<(), Error> { - if self.loaded == Loaded::Nothing || !self.out.is_empty() { - bail!("Invalid use of mimefactory-object."); + + fn peerstates_for_recipients(&self) -> Result, &str)>, Error> { + let self_addr = self + .context + .get_config(Config::ConfiguredAddr) + .ok_or_else(|| format_err!("Not configured"))?; + + Ok(self + .recipients_addr + .iter() + .filter(|addr| *addr != &self_addr) + .map(|addr| { + ( + Peerstate::from_addr(self.context, &self.context.sql, addr), + addr.as_str(), + ) + }) + .collect()) + } + + fn is_e2ee_guranteed(&self) -> Result { + match self.loaded { + Loaded::Message => { + if self.chat.as_ref().unwrap().typ == Chattype::VerifiedGroup { + return Ok(true); + } + + let force_plaintext = self + .msg + .param + .get_int(Param::ForcePlaintext) + .unwrap_or_default(); + + if force_plaintext == 0 { + return Ok(self + .msg + .param + .get_int(Param::GuaranteeE2ee) + .unwrap_or_default() + != 0); + } + + Ok(false) + } + Loaded::MDN => Ok(false), + Loaded::Nothing => bail!("No message loaded"), } + } + + fn min_verified(&self) -> Result { + match self.loaded { + Loaded::Message => { + let chat = self.chat.as_ref().unwrap(); + if chat.typ == Chattype::VerifiedGroup { + Ok(PeerstateVerifiedStatus::BidirectVerified) + } else { + Ok(PeerstateVerifiedStatus::Unverified) + } + } + Loaded::MDN => Ok(PeerstateVerifiedStatus::Unverified), + Loaded::Nothing => bail!("No message loaded"), + } + } + + fn should_force_plaintext(&self) -> Result { + match self.loaded { + Loaded::Message => { + let chat = self.chat.as_ref().unwrap(); + if chat.typ == Chattype::VerifiedGroup { + Ok(0) + } else { + Ok(self + .msg + .param + .get_int(Param::ForcePlaintext) + .unwrap_or_default()) + } + } + Loaded::MDN => Ok(DC_FP_NO_AUTOCRYPT_HEADER), + Loaded::Nothing => bail!("No message loaded"), + } + } + + fn should_do_gossip(&self) -> Result { + match self.loaded { + Loaded::Message => { + let chat = self.chat.as_ref().unwrap(); + // beside key- and member-changes, force re-gossip every 48 hours + if chat.gossiped_timestamp == 0 + || (chat.gossiped_timestamp + (2 * 24 * 60 * 60)) < time() + { + return Ok(true); + } + + let cmd = self.msg.param.get_cmd(); + match cmd { + SystemMessage::MemberAddedToGroup => { + return Ok(true); + } + _ => {} + } + + Ok(false) + } + Loaded::MDN => Ok(false), + Loaded::Nothing => bail!("No message loaded"), + } + } + + fn grpimage(&self) -> Result, Error> { + match self.loaded { + Loaded::Message => { + let chat = self.chat.as_ref().unwrap(); + let cmd = self.msg.param.get_cmd(); + + match cmd { + SystemMessage::MemberAddedToGroup => { + return Ok(chat.param.get(Param::ProfileImage).map(Into::into)); + } + SystemMessage::GroupImageChanged => { + return Ok(self.msg.param.get(Param::Arg).map(Into::into)) + } + _ => {} + } + + Ok(None) + } + Loaded::MDN => Ok(None), + Loaded::Nothing => bail!("No message loaded"), + } + } + + fn subject_str(&self) -> Result { + match self.loaded { + Loaded::Message => { + match self.chat { + Some(ref chat) => { + let raw_subject = message::get_summarytext_by_raw( + self.msg.type_0, + self.msg.text.as_ref(), + &self.msg.param, + 32, + self.context, + ); + + let afwd_email = self.msg.param.exists(Param::Forwarded); + let fwd = if afwd_email { "Fwd: " } else { "" }; + + if self.msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage { + // do not add the "Chat:" prefix for setup messages + Ok(self + .context + .stock_str(StockMessage::AcSetupMsgSubject) + .into_owned()) + } else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup + { + Ok(format!("Chat: {}: {}{}", chat.name, fwd, raw_subject,)) + } else { + Ok(format!("Chat: {}{}", fwd, raw_subject)) + } + } + None => Ok(String::default()), + } + } + Loaded::MDN => { + let e = self.context.stock_str(StockMessage::ReadRcpt); + Ok(format!("Chat: {}", e).to_string()) + } + Loaded::Nothing => bail!("No message loaded"), + } + } + + pub fn render(&mut self) -> Result<(), Error> { + // TODO: take self + + ensure!( + self.loaded != Loaded::Nothing && self.out.is_empty(), + "Invalid use of mimefactory-object." + ); + let context = &self.context; - unimplemented!(); - // let from = wrapmime::new_mailbox_list(&self.from_displayname, &self.from_addr); + let peerstates = self.peerstates_for_recipients()?; + let e2ee_guranteed = self.is_e2ee_guranteed()?; - // let to = mailimf_address_list_new_empty(); - // let name_iter = self.recipients_names.iter(); - // let addr_iter = self.recipients_addr.iter(); - // for (name, addr) in name_iter.zip(addr_iter) { - // mailimf_address_list_add( - // to, - // mailimf_address_new( - // MAILIMF_ADDRESS_MAILBOX as libc::c_int, - // mailimf_mailbox_new( - // if !name.is_empty() { - // dc_encode_header_words(&name).strdup() - // } else { - // ptr::null_mut() - // }, - // addr.strdup(), - // ), - // ptr::null_mut(), - // ), - // ); - // } - // let references_list = if !self.references.is_empty() { - // dc_str_to_clist(&self.references, " ") - // } else { - // ptr::null_mut() - // }; - // let in_reply_to_list = if !self.in_reply_to.is_empty() { - // dc_str_to_clist(&self.in_reply_to, " ") - // } else { - // ptr::null_mut() - // }; + let mut encrypt_helper = EncryptHelper::new(&context)?; + let should_encrypt = + encrypt_helper.should_encrypt(self.context, e2ee_guranteed, &peerstates)?; - // let imf_fields = mailimf_fields_new_with_data_all( - // mailimf_get_date(self.timestamp as i64), - // from, - // ptr::null_mut(), - // ptr::null_mut(), - // to, - // ptr::null_mut(), - // ptr::null_mut(), - // self.rfc724_mid.strdup(), - // in_reply_to_list, - // references_list, - // ptr::null_mut(), - // ); + // Headers that are encrypted + // - Chat-*, except Chat-Version + // - Secure-Join* + // - Subject + let mut protected_headers: Vec
= Vec::new(); - // let os_name = &self.context.os_name; - // let os_part = os_name - // .as_ref() - // .map(|s| format!("/{}", s)) - // .unwrap_or_default(); - // let version = get_version_str(); - // let headerval = format!("Delta Chat Core {}{}", version, os_part); + // All other headers + let mut unprotected_headers: Vec
= Vec::new(); - // /* Add a X-Mailer header. + let from = Address::new_mailbox_with_name( + dc_encode_header_words(&self.from_displayname), + self.from_addr.clone(), + ); + + let mut to = Vec::with_capacity(self.recipients_names.len()); + let name_iter = self.recipients_names.iter(); + let addr_iter = self.recipients_addr.iter(); + for (name, addr) in name_iter.zip(addr_iter) { + if name.is_empty() { + to.push(Address::new_mailbox(addr.clone())); + } else { + to.push(Address::new_mailbox_with_name( + dc_encode_header_words(name), + addr.clone(), + )); + } + } + + if !self.references.is_empty() { + unprotected_headers.push(Header::new("References".into(), self.references.clone())); + } + + if !self.in_reply_to.is_empty() { + unprotected_headers.push(Header::new("In-Reply-To".into(), self.in_reply_to.clone())); + } + + let date = chrono::Utc + .from_local_datetime(&chrono::NaiveDateTime::from_timestamp(self.timestamp, 0)) + .unwrap() + .to_rfc2822(); + + let os_name = &self.context.os_name; + let os_part = os_name + .as_ref() + .map(|s| format!("/{}", s)) + .unwrap_or_default(); + let version = get_version_str(); + + // Add a X-Mailer header. // This is only informational for debugging and may be removed in the release. - // We do not rely on this header as it may be removed by MTAs. */ - // wrapmime::new_custom_field(imf_fields, "X-Mailer", &headerval); - // wrapmime::new_custom_field(imf_fields, "Chat-Version", "1.0"); - // if self.req_mdn { - // /* we use "Chat-Disposition-Notification-To" - // because replies to "Disposition-Notification-To" are weird in many cases - // eg. are just freetext and/or do not follow any standard. */ - // wrapmime::new_custom_field( - // imf_fields, - // "Chat-Disposition-Notification-To", - // &self.from_addr, - // ); - // } + // We do not rely on this header as it may be removed by MTAs. - // let cleanup = |message: *mut Mailmime| { - // if !message.is_null() { - // mailmime_free(message); - // } - // }; - // let message = mailmime_new_message_data(0 as *mut Mailmime); - // ensure!(!message.is_null(), "could not create mime message data"); + unprotected_headers.push(Header::new( + "X-Mailer".into(), + format!("Delta Chat Core {}{}", version, os_part), + )); + unprotected_headers.push(Header::new("Chat-Version".to_string(), "1.0".to_string())); - // mailmime_set_imf_fields(message, imf_fields); + if self.req_mdn { + // we use "Chat-Disposition-Notification-To" + // because replies to "Disposition-Notification-To" are weird in many cases + // eg. are just freetext and/or do not follow any standard. + protected_headers.push(Header::new( + "Chat-Disposition-Notification-To".into(), + self.from_addr.clone(), + )); + } - // // 1=add Autocrypt-header (needed eg. for handshaking), 2=no Autocrypte-header (used for MDN) - // let mut e2ee_guaranteed = false; - // let mut min_verified = crate::peerstate::PeerstateVerifiedStatus::Unverified; - // let mut do_gossip = false; - // let mut grpimage = None; - // let force_plaintext: libc::c_int; - // let subject_str = match self.loaded { - // Loaded::Message => { - // /* Render a normal message - // *********************************************************************/ - // let chat = self.chat.as_ref().unwrap(); - // let mut meta_part: *mut Mailmime = ptr::null_mut(); - // let mut placeholdertext = None; + // 1=add Autocrypt-header (needed eg. for handshaking), 2=no Autocrypte-header (used for MDN) - // if chat.typ == Chattype::VerifiedGroup { - // wrapmime::new_custom_field(imf_fields, "Chat-Verified", "1"); - // force_plaintext = 0; - // e2ee_guaranteed = true; - // min_verified = crate::peerstate::PeerstateVerifiedStatus::BidirectVerified; - // } else { - // force_plaintext = self - // .msg - // .param - // .get_int(Param::ForcePlaintext) - // .unwrap_or_default(); - // if force_plaintext == 0 { - // e2ee_guaranteed = self - // .msg - // .param - // .get_int(Param::GuaranteeE2ee) - // .unwrap_or_default() - // != 0; - // } - // } + let min_verified = self.min_verified()?; + let do_gossip = self.should_do_gossip()?; + let grpimage = self.grpimage()?; + let force_plaintext = self.should_force_plaintext()?; + let subject_str = self.subject_str()?; - // /* beside key- and member-changes, force re-gossip every 48 hours */ - // if chat.gossiped_timestamp == 0 - // || (chat.gossiped_timestamp + (2 * 24 * 60 * 60)) < time() - // { - // do_gossip = true - // } + let subject = dc_encode_header_words(subject_str); - // /* build header etc. */ - // let command = self.msg.param.get_cmd(); - // if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { - // wrapmime::new_custom_field(imf_fields, "Chat-Group-ID", &chat.grpid); + let mut message = match self.loaded { + Loaded::Message => { + self.render_message(&mut protected_headers, &mut unprotected_headers, &grpimage)? + } + Loaded::MDN => self.render_mdn(&mut protected_headers, &mut unprotected_headers)?, + Loaded::Nothing => bail!("No message loaded"), + }; - // let encoded = dc_encode_header_words(&chat.name); - // wrapmime::new_custom_field(imf_fields, "Chat-Group-Name", &encoded); + if force_plaintext != DC_FP_NO_AUTOCRYPT_HEADER { + // unless determined otherwise we add the Autocrypt header + let aheader = encrypt_helper.get_aheader().to_string(); + unprotected_headers.push(Header::new("Autocrypt".into(), aheader)); + } - // match command { - // SystemMessage::MemberRemovedFromGroup => { - // let email_to_remove = - // self.msg.param.get(Param::Arg).unwrap_or_default(); - // if !email_to_remove.is_empty() { - // wrapmime::new_custom_field( - // imf_fields, - // "Chat-Group-Member-Removed", - // &email_to_remove, - // ); - // } - // } - // SystemMessage::MemberAddedToGroup => { - // let msg = &self.msg; - // do_gossip = true; - // let email_to_add = msg.param.get(Param::Arg).unwrap_or_default(); - // if !email_to_add.is_empty() { - // wrapmime::new_custom_field( - // imf_fields, - // "Chat-Group-Member-Added", - // &email_to_add, - // ); - // grpimage = chat.param.get(Param::ProfileImage); - // } - // if 0 != msg.param.get_int(Param::Arg2).unwrap_or_default() & 0x1 { - // info!( - // context, - // "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", - // "vg-member-added", - // ); - // wrapmime::new_custom_field( - // imf_fields, - // "Secure-Join", - // "vg-member-added", - // ); - // } - // } - // SystemMessage::GroupNameChanged => { - // let msg = &self.msg; - // let value_to_add = msg.param.get(Param::Arg).unwrap_or_default(); + let mut outer_message = if should_encrypt && force_plaintext == 0 { + for header in protected_headers.into_iter() { + message = message.header(header); + } - // wrapmime::new_custom_field( - // imf_fields, - // "Chat-Group-Name-Changed", - // &value_to_add, - // ); - // } - // SystemMessage::GroupImageChanged => { - // let msg = &self.msg; - // grpimage = msg.param.get(Param::Arg); - // if grpimage.is_none() { - // wrapmime::new_custom_field(imf_fields, "Chat-Group-Image", "0"); - // } - // } - // _ => {} - // } - // } + let mut outer_message = PartBuilder::new(); + for header in unprotected_headers.into_iter() { + outer_message = outer_message.header(header); + } + // if let Some(encrypted) = encrypt_helper.try_encrypt( + // self, + // e2ee_guaranteed, + // min_verified, + // do_gossip, + // message, + // imffields_unprotected, + // )? { - // match command { - // SystemMessage::LocationStreamingEnabled => { - // wrapmime::new_custom_field( - // imf_fields, - // "Chat-Content", - // "location-streaming-enabled", - // ); - // } - // SystemMessage::AutocryptSetupMessage => { - // wrapmime::new_custom_field(imf_fields, "Autocrypt-Setup-Message", "v1"); - // placeholdertext = Some( - // self.context - // .stock_str(StockMessage::AcSetupMsgBody) - // .to_string(), - // ); - // } - // SystemMessage::SecurejoinMessage => { - // let msg = &self.msg; - // let step = msg.param.get(Param::Arg).unwrap_or_default(); - // if !step.is_empty() { - // info!( - // context, - // "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", - // step, - // ); - // wrapmime::new_custom_field(imf_fields, "Secure-Join", &step); - // let param2 = msg.param.get(Param::Arg2).unwrap_or_default(); - // if !param2.is_empty() { - // wrapmime::new_custom_field( - // imf_fields, - // if step == "vg-request-with-auth" - // || step == "vc-request-with-auth" - // { - // "Secure-Join-Auth" - // } else { - // "Secure-Join-Invitenumber" - // }, - // param2, - // ) - // } - // let fingerprint = msg.param.get(Param::Arg3).unwrap_or_default(); - // if !fingerprint.is_empty() { - // wrapmime::new_custom_field( - // imf_fields, - // "Secure-Join-Fingerprint", - // &fingerprint, - // ); - // } - // if let Some(id) = msg.param.get(Param::Arg4) { - // wrapmime::new_custom_field(imf_fields, "Secure-Join-Group", &id); - // }; - // } - // } - // _ => {} - // } + outer_message + } else { + // In the unencrypted case, we add all headers to the outer message. + for header in protected_headers.into_iter() { + message = message.header(header); + } + for header in unprotected_headers.into_iter() { + message = message.header(header); + } + self.finalize_mime_message(false, false)?; - // if let Some(grpimage) = grpimage { - // info!(self.context, "setting group image '{}'", grpimage); - // let mut meta = Message::default(); - // meta.type_0 = Viewtype::Image; - // meta.param.set(Param::File, grpimage); + message + }; - // let res = build_body_file(context, &meta, "group-image")?; - // meta_part = res.0; - // let filename_as_sent = res.1; - // if !meta_part.is_null() { - // wrapmime::new_custom_field( - // imf_fields, - // "Chat-Group-Image", - // &filename_as_sent, - // ) - // } - // } + outer_message = outer_message + .header(Header::new_with_value("To".into(), to).unwrap()) + .header(Header::new_with_value("From".into(), vec![from]).unwrap()) + .header(Header::new("Subject".into(), subject)); - // if self.msg.type_0 == Viewtype::Sticker { - // wrapmime::new_custom_field(imf_fields, "Chat-Content", "sticker"); - // } + // TODO + // self.envelope = Some(Envelope::new(Some(from), to).expect("setting from")); + self.out = outer_message.build().as_string().into_bytes(); - // if self.msg.type_0 == Viewtype::Voice - // || self.msg.type_0 == Viewtype::Audio - // || self.msg.type_0 == Viewtype::Video - // { - // if self.msg.type_0 == Viewtype::Voice { - // wrapmime::new_custom_field(imf_fields, "Chat-Voice-Message", "1"); - // } - // let duration_ms = self.msg.param.get_int(Param::Duration).unwrap_or_default(); - // if duration_ms > 0 { - // let dur = duration_ms.to_string(); - // wrapmime::new_custom_field(imf_fields, "Chat-Duration", &dur); - // } - // } - - // /* add text part - we even add empty text and force a MIME-multipart-message as: - // - some Apps have problems with Non-text in the main part (eg. "Mail" from stock Android) - // - we can add "forward hints" this way - // - it looks better */ - // let afwd_email = self.msg.param.exists(Param::Forwarded); - // let fwdhint = if afwd_email { - // Some( - // "---------- Forwarded message ----------\r\nFrom: Delta Chat\r\n\r\n" - // .to_string(), - // ) - // } else { - // None - // }; - - // let final_text = { - // if let Some(ref text) = placeholdertext { - // text - // } else if let Some(ref text) = self.msg.text { - // text - // } else { - // "" - // } - // }; - - // let footer = &self.selfstatus; - // let message_text = format!( - // "{}{}{}{}{}", - // fwdhint.unwrap_or_default(), - // &final_text, - // if !final_text.is_empty() && !footer.is_empty() { - // "\r\n\r\n" - // } else { - // "" - // }, - // if !footer.is_empty() { "-- \r\n" } else { "" }, - // footer - // ); - // let text_part = wrapmime::build_body_text(&message_text)?; - // mailmime_smart_add_part(message, text_part); - - // /* add attachment part */ - // if chat::msgtype_has_file(self.msg.type_0) { - // if !is_file_size_okay(context, &self.msg) { - // cleanup(message); - // bail!( - // "Message exceeds the recommended {} MB.", - // 24 * 1024 * 1024 / 4 * 3 / 1000 / 1000, - // ); - // } else { - // let (file_part, _) = build_body_file(context, &self.msg, "")?; - // mailmime_smart_add_part(message, file_part); - // } - // } - // if !meta_part.is_null() { - // mailmime_smart_add_part(message, meta_part); - // } - - // if self.msg.param.exists(Param::SetLatitude) { - // let param = &self.msg.param; - // let kml_file = location::get_message_kml( - // self.msg.timestamp_sort, - // param.get_float(Param::SetLatitude).unwrap_or_default(), - // param.get_float(Param::SetLongitude).unwrap_or_default(), - // ); - // wrapmime::add_filename_part( - // message, - // "message.kml", - // "application/vnd.google-earth.kml+xml", - // &kml_file, - // )?; - // } - - // if location::is_sending_locations_to_chat(context, self.msg.chat_id) { - // match location::get_kml(context, self.msg.chat_id) { - // Ok((kml_content, last_added_location_id)) => { - // wrapmime::add_filename_part( - // message, - // "location.kml", - // "application/vnd.google-earth.kml+xml", - // &kml_content, - // )?; - // if !self.msg.param.exists(Param::SetLatitude) { - // // otherwise, the independent location is already filed - // self.out_last_added_location_id = last_added_location_id; - // } - // } - // Err(err) => { - // warn!(context, "mimefactory: could not get location: {}", err); - // } - // } - // } - // get_subject(context, self.chat.as_ref(), &mut self.msg, afwd_email) - // } - // Loaded::MDN => { - // /* Render a MDN - // *********************************************************************/ - // /* RFC 6522, this also requires the `report-type` parameter which is equal - // to the MIME subtype of the second body part of the multipart/report */ - // let multipart = mailmime_multiple_new( - // b"multipart/report\x00" as *const u8 as *const libc::c_char, - // ); - // wrapmime::append_ct_param( - // (*multipart).mm_content_type, - // "report-type", - // "disposition-notification", - // )?; - - // mailmime_add_part(message, multipart); - - // /* first body part: always human-readable, always REQUIRED by RFC 6522 */ - // let p1 = if 0 - // != self - // .msg - // .param - // .get_int(Param::GuaranteeE2ee) - // .unwrap_or_default() - // { - // self.context - // .stock_str(StockMessage::EncryptedMsg) - // .into_owned() - // } else { - // self.msg.get_summarytext(context, 32) - // }; - // let p2 = self - // .context - // .stock_string_repl_str(StockMessage::ReadRcptMailBody, p1); - // let message_text = format!("{}\r\n", p2); - // let human_mime_part = wrapmime::build_body_text(&message_text)?; - // mailmime_add_part(multipart, human_mime_part); - - // /* second body part: machine-readable, always REQUIRED by RFC 6522 */ - // let version = get_version_str(); - // let message_text2 = format!( - // "Reporting-UA: Delta Chat {}\r\nOriginal-Recipient: rfc822;{}\r\nFinal-Recipient: rfc822;{}\r\nOriginal-Message-ID: <{}>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n", - // version, - // self.from_addr, - // self.from_addr, - // self.msg.rfc724_mid - // ); - - // let content_type_0 = - // wrapmime::new_content_type("message/disposition-notification")?; - // let mime_fields_0: *mut mailmime_fields = - // mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int); - // let mach_mime_part: *mut Mailmime = - // mailmime_new_empty(content_type_0, mime_fields_0); - // wrapmime::set_body_text(mach_mime_part, &message_text2)?; - // mailmime_add_part(multipart, mach_mime_part); - // force_plaintext = DC_FP_NO_AUTOCRYPT_HEADER; - // /* currently, we do not send MDNs encrypted: - // - in a multi-device-setup that is not set up properly, MDNs would disturb the communication as they - // are send automatically which may lead to spreading outdated Autocrypt headers. - // - they do not carry any information but the Message-ID - // - this save some KB - // - in older versions, we did not encrypt messages to ourself when they to to SMTP - however, if these messages - // are forwarded for any reasons (eg. gmail always forwards to IMAP), we have no chance to decrypt them; - // this issue is fixed with 0.9.4 */ - // let e = self.context.stock_str(StockMessage::ReadRcpt); - // format!("Chat: {}", e).to_string() - // } - // _ => { - // cleanup(message); - // bail!("No message loaded."); - // } - // }; - - // /* Create the mime message - // *************************************************************************/ - // mailimf_fields_add( - // imf_fields, - // mailimf_field_new( - // MAILIMF_FIELD_SUBJECT as libc::c_int, - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // mailimf_subject_new(dc_encode_header_words(subject_str).strdup()), - // ptr::null_mut(), - // ptr::null_mut(), - // ptr::null_mut(), - // ), - // ); - - // /*just a pointer into mailmime structure, must not be freed*/ - // let imffields_unprotected = wrapmime::mailmime_find_mailimf_fields(message); - // ensure!( - // !imffields_unprotected.is_null(), - // "could not find mime fields" - // ); - - // let mut encrypt_helper = EncryptHelper::new(&context)?; - // if force_plaintext != DC_FP_NO_AUTOCRYPT_HEADER { - // // unless determined otherwise we add Autocrypt header - // let aheader = encrypt_helper.get_aheader().to_string(); - // wrapmime::new_custom_field(imffields_unprotected, "Autocrypt", &aheader); - // } - // let finalized = if force_plaintext == 0 { - // encrypt_helper.try_encrypt( - // self, - // e2ee_guaranteed, - // min_verified, - // do_gossip, - // message, - // imffields_unprotected, - // )? - // } else { - // false - // }; - // if !finalized { - // self.finalize_mime_message(message, false, false)?; - // } - // cleanup(message); Ok(()) } - pub fn load_msg(context: &Context, msg_id: MsgId) -> Result { + fn render_message( + &mut self, + protected_headers: &mut Vec
, + unprotected_headers: &mut Vec
, + grpimage: &Option, + ) -> Result { + let context = self.context; + let chat = self.chat.as_ref().unwrap(); + let command = self.msg.param.get_cmd(); + let mut placeholdertext = None; + let mut meta_part = None; + + if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { + protected_headers.push(Header::new("Chat-Group-ID".into(), chat.grpid.clone())); + + let encoded = dc_encode_header_words(&chat.name); + protected_headers.push(Header::new("Chat-Group-Name".into(), encoded)); + + match command { + SystemMessage::MemberRemovedFromGroup => { + let email_to_remove = self.msg.param.get(Param::Arg).unwrap_or_default(); + if !email_to_remove.is_empty() { + protected_headers.push(Header::new( + "Chat-Group-Member-Removed".into(), + email_to_remove.into(), + )); + } + } + SystemMessage::MemberAddedToGroup => { + let email_to_add = self.msg.param.get(Param::Arg).unwrap_or_default(); + if !email_to_add.is_empty() { + protected_headers.push(Header::new( + "Chat-Group-Member-Added".into(), + email_to_add.into(), + )); + } + if 0 != self.msg.param.get_int(Param::Arg2).unwrap_or_default() & 0x1 { + info!( + context, + "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", + "vg-member-added", + ); + protected_headers.push(Header::new( + "Secure-Join".to_string(), + "vg-member-added".to_string(), + )); + } + } + SystemMessage::GroupNameChanged => { + let value_to_add = self.msg.param.get(Param::Arg).unwrap_or_default(); + + protected_headers.push(Header::new( + "Chat-Group-Name-Changed".into(), + value_to_add.into(), + )); + } + SystemMessage::GroupImageChanged => { + if grpimage.is_none() { + protected_headers + .push(Header::new("Chat-Group-Image".to_string(), "0".to_string())); + } + } + _ => {} + } + } + + match command { + SystemMessage::LocationStreamingEnabled => { + protected_headers.push(Header::new( + "Chat-Content".into(), + "location-streaming-enabled".into(), + )); + } + SystemMessage::AutocryptSetupMessage => { + unprotected_headers + .push(Header::new("Autocrypt-Setup-Message".into(), "v1".into())); + + placeholdertext = Some( + self.context + .stock_str(StockMessage::AcSetupMsgBody) + .to_string(), + ); + } + SystemMessage::SecurejoinMessage => { + let msg = &self.msg; + let step = msg.param.get(Param::Arg).unwrap_or_default(); + if !step.is_empty() { + info!( + context, + "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", step, + ); + protected_headers.push(Header::new("Secure-Join".into(), step.into())); + + let param2 = msg.param.get(Param::Arg2).unwrap_or_default(); + if !param2.is_empty() { + protected_headers.push(Header::new( + if step == "vg-request-with-auth" || step == "vc-request-with-auth" { + "Secure-Join-Auth".into() + } else { + "Secure-Join-Invitenumber".into() + }, + param2.into(), + )); + } + + let fingerprint = msg.param.get(Param::Arg3).unwrap_or_default(); + if !fingerprint.is_empty() { + protected_headers.push(Header::new( + "Secure-Join-Fingerprint".into(), + fingerprint.into(), + )); + } + if let Some(id) = msg.param.get(Param::Arg4) { + protected_headers.push(Header::new("Secure-Join-Group".into(), id.into())); + }; + } + } + _ => {} + } + + if let Some(grpimage) = grpimage { + info!(self.context, "setting group image '{}'", grpimage); + let mut meta = Message::default(); + meta.type_0 = Viewtype::Image; + meta.param.set(Param::File, grpimage); + + let (mail, filename_as_sent) = build_body_file(context, &meta, "group-image")?; + meta_part = Some(mail); + protected_headers.push(Header::new("Chat-Group-Image".into(), filename_as_sent)); + } + + if self.msg.type_0 == Viewtype::Sticker { + protected_headers.push(Header::new("Chat-Content".into(), "sticker".into())); + } + + if self.msg.type_0 == Viewtype::Voice + || self.msg.type_0 == Viewtype::Audio + || self.msg.type_0 == Viewtype::Video + { + if self.msg.type_0 == Viewtype::Voice { + protected_headers.push(Header::new("Chat-Voice-Message".into(), "1".into())); + } + let duration_ms = self.msg.param.get_int(Param::Duration).unwrap_or_default(); + if duration_ms > 0 { + let dur = duration_ms.to_string(); + protected_headers.push(Header::new("Chat-Duration".into(), dur)); + } + } + + // add text part - we even add empty text and force a MIME-multipart-message as: + // - some Apps have problems with Non-text in the main part (eg. "Mail" from stock Android) + // - we can add "forward hints" this way + // - it looks better + + let afwd_email = self.msg.param.exists(Param::Forwarded); + let fwdhint = if afwd_email { + Some( + "---------- Forwarded message ----------\r\n\ + From: Delta Chat\r\n\ + \r\n" + .to_string(), + ) + } else { + None + }; + let final_text = { + if let Some(ref text) = placeholdertext { + text + } else if let Some(ref text) = self.msg.text { + text + } else { + "" + } + }; + + let footer = &self.selfstatus; + let message_text = format!( + "{}{}{}{}{}", + fwdhint.unwrap_or_default(), + &final_text, + if !final_text.is_empty() && !footer.is_empty() { + "\r\n\r\n" + } else { + "" + }, + if !footer.is_empty() { "-- \r\n" } else { "" }, + footer + ); + + // Message is sent as text/plain, with charset = utf-8 + let mut message = lettre_email::PartBuilder::new() + .content_type(&mime::TEXT_PLAIN_UTF_8) + .body(message_text); + let mut is_multipart = false; + + // add attachment part + if chat::msgtype_has_file(self.msg.type_0) { + if !is_file_size_okay(context, &self.msg) { + bail!( + "Message exceeds the recommended {} MB.", + 24 * 1024 * 1024 / 4 * 3 / 1000 / 1000, + ); + } else { + let (file_part, _) = build_body_file(context, &self.msg, "")?; + message = message.child(file_part); + is_multipart = true; + } + } + + if let Some(meta_part) = meta_part { + message = message.child(meta_part); + is_multipart = true; + } + + if self.msg.param.exists(Param::SetLatitude) { + let param = &self.msg.param; + let kml_file = location::get_message_kml( + self.msg.timestamp_sort, + param.get_float(Param::SetLatitude).unwrap_or_default(), + param.get_float(Param::SetLongitude).unwrap_or_default(), + ); + message = message.child( + lettre_email::PartBuilder::new() + .content_type( + &"application/vnd.google-earth.kml+xml" + .parse::() + .unwrap(), + ) + .header(( + "Content-Disposition", + "attachment; filename=\"message.kml\"", + )) + .body(kml_file) + .build(), + ); + is_multipart = true; + } + + if location::is_sending_locations_to_chat(context, self.msg.chat_id) { + match location::get_kml(context, self.msg.chat_id) { + Ok((kml_content, last_added_location_id)) => { + message = message.child( + lettre_email::PartBuilder::new() + .content_type( + &"application/vnd.google-earth.kml+xml" + .parse::() + .unwrap(), + ) + .header(( + "Content-Disposition", + "attachment; filename=\"message.kml\"", + )) + .body(kml_content) + .build(), + ); + is_multipart = true; + if !self.msg.param.exists(Param::SetLatitude) { + // otherwise, the independent location is already filed + self.out_last_added_location_id = last_added_location_id; + } + } + Err(err) => { + warn!(context, "mimefactory: could not get location: {}", err); + } + } + } + + if is_multipart { + message = message.message_type(MimeMultipartType::Mixed); + } + + Ok(message) + } + + fn render_mdn( + &mut self, + protected_headers: &mut Vec
, + unprotected_headers: &mut Vec
, + ) -> Result { + unimplemented!() + } + + pub fn load_msg(context: &Context, msg_id: MsgId) -> Result, Error> { let msg = Message::load_from_db(context, msg_id)?; let chat = Chat::load_from_db(context, msg.chat_id)?; - let mut factory = MimeFactory::new(context, msg); + let mut factory = MimeFactory::from_message(context, msg); factory.chat = Some(chat); // just set the chat above @@ -744,136 +821,80 @@ impl<'a> MimeFactory<'a> { } } -fn get_subject( +fn build_body_file( context: &Context, - chat: Option<&Chat>, - msg: &mut Message, - afwd_email: bool, -) -> String { - if chat.is_none() { - return String::default(); - } + msg: &Message, + base_name: &str, +) -> Result<(MimeMessage, String), Error> { + let blob = msg + .param + .get_blob(Param::File, context, true)? + .ok_or_else(|| format_err!("msg has no filename"))?; + let suffix = blob.suffix().unwrap_or("dat"); - let chat = chat.unwrap(); - let raw_subject = - message::get_summarytext_by_raw(msg.type_0, msg.text.as_ref(), &mut msg.param, 32, context); - let fwd = if afwd_email { "Fwd: " } else { "" }; + // Get file name to use for sending. For privacy purposes, we do + // not transfer the original filenames eg. for images; these names + // are normally not needed and contain timestamps, running numbers + // etc. + let filename_to_send: String = match msg.type_0 { + Viewtype::Voice => chrono::Utc + .timestamp(msg.timestamp_sort as i64, 0) + .format(&format!("voice-message_%Y-%m-%d_%H-%M-%S.{}", &suffix)) + .to_string(), + Viewtype::Image | Viewtype::Gif => format!( + "{}.{}", + if base_name.is_empty() { + "image" + } else { + base_name + }, + &suffix, + ), + Viewtype::Video => format!("video.{}", &suffix), + _ => blob.as_file_name().to_string(), + }; - if msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage { - /* do not add the "Chat:" prefix for setup messages */ - context - .stock_str(StockMessage::AcSetupMsgSubject) - .into_owned() - } else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { - format!("Chat: {}: {}{}", chat.name, fwd, raw_subject,) + /* check mimetype */ + let mimetype: mime::Mime = match msg.param.get(Param::MimeType) { + Some(mtype) => mtype.parse()?, + None => { + if let Some(res) = message::guess_msgtype_from_suffix(blob.as_rel_path()) { + res.1.parse()? + } else { + mime::APPLICATION_OCTET_STREAM + } + } + }; + + let needs_ext = dc_needs_ext_header(&filename_to_send); + + // create mime part, for Content-Disposition, see RFC 2183. + // `Content-Disposition: attachment` seems not to make a difference to `Content-Disposition: inline` + // at least on tested Thunderbird and Gma'l in 2017. + // But I've heard about problems with inline and outl'k, so we just use the attachment-type until we + // run into other problems ... + let cd_value = if needs_ext { + format!("attachment; filename=\"{}\"", &filename_to_send) } else { - format!("Chat: {}{}", fwd, raw_subject) - } + format!( + "attachment; filename*=\"{}\"", + dc_encode_header_words(&filename_to_send) + ) + }; + + let body = std::fs::read(blob.to_abs_path())?; + let encoded_body = base64::encode(&body); + + let mail = PartBuilder::new() + .content_type(&mimetype) + .header(("Content-Disposition", cd_value)) + .header(("Content-Transfer-Encoding", "base64")) + .body(encoded_body) + .build(); + + Ok((mail, filename_to_send)) } -// fn build_body_file( -// context: &Context, -// msg: &Message, -// base_name: &str, -// ) -> Result<(*mut Mailmime, String), Error> { -// let blob = msg -// .param -// .get_blob(Param::File, context, true)? -// .ok_or_else(|| format_err!("msg has no filename"))?; -// let suffix = blob.suffix().unwrap_or("dat"); - -// // Get file name to use for sending. For privacy purposes, we do -// // not transfer the original filenames eg. for images; these names -// // are normally not needed and contain timestamps, running numbers -// // etc. -// let filename_to_send: String = match msg.type_0 { -// Viewtype::Voice => chrono::Utc -// .timestamp(msg.timestamp_sort as i64, 0) -// .format(&format!("voice-message_%Y-%m-%d_%H-%M-%S.{}", &suffix)) -// .to_string(), -// Viewtype::Image | Viewtype::Gif => format!( -// "{}.{}", -// if base_name.is_empty() { -// "image" -// } else { -// base_name -// }, -// &suffix, -// ), -// Viewtype::Video => format!("video.{}", &suffix), -// _ => blob.as_file_name().to_string(), -// }; - -// /* check mimetype */ -// let mimetype = match msg.param.get(Param::MimeType) { -// Some(mtype) => mtype, -// None => { -// if let Some(res) = message::guess_msgtype_from_suffix(blob.as_rel_path()) { -// res.1 -// } else { -// "application/octet-stream" -// } -// } -// }; - -// let needs_ext = dc_needs_ext_header(&filename_to_send); - -// { -// /* create mime part, for Content-Disposition, see RFC 2183. -// `Content-Disposition: attachment` seems not to make a difference to `Content-Disposition: inline` at least on tested Thunderbird and Gma'l in 2017. -// But I've heard about problems with inline and outl'k, so we just use the attachment-type until we run into other problems ... */ -// let mime_fields = mailmime_fields_new_filename( -// MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int, -// if needs_ext { -// ptr::null_mut() -// } else { -// filename_to_send.strdup() -// }, -// MAILMIME_MECHANISM_BASE64 as libc::c_int, -// ); -// if needs_ext { -// for cur_data in (*(*mime_fields).fld_list).into_iter() { -// let field: *mut mailmime_field = cur_data as *mut _; -// if (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int -// && !(*field).fld_data.fld_disposition.is_null() -// { -// let file_disposition = (*field).fld_data.fld_disposition; -// if !file_disposition.is_null() { -// let parm = mailmime_disposition_parm_new( -// MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int, -// ptr::null_mut(), -// ptr::null_mut(), -// ptr::null_mut(), -// ptr::null_mut(), -// 0 as libc::size_t, -// mailmime_parameter_new( -// strdup(b"filename*\x00" as *const u8 as *const libc::c_char), -// dc_encode_ext_header(&filename_to_send).strdup(), -// ), -// ); -// if !parm.is_null() { -// clist_insert_after( -// (*file_disposition).dsp_parms, -// (*(*file_disposition).dsp_parms).last, -// parm as *mut libc::c_void, -// ); -// } -// } -// break; -// } -// } -// } -// let content = wrapmime::new_content_type(&mimetype)?; -// let filename_encoded = dc_encode_header_words(&filename_to_send); -// wrapmime::append_ct_param(content, "name", &filename_encoded)?; - -// let mime_sub = mailmime_new_empty(content, mime_fields); -// let abs_path = blob.to_abs_path().to_c_string()?; -// mailmime_set_body_file(mime_sub, dc_strdup(abs_path.as_ptr())); -// Ok((mime_sub, filename_to_send)) -// } -// } - pub(crate) fn vec_contains_lowercase(vec: &[String], part: &str) -> bool { let partlc = part.to_lowercase(); for cur in vec.iter() { diff --git a/src/mimeparser.rs b/src/mimeparser.rs index c55633a08..2b1d8359e 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -462,7 +462,7 @@ impl<'a> MimeParser<'a> { https://k9mail.github.io/2016/11/24/OpenPGP-Considerations-Part-I.html for background information why we use encrypted+signed) */ if let Some(first) = mail.subparts.iter().next() { - any_part_added = self.parse_mime_recursive(mail)?; + any_part_added = self.parse_mime_recursive(first)?; } } (DC_MIMETYPE_MP_REPORT, _) => { @@ -802,7 +802,7 @@ impl<'a> MimeParser<'a> { // 3. retrieve information // must be present - if let Some(disposition) = report_fields.get_first_value("Disposition").ok().flatten() { + if let Some(_disposition) = report_fields.get_first_value("Disposition").ok().flatten() { if let Some(original_message_id) = report_fields .get_first_value("Original-Message-ID") .ok() diff --git a/src/wrapmime.rs b/src/wrapmime.rs index 51d0c3928..ea37cdb12 100644 --- a/src/wrapmime.rs +++ b/src/wrapmime.rs @@ -48,16 +48,6 @@ pub fn get_autocrypt_mime<'a, 'b>(mail: &'a ParsedMail<'b>) -> Result<&'a Parsed Ok(&mail.subparts[1]) } -pub fn has_decryptable_data(mail: &ParsedMail<'_>) -> bool { - false - // /* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */ - // { - // (*mime_data).dt_type == MAILMIME_DATA_TEXT as libc::c_int - // && !(*mime_data).dt_data.dt_text.dt_data.is_null() - // && (*mime_data).dt_data.dt_text.dt_length > 0 - // } -} - // returned addresses are normalized. pub fn mailimf_get_recipients(headers: &HashMap) -> HashSet { let mut recipients: HashSet = Default::default(); From c69a2406ad6aec6faf08f22ecec9cfb2dd6e39c6 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 03:04:48 +0100 Subject: [PATCH 05/20] integrate encryption when sending --- Cargo.lock | 6 +-- src/e2ee.rs | 114 ++++----------------------------------------- src/mimefactory.rs | 66 +++++++++++++++++++------- 3 files changed, 62 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aeb2b4fb4..0526d1706 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,7 +99,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures_codec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures_codec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "imap-proto 0.9.1 (git+https://github.com/djc/tokio-imap)", "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1116,7 +1116,7 @@ dependencies = [ [[package]] name = "futures_codec" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3483,7 +3483,7 @@ dependencies = [ "checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" "checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" "checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" -"checksum futures_codec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b4043054a6220de5dc5c814eb82ab6fd7cd2b6574a844406f651ec688cfa6fcc" +"checksum futures_codec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "793d2283ff61ffff52d51cc631be0c8e75370d96056a38e09f124a67263913da" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" diff --git a/src/e2ee.rs b/src/e2ee.rs index d510a623c..f48dc8452 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -10,7 +10,6 @@ use crate::context::Context; use crate::error::*; use crate::key::*; use crate::keyring::*; -use crate::mimefactory::MimeFactory; use crate::peerstate::*; use crate::pgp; use crate::securejoin::handle_degrade_event; @@ -89,19 +88,17 @@ impl EncryptHelper { } /// Tries to encrypt the passed in `mail`. - pub fn try_encrypt( + pub fn encrypt( &mut self, - factory: &mut MimeFactory, + context: &Context, e2ee_guaranteed: bool, min_verified: PeerstateVerifiedStatus, do_gossip: bool, - mut mail: lettre_email::Email, - imffields_unprotected: Vec, + mut mail_to_encrypt: lettre_email::PartBuilder, peerstates: &[(Option, &str)], - ) -> Result<(lettre_email::Email, bool)> { - let context = &factory.context; + ) -> Result { let mut keyring = Keyring::default(); - let mut gossip_headers: Vec = Vec::with_capacity(factory.recipients_addr.len()); + let mut gossip_headers: Vec = Vec::with_capacity(peerstates.len()); for (peerstate, addr) in peerstates .iter() @@ -129,109 +126,16 @@ impl EncryptHelper { key }; - // encrypt message - use lettre_email::{EmailBuilder, MimeMessage, PartBuilder}; - - // let mut part_to_encrypt: lettre::SendableEmail = mail.into().to_string()?.into_bytes(); - - let mut mail_to_encrypt = EmailBuilder::new(); - + // Add gossip headers for header in &gossip_headers { mail_to_encrypt = mail_to_encrypt.header(("Autocrypt-Gossip", header)); } - // memoryhole headers: move some headers into encrypted part + let raw_message = mail_to_encrypt.build().as_string().into_bytes(); - // while !cur.is_null() { - // let field = (*cur).data as *mut mailimf_field; - // let mut move_to_encrypted = false; + let ctext = pgp::pk_encrypt(&raw_message, &keyring, sign_key.as_ref())?; - // if !field.is_null() { - // if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { - // move_to_encrypted = true; - // } else if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { - // let opt_field = (*field).fld_data.fld_optional_field; - // if !opt_field.is_null() && !(*opt_field).fld_name.is_null() { - // let fld_name = to_string_lossy((*opt_field).fld_name); - // if fld_name.starts_with("Secure-Join") - // || (fld_name.starts_with("Chat-") && fld_name != "Chat-Version") - // { - // move_to_encrypted = true; - // } - // } - // } - // } - - // if move_to_encrypted { - // mailimf_fields_add(imffields_encrypted, field); - // cur = clist_delete((*imffields_unprotected).fld_list, cur); - // } else { - // cur = (*cur).next; - // } - // } - - // let subject = mailimf_subject_new("...".strdup()); - // mailimf_fields_add(imffields_unprotected, mailimf_field_new_subject(subject)); - - // wrapmime::append_ct_param( - // (*part_to_encrypt).mm_content_type, - // "protected-headers", - // "v1", - // )?; - // let plain = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - // let mut col = 0; - // mailmime_write_mem(plain, &mut col, message_to_encrypt); - // mailmime_free(message_to_encrypt); - - // ensure!( - // !(*plain).str_0.is_null() && (*plain).len > 0, - // "could not write/allocate" - // ); - - // let ctext = pgp::pk_encrypt( - // std::slice::from_raw_parts((*plain).str_0 as *const u8, (*plain).len), - // &keyring, - // sign_key.as_ref(), - // ); - // mmap_string_free(plain); - - // let ctext_v = ctext?; - - // // create MIME-structure that will contain the encrypted text - // let mut encrypted_part = new_data_part( - // ptr::null_mut(), - // 0 as libc::size_t, - // "multipart/encrypted", - // MAILMIME_MECHANISM_BASE64, - // )?; - // let content = (*encrypted_part).mm_content_type; - // wrapmime::append_ct_param(content, "protocol", "application/pgp-encrypted")?; - - // let version_mime = new_data_part( - // VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void, - // strlen(VERSION_CONTENT.as_mut_ptr()), - // "application/pgp-encrypted", - // MAILMIME_MECHANISM_7BIT, - // )?; - // mailmime_smart_add_part(encrypted_part, version_mime); - - // // we assume that ctext_v is not dropped until the end - // // of this if-scope - // let ctext_part = new_data_part( - // ctext_v.as_ptr() as *mut libc::c_void, - // ctext_v.len(), - // "application/octet-stream", - // MAILMIME_MECHANISM_7BIT, - // )?; - - // mailmime_smart_add_part(encrypted_part, ctext_part); - // (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; - // (*encrypted_part).mm_parent = in_out_message; - - // let gossiped = !&gossip_headers.is_empty(); - // factory.finalize_mime_message(true, gossiped)?; - - Ok((mail_to_encrypt.build()?, true)) + Ok(ctext) } } diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 1b36ce2f7..6462a3bcb 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -300,13 +300,9 @@ impl<'a> MimeFactory<'a> { "Invalid use of mimefactory-object." ); - let context = &self.context; - let peerstates = self.peerstates_for_recipients()?; let e2ee_guranteed = self.is_e2ee_guranteed()?; - let mut encrypt_helper = EncryptHelper::new(&context)?; - let should_encrypt = - encrypt_helper.should_encrypt(self.context, e2ee_guranteed, &peerstates)?; + let mut encrypt_helper = EncryptHelper::new(self.context)?; // Headers that are encrypted // - Chat-*, except Chat-Version @@ -400,23 +396,62 @@ impl<'a> MimeFactory<'a> { unprotected_headers.push(Header::new("Autocrypt".into(), aheader)); } + protected_headers.push(Header::new("Subject".into(), subject)); + + let peerstates = self.peerstates_for_recipients()?; + let should_encrypt = + encrypt_helper.should_encrypt(self.context, e2ee_guranteed, &peerstates)?; + let mut outer_message = if should_encrypt && force_plaintext == 0 { for header in protected_headers.into_iter() { message = message.header(header); } - let mut outer_message = PartBuilder::new(); + // Manual Content-Type only works with https://github.com/niax/rust-email/pull/51 + // At the moment the boundary will not be inserted. + let mut outer_message = PartBuilder::new().header(( + "Content-Type".to_string(), + "multipart/encrypted; protocol=\"application/pgp-encrypted\"".to_string(), + )); + for header in unprotected_headers.into_iter() { outer_message = outer_message.header(header); } - // if let Some(encrypted) = encrypt_helper.try_encrypt( - // self, - // e2ee_guaranteed, - // min_verified, - // do_gossip, - // message, - // imffields_unprotected, - // )? { + + let encrypted = encrypt_helper.encrypt( + self.context, + e2ee_guranteed, + min_verified, + do_gossip, + message, + &peerstates, + )?; + + outer_message = outer_message + .child( + // Autocrypt part 1 + PartBuilder::new() + .content_type(&"application/pgp-encrypted".parse::().unwrap()) + .header(("Content-Description", "PGP/MIME version identification")) + .body("Version: 1") + .build(), + ) + .child( + // Autocrypt part 2 + PartBuilder::new() + .content_type( + &"application/octet-stream; name=\"encrypted.asc\"" + .parse::() + .unwrap(), + ) + .header(("Content-Description", "OpenPGP encrypted message")) + .header(("Content-Disposition", "inline; filename=\"encrypted.asc\"")) + .body(encrypted) + .build(), + ) + .header(("Subject".to_string(), "...".to_string())); + + self.finalize_mime_message(true, do_gossip && !peerstates.is_empty())?; outer_message } else { @@ -434,8 +469,7 @@ impl<'a> MimeFactory<'a> { outer_message = outer_message .header(Header::new_with_value("To".into(), to).unwrap()) - .header(Header::new_with_value("From".into(), vec![from]).unwrap()) - .header(Header::new("Subject".into(), subject)); + .header(Header::new_with_value("From".into(), vec![from]).unwrap()); // TODO // self.envelope = Some(Envelope::new(Some(from), to).expect("setting from")); From 9196ed1e9f355be4805743d7239307312c64555c Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 03:15:02 +0100 Subject: [PATCH 06/20] remove dead code --- Cargo.lock | 7 --- Cargo.toml | 1 - src/dc_strencode.rs | 135 ++++---------------------------------------- src/dc_tools.rs | 16 +----- src/e2ee.rs | 42 -------------- src/lib.rs | 2 - src/mimefactory.rs | 8 ++- src/mimeparser.rs | 2 +- 8 files changed, 19 insertions(+), 194 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0526d1706..bd4497790 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -635,7 +635,6 @@ dependencies = [ "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "image-meta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jetscii 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", "lettre_email 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", @@ -1367,11 +1366,6 @@ name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "jetscii" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "js-sys" version = "0.3.32" @@ -3509,7 +3503,6 @@ dependencies = [ "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum jetscii 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5f25cca2463cb19dbb1061eb3bd38a8b5e4ce1cc5a5a9fc0e02de486d92b9b05" "checksum js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "1c840fdb2167497b0bd0db43d6dfe61e91637fa72f9d061f8bd17ddc44ba6414" "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" diff --git a/Cargo.toml b/Cargo.toml index 7fa9f7d1b..5d364b7f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,6 @@ image-meta = "0.1.0" quick-xml = "0.15.0" escaper = "0.1.0" bitflags = "1.1.0" -jetscii = "0.4.4" debug_stub_derive = "0.3.0" sanitize-filename = "0.2.1" stop-token = { version = "0.1.1", features = ["unstable"] } diff --git a/src/dc_strencode.rs b/src/dc_strencode.rs index 7f6eb1413..dcf589a84 100644 --- a/src/dc_strencode.rs +++ b/src/dc_strencode.rs @@ -1,28 +1,21 @@ use itertools::Itertools; use std::borrow::Cow; -use std::ffi::CString; -use std::ptr; use charset::Charset; -use libc::free; use percent_encoding::{percent_decode, utf8_percent_encode, AsciiSet, CONTROLS}; -use crate::dc_tools::*; - -/** - * Encode non-ascii-strings as `=?UTF-8?Q?Bj=c3=b6rn_Petersen?=`. - * Belongs to RFC 2047: https://tools.ietf.org/html/rfc2047 - * - * We do not fold at position 72; this would result in empty words as `=?utf-8?Q??=` which are correct, - * but cannot be displayed by some mail programs (eg. Android Stock Mail). - * however, this is not needed, as long as _one_ word is not longer than 72 characters. - * _if_ it is, the display may get weird. This affects the subject only. - * the best solution wor all this would be if libetpan encodes the line as only libetpan knowns when a header line is full. - * - * @param to_encode Null-terminated UTF-8-string to encode. - * @return Returns the encoded string which must be free()'d when no longed needed. - * On errors, NULL is returned. - */ +/// Encode non-ascii-strings as `=?UTF-8?Q?Bj=c3=b6rn_Petersen?=`. +/// Belongs to RFC 2047: https://tools.ietf.org/html/rfc2047 +/// +/// We do not fold at position 72; this would result in empty words as `=?utf-8?Q??=` which are correct, +/// but cannot be displayed by some mail programs (eg. Android Stock Mail). +/// however, this is not needed, as long as _one_ word is not longer than 72 characters. +/// _if_ it is, the display may get weird. This affects the subject only. +/// the best solution wor all this would be if libetpan encodes the line as only libetpan knowns when a header line is full. +/// +/// @param to_encode Null-terminated UTF-8-string to encode. +/// @return Returns the encoded string which must be free()'d when no longed needed. +/// On errors, NULL is returned. pub fn dc_encode_header_words(input: impl AsRef) -> String { let mut result = String::default(); for (_, group) in &input.as_ref().chars().group_by(|c| c.is_whitespace()) { @@ -83,107 +76,3 @@ pub fn dc_needs_ext_header(to_check: impl AsRef) -> bool { || c == '%') }) } - -const EXT_ASCII_ST: &AsciiSet = &CONTROLS - .add(b' ') - .add(b'-') - .add(b'_') - .add(b'.') - .add(b'~') - .add(b'%'); - -/// Encode an UTF-8 string to the extended header format. -pub fn dc_encode_ext_header(to_encode: impl AsRef) -> String { - let encoded = utf8_percent_encode(to_encode.as_ref(), &EXT_ASCII_ST); - format!("utf-8''{}", encoded) -} - -/// Decode an extended-header-format strings to UTF-8. -pub fn dc_decode_ext_header(to_decode: &[u8]) -> Cow { - if let Some(index) = bytes!(b'\'').find(to_decode) { - let (charset, rest) = to_decode.split_at(index); - if !charset.is_empty() { - // skip language - if let Some(index2) = bytes!(b'\'').find(&rest[1..]) { - let decoded = percent_decode(&rest[index2 + 2..]); - - if charset != b"utf-8" && charset != b"UTF-8" { - if let Some(encoding) = Charset::for_label(charset) { - let bytes = decoded.collect::>(); - let (res, _, _) = encoding.decode(&bytes); - return Cow::Owned(res.into_owned()); - } else { - return decoded.decode_utf8_lossy(); - } - } else { - return decoded.decode_utf8_lossy(); - } - } - } - } - - String::from_utf8_lossy(to_decode) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_dc_encode_ext_header() { - let buf1 = dc_encode_ext_header("Björn Petersen"); - assert_eq!(&buf1, "utf-8\'\'Bj%C3%B6rn%20Petersen"); - let buf2 = dc_decode_ext_header(buf1.as_bytes()); - assert_eq!(&buf2, "Björn Petersen",); - - let buf1 = dc_decode_ext_header(b"iso-8859-1\'en\'%A3%20rates"); - assert_eq!(buf1, "£ rates",); - - let buf1 = dc_decode_ext_header(b"wrong\'format"); - assert_eq!(buf1, "wrong\'format",); - - let buf1 = dc_decode_ext_header(b"\'\'"); - assert_eq!(buf1, "\'\'"); - - let buf1 = dc_decode_ext_header(b"x\'\'"); - assert_eq!(buf1, ""); - - let buf1 = dc_decode_ext_header(b"\'"); - assert_eq!(buf1, "\'"); - - let buf1 = dc_decode_ext_header(b""); - assert_eq!(buf1, ""); - - // regressions - assert_eq!( - dc_decode_ext_header(dc_encode_ext_header("%0A").as_bytes()), - "%0A" - ); - } - - #[test] - fn test_dc_needs_ext_header() { - assert_eq!(dc_needs_ext_header("Björn"), true); - assert_eq!(dc_needs_ext_header("Bjoern"), false); - assert_eq!(dc_needs_ext_header(""), false); - assert_eq!(dc_needs_ext_header(" "), true); - assert_eq!(dc_needs_ext_header("a b"), true); - } - - use proptest::prelude::*; - - proptest! { - #[test] - fn test_ext_header_roundtrip(buf: String) { - let encoded = dc_encode_ext_header(&buf); - let decoded = dc_decode_ext_header(encoded.as_bytes()); - assert_eq!(buf, decoded); - } - - #[test] - fn test_ext_header_decode_anything(buf: Vec) { - // make sure this never panics - let _decoded = dc_decode_ext_header(&buf); - } - } -} diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 87db1b882..b0409319e 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -7,7 +7,7 @@ use std::ffi::{CStr, CString}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::time::SystemTime; -use std::{fmt, fs, ptr}; +use std::{fmt, fs}; use chrono::{Local, TimeZone}; use libc::{memcpy, strlen}; @@ -857,20 +857,6 @@ pub(crate) unsafe fn strdup(s: *const libc::c_char) -> *mut libc::c_char { result as *mut _ } -pub(crate) unsafe fn strcasecmp(s1: *const libc::c_char, s2: *const libc::c_char) -> libc::c_int { - let s1 = std::ffi::CStr::from_ptr(s1) - .to_string_lossy() - .to_lowercase(); - let s2 = std::ffi::CStr::from_ptr(s2) - .to_string_lossy() - .to_lowercase(); - if s1 == s2 { - 0 - } else { - 1 - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/e2ee.rs b/src/e2ee.rs index f48dc8452..4f6b6ce06 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -15,10 +15,6 @@ use crate::pgp; use crate::securejoin::handle_degrade_event; use crate::wrapmime; -// standard mime-version header aka b"Version: 1\r\n\x00" -static mut VERSION_CONTENT: [libc::c_char; 13] = - [86, 101, 114, 115, 105, 111, 110, 58, 32, 49, 13, 10, 0]; - #[derive(Debug)] pub struct EncryptHelper { pub prefer_encrypt: EncryptPreference, @@ -91,7 +87,6 @@ impl EncryptHelper { pub fn encrypt( &mut self, context: &Context, - e2ee_guaranteed: bool, min_verified: PeerstateVerifiedStatus, do_gossip: bool, mut mail_to_encrypt: lettre_email::PartBuilder, @@ -215,43 +210,6 @@ pub fn try_decrypt( Ok((out_mail, signatures, gossipped_addr)) } -// fn new_data_part( -// data: *mut libc::c_void, -// data_bytes: libc::size_t, -// content_type: &str, -// default_encoding: u32, -// ) -> Result<*mut Mailmime> { -// let content = new_content_type(&content_type)?; -// let mut encoding = ptr::null_mut(); -// if wrapmime::content_type_needs_encoding(content) { -// encoding = { mailmime_mechanism_new(default_encoding as i32, ptr::null_mut()) }; -// ensure!(!encoding.is_null(), "failed to create encoding"); -// } -// let mime_fields = { -// { -// mailmime_fields_new_with_data( -// encoding, -// ptr::null_mut(), -// ptr::null_mut(), -// ptr::null_mut(), -// ptr::null_mut(), -// ) -// } -// }; -// ensure!(!mime_fields.is_null(), "internal mime error"); -// -// let mime = { mailmime_new_empty(content, mime_fields) }; -// ensure!(!mime.is_null(), "internal mime error"); -// -// if { (*mime).mm_type } == MAILMIME_SINGLE as libc::c_int { -// if !data.is_null() && data_bytes > 0 { -// { mailmime_set_body_text(mime, data as *mut libc::c_char, data_bytes) }; -// } -// } -// -// Ok(mime) -// } - /// Load public key from database or generate a new one. /// /// This will load a public key from the database, generating and diff --git a/src/lib.rs b/src/lib.rs index 9f75b5303..698edee37 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,8 +17,6 @@ extern crate strum; #[macro_use] extern crate strum_macros; #[macro_use] -extern crate jetscii; -#[macro_use] extern crate debug_stub_derive; #[macro_use] diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 6462a3bcb..fb88292ee 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -345,6 +345,8 @@ impl<'a> MimeFactory<'a> { .unwrap() .to_rfc2822(); + unprotected_headers.push(Header::new("Date".into(), date)); + let os_name = &self.context.os_name; let os_part = os_name .as_ref() @@ -420,7 +422,6 @@ impl<'a> MimeFactory<'a> { let encrypted = encrypt_helper.encrypt( self.context, - e2ee_guranteed, min_verified, do_gossip, message, @@ -433,7 +434,7 @@ impl<'a> MimeFactory<'a> { PartBuilder::new() .content_type(&"application/pgp-encrypted".parse::().unwrap()) .header(("Content-Description", "PGP/MIME version identification")) - .body("Version: 1") + .body("Version: 1\r\n") .build(), ) .child( @@ -451,7 +452,8 @@ impl<'a> MimeFactory<'a> { ) .header(("Subject".to_string(), "...".to_string())); - self.finalize_mime_message(true, do_gossip && !peerstates.is_empty())?; + let gossiped = do_gossip && !peerstates.is_empty(); + self.finalize_mime_message(true, gossiped)?; outer_message } else { diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 2b1d8359e..ca668810a 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -478,7 +478,7 @@ impl<'a> MimeParser<'a> { /* eg. `report-type=delivery-status`; maybe we should show them as a little error icon */ if let Some(first) = mail.subparts.iter().next() { - any_part_added = self.parse_mime_recursive(mail)?; + any_part_added = self.parse_mime_recursive(first)?; } } } From 5079e15401c54cdbffcbf537ce4f23858db48b9f Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 14:03:02 +0100 Subject: [PATCH 07/20] restructure mimefactory --- src/dc_strencode.rs | 4 - src/job.rs | 109 +++++++------- src/mimefactory.rs | 344 ++++++++++++++++++++++---------------------- 3 files changed, 225 insertions(+), 232 deletions(-) diff --git a/src/dc_strencode.rs b/src/dc_strencode.rs index dcf589a84..23fe37e68 100644 --- a/src/dc_strencode.rs +++ b/src/dc_strencode.rs @@ -1,8 +1,4 @@ use itertools::Itertools; -use std::borrow::Cow; - -use charset::Charset; -use percent_encoding::{percent_decode, utf8_percent_encode, AsciiSet, CONTROLS}; /// Encode non-ascii-strings as `=?UTF-8?Q?Bj=c3=b6rn_Petersen?=`. /// Belongs to RFC 2047: https://tools.ietf.org/html/rfc2047 diff --git a/src/job.rs b/src/job.rs index 87bea8054..63b8e1063 100644 --- a/src/job.rs +++ b/src/job.rs @@ -18,7 +18,7 @@ use crate::location; use crate::login_param::LoginParam; use crate::message::MsgId; use crate::message::{self, Message, MessageState}; -use crate::mimefactory::{vec_contains_lowercase, Loaded, MimeFactory}; +use crate::mimefactory::{vec_contains_lowercase, MimeFactory, RenderedEmail}; use crate::param::*; use crate::sql; @@ -604,22 +604,21 @@ fn set_delivered(context: &Context, msg_id: MsgId) { /* special case for DC_JOB_SEND_MSG_TO_SMTP */ #[allow(non_snake_case)] pub fn job_send_msg(context: &Context, msg_id: MsgId) -> Result<(), Error> { - let mut mimefactory = MimeFactory::load_msg(context, msg_id)?; - mimefactory.msg.try_calc_and_set_dimensions(context).ok(); + let mut msg = Message::load_from_db(context, msg_id)?; + msg.try_calc_and_set_dimensions(context).ok(); + + let mut mimefactory = MimeFactory::from_msg(context, &msg)?; /* create message */ - if let Err(msg) = mimefactory.render() { - let e = msg.to_string(); - message::set_msg_failed(context, msg_id, Some(e)); - return Err(msg); - } - if 0 != mimefactory - .msg - .param - .get_int(Param::GuaranteeE2ee) - .unwrap_or_default() - && !mimefactory.out_encrypted - { + let needs_encryption = msg.param.get_int(Param::GuaranteeE2ee).unwrap_or_default(); + + let mimefactory = MimeFactory::from_msg(context, &msg)?; + let mut rendered_msg = mimefactory.render().map_err(|err| { + message::set_msg_failed(context, msg_id, Some(err.to_string())); + err + })?; + + if 0 != needs_encryption && !rendered_msg.is_encrypted { /* unrecoverable */ message::set_msg_failed( context, @@ -629,19 +628,17 @@ pub fn job_send_msg(context: &Context, msg_id: MsgId) -> Result<(), Error> { bail!( "e2e encryption unavailable {} - {:?}", msg_id, - mimefactory.msg.param.get_int(Param::GuaranteeE2ee), + needs_encryption ); } + if context.get_config_bool(Config::BccSelf) - && !vec_contains_lowercase(&mimefactory.recipients_addr, &mimefactory.from_addr) + && !vec_contains_lowercase(&rendered_msg.recipients, &rendered_msg.from) { - mimefactory.recipients_names.push("".to_string()); - mimefactory - .recipients_addr - .push(mimefactory.from_addr.to_string()); + rendered_msg.recipients.push(rendered_msg.from.clone()); } - if mimefactory.recipients_addr.is_empty() { + if rendered_msg.recipients.is_empty() { // may happen eg. for groups with only SELF and bcc_self disabled info!( context, @@ -651,36 +648,27 @@ pub fn job_send_msg(context: &Context, msg_id: MsgId) -> Result<(), Error> { return Ok(()); } - if mimefactory.out_gossiped { - chat::set_gossiped_timestamp(context, mimefactory.msg.chat_id, time()); + if rendered_msg.is_gossiped { + chat::set_gossiped_timestamp(context, msg.chat_id, time()); } - if 0 != mimefactory.out_last_added_location_id { - if let Err(err) = location::set_kml_sent_timestamp(context, mimefactory.msg.chat_id, time()) - { + if 0 != rendered_msg.last_added_location_id { + if let Err(err) = location::set_kml_sent_timestamp(context, msg.chat_id, time()) { error!(context, "Failed to set kml sent_timestamp: {:?}", err); } - if !mimefactory.msg.hidden { - if let Err(err) = location::set_msg_location_id( - context, - mimefactory.msg.id, - mimefactory.out_last_added_location_id, - ) { + if !msg.hidden { + if let Err(err) = + location::set_msg_location_id(context, msg.id, rendered_msg.last_added_location_id) + { error!(context, "Failed to set msg_location_id: {:?}", err); } } } - if mimefactory.out_encrypted - && mimefactory - .msg - .param - .get_int(Param::GuaranteeE2ee) - .unwrap_or_default() - == 0 - { - mimefactory.msg.param.set_int(Param::GuaranteeE2ee, 1); - mimefactory.msg.save_param_to_disk(context); + if rendered_msg.is_encrypted && needs_encryption == 0 { + msg.param.set_int(Param::GuaranteeE2ee, 1); + msg.save_param_to_disk(context); } - add_smtp_job(context, Action::SendMsgToSmtp, &mut mimefactory)?; + + add_smtp_job(context, Action::SendMsgToSmtp, &rendered_msg)?; Ok(()) } @@ -866,33 +854,40 @@ fn suspend_smtp_thread(context: &Context, suspend: bool) { } fn send_mdn(context: &Context, msg_id: MsgId) -> Result<(), Error> { - let mut mimefactory = MimeFactory::load_mdn(context, msg_id)?; - mimefactory.render()?; - add_smtp_job(context, Action::SendMdn, &mut mimefactory)?; + let msg = Message::load_from_db(context, msg_id)?; + let mimefactory = MimeFactory::from_mdn(context, &msg)?; + let rendered_msg = mimefactory.render()?; + + add_smtp_job(context, Action::SendMdn, &rendered_msg)?; Ok(()) } #[allow(non_snake_case)] -fn add_smtp_job(context: &Context, action: Action, mimefactory: &MimeFactory) -> Result<(), Error> { +fn add_smtp_job( + context: &Context, + action: Action, + rendered_msg: &RenderedEmail, +) -> Result<(), Error> { ensure!( - !mimefactory.recipients_addr.is_empty(), + !rendered_msg.recipients.is_empty(), "no recipients for smtp job set" ); let mut param = Params::new(); - let bytes = &mimefactory.out; - let blob = BlobObject::create(context, &mimefactory.rfc724_mid, bytes)?; - let recipients = mimefactory.recipients_addr.join("\x1e"); + let bytes = &rendered_msg.message; + let blob = BlobObject::create(context, &rendered_msg.rfc724_mid, bytes)?; + + let recipients = rendered_msg.recipients.join("\x1e"); param.set(Param::File, blob.as_name()); param.set(Param::Recipients, &recipients); + job_add( context, action, - (if mimefactory.loaded == Loaded::Message { - mimefactory.msg.id.to_u32() as i32 - } else { - 0 - }) as libc::c_int, + rendered_msg + .foreign_id + .map(|v| v.to_u32() as i32) + .unwrap_or_default(), param, 0, ); diff --git a/src/mimefactory.rs b/src/mimefactory.rs index fb88292ee..77b2412de 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -1,5 +1,4 @@ use chrono::TimeZone; -use lettre::Envelope; use lettre_email::{Address, Header, MimeMessage, MimeMultipartType, PartBuilder}; use crate::chat::{self, Chat}; @@ -21,38 +20,53 @@ use crate::stock::StockMessage; #[derive(Clone, Copy, Eq, PartialEq)] pub enum Loaded { - Nothing, Message, - MDN, // TODO: invent more descriptive name + MDN, } +/// Helper to construct mime messages. #[derive(Clone)] -pub struct MimeFactory<'a> { +pub struct MimeFactory<'a, 'b> { pub from_addr: String, pub from_displayname: String, pub selfstatus: String, pub recipients_names: Vec, pub recipients_addr: Vec, pub timestamp: i64, - pub rfc724_mid: String, pub loaded: Loaded, - pub msg: Message, + pub msg: &'b Message, pub chat: Option, pub increation: bool, pub in_reply_to: String, pub references: String, pub req_mdn: bool, - pub out: Vec, - pub envelope: Option, - pub out_encrypted: bool, - pub out_gossiped: bool, - pub out_last_added_location_id: u32, pub context: &'a Context, + last_added_location_id: u32, } -impl<'a> MimeFactory<'a> { - fn from_message(context: &'a Context, msg: Message) -> Self { - MimeFactory { +/// Result of rendering a message, ready to be submitted to a send job. +#[derive(Debug, Clone)] +pub struct RenderedEmail { + pub message: Vec, + // pub envelope: Envelope, + pub is_encrypted: bool, + pub is_gossiped: bool, + pub last_added_location_id: u32, + /// None for MDN, the message id otherwise + pub foreign_id: Option, + + pub from: String, + pub recipients: Vec, + + /// Message ID (Message in the sense of Email) + pub rfc724_mid: String, +} + +impl<'a, 'b> MimeFactory<'a, 'b> { + pub fn from_msg(context: &'a Context, msg: &'b Message) -> Result, Error> { + let chat = Chat::load_from_db(context, msg.chat_id)?; + + let mut factory = MimeFactory { from_addr: context .get_config(Config::ConfiguredAddr) .unwrap_or_default(), @@ -62,31 +76,103 @@ impl<'a> MimeFactory<'a> { .unwrap_or_else(|| context.stock_str(StockMessage::StatusLine).to_string()), recipients_names: Vec::with_capacity(5), recipients_addr: Vec::with_capacity(5), - timestamp: 0, - rfc724_mid: String::default(), - loaded: Loaded::Nothing, + timestamp: msg.timestamp_sort, + loaded: Loaded::Message, msg, - chat: None, - increation: false, + chat: Some(chat), + increation: msg.is_increation(), in_reply_to: String::default(), references: String::default(), req_mdn: false, - out: Vec::new(), - envelope: None, - out_encrypted: false, - out_gossiped: false, - out_last_added_location_id: 0, + last_added_location_id: 0, context, + }; + + // just set the chat above + let chat = factory.chat.as_ref().unwrap(); + + if chat.is_self_talk() { + factory + .recipients_names + .push(factory.from_displayname.to_string()); + factory.recipients_addr.push(factory.from_addr.to_string()); + } else { + context.sql.query_map( + "SELECT c.authname, c.addr \ + FROM chats_contacts cc \ + LEFT JOIN contacts c ON cc.contact_id=c.id \ + WHERE cc.chat_id=? AND cc.contact_id>9;", + params![factory.msg.chat_id as i32], + |row| { + let authname: String = row.get(0)?; + let addr: String = row.get(1)?; + Ok((authname, addr)) + }, + |rows| { + for row in rows { + let (authname, addr) = row?; + if !vec_contains_lowercase(&factory.recipients_addr, &addr) { + factory.recipients_addr.push(addr); + factory.recipients_names.push(authname); + } + } + Ok(()) + }, + )?; + + let command = factory.msg.param.get_cmd(); + let msg = &factory.msg; + + /* for added members, the list is just fine */ + if command == SystemMessage::MemberRemovedFromGroup { + let email_to_remove = msg.param.get(Param::Arg).unwrap_or_default(); + + let self_addr = context + .get_config(Config::ConfiguredAddr) + .unwrap_or_default(); + + if !email_to_remove.is_empty() && !addr_cmp(email_to_remove, self_addr) { + if !vec_contains_lowercase(&factory.recipients_addr, &email_to_remove) { + factory.recipients_names.push("".to_string()); + factory.recipients_addr.push(email_to_remove.to_string()); + } + } + } + if command != SystemMessage::AutocryptSetupMessage + && command != SystemMessage::SecurejoinMessage + && context.get_config_bool(Config::MdnsEnabled) + { + factory.req_mdn = true; + } } + let row = context.sql.query_row( + "SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?", + params![msg.id], + |row| { + let in_reply_to: String = row.get(0)?; + let references: String = row.get(1)?; + + Ok((in_reply_to, references)) + }, + ); + + match row { + Ok((in_reply_to, references)) => { + factory.in_reply_to = in_reply_to; + factory.references = references; + } + Err(err) => { + error!( + context, + "mimefactory: failed to load mime_in_reply_to: {:?}", err + ); + } + } + + Ok(factory) } - pub fn finalize_mime_message(&mut self, encrypted: bool, gossiped: bool) -> Result<(), Error> { - self.out_encrypted = encrypted; - self.out_gossiped = encrypted && gossiped; - Ok(()) - } - - pub fn load_mdn(context: &'a Context, msg_id: MsgId) -> Result { + pub fn from_mdn(context: &'a Context, msg: &'b Message) -> Result { // MDNs not enabled - check this is late, in the job. the // user may have changed its choice while offline ... ensure!( @@ -94,33 +180,36 @@ impl<'a> MimeFactory<'a> { "MDNs meanwhile disabled" ); - let msg = Message::load_from_db(context, msg_id)?; - let mut factory = MimeFactory::from_message(context, msg); - let contact = Contact::load_from_db(factory.context, factory.msg.from_id)?; + let contact = Contact::load_from_db(context, msg.from_id)?; // Do not send MDNs trash etc.; chats.blocked is already checked by the caller // in dc_markseen_msgs() ensure!(!contact.is_blocked(), "Contact blocked"); - ensure!( - factory.msg.chat_id > DC_CHAT_ID_LAST_SPECIAL, - "Invalid chat id" - ); + ensure!(msg.chat_id > DC_CHAT_ID_LAST_SPECIAL, "Invalid chat id"); - factory - .recipients_names - .push(contact.get_authname().to_string()); - factory.recipients_addr.push(contact.get_addr().to_string()); - factory.timestamp = dc_create_smeared_timestamp(factory.context); - factory.rfc724_mid = dc_create_outgoing_rfc724_mid(None, &factory.from_addr); - factory.loaded = Loaded::MDN; - - Ok(factory) + Ok(MimeFactory { + context, + from_addr: context + .get_config(Config::ConfiguredAddr) + .unwrap_or_default(), + from_displayname: context.get_config(Config::Displayname).unwrap_or_default(), + selfstatus: context + .get_config(Config::Selfstatus) + .unwrap_or_else(|| context.stock_str(StockMessage::StatusLine).to_string()), + recipients_names: vec![contact.get_authname().to_string()], + recipients_addr: vec![contact.get_addr().to_string()], + timestamp: dc_create_smeared_timestamp(context), + loaded: Loaded::MDN, + msg, + chat: None, + increation: false, + in_reply_to: String::default(), + references: String::default(), + req_mdn: false, + last_added_location_id: 0, + }) } - /******************************************************************************* - * Render a basic email - ******************************************************************************/ - fn peerstates_for_recipients(&self) -> Result, &str)>, Error> { let self_addr = self .context @@ -165,7 +254,6 @@ impl<'a> MimeFactory<'a> { Ok(false) } Loaded::MDN => Ok(false), - Loaded::Nothing => bail!("No message loaded"), } } @@ -180,7 +268,6 @@ impl<'a> MimeFactory<'a> { } } Loaded::MDN => Ok(PeerstateVerifiedStatus::Unverified), - Loaded::Nothing => bail!("No message loaded"), } } @@ -199,7 +286,6 @@ impl<'a> MimeFactory<'a> { } } Loaded::MDN => Ok(DC_FP_NO_AUTOCRYPT_HEADER), - Loaded::Nothing => bail!("No message loaded"), } } @@ -225,7 +311,6 @@ impl<'a> MimeFactory<'a> { Ok(false) } Loaded::MDN => Ok(false), - Loaded::Nothing => bail!("No message loaded"), } } @@ -248,7 +333,6 @@ impl<'a> MimeFactory<'a> { Ok(None) } Loaded::MDN => Ok(None), - Loaded::Nothing => bail!("No message loaded"), } } @@ -288,18 +372,10 @@ impl<'a> MimeFactory<'a> { let e = self.context.stock_str(StockMessage::ReadRcpt); Ok(format!("Chat: {}", e).to_string()) } - Loaded::Nothing => bail!("No message loaded"), } } - pub fn render(&mut self) -> Result<(), Error> { - // TODO: take self - - ensure!( - self.loaded != Loaded::Nothing && self.out.is_empty(), - "Invalid use of mimefactory-object." - ); - + pub fn render(mut self) -> Result { let e2ee_guranteed = self.is_e2ee_guranteed()?; let mut encrypt_helper = EncryptHelper::new(self.context)?; @@ -389,7 +465,6 @@ impl<'a> MimeFactory<'a> { self.render_message(&mut protected_headers, &mut unprotected_headers, &grpimage)? } Loaded::MDN => self.render_mdn(&mut protected_headers, &mut unprotected_headers)?, - Loaded::Nothing => bail!("No message loaded"), }; if force_plaintext != DC_FP_NO_AUTOCRYPT_HEADER { @@ -403,8 +478,9 @@ impl<'a> MimeFactory<'a> { let peerstates = self.peerstates_for_recipients()?; let should_encrypt = encrypt_helper.should_encrypt(self.context, e2ee_guranteed, &peerstates)?; + let is_encrypted = should_encrypt && force_plaintext == 0; - let mut outer_message = if should_encrypt && force_plaintext == 0 { + let mut outer_message = if is_encrypted { for header in protected_headers.into_iter() { message = message.header(header); } @@ -452,9 +528,6 @@ impl<'a> MimeFactory<'a> { ) .header(("Subject".to_string(), "...".to_string())); - let gossiped = do_gossip && !peerstates.is_empty(); - self.finalize_mime_message(true, gossiped)?; - outer_message } else { // In the unencrypted case, we add all headers to the outer message. @@ -464,8 +537,6 @@ impl<'a> MimeFactory<'a> { for header in unprotected_headers.into_iter() { message = message.header(header); } - self.finalize_mime_message(false, false)?; - message }; @@ -473,11 +544,36 @@ impl<'a> MimeFactory<'a> { .header(Header::new_with_value("To".into(), to).unwrap()) .header(Header::new_with_value("From".into(), vec![from]).unwrap()); - // TODO - // self.envelope = Some(Envelope::new(Some(from), to).expect("setting from")); - self.out = outer_message.build().as_string().into_bytes(); + let is_gossiped = is_encrypted && do_gossip && !peerstates.is_empty(); - Ok(()) + let MimeFactory { + recipients_addr, + from_addr, + last_added_location_id, + msg, + loaded, + .. + } = self; + + let rfc724_mid = match loaded { + Loaded::Message => msg.rfc724_mid.clone(), + Loaded::MDN => dc_create_outgoing_rfc724_mid(None, &from_addr), + }; + + Ok(RenderedEmail { + message: outer_message.build().as_string().into_bytes(), + // envelope: Envelope::new, + is_encrypted, + is_gossiped, + last_added_location_id, + foreign_id: match loaded { + Loaded::Message => Some(msg.id), + Loaded::MDN => None, + }, + recipients: recipients_addr, + from: from_addr, + rfc724_mid, + }) } fn render_message( @@ -738,7 +834,7 @@ impl<'a> MimeFactory<'a> { is_multipart = true; if !self.msg.param.exists(Param::SetLatitude) { // otherwise, the independent location is already filed - self.out_last_added_location_id = last_added_location_id; + self.last_added_location_id = last_added_location_id; } } Err(err) => { @@ -761,100 +857,6 @@ impl<'a> MimeFactory<'a> { ) -> Result { unimplemented!() } - - pub fn load_msg(context: &Context, msg_id: MsgId) -> Result, Error> { - let msg = Message::load_from_db(context, msg_id)?; - let chat = Chat::load_from_db(context, msg.chat_id)?; - let mut factory = MimeFactory::from_message(context, msg); - factory.chat = Some(chat); - - // just set the chat above - let chat = factory.chat.as_ref().unwrap(); - - if chat.is_self_talk() { - factory - .recipients_names - .push(factory.from_displayname.to_string()); - factory.recipients_addr.push(factory.from_addr.to_string()); - } else { - context.sql.query_map( - "SELECT c.authname, c.addr \ - FROM chats_contacts cc \ - LEFT JOIN contacts c ON cc.contact_id=c.id \ - WHERE cc.chat_id=? AND cc.contact_id>9;", - params![factory.msg.chat_id as i32], - |row| { - let authname: String = row.get(0)?; - let addr: String = row.get(1)?; - Ok((authname, addr)) - }, - |rows| { - for row in rows { - let (authname, addr) = row?; - if !vec_contains_lowercase(&factory.recipients_addr, &addr) { - factory.recipients_addr.push(addr); - factory.recipients_names.push(authname); - } - } - Ok(()) - }, - )?; - - let command = factory.msg.param.get_cmd(); - let msg = &factory.msg; - - /* for added members, the list is just fine */ - if command == SystemMessage::MemberRemovedFromGroup { - let email_to_remove = msg.param.get(Param::Arg).unwrap_or_default(); - - let self_addr = context - .get_config(Config::ConfiguredAddr) - .unwrap_or_default(); - - if !email_to_remove.is_empty() && !addr_cmp(email_to_remove, self_addr) { - if !vec_contains_lowercase(&factory.recipients_addr, &email_to_remove) { - factory.recipients_names.push("".to_string()); - factory.recipients_addr.push(email_to_remove.to_string()); - } - } - } - if command != SystemMessage::AutocryptSetupMessage - && command != SystemMessage::SecurejoinMessage - && context.get_config_bool(Config::MdnsEnabled) - { - factory.req_mdn = true; - } - } - let row = context.sql.query_row( - "SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?", - params![factory.msg.id], - |row| { - let in_reply_to: String = row.get(0)?; - let references: String = row.get(1)?; - - Ok((in_reply_to, references)) - }, - ); - match row { - Ok((in_reply_to, references)) => { - factory.in_reply_to = in_reply_to; - factory.references = references; - } - Err(err) => { - error!( - context, - "mimefactory: failed to load mime_in_reply_to: {:?}", err - ); - } - } - - factory.loaded = Loaded::Message; - factory.timestamp = factory.msg.timestamp_sort; - factory.rfc724_mid = factory.msg.rfc724_mid.clone(); - factory.increation = factory.msg.is_increation(); - - Ok(factory) - } } fn build_body_file( From 5adde12dff6609e499b266350c09bee2ca74db6c Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 14:14:28 +0100 Subject: [PATCH 08/20] implement mdn rendering --- src/message.rs | 4 +-- src/mimefactory.rs | 71 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/message.rs b/src/message.rs index 09918a55d..b1175ad88 100644 --- a/src/message.rs +++ b/src/message.rs @@ -470,11 +470,11 @@ impl Message { ret } - pub fn get_summarytext(&mut self, context: &Context, approx_characters: usize) -> String { + pub fn get_summarytext(&self, context: &Context, approx_characters: usize) -> String { get_summarytext_by_raw( self.type_0, self.text.as_ref(), - &mut self.param, + &self.param, approx_characters, context, ) diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 77b2412de..dd34d6294 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -464,7 +464,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> { Loaded::Message => { self.render_message(&mut protected_headers, &mut unprotected_headers, &grpimage)? } - Loaded::MDN => self.render_mdn(&mut protected_headers, &mut unprotected_headers)?, + Loaded::MDN => self.render_mdn()?, }; if force_plaintext != DC_FP_NO_AUTOCRYPT_HEADER { @@ -850,12 +850,69 @@ impl<'a, 'b> MimeFactory<'a, 'b> { Ok(message) } - fn render_mdn( - &mut self, - protected_headers: &mut Vec
, - unprotected_headers: &mut Vec
, - ) -> Result { - unimplemented!() + /// Render an MDN + fn render_mdn(&mut self) -> Result { + // RFC 6522, this also requires the `report-type` parameter which is equal + // to the MIME subtype of the second body part of the multipart/report */ + // + // currently, we do not send MDNs encrypted: + // - in a multi-device-setup that is not set up properly, MDNs would disturb the communication as they + // are send automatically which may lead to spreading outdated Autocrypt headers. + // - they do not carry any information but the Message-ID + // - this save some KB + // - in older versions, we did not encrypt messages to ourself when they to to SMTP - however, if these messages + // are forwarded for any reasons (eg. gmail always forwards to IMAP), we have no chance to decrypt them; + // this issue is fixed with 0.9.4 + + let mut message = PartBuilder::new().header(( + "Content-Type".to_string(), + "multipart/report; report-type=disposition-notification".to_string(), + )); + + // first body part: always human-readable, always REQUIRED by RFC 6522 + let p1 = if 0 + != self + .msg + .param + .get_int(Param::GuaranteeE2ee) + .unwrap_or_default() + { + self.context + .stock_str(StockMessage::EncryptedMsg) + .into_owned() + } else { + self.msg.get_summarytext(self.context, 32) + }; + let p2 = self + .context + .stock_string_repl_str(StockMessage::ReadRcptMailBody, p1); + let message_text = format!("{}\r\n", p2); + message = message.child( + PartBuilder::new() + .content_type(&mime::TEXT_PLAIN_UTF_8) + .body(message_text) + .build(), + ); + + // second body part: machine-readable, always REQUIRED by RFC 6522 + let version = get_version_str(); + let message_text2 = format!( + "Reporting-UA: Delta Chat {}\r\n\ + Original-Recipient: rfc822;{}\r\n\ + Final-Recipient: rfc822;{}\r\n\ + Original-Message-ID: <{}>\r\n\ + Disposition: manual-action/MDN-sent-automatically; displayed\r\n", + version, self.from_addr, self.from_addr, self.msg.rfc724_mid + ); + + message = message.child( + PartBuilder::new() + .content_type(&"message/disposition-notification".parse().unwrap()) + .body(message_text2) + .build(), + ); + + Ok(message) } } From 734bbff04d9f0a38e1bcb0dcab6c16ca7f4522b2 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 16:48:50 +0100 Subject: [PATCH 09/20] cleanup and finish missing parts --- src/dc_receive_imf.rs | 3 +- src/e2ee.rs | 107 +------- src/mimeparser.rs | 106 +++++++- src/securejoin.rs | 614 +++++++++++++++++++++--------------------- src/wrapmime.rs | 183 +------------ 5 files changed, 415 insertions(+), 598 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index b014377e8..bf96b159f 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -116,8 +116,7 @@ pub fn dc_receive_imf( if let Some(value) = mime_parser.lookup_field("Date") { // is not yet checked against bad times! we do this later if we have the database information. - // sent_timestamp = dc_timestamp_from_date((*orig_date).dt_date_time) - // TODO + sent_timestamp = mailparse::dateparse(value).unwrap_or_default(); } // get From: and check if it is known (for known From:'s we add the other To:/Cc: in the 3rd pass) diff --git a/src/e2ee.rs b/src/e2ee.rs index 4f6b6ce06..8e1931630 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -137,14 +137,14 @@ impl EncryptHelper { pub fn try_decrypt( context: &Context, mail: &mailparse::ParsedMail<'_>, -) -> Result<(Option>, HashSet, HashSet)> { +) -> Result<(Option>, HashSet, i64)> { use mailparse::MailHeaderMap; let from = mail.headers.get_first_value("From")?.unwrap_or_default(); let message_time = mail .headers .get_first_value("Date")? - .and_then(|v| v.parse().ok()) + .and_then(|v| mailparse::dateparse(&v).ok()) .unwrap_or_default(); let mut peerstate = None; @@ -171,7 +171,6 @@ pub fn try_decrypt( let mut private_keyring = Keyring::default(); let mut public_keyring_for_validate = Keyring::default(); let mut out_mail = None; - let mut gossipped_addr = HashSet::default(); let mut signatures = HashSet::default(); let self_addr = context.get_config(Config::ConfiguredAddr); @@ -199,15 +198,9 @@ pub fn try_decrypt( &public_keyring_for_validate, &mut signatures, )?; - - // TODO: - // if !gossip_headers.is_empty() { - // gossipped_addr = - // update_gossip_peerstates(context, message_time, imffields, gossip_headers)?; - // } } } - Ok((out_mail, signatures, gossipped_addr)) + Ok((out_mail, signatures, message_time)) } /// Load public key from database or generate a new one. @@ -257,74 +250,6 @@ fn load_or_generate_self_public_key(context: &Context, self_addr: impl AsRef Result> { -// // XXX split the parsing from the modification part -// let mut recipients: Option> = None; -// let mut gossipped_addr: HashSet = Default::default(); - -// for cur_data in { (*(*gossip_headers).fld_list).into_iter() } { -// let field = cur_data as *mut mailimf_field; -// if field.is_null() { -// continue; -// } - -// let field = { *field }; - -// if field.fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { -// let optional_field = { field.fld_data.fld_optional_field }; -// if optional_field.is_null() { -// continue; -// } - -// let optional_field = { *optional_field }; -// if !optional_field.fld_name.is_null() -// && to_string_lossy(optional_field.fld_name) == "Autocrypt-Gossip" -// { -// let value = to_string_lossy(optional_field.fld_value); -// let gossip_header = Aheader::from_str(&value); - -// if let Ok(ref header) = gossip_header { -// if recipients.is_none() { -// recipients = Some(mailimf_get_recipients(imffields)); -// } -// if recipients.as_ref().unwrap().contains(&header.addr) { -// let mut peerstate = -// Peerstate::from_addr(context, &context.sql, &header.addr); -// if let Some(ref mut peerstate) = peerstate { -// peerstate.apply_gossip(header, message_time); -// peerstate.save_to_db(&context.sql, false)?; -// } else { -// let p = Peerstate::from_gossip(context, header, message_time); -// p.save_to_db(&context.sql, true)?; -// peerstate = Some(p); -// } -// if let Some(peerstate) = peerstate { -// if peerstate.degrade_event.is_some() { -// handle_degrade_event(context, &peerstate)?; -// } -// } - -// gossipped_addr.insert(header.addr.clone()); -// } else { -// info!( -// context, -// "Ignoring gossipped \"{}\" as the address is not in To/Cc list.", -// &header.addr, -// ); -// } -// } -// } -// } -// } - -// Ok(gossipped_addr) -// } - fn decrypt_if_autocrypt_message<'a>( context: &Context, mail: &mailparse::ParsedMail<'a>, @@ -347,35 +272,13 @@ fn decrypt_if_autocrypt_message<'a>( Ok(res) => res, }; - let decrypted = decrypt_part( + decrypt_part( context, encrypted_data_part, private_keyring, public_keyring_for_validate, ret_valid_signatures, - )?; - - // finally, let's also return gossip headers - // XXX better return parsed headers so that upstream - // does not need to dive into mmime-stuff again. - // { - // if (*ret_gossip_headers).is_null() && !ret_valid_signatures.is_empty() { - // let mut dummy: libc::size_t = 0; - // let mut test: *mut mailimf_fields = ptr::null_mut(); - // if mailimf_envelope_and_optional_fields_parse( - // (*decrypted_mime).mm_mime_start, - // (*decrypted_mime).mm_length, - // &mut dummy, - // &mut test, - // ) == MAILIMF_NO_ERROR as libc::c_int - // && !test.is_null() - // { - // *ret_gossip_headers = test; - // } - // } - // } - - Ok(decrypted) + ) } /// Returns Ok(None) if nothing encrypted was found. diff --git a/src/mimeparser.rs b/src/mimeparser.rs index ca668810a..97ee40e5c 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -1,7 +1,9 @@ use std::collections::{HashMap, HashSet}; use deltachat_derive::{FromSql, ToSql}; +use mailparse::MailHeaderMap; +use crate::aheader::Aheader; use crate::blob::BlobObject; use crate::config::Config; use crate::constants::Viewtype; @@ -16,8 +18,9 @@ use crate::location; use crate::message; use crate::message::MsgId; use crate::param::*; +use crate::peerstate::Peerstate; +use crate::securejoin::handle_degrade_event; use crate::stock::StockMessage; -use crate::wrapmime; #[derive(Debug)] pub struct MimeParser<'a> { @@ -100,14 +103,27 @@ impl<'a> MimeParser<'a> { let mail_raw; let mail = match e2ee::try_decrypt(parser.context, &mail) { - Ok((raw, signatures, gossipped_addr)) => { + Ok((raw, signatures, message_time)) => { + // Valid autocrypt message, encrypted parser.encrypted = raw.is_some(); parser.signatures = signatures; - parser.gossipped_addr = gossipped_addr; + if let Some(raw) = raw { mail_raw = raw; - mailparse::parse_mail(&mail_raw)? + let decrypted_mail = mailparse::parse_mail(&mail_raw)?; + + // we have a decrypted mail, that is valid, check for gossip headers + + let gossip_headers = + decrypted_mail.headers.get_all_values("Autocrypt-Gossip")?; + if !gossip_headers.is_empty() { + parser.gossipped_addr = + update_gossip_peerstates(context, message_time, &mail, gossip_headers)?; + } + + decrypted_mail } else { + // Message was not encrypted mail } } @@ -726,7 +742,7 @@ impl<'a> MimeParser<'a> { } if let mailparse::MailAddr::Single(ref info) = addrs[0] { let from_addr_norm = addr_normalize(&info.addr); - let recipients = wrapmime::mailimf_get_recipients(&self.header); + let recipients = get_recipients(self.header.iter()); if recipients.len() == 1 && recipients.contains(from_addr_norm) { return true; } @@ -774,8 +790,6 @@ impl<'a> MimeParser<'a> { } fn process_report(&self, report: &mailparse::ParsedMail<'_>) -> Result> { - use mailparse::MailHeaderMap; - let ct = report.get_content_disposition()?; let report_type = ct.params.get("report-type"); if report_type.is_none() { @@ -853,6 +867,55 @@ impl<'a> MimeParser<'a> { } } +fn update_gossip_peerstates( + context: &Context, + message_time: i64, + mail: &mailparse::ParsedMail<'_>, + gossip_headers: Vec, +) -> Result> { + // XXX split the parsing from the modification part + let mut recipients: Option> = None; + let mut gossipped_addr: HashSet = Default::default(); + + for value in &gossip_headers { + let gossip_header = value.parse::(); + + if let Ok(ref header) = gossip_header { + if recipients.is_none() { + recipients = Some(get_recipients(mail.headers.iter().map(|v| { + // TODO: error handling + (v.get_key().unwrap(), v.get_value().unwrap()) + }))); + } + if recipients.as_ref().unwrap().contains(&header.addr) { + let mut peerstate = Peerstate::from_addr(context, &context.sql, &header.addr); + if let Some(ref mut peerstate) = peerstate { + peerstate.apply_gossip(header, message_time); + peerstate.save_to_db(&context.sql, false)?; + } else { + let p = Peerstate::from_gossip(context, header, message_time); + p.save_to_db(&context.sql, true)?; + peerstate = Some(p); + } + if let Some(peerstate) = peerstate { + if peerstate.degrade_event.is_some() { + handle_degrade_event(context, &peerstate)?; + } + } + + gossipped_addr.insert(header.addr.clone()); + } else { + info!( + context, + "Ignoring gossipped \"{}\" as the address is not in To/Cc list.", &header.addr, + ); + } + } + } + + Ok(gossipped_addr) +} + #[derive(Debug)] struct Report { original_message_id: String, @@ -967,6 +1030,35 @@ fn mailmime_is_attachment_disposition(mail: &mailparse::ParsedMail<'_>) -> bool false } +// returned addresses are normalized. +fn get_recipients<'a, S: AsRef, T: Iterator>(headers: T) -> HashSet { + let mut recipients: HashSet = Default::default(); + + for (hkey, hvalue) in headers { + let hkey = hkey.as_ref(); + let hvalue = hvalue.as_ref(); + + if hkey == "to" || hkey == "cc" { + if let Ok(addrs) = mailparse::addrparse(hvalue) { + for addr in addrs.iter() { + match addr { + mailparse::MailAddr::Single(ref info) => { + recipients.insert(addr_normalize(&info.addr).into()); + } + mailparse::MailAddr::Group(ref infos) => { + for info in &infos.addrs { + recipients.insert(addr_normalize(&info.addr).into()); + } + } + } + } + } + } + } + + recipients +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/securejoin.rs b/src/securejoin.rs index b22bb4fde..85d6b2cd4 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -337,325 +337,329 @@ impl Default for HandshakeMessageStatus { } } -/* library private: secure-join */ +/// Handle incoming secure-join handshake. pub(crate) fn handle_securejoin_handshake( context: &Context, mimeparser: &MimeParser, contact_id: u32, ) -> Result { - unimplemented!() - // let own_fingerprint: String; + let own_fingerprint: String; - // ensure!( - // contact_id > DC_CONTACT_ID_LAST_SPECIAL, - // "handle_securejoin_handshake(): called with special contact id" - // ); - // let step = match mimeparser.lookup_optional_field("Secure-Join") { - // Some(s) => s, - // None => { - // bail!("This message is not a Secure-Join message"); - // } - // }; - // info!( - // context, - // ">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received", step, - // ); - // let (contact_chat_id, contact_chat_id_blocked) = - // chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not).unwrap_or_default(); + ensure!( + contact_id > DC_CONTACT_ID_LAST_SPECIAL, + "handle_securejoin_handshake(): called with special contact id" + ); + let step = mimeparser + .lookup_field("Secure-Join") + .ok_or_else(|| format_err!("This message is not a Secure-Join message"))?; - // if contact_chat_id_blocked != Blocked::Not { - // chat::unblock(context, contact_chat_id); - // } - // let join_vg = step.starts_with("vg-"); - // let mut ret = HandshakeMessageStatus::default(); + info!( + context, + ">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received", step, + ); - // match step.as_str() { - // "vg-request" | "vc-request" => { - // /* ========================================================= - // ==== Alice - the inviter side ==== - // ==== Step 3 in "Setup verified contact" protocol ==== - // ========================================================= */ - // // this message may be unencrypted (Bob, the joinder and the sender, might not have Alice's key yet) - // // 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_optional_field("Secure-Join-Invitenumber") { - // Some(n) => n, - // None => { - // warn!(context, "Secure-join denied (invitenumber missing).",); - // return Ok(ret); - // } - // }; - // if !token::exists(context, token::Namespace::InviteNumber, &invitenumber) { - // warn!(context, "Secure-join denied (bad invitenumber).",); - // return Ok(ret); - // } - // info!(context, "Secure-join requested.",); + let (contact_chat_id, contact_chat_id_blocked) = + chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not).unwrap_or_default(); - // inviter_progress!(context, contact_id, 300); - // send_handshake_msg( - // context, - // contact_chat_id, - // &format!("{}-auth-required", &step[..2]), - // "", - // None, - // "", - // ); - // } - // "vg-auth-required" | "vc-auth-required" => { - // let cond = { - // let bob = context.bob.read().unwrap(); - // let scan = bob.qr_scan.as_ref(); - // scan.is_none() - // || bob.expects != DC_VC_AUTH_REQUIRED - // || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup - // }; + if contact_chat_id_blocked != Blocked::Not { + chat::unblock(context, contact_chat_id); + } - // if cond { - // warn!(context, "auth-required message out of sync.",); - // // no error, just aborted somehow or a mail from another handshake - // return Ok(ret); - // } - // let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string(); - // let auth = get_qr_attr!(context, auth).to_string(); + let join_vg = step.starts_with("vg-"); + let mut ret = HandshakeMessageStatus::default(); - // if !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) { - // could_not_establish_secure_connection( - // context, - // contact_chat_id, - // if mimeparser.encrypted { - // "No valid signature." - // } else { - // "Not encrypted." - // }, - // ); - // ret.stop_ongoing_process = true; - // ret.bob_securejoin_success = Some(false); - // return Ok(ret); - // } - // if !fingerprint_equals_sender(context, &scanned_fingerprint_of_alice, contact_chat_id) { - // could_not_establish_secure_connection( - // context, - // contact_chat_id, - // "Fingerprint mismatch on joiner-side.", - // ); - // ret.stop_ongoing_process = true; - // ret.bob_securejoin_success = Some(false); - // return Ok(ret); - // } - // info!(context, "Fingerprint verified.",); - // own_fingerprint = get_self_fingerprint(context).unwrap(); - // joiner_progress!(context, contact_id, 400); - // context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM; + match step.as_str() { + "vg-request" | "vc-request" => { + /* ========================================================= + ==== Alice - the inviter side ==== + ==== Step 3 in "Setup verified contact" protocol ==== + ========================================================= */ + // this message may be unencrypted (Bob, the joinder and the sender, might not have Alice's key yet) + // 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") { + Some(n) => n, + None => { + warn!(context, "Secure-join denied (invitenumber missing).",); + return Ok(ret); + } + }; + if !token::exists(context, token::Namespace::InviteNumber, &invitenumber) { + warn!(context, "Secure-join denied (bad invitenumber).",); + return Ok(ret); + } + info!(context, "Secure-join requested.",); - // send_handshake_msg( - // context, - // contact_chat_id, - // &format!("{}-request-with-auth", &step[..2]), - // auth, - // Some(own_fingerprint), - // if join_vg { - // get_qr_attr!(context, text2).to_string() - // } else { - // "".to_string() - // }, - // ); - // } - // "vg-request-with-auth" | "vc-request-with-auth" => { - // /* ============================================================ - // ==== Alice - the inviter side ==== - // ==== Steps 5+6 in "Setup verified contact" protocol ==== - // ==== 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_optional_field("Secure-Join-Fingerprint") { - // Some(fp) => fp, - // None => { - // could_not_establish_secure_connection( - // context, - // contact_chat_id, - // "Fingerprint not provided.", - // ); - // return Ok(ret); - // } - // }; - // if !encrypted_and_signed(mimeparser, &fingerprint) { - // could_not_establish_secure_connection( - // context, - // contact_chat_id, - // "Auth not encrypted.", - // ); - // return Ok(ret); - // } - // if !fingerprint_equals_sender(context, &fingerprint, contact_chat_id) { - // could_not_establish_secure_connection( - // context, - // contact_chat_id, - // "Fingerprint mismatch on inviter-side.", - // ); - // return Ok(ret); - // } - // 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_optional_field("Secure-Join-Auth") { - // Some(auth) => auth, - // None => { - // could_not_establish_secure_connection( - // context, - // contact_chat_id, - // "Auth not provided.", - // ); - // return Ok(ret); - // } - // }; - // if !token::exists(context, token::Namespace::Auth, &auth_0) { - // could_not_establish_secure_connection(context, contact_chat_id, "Auth invalid."); - // return Ok(ret); - // } - // if mark_peer_as_verified(context, fingerprint).is_err() { - // could_not_establish_secure_connection( - // context, - // contact_chat_id, - // "Fingerprint mismatch on inviter-side.", - // ); - // return Ok(ret); - // } - // Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited); - // info!(context, "Auth verified.",); - // secure_connection_established(context, contact_chat_id); - // emit_event!(context, Event::ContactsChanged(Some(contact_id))); - // inviter_progress!(context, contact_id, 600); - // if join_vg { - // 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); - // if group_chat_id == 0 { - // error!(context, "Chat {} not found.", &field_grpid); - // return Ok(ret); - // } else { - // if let Err(err) = - // chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, true) - // { - // error!(context, "failed to add contact: {}", err); - // } - // } - // } else { - // send_handshake_msg(context, contact_chat_id, "vc-contact-confirm", "", None, ""); - // inviter_progress!(context, contact_id, 1000); - // } - // } - // "vg-member-added" | "vc-contact-confirm" => { - // if join_vg { - // ret.hide_this_msg = false; - // } - // if context.bob.read().unwrap().expects != DC_VC_CONTACT_CONFIRM { - // info!(context, "Message belongs to a different handshake.",); - // return Ok(ret); - // } - // let cond = { - // let bob = context.bob.read().unwrap(); - // let scan = bob.qr_scan.as_ref(); - // scan.is_none() || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup - // }; - // if cond { - // warn!( - // context, - // "Message out of sync or belongs to a different handshake.", - // ); - // return Ok(ret); - // } - // let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string(); + inviter_progress!(context, contact_id, 300); + send_handshake_msg( + context, + contact_chat_id, + &format!("{}-auth-required", &step[..2]), + "", + None, + "", + ); + } + "vg-auth-required" | "vc-auth-required" => { + let cond = { + let bob = context.bob.read().unwrap(); + let scan = bob.qr_scan.as_ref(); + scan.is_none() + || bob.expects != DC_VC_AUTH_REQUIRED + || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup + }; - // let vg_expect_encrypted = if join_vg { - // let group_id = get_qr_attr!(context, text2).to_string(); - // let (_, is_verified_group, _) = chat::get_chat_id_by_grpid(context, group_id); - // // when joining a non-verified group - // // the vg-member-added message may be unencrypted - // // when not all group members have keys or prefer encryption. - // // So only expect encryption if this is a verified group - // is_verified_group - // } else { - // // setup contact is always encrypted - // true - // }; - // if vg_expect_encrypted - // && !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) - // { - // could_not_establish_secure_connection( - // context, - // contact_chat_id, - // "Contact confirm message not encrypted.", - // ); - // ret.bob_securejoin_success = Some(false); - // return Ok(ret); - // } + if cond { + warn!(context, "auth-required message out of sync.",); + // no error, just aborted somehow or a mail from another handshake + return Ok(ret); + } + let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string(); + let auth = get_qr_attr!(context, auth).to_string(); - // if mark_peer_as_verified(context, &scanned_fingerprint_of_alice).is_err() { - // could_not_establish_secure_connection( - // context, - // contact_chat_id, - // "Fingerprint mismatch on joiner-side.", - // ); - // return Ok(ret); - // } - // Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined); - // emit_event!(context, Event::ContactsChanged(None)); - // let cg_member_added = mimeparser - // .lookup_optional_field("Chat-Group-Member-Added") - // .unwrap_or_default(); - // 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)."); - // return Ok(ret); - // } - // secure_connection_established(context, contact_chat_id); - // context.bob.write().unwrap().expects = 0; - // if join_vg { - // send_handshake_msg( - // context, - // contact_chat_id, - // "vg-member-added-received", - // "", - // None, - // "", - // ); - // } - // ret.stop_ongoing_process = true; - // ret.bob_securejoin_success = Some(true); - // } - // "vg-member-added-received" => { - // /* ============================================================ - // ==== Alice - the inviter side ==== - // ==== Step 8 in "Out-of-band verified groups" protocol ==== - // ============================================================ */ - // if let Ok(contact) = Contact::get_by_id(context, contact_id) { - // if contact.is_verified(context) == VerifiedStatus::Unverified { - // warn!(context, "vg-member-added-received invalid.",); - // return Ok(ret); - // } - // inviter_progress!(context, contact_id, 800); - // inviter_progress!(context, contact_id, 1000); - // 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); - // context.call_cb(Event::SecurejoinMemberAdded { - // chat_id: group_chat_id, - // contact_id: contact_id, - // }); - // } else { - // warn!(context, "vg-member-added-received invalid.",); - // return Ok(ret); - // } - // } - // _ => { - // warn!(context, "invalid step: {}", step); - // } - // } - // if ret.hide_this_msg { - // ret.delete_this_msg = true; - // } - // Ok(ret) + if !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) { + could_not_establish_secure_connection( + context, + contact_chat_id, + if mimeparser.encrypted { + "No valid signature." + } else { + "Not encrypted." + }, + ); + ret.stop_ongoing_process = true; + ret.bob_securejoin_success = Some(false); + return Ok(ret); + } + if !fingerprint_equals_sender(context, &scanned_fingerprint_of_alice, contact_chat_id) { + could_not_establish_secure_connection( + context, + contact_chat_id, + "Fingerprint mismatch on joiner-side.", + ); + ret.stop_ongoing_process = true; + ret.bob_securejoin_success = Some(false); + return Ok(ret); + } + info!(context, "Fingerprint verified.",); + own_fingerprint = get_self_fingerprint(context).unwrap(); + joiner_progress!(context, contact_id, 400); + context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM; + + send_handshake_msg( + context, + contact_chat_id, + &format!("{}-request-with-auth", &step[..2]), + auth, + Some(own_fingerprint), + if join_vg { + get_qr_attr!(context, text2).to_string() + } else { + "".to_string() + }, + ); + } + "vg-request-with-auth" | "vc-request-with-auth" => { + /* ============================================================ + ==== Alice - the inviter side ==== + ==== Steps 5+6 in "Setup verified contact" protocol ==== + ==== 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") { + Some(fp) => fp, + None => { + could_not_establish_secure_connection( + context, + contact_chat_id, + "Fingerprint not provided.", + ); + return Ok(ret); + } + }; + if !encrypted_and_signed(mimeparser, &fingerprint) { + could_not_establish_secure_connection( + context, + contact_chat_id, + "Auth not encrypted.", + ); + return Ok(ret); + } + if !fingerprint_equals_sender(context, &fingerprint, contact_chat_id) { + could_not_establish_secure_connection( + context, + contact_chat_id, + "Fingerprint mismatch on inviter-side.", + ); + return Ok(ret); + } + 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") { + Some(auth) => auth, + None => { + could_not_establish_secure_connection( + context, + contact_chat_id, + "Auth not provided.", + ); + return Ok(ret); + } + }; + if !token::exists(context, token::Namespace::Auth, &auth_0) { + could_not_establish_secure_connection(context, contact_chat_id, "Auth invalid."); + return Ok(ret); + } + if mark_peer_as_verified(context, fingerprint).is_err() { + could_not_establish_secure_connection( + context, + contact_chat_id, + "Fingerprint mismatch on inviter-side.", + ); + return Ok(ret); + } + Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited); + info!(context, "Auth verified.",); + secure_connection_established(context, contact_chat_id); + emit_event!(context, Event::ContactsChanged(Some(contact_id))); + inviter_progress!(context, contact_id, 600); + if join_vg { + let field_grpid = mimeparser + .lookup_field("Secure-Join-Group") + .map(|s| s.as_str()) + .unwrap_or_else(|| ""); + let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, field_grpid); + if group_chat_id == 0 { + error!(context, "Chat {} not found.", &field_grpid); + return Ok(ret); + } else { + if let Err(err) = + chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, true) + { + error!(context, "failed to add contact: {}", err); + } + } + } else { + send_handshake_msg(context, contact_chat_id, "vc-contact-confirm", "", None, ""); + inviter_progress!(context, contact_id, 1000); + } + } + "vg-member-added" | "vc-contact-confirm" => { + if join_vg { + ret.hide_this_msg = false; + } + if context.bob.read().unwrap().expects != DC_VC_CONTACT_CONFIRM { + info!(context, "Message belongs to a different handshake.",); + return Ok(ret); + } + let cond = { + let bob = context.bob.read().unwrap(); + let scan = bob.qr_scan.as_ref(); + scan.is_none() || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup + }; + if cond { + warn!( + context, + "Message out of sync or belongs to a different handshake.", + ); + return Ok(ret); + } + let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string(); + + let vg_expect_encrypted = if join_vg { + let group_id = get_qr_attr!(context, text2).to_string(); + let (_, is_verified_group, _) = chat::get_chat_id_by_grpid(context, group_id); + // when joining a non-verified group + // the vg-member-added message may be unencrypted + // when not all group members have keys or prefer encryption. + // So only expect encryption if this is a verified group + is_verified_group + } else { + // setup contact is always encrypted + true + }; + if vg_expect_encrypted + && !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) + { + could_not_establish_secure_connection( + context, + contact_chat_id, + "Contact confirm message not encrypted.", + ); + ret.bob_securejoin_success = Some(false); + return Ok(ret); + } + + if mark_peer_as_verified(context, &scanned_fingerprint_of_alice).is_err() { + could_not_establish_secure_connection( + context, + contact_chat_id, + "Fingerprint mismatch on joiner-side.", + ); + return Ok(ret); + } + 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") + .map(|s| s.as_str()) + .unwrap_or_else(|| ""); + 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)."); + return Ok(ret); + } + secure_connection_established(context, contact_chat_id); + context.bob.write().unwrap().expects = 0; + if join_vg { + send_handshake_msg( + context, + contact_chat_id, + "vg-member-added-received", + "", + None, + "", + ); + } + ret.stop_ongoing_process = true; + ret.bob_securejoin_success = Some(true); + } + "vg-member-added-received" => { + /* ============================================================ + ==== Alice - the inviter side ==== + ==== Step 8 in "Out-of-band verified groups" protocol ==== + ============================================================ */ + if let Ok(contact) = Contact::get_by_id(context, contact_id) { + if contact.is_verified(context) == VerifiedStatus::Unverified { + warn!(context, "vg-member-added-received invalid.",); + return Ok(ret); + } + inviter_progress!(context, contact_id, 800); + inviter_progress!(context, contact_id, 1000); + let field_grpid = mimeparser + .lookup_field("Secure-Join-Group") + .map(|s| s.as_str()) + .unwrap_or_else(|| ""); + let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, &field_grpid); + context.call_cb(Event::SecurejoinMemberAdded { + chat_id: group_chat_id, + contact_id: contact_id, + }); + } else { + warn!(context, "vg-member-added-received invalid.",); + return Ok(ret); + } + } + _ => { + warn!(context, "invalid step: {}", step); + } + } + + if ret.hide_this_msg { + ret.delete_this_msg = true; + } + + Ok(ret) } fn secure_connection_established(context: &Context, contact_chat_id: u32) { diff --git a/src/wrapmime.rs b/src/wrapmime.rs index ea37cdb12..4f4b6562d 100644 --- a/src/wrapmime.rs +++ b/src/wrapmime.rs @@ -1,14 +1,7 @@ -use std::collections::{HashMap, HashSet}; - use mailparse::ParsedMail; -use crate::contact::addr_normalize; use crate::error::Error; -/************************************** -* mime parsing API -**************************************/ - pub fn parse_message_id(message_id: &[u8]) -> Result { let value = std::str::from_utf8(message_id)?; let addrs = mailparse::addrparse(value) @@ -18,10 +11,7 @@ pub fn parse_message_id(message_id: &[u8]) -> Result { return Ok(info.addr); } - bail!( - "could not parse message_id: {}", - String::from_utf8_lossy(message_id) - ); + bail!("could not parse message_id: {}", value); } /// Returns a reference to the encrypted payload and validates the autocrypt structure. @@ -48,181 +38,10 @@ pub fn get_autocrypt_mime<'a, 'b>(mail: &'a ParsedMail<'b>) -> Result<&'a Parsed Ok(&mail.subparts[1]) } -// returned addresses are normalized. -pub fn mailimf_get_recipients(headers: &HashMap) -> HashSet { - let mut recipients: HashSet = Default::default(); - - for (hkey, hvalue) in headers.iter() { - if hkey == "to" || hkey == "cc" { - if let Ok(addrs) = mailparse::addrparse(hvalue) { - for addr in addrs.iter() { - match addr { - mailparse::MailAddr::Single(ref info) => { - recipients.insert(addr_normalize(&info.addr).into()); - } - mailparse::MailAddr::Group(ref infos) => { - for info in &infos.addrs { - recipients.insert(addr_normalize(&info.addr).into()); - } - } - } - } - } - } - } - - recipients -} - -/************************************** -* mime creation API -**************************************/ - -// pub fn add_filename_part( -// message: *mut Mailmime, -// basename: &str, -// mime_type: &str, -// file_content: &str, -// ) -> Result<(), Error> { -// let mime_type_c = CString::new(mime_type.to_string()).expect("failed to create CString"); -// { -// let content_type = mailmime_content_new_with_str(mime_type_c.as_ptr()); -// let mime_fields = mailmime_fields_new_filename( -// MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int, -// basename.strdup(), -// MAILMIME_MECHANISM_8BIT as libc::c_int, -// ); -// let file_mime_part = mailmime_new_empty(content_type, mime_fields); -// set_body_text(file_mime_part, file_content)?; -// mailmime_smart_add_part(message, file_mime_part); -// } -// Ok(()) -// } - -// pub fn new_custom_field(fields: *mut mailimf_fields, name: &str, value: &str) { -// { -// let field = mailimf_field_new_custom(name.strdup(), value.strdup()); -// let res = mailimf_fields_add(fields, field); -// assert!( -// res as u32 == MAILIMF_NO_ERROR, -// "could not create mailimf field" -// ); -// } -// } - -// pub fn build_body_text(text: &str) -> Result<*mut Mailmime, Error> { -// let mime_fields: *mut mailmime_fields; -// let message_part: *mut Mailmime; - -// let content = new_content_type("text/plain")?; -// append_ct_param(content, "charset", "utf-8")?; - -// { -// mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int); -// message_part = mailmime_new_empty(content, mime_fields); -// } -// set_body_text(message_part, text)?; - -// Ok(message_part) -// } - -// pub fn append_ct_param( -// content: *mut mailmime_content, -// name: &str, -// value: &str, -// ) -> Result<(), Error> { -// { -// let name_c = CString::new(name).unwrap_or_default(); -// let value_c = CString::new(value).unwrap_or_default(); - -// clist_append!( -// (*content).ct_parameters, -// mailmime_param_new_with_data( -// name_c.as_ptr() as *const u8 as *const libc::c_char as *mut libc::c_char, -// value_c.as_ptr() as *const u8 as *const libc::c_char as *mut libc::c_char -// ) -// ); -// } -// Ok(()) -// } - -// pub fn new_content_type(content_type: &str) -> Result<*mut mailmime_content, Error> { -// let ct = CString::new(content_type).unwrap_or_default(); -// let content: *mut mailmime_content; -// // mailmime_content_new_with_str only parses but does not retain/own ct -// { -// content = mailmime_content_new_with_str(ct.as_ptr()); -// } -// ensure!(!content.is_null(), "mailimf failed to allocate"); -// Ok(content) -// } - -// pub fn set_body_text(part: *mut Mailmime, text: &str) -> Result<(), Error> { -// use libc::strlen; -// { -// let text_c = text.strdup(); -// if 0 != mailmime_set_body_text(part, text_c, strlen(text_c)) { -// bail!("could not set body text on mime-structure"); -// } -// } -// Ok(()) -// } - -// pub fn content_type_needs_encoding(content: *const mailmime_content) -> bool { -// { -// if (*(*content).ct_type).tp_type == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int { -// let composite = (*(*content).ct_type).tp_data.tp_composite_type; -// match (*composite).ct_type as u32 { -// MAILMIME_COMPOSITE_TYPE_MESSAGE => { -// to_string_lossy((*content).ct_subtype) != "rfc822" -// } -// MAILMIME_COMPOSITE_TYPE_MULTIPART => false, -// _ => false, -// } -// } else { -// true -// } -// } -// } - -// pub fn new_mailbox_list(displayname: &str, addr: &str) -> *mut mailimf_mailbox_list { -// let mbox: *mut mailimf_mailbox_list = { mailimf_mailbox_list_new_empty() }; -// { -// mailimf_mailbox_list_add( -// mbox, -// mailimf_mailbox_new( -// if !displayname.is_empty() { -// dc_encode_header_words(&displayname).strdup() -// } else { -// ptr::null_mut() -// }, -// addr.strdup(), -// ), -// ); -// } -// mbox -// } - #[cfg(test)] mod tests { use super::*; - // #[test] - // fn test_needs_encoding() { - // assert!(content_type_needs_encoding( - // new_content_type("text/plain").unwrap() - // )); - // assert!(content_type_needs_encoding( - // new_content_type("application/octect-stream").unwrap() - // )); - // assert!(!content_type_needs_encoding( - // new_content_type("multipart/encrypted").unwrap() - // )); - // assert!(content_type_needs_encoding( - // new_content_type("application/pgp-encrypted").unwrap() - // )); - // } - #[test] fn test_parse_message_id() { assert_eq!( From 48dd3b8506e60944c3a2390d7bc4c9e63cc1ca37 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 17:04:30 +0100 Subject: [PATCH 10/20] less dead code, and update test --- src/dc_tools.rs | 27 -------------------------- src/e2ee.rs | 51 ++++++++++++++++++++++--------------------------- 2 files changed, 23 insertions(+), 55 deletions(-) diff --git a/src/dc_tools.rs b/src/dc_tools.rs index b0409319e..0e58b2a88 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -96,33 +96,6 @@ pub(crate) fn dc_str_to_color(s: impl AsRef) -> u32 { COLORS[color_index] } -/* date/time tools */ -/* the result is UTC or DC_INVALID_TIMESTAMP */ -// pub(crate) fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 { -// assert!(!date_time.is_null()); -// let dt = { *date_time }; - -// let sec = dt.dt_sec; -// let min = dt.dt_min; -// let hour = dt.dt_hour; -// let day = dt.dt_day; -// let month = dt.dt_month; -// let year = dt.dt_year; - -// let ts = chrono::NaiveDateTime::new( -// chrono::NaiveDate::from_ymd(year, month as u32, day as u32), -// chrono::NaiveTime::from_hms(hour as u32, min as u32, sec as u32), -// ); - -// let (zone_hour, zone_min) = if dt.dt_zone >= 0 { -// (dt.dt_zone / 100, dt.dt_zone % 100) -// } else { -// (-(-dt.dt_zone / 100), -(-dt.dt_zone % 100)) -// }; - -// ts.timestamp() - (zone_hour * 3600 + zone_min * 60) as i64 -// } - /* ****************************************************************************** * date/time tools ******************************************************************************/ diff --git a/src/e2ee.rs b/src/e2ee.rs index 8e1931630..42bfc0102 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -377,9 +377,10 @@ mod tests { } } - // #[test] - // fn test_mailmime_parse() { - // let plain = b"Chat-Disposition-Notification-To: holger@deltachat.de + // FIXME: https://github.com/staktrace/mailparse/issues/49 + // #[test] + // fn test_mailmime_parse() { + // let plain = b"Chat-Disposition-Notification-To: hello@world.de // Chat-Group-ID: CovhGgau8M- // Chat-Group-Name: Delta Chat Dev // Subject: =?utf-8?Q?Chat=3A?= Delta Chat =?utf-8?Q?Dev=3A?= sidenote for @@ -387,36 +388,30 @@ mod tests { // Content-Type: text/plain; charset=\"utf-8\"; protected-headers=\"v1\" // Content-Transfer-Encoding: quoted-printable - // sidenote for all: rust core master is broken currently ... so dont recomm= - // end to try to run with desktop or ios unless you are ready to hunt bugs + // sidenote for all: things are trick atm recomm= + // end not to try to run with desktop or ios unless you are ready to hunt bugs // -- =20 // Sent with my Delta Chat Messenger: https://delta.chat"; - // let plain_bytes = plain.len(); - // let plain_buf = plain.as_ptr() as *const libc::c_char; + // let mail = mailparse::parse_mail(plain).expect("failed to parse valid message"); - // let mut index = 0; - // let mut decrypted_mime = std::ptr::null_mut(); + // println!( + // "{:?}", + // mail.headers + // .iter() + // .map(|h| (h.get_key(), h.get_value())) + // .collect::>() + // ); + // assert_eq!(mail.headers.len(), 6); + // assert_eq!( + // mail.get_body().unwrap(), + // " sidenote for all: things are trick atm recomm= + // end not to try to run with desktop or ios unless you are ready to hunt bugs - // let res = { - // mailmime_parse( - // plain_buf as *const _, - // plain_bytes, - // &mut index, - // &mut decrypted_mime, - // ) - // }; - // { - // let msg1 = (*decrypted_mime).mm_data.mm_message.mm_msg_mime; - // let data = mailmime_transfer_decode(msg1).unwrap(); - // println!("{:?}", String::from_utf8_lossy(&data)); - // } - - // assert_eq!(res, 0); - // assert!(!decrypted_mime.is_null()); - - // { free(decrypted_mime as *mut _) }; - // } + // -- =20 + // Sent with my Delta Chat Messenger: https://delta.chat" + // ); + // } mod load_or_generate_self_public_key { use super::*; From 7d3a56a8703c95ca5d0aa0ebcb6330e8c3137e47 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 17:33:31 +0100 Subject: [PATCH 11/20] switch to forked rust-email --- Cargo.lock | 44 +++++++++++++++++--------------------------- Cargo.toml | 6 +++--- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd4497790..6b098a71e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -195,15 +195,6 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "base64" version = "0.10.1" @@ -622,7 +613,7 @@ dependencies = [ "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "async-tls 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -636,8 +627,8 @@ dependencies = [ "image-meta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", - "lettre_email 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", + "lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/mail)", + "lettre_email 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/mail)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "mailparse 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -793,16 +784,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "email" -version = "0.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.0.21" +source = "git+https://github.com/deltachat/rust-email#5fb7dac53e7e0014a8c5715017be3360aa83646c" dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1407,9 +1398,9 @@ dependencies = [ [[package]] name = "lettre" version = "0.9.2" -source = "git+https://github.com/deltachat/lettre?branch=feat/rustls#a422872e92e8cf089bdfb24489f3446f9865ba19" +source = "git+https://github.com/deltachat/lettre?branch=feat/mail#0f393a3d1d3860183c5df97b4429d0919199344a" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "fast_chemail 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1426,11 +1417,11 @@ dependencies = [ [[package]] name = "lettre_email" version = "0.9.2" -source = "git+https://github.com/deltachat/lettre?branch=feat/rustls#a422872e92e8cf089bdfb24489f3446f9865ba19" +source = "git+https://github.com/deltachat/lettre?branch=feat/mail#0f393a3d1d3860183c5df97b4429d0919199344a" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "email 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "email 0.0.21 (git+https://github.com/deltachat/rust-email)", + "lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/mail)", "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3378,7 +3369,6 @@ dependencies = [ "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" "checksum bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" @@ -3437,7 +3427,7 @@ dependencies = [ "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)" = "845aaacc16f01178f33349e7c992ecd0cee095aa5e577f0f4dee35971bd36455" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum email 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4" +"checksum email 0.0.21 (git+https://github.com/deltachat/rust-email)" = "" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" "checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" @@ -3508,8 +3498,8 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)" = "" -"checksum lettre_email 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/rustls)" = "" +"checksum lettre 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/mail)" = "" +"checksum lettre_email 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/mail)" = "" "checksum lexical-core 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2304bccb228c4b020f3a4835d247df0a02a7c4686098d4167762cfbbe4c5cb14" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" diff --git a/Cargo.toml b/Cargo.toml index 5d364b7f9..4b9febc27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,12 +17,12 @@ smallvec = "0.6.9" reqwest = { version = "0.9.15", default-features = false, features = ["rustls-tls"] } num-derive = "0.2.5" num-traits = "0.2.6" -lettre = { git = "https://github.com/deltachat/lettre", branch = "feat/rustls" } -lettre_email = { git = "https://github.com/deltachat/lettre", branch = "feat/rustls" } +lettre = { git = "https://github.com/deltachat/lettre", branch = "feat/mail" } +lettre_email = { git = "https://github.com/deltachat/lettre", branch = "feat/mail" } async-imap = { git = "https://github.com/async-email/async-imap", branch="master" } async-tls = "0.6" async-std = { version = "1.0", features = ["unstable"] } -base64 = "0.10" +base64 = "0.11" charset = "0.1" percent-encoding = "2.0" serde = { version = "1.0", features = ["derive"] } From 64fcd56998890feb2b59dc268a229cf65146ba3b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 18:49:15 +0100 Subject: [PATCH 12/20] fix mailparsing test --- src/e2ee.rs | 52 ++++++++++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/src/e2ee.rs b/src/e2ee.rs index 42bfc0102..aae9ec045 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -377,41 +377,29 @@ mod tests { } } - // FIXME: https://github.com/staktrace/mailparse/issues/49 - // #[test] - // fn test_mailmime_parse() { - // let plain = b"Chat-Disposition-Notification-To: hello@world.de - // Chat-Group-ID: CovhGgau8M- - // Chat-Group-Name: Delta Chat Dev - // Subject: =?utf-8?Q?Chat=3A?= Delta Chat =?utf-8?Q?Dev=3A?= sidenote for - // =?utf-8?Q?all=3A?= rust core master ... - // Content-Type: text/plain; charset=\"utf-8\"; protected-headers=\"v1\" - // Content-Transfer-Encoding: quoted-printable + #[test] + fn test_mailmime_parse() { + let plain = b"Chat-Disposition-Notification-To: hello@world.de +Chat-Group-ID: CovhGgau8M- +Chat-Group-Name: Delta Chat Dev +Subject: =?utf-8?Q?Chat=3A?= Delta Chat =?utf-8?Q?Dev=3A?= sidenote for + =?utf-8?Q?all=3A?= rust core master ... +Content-Type: text/plain; charset=\"utf-8\"; protected-headers=\"v1\" +Content-Transfer-Encoding: quoted-printable - // sidenote for all: things are trick atm recomm= - // end not to try to run with desktop or ios unless you are ready to hunt bugs +sidenote for all: things are trick atm recomm= +end not to try to run with desktop or ios unless you are ready to hunt bugs - // -- =20 - // Sent with my Delta Chat Messenger: https://delta.chat"; - // let mail = mailparse::parse_mail(plain).expect("failed to parse valid message"); +-- =20 +Sent with my Delta Chat Messenger: https://delta.chat"; + let mail = mailparse::parse_mail(plain).expect("failed to parse valid message"); - // println!( - // "{:?}", - // mail.headers - // .iter() - // .map(|h| (h.get_key(), h.get_value())) - // .collect::>() - // ); - // assert_eq!(mail.headers.len(), 6); - // assert_eq!( - // mail.get_body().unwrap(), - // " sidenote for all: things are trick atm recomm= - // end not to try to run with desktop or ios unless you are ready to hunt bugs - - // -- =20 - // Sent with my Delta Chat Messenger: https://delta.chat" - // ); - // } + assert_eq!(mail.headers.len(), 6); + assert!( + mail.get_body().unwrap().starts_with( + "sidenote for all: things are trick atm recommend not to try to run with desktop or ios unless you are ready to hunt bugs") + ); + } mod load_or_generate_self_public_key { use super::*; From 6bb2adaf459264460c45d57831407b1436d0efd9 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 19:09:04 +0100 Subject: [PATCH 13/20] some fixes for mdn handling --- src/mimeparser.rs | 50 +++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 97ee40e5c..a6692a859 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -305,10 +305,12 @@ impl<'a> MimeParser<'a> { if let Some(dn_to_addr) = addrs.first() { if let Some(from_field) = self.lookup_field("From") { - let value = from_field; - let from_addrs = mailparse::addrparse(&value).unwrap(); + info!(self.context, "From {:?}", from_field); + let from_addrs = mailparse::addrparse(&from_field).unwrap(); + if let Some(from_addr) = from_addrs.first() { - if from_addr == dn_to_addr { + info!(self.context, "comparing {:?} - {:?}", from_addr, dn_to_addr); + if compare_addrs(from_addr, dn_to_addr) { if let Some(part_4) = self.get_last_nonmeta_mut() { part_4.param.set_int(Param::WantsMdn, 1); } @@ -484,8 +486,8 @@ impl<'a> MimeParser<'a> { (DC_MIMETYPE_MP_REPORT, _) => { /* RFC 6522: the first part is for humans, the second for machines */ if mail.subparts.len() >= 2 { - let ct = mail.get_content_disposition()?; - if let Some(report_type) = ct.params.get("report-type") { + info!(self.context, "report: {:?}", &mail.ctype); + if let Some(report_type) = mail.ctype.params.get("report-type") { if report_type == "disposition-notification" { if let Some(report) = self.process_report(mail)? { self.reports.push(report); @@ -790,31 +792,15 @@ impl<'a> MimeParser<'a> { } fn process_report(&self, report: &mailparse::ParsedMail<'_>) -> Result> { - let ct = report.get_content_disposition()?; - let report_type = ct.params.get("report-type"); - if report_type.is_none() { - return Ok(None); - } - let report_type = report_type.unwrap(); - if report_type != "disposition-notification" || report.subparts.len() < 2 { - // the first part is for humans, the second for machines - return Ok(None); - } - // to get a clear functionality, do not show incoming MDNs if the options is disabled if !self.mdns_enabled { return Ok(None); } - // 1. get content - let raw = report.subparts[1].get_body_raw()?; - let report_details = mailparse::parse_mail(&raw)?; - // 2. parse as mailheaders - let report_body = report_details.get_body_raw()?; + // parse as mailheaders + let report_body = report.subparts[1].get_body_raw()?; let (report_fields, _) = mailparse::parse_headers(&report_body)?; - // 3. retrieve information - // must be present if let Some(_disposition) = report_fields.get_first_value("Disposition").ok().flatten() { if let Some(original_message_id) = report_fields @@ -1059,6 +1045,24 @@ fn get_recipients<'a, S: AsRef, T: Iterator>(headers: T) -> recipients } +/// Check if the only addrs match, ignoring names. +fn compare_addrs(a: &mailparse::MailAddr, b: &mailparse::MailAddr) -> bool { + match a { + mailparse::MailAddr::Group(group_a) => match b { + mailparse::MailAddr::Group(group_b) => group_a + .addrs + .iter() + .zip(group_b.addrs.iter()) + .all(|(a, b)| a.addr == b.addr), + _ => false, + }, + mailparse::MailAddr::Single(single_a) => match b { + mailparse::MailAddr::Single(single_b) => single_a.addr == single_b.addr, + _ => false, + }, + } +} + #[cfg(test)] mod tests { use super::*; From d5287256e0fc3eb8b0e2b03f0da82461db2db8b4 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 1 Dec 2019 21:32:15 +0100 Subject: [PATCH 14/20] fix various parsing and sending issues --- src/aheader.rs | 20 ++++- src/e2ee.rs | 66 +++++++------- src/message.rs | 9 +- src/mimefactory.rs | 179 +++++++++++++++++++------------------- src/mimeparser.rs | 212 ++++++++++++++++++++++++++------------------- src/wrapmime.rs | 11 ++- 6 files changed, 270 insertions(+), 227 deletions(-) diff --git a/src/aheader.rs b/src/aheader.rs index b608932e3..06ec17b88 100644 --- a/src/aheader.rs +++ b/src/aheader.rs @@ -8,6 +8,7 @@ use std::{fmt, str}; use crate::constants::*; use crate::contact::*; +use crate::context::Context; use crate::key::*; /// Possible values for encryption preference @@ -65,16 +66,27 @@ impl Aheader { } } - pub fn from_imffields( + pub fn from_headers( + context: &Context, wanted_from: &str, headers: &[mailparse::MailHeader<'_>], ) -> Option { use mailparse::MailHeaderMap; if let Ok(Some(value)) = headers.get_first_value("Autocrypt") { - if let Ok(test) = Self::from_str(&value) { - if addr_cmp(&test.addr, wanted_from) { - return Some(test); + match Self::from_str(&value) { + Ok(header) => { + info!(context, "comparing {} - {}", header.addr, wanted_from); + if addr_cmp(&header.addr, wanted_from) { + info!(context, "found header {:?}", header); + return Some(header); + } + } + Err(err) => { + warn!( + context, + "found invalid autocrypt header {}: {:?}", value, err + ); } } } diff --git a/src/e2ee.rs b/src/e2ee.rs index aae9ec045..7442e7867 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -88,47 +88,29 @@ impl EncryptHelper { &mut self, context: &Context, min_verified: PeerstateVerifiedStatus, - do_gossip: bool, - mut mail_to_encrypt: lettre_email::PartBuilder, + mail_to_encrypt: lettre_email::PartBuilder, peerstates: &[(Option, &str)], ) -> Result { let mut keyring = Keyring::default(); - let mut gossip_headers: Vec = Vec::with_capacity(peerstates.len()); for (peerstate, addr) in peerstates .iter() .filter_map(|(state, addr)| state.as_ref().map(|s| (s, addr))) { - if let Some(key) = peerstate.peek_key(min_verified) { - keyring.add_owned(key.clone()); - if do_gossip { - if let Some(header) = peerstate.render_gossip_header(min_verified) { - gossip_headers.push(header.to_string()); - } - } - } else { - bail!("proper enc-key for {} missing, cannot encrypt", addr); - } + info!(context, "adding for {}: {:?}", addr, peerstate); + let key = peerstate.peek_key(min_verified).ok_or_else(|| { + format_err!("proper enc-key for {} missing, cannot encrypt", addr) + })?; + keyring.add_ref(key); } - // libEtPan's pgp_encrypt_mime() takes the parent as the new root. - // We just expect the root as being given to this function. - let sign_key = { - keyring.add_ref(&self.public_key); - let key = Key::from_self_private(context, self.addr.clone(), &context.sql); - ensure!(key.is_some(), "no own private key found"); - - key - }; - - // Add gossip headers - for header in &gossip_headers { - mail_to_encrypt = mail_to_encrypt.header(("Autocrypt-Gossip", header)); - } + keyring.add_ref(&self.public_key); + let sign_key = Key::from_self_private(context, self.addr.clone(), &context.sql) + .ok_or_else(|| format_err!("missing own private key"))?; let raw_message = mail_to_encrypt.build().as_string().into_bytes(); - let ctext = pgp::pk_encrypt(&raw_message, &keyring, sign_key.as_ref())?; + let ctext = pgp::pk_encrypt(&raw_message, &keyring, Some(&sign_key))?; Ok(ctext) } @@ -137,18 +119,25 @@ impl EncryptHelper { pub fn try_decrypt( context: &Context, mail: &mailparse::ParsedMail<'_>, -) -> Result<(Option>, HashSet, i64)> { + message_time: i64, +) -> Result<(Option>, HashSet)> { use mailparse::MailHeaderMap; + info!(context, "trying to decrypt: {:?}", mail.get_body()); + for part in &mail.subparts { + info!(context, "trying to decrypt part: {:?}", part.get_body()); + } - let from = mail.headers.get_first_value("From")?.unwrap_or_default(); - let message_time = mail + let from = mail .headers - .get_first_value("Date")? - .and_then(|v| mailparse::dateparse(&v).ok()) + .get_first_value("From")? + .and_then(|from_addr| mailparse::addrparse(&from_addr).ok()) + .and_then(|from| from.extract_single_info()) + .map(|from| from.addr) .unwrap_or_default(); let mut peerstate = None; - let autocryptheader = Aheader::from_imffields(&from, &mail.headers); + let autocryptheader = Aheader::from_headers(context, &from, &mail.headers); + info!(context, "got autocryptheader {:?}", &autocryptheader); if message_time > 0 { peerstate = Peerstate::from_addr(context, &context.sql, &from); @@ -167,6 +156,7 @@ pub fn try_decrypt( peerstate = Some(p); } } + /* possibly perform decryption */ let mut private_keyring = Keyring::default(); let mut public_keyring_for_validate = Keyring::default(); @@ -200,7 +190,7 @@ pub fn try_decrypt( )?; } } - Ok((out_mail, signatures, message_time)) + Ok((out_mail, signatures)) } /// Load public key from database or generate a new one. @@ -265,8 +255,9 @@ fn decrypt_if_autocrypt_message<'a>( // Errors are returned for failures related to decryption of AC-messages. let encrypted_data_part = match wrapmime::get_autocrypt_mime(mail) { - Err(_) => { + Err(err) => { // not a proper autocrypt message, abort and ignore + warn!(context, "Invalid autocrypt message: {:?}", err); return Ok(None); } Ok(res) => res, @@ -283,12 +274,13 @@ fn decrypt_if_autocrypt_message<'a>( /// Returns Ok(None) if nothing encrypted was found. fn decrypt_part( - _context: &Context, + context: &Context, mail: &mailparse::ParsedMail<'_>, private_keyring: &Keyring, public_keyring_for_validate: &Keyring, ret_valid_signatures: &mut HashSet, ) -> Result>> { + info!(context, "decrypting part"); let data = mail.get_body_raw()?; if has_decrypted_pgp_armor(&data) { diff --git a/src/message.rs b/src/message.rs index b1175ad88..555c511b7 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1137,7 +1137,7 @@ pub fn mdn_from_ext( return None; } - if let Ok((msg_id, chat_id, chat_type, msg_state)) = context.sql.query_row( + let res = context.sql.query_row( concat!( "SELECT", " m.id AS msg_id,", @@ -1157,7 +1157,12 @@ pub fn mdn_from_ext( row.get::<_, MessageState>("state")?, )) }, - ) { + ); + if let Err(ref err) = res { + info!(context, "Failed to select MDN {:?}", err); + } + + if let Ok((msg_id, chat_id, chat_type, msg_state)) = res { let mut read_by_all = false; // if already marked as MDNS_RCVD msgstate_can_fail() returns false. diff --git a/src/mimefactory.rs b/src/mimefactory.rs index dd34d6294..8c79c26fc 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -1,5 +1,5 @@ use chrono::TimeZone; -use lettre_email::{Address, Header, MimeMessage, MimeMultipartType, PartBuilder}; +use lettre_email::{Address, Header, MimeMultipartType, PartBuilder}; use crate::chat::{self, Chat}; use crate::config::Config; @@ -229,11 +229,11 @@ impl<'a, 'b> MimeFactory<'a, 'b> { .collect()) } - fn is_e2ee_guranteed(&self) -> Result { + fn is_e2ee_guranteed(&self) -> bool { match self.loaded { Loaded::Message => { if self.chat.as_ref().unwrap().typ == Chattype::VerifiedGroup { - return Ok(true); + return true; } let force_plaintext = self @@ -243,78 +243,76 @@ impl<'a, 'b> MimeFactory<'a, 'b> { .unwrap_or_default(); if force_plaintext == 0 { - return Ok(self + return self .msg .param .get_int(Param::GuaranteeE2ee) .unwrap_or_default() - != 0); + != 0; } - Ok(false) + false } - Loaded::MDN => Ok(false), + Loaded::MDN => false, } } - fn min_verified(&self) -> Result { + fn min_verified(&self) -> PeerstateVerifiedStatus { match self.loaded { Loaded::Message => { let chat = self.chat.as_ref().unwrap(); if chat.typ == Chattype::VerifiedGroup { - Ok(PeerstateVerifiedStatus::BidirectVerified) + PeerstateVerifiedStatus::BidirectVerified } else { - Ok(PeerstateVerifiedStatus::Unverified) + PeerstateVerifiedStatus::Unverified } } - Loaded::MDN => Ok(PeerstateVerifiedStatus::Unverified), + Loaded::MDN => PeerstateVerifiedStatus::Unverified, } } - fn should_force_plaintext(&self) -> Result { + fn should_force_plaintext(&self) -> i32 { match self.loaded { Loaded::Message => { let chat = self.chat.as_ref().unwrap(); if chat.typ == Chattype::VerifiedGroup { - Ok(0) + 0 } else { - Ok(self - .msg + self.msg .param .get_int(Param::ForcePlaintext) - .unwrap_or_default()) + .unwrap_or_default() } } - Loaded::MDN => Ok(DC_FP_NO_AUTOCRYPT_HEADER), + Loaded::MDN => DC_FP_NO_AUTOCRYPT_HEADER, } } - fn should_do_gossip(&self) -> Result { + fn should_do_gossip(&self) -> bool { match self.loaded { Loaded::Message => { let chat = self.chat.as_ref().unwrap(); // beside key- and member-changes, force re-gossip every 48 hours if chat.gossiped_timestamp == 0 - || (chat.gossiped_timestamp + (2 * 24 * 60 * 60)) < time() + || (chat.gossiped_timestamp + (2 * 24 * 60 * 60)) > time() { - return Ok(true); + return true; } - let cmd = self.msg.param.get_cmd(); - match cmd { + match self.msg.param.get_cmd() { SystemMessage::MemberAddedToGroup => { - return Ok(true); + return true; } _ => {} } - Ok(false) + false } - Loaded::MDN => Ok(false), + Loaded::MDN => false, } } - fn grpimage(&self) -> Result, Error> { + fn grpimage(&self) -> Option { match self.loaded { Loaded::Message => { let chat = self.chat.as_ref().unwrap(); @@ -322,21 +320,21 @@ impl<'a, 'b> MimeFactory<'a, 'b> { match cmd { SystemMessage::MemberAddedToGroup => { - return Ok(chat.param.get(Param::ProfileImage).map(Into::into)); + return chat.param.get(Param::ProfileImage).map(Into::into); } SystemMessage::GroupImageChanged => { - return Ok(self.msg.param.get(Param::Arg).map(Into::into)) + return self.msg.param.get(Param::Arg).map(Into::into) } _ => {} } - Ok(None) + None } - Loaded::MDN => Ok(None), + Loaded::MDN => None, } } - fn subject_str(&self) -> Result { + fn subject_str(&self) -> String { match self.loaded { Loaded::Message => { match self.chat { @@ -354,32 +352,27 @@ impl<'a, 'b> MimeFactory<'a, 'b> { if self.msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage { // do not add the "Chat:" prefix for setup messages - Ok(self - .context + self.context .stock_str(StockMessage::AcSetupMsgSubject) - .into_owned()) + .into_owned() } else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { - Ok(format!("Chat: {}: {}{}", chat.name, fwd, raw_subject,)) + format!("Chat: {}: {}{}", chat.name, fwd, raw_subject) } else { - Ok(format!("Chat: {}{}", fwd, raw_subject)) + format!("Chat: {}{}", fwd, raw_subject) } } - None => Ok(String::default()), + None => String::new(), } } Loaded::MDN => { let e = self.context.stock_str(StockMessage::ReadRcpt); - Ok(format!("Chat: {}", e).to_string()) + format!("Chat: {}", e) } } } pub fn render(mut self) -> Result { - let e2ee_guranteed = self.is_e2ee_guranteed()?; - - let mut encrypt_helper = EncryptHelper::new(self.context)?; - // Headers that are encrypted // - Chat-*, except Chat-Version // - Secure-Join* @@ -450,13 +443,13 @@ impl<'a, 'b> MimeFactory<'a, 'b> { )); } - // 1=add Autocrypt-header (needed eg. for handshaking), 2=no Autocrypte-header (used for MDN) - - let min_verified = self.min_verified()?; - let do_gossip = self.should_do_gossip()?; - let grpimage = self.grpimage()?; - let force_plaintext = self.should_force_plaintext()?; - let subject_str = self.subject_str()?; + let min_verified = self.min_verified(); + let do_gossip = self.should_do_gossip(); + let grpimage = self.grpimage(); + let force_plaintext = self.should_force_plaintext(); + let subject_str = self.subject_str(); + let e2ee_guranteed = self.is_e2ee_guranteed(); + let mut encrypt_helper = EncryptHelper::new(self.context)?; let subject = dc_encode_header_words(subject_str); @@ -480,13 +473,34 @@ impl<'a, 'b> MimeFactory<'a, 'b> { encrypt_helper.should_encrypt(self.context, e2ee_guranteed, &peerstates)?; let is_encrypted = should_encrypt && force_plaintext == 0; - let mut outer_message = if is_encrypted { + // Add gossip headers + info!(self.context, "gossip: {:?}", do_gossip); + if do_gossip { + info!(self.context, "Gossip headers: {:?}", &peerstates); + for peerstate in peerstates.iter().filter_map(|(state, _)| state.as_ref()) { + if peerstate.peek_key(min_verified).is_some() { + if let Some(header) = peerstate.render_gossip_header(min_verified) { + protected_headers.push(Header::new("Autocrypt-Gossip".into(), header)); + } + } + } + } + + let rfc724_mid = match self.loaded { + Loaded::Message => self.msg.rfc724_mid.clone(), + Loaded::MDN => dc_create_outgoing_rfc724_mid(None, &self.from_addr), + }; + + protected_headers.push(Header::new("Message-ID".into(), rfc724_mid.clone())); + + unprotected_headers.push(Header::new_with_value("To".into(), to).unwrap()); + unprotected_headers.push(Header::new_with_value("From".into(), vec![from]).unwrap()); + + let outer_message = if is_encrypted { for header in protected_headers.into_iter() { message = message.header(header); } - // Manual Content-Type only works with https://github.com/niax/rust-email/pull/51 - // At the moment the boundary will not be inserted. let mut outer_message = PartBuilder::new().header(( "Content-Type".to_string(), "multipart/encrypted; protocol=\"application/pgp-encrypted\"".to_string(), @@ -496,13 +510,8 @@ impl<'a, 'b> MimeFactory<'a, 'b> { outer_message = outer_message.header(header); } - let encrypted = encrypt_helper.encrypt( - self.context, - min_verified, - do_gossip, - message, - &peerstates, - )?; + let encrypted = + encrypt_helper.encrypt(self.context, min_verified, message, &peerstates)?; outer_message = outer_message .child( @@ -540,10 +549,6 @@ impl<'a, 'b> MimeFactory<'a, 'b> { message }; - outer_message = outer_message - .header(Header::new_with_value("To".into(), to).unwrap()) - .header(Header::new_with_value("From".into(), vec![from]).unwrap()); - let is_gossiped = is_encrypted && do_gossip && !peerstates.is_empty(); let MimeFactory { @@ -555,11 +560,6 @@ impl<'a, 'b> MimeFactory<'a, 'b> { .. } = self; - let rfc724_mid = match loaded { - Loaded::Message => msg.rfc724_mid.clone(), - Loaded::MDN => dc_create_outgoing_rfc724_mid(None, &from_addr), - }; - Ok(RenderedEmail { message: outer_message.build().as_string().into_bytes(), // envelope: Envelope::new, @@ -766,10 +766,9 @@ impl<'a, 'b> MimeFactory<'a, 'b> { ); // Message is sent as text/plain, with charset = utf-8 - let mut message = lettre_email::PartBuilder::new() + let mut parts = vec![PartBuilder::new() .content_type(&mime::TEXT_PLAIN_UTF_8) - .body(message_text); - let mut is_multipart = false; + .body(message_text)]; // add attachment part if chat::msgtype_has_file(self.msg.type_0) { @@ -780,14 +779,12 @@ impl<'a, 'b> MimeFactory<'a, 'b> { ); } else { let (file_part, _) = build_body_file(context, &self.msg, "")?; - message = message.child(file_part); - is_multipart = true; + parts.push(file_part); } } if let Some(meta_part) = meta_part { - message = message.child(meta_part); - is_multipart = true; + parts.push(meta_part); } if self.msg.param.exists(Param::SetLatitude) { @@ -797,8 +794,8 @@ impl<'a, 'b> MimeFactory<'a, 'b> { param.get_float(Param::SetLatitude).unwrap_or_default(), param.get_float(Param::SetLongitude).unwrap_or_default(), ); - message = message.child( - lettre_email::PartBuilder::new() + parts.push( + PartBuilder::new() .content_type( &"application/vnd.google-earth.kml+xml" .parse::() @@ -808,17 +805,15 @@ impl<'a, 'b> MimeFactory<'a, 'b> { "Content-Disposition", "attachment; filename=\"message.kml\"", )) - .body(kml_file) - .build(), + .body(kml_file), ); - is_multipart = true; } if location::is_sending_locations_to_chat(context, self.msg.chat_id) { match location::get_kml(context, self.msg.chat_id) { Ok((kml_content, last_added_location_id)) => { - message = message.child( - lettre_email::PartBuilder::new() + parts.push( + PartBuilder::new() .content_type( &"application/vnd.google-earth.kml+xml" .parse::() @@ -828,10 +823,8 @@ impl<'a, 'b> MimeFactory<'a, 'b> { "Content-Disposition", "attachment; filename=\"message.kml\"", )) - .body(kml_content) - .build(), + .body(kml_content), ); - is_multipart = true; if !self.msg.param.exists(Param::SetLatitude) { // otherwise, the independent location is already filed self.last_added_location_id = last_added_location_id; @@ -843,8 +836,15 @@ impl<'a, 'b> MimeFactory<'a, 'b> { } } - if is_multipart { - message = message.message_type(MimeMultipartType::Mixed); + // Single part, render as regular message. + if parts.len() == 1 { + return Ok(parts.pop().unwrap()); + } + + // Multiple parts, render as multipart. + let mut message = PartBuilder::new().message_type(MimeMultipartType::Mixed); + for part in parts.into_iter() { + message = message.child(part.build()); } Ok(message) @@ -920,7 +920,7 @@ fn build_body_file( context: &Context, msg: &Message, base_name: &str, -) -> Result<(MimeMessage, String), Error> { +) -> Result<(PartBuilder, String), Error> { let blob = msg .param .get_blob(Param::File, context, true)? @@ -984,8 +984,7 @@ fn build_body_file( .content_type(&mimetype) .header(("Content-Disposition", cd_value)) .header(("Content-Transfer-Encoding", "base64")) - .body(encoded_body) - .build(); + .body(encoded_body); Ok((mail, filename_to_send)) } diff --git a/src/mimeparser.rs b/src/mimeparser.rs index a6692a859..f0a90cfbe 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -38,8 +38,8 @@ pub struct MimeParser<'a> { pub location_kml: Option, pub message_kml: Option, reports: Vec, - parsed_header_protected: bool, mdns_enabled: bool, + parsed_protected_headers: bool, } #[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql)] @@ -62,20 +62,30 @@ impl Default for SystemMessage { } } -const DC_MIMETYPE_MP_ALTERNATIVE: i32 = 10; -const DC_MIMETYPE_MP_RELATED: i32 = 20; -const DC_MIMETYPE_MP_MIXED: i32 = 30; -const DC_MIMETYPE_MP_NOT_DECRYPTABLE: i32 = 40; -const DC_MIMETYPE_MP_REPORT: i32 = 45; -const DC_MIMETYPE_MP_SIGNED: i32 = 46; -const DC_MIMETYPE_MP_OTHER: i32 = 50; -const DC_MIMETYPE_TEXT_PLAIN: i32 = 60; -const DC_MIMETYPE_TEXT_HTML: i32 = 70; -const DC_MIMETYPE_IMAGE: i32 = 80; -const DC_MIMETYPE_AUDIO: i32 = 90; -const DC_MIMETYPE_VIDEO: i32 = 100; -const DC_MIMETYPE_FILE: i32 = 110; -const DC_MIMETYPE_AC_SETUP_FILE: i32 = 111; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DcMimeType { + Unknown, + MpAlternative, + MpRelated, + MpMixed, + MpNotDecryptable, + MpReport, + MpSigned, + MpOther, + TextPlain, + TextHtml, + Image, + Audio, + Video, + File, + AcSetupFile, +} + +impl Default for DcMimeType { + fn default() -> Self { + DcMimeType::Unknown + } +} impl<'a> MimeParser<'a> { pub fn from_bytes(context: &'a Context, body: &[u8]) -> Result { @@ -85,7 +95,6 @@ impl<'a> MimeParser<'a> { let mut parser = MimeParser { parts: Vec::new(), header: Default::default(), - parsed_header_protected: false, subject: None, is_send_by_messenger: false, decrypting_failed: false, @@ -99,11 +108,22 @@ impl<'a> MimeParser<'a> { location_kml: None, message_kml: None, mdns_enabled, + parsed_protected_headers: false, }; + let message_time = mail + .headers + .get_first_value("Date")? + .and_then(|v| mailparse::dateparse(&v).ok()) + .unwrap_or_default(); + + parser.hash_header(&mail.headers); + + // Memory location for a possible decrypted message. let mail_raw; - let mail = match e2ee::try_decrypt(parser.context, &mail) { - Ok((raw, signatures, message_time)) => { + + let mail = match e2ee::try_decrypt(parser.context, &mail, message_time) { + Ok((raw, signatures)) => { // Valid autocrypt message, encrypted parser.encrypted = raw.is_some(); parser.signatures = signatures; @@ -111,16 +131,7 @@ impl<'a> MimeParser<'a> { if let Some(raw) = raw { mail_raw = raw; let decrypted_mail = mailparse::parse_mail(&mail_raw)?; - - // we have a decrypted mail, that is valid, check for gossip headers - - let gossip_headers = - decrypted_mail.headers.get_all_values("Autocrypt-Gossip")?; - if !gossip_headers.is_empty() { - parser.gossipped_addr = - update_gossip_peerstates(context, message_time, &mail, gossip_headers)?; - } - + // Decrypted the mail decrypted_mail } else { // Message was not encrypted @@ -140,7 +151,11 @@ impl<'a> MimeParser<'a> { } }; - parser.hash_header(&mail.headers); + // Handle gossip headers + let gossip_headers = mail.headers.get_all_values("Autocrypt-Gossip")?; + parser.gossipped_addr = + update_gossip_peerstates(context, message_time, &mail, gossip_headers)?; + parser.parse_mime_recursive(&mail)?; parser.parse_headers()?; @@ -160,7 +175,7 @@ impl<'a> MimeParser<'a> { let has_setup_file = self .parts .iter() - .any(|p| p.mimetype == DC_MIMETYPE_AC_SETUP_FILE); + .any(|p| p.mimetype == DcMimeType::AcSetupFile); if has_setup_file { self.is_system_message = SystemMessage::AutocryptSetupMessage; @@ -178,7 +193,7 @@ impl<'a> MimeParser<'a> { let mut i = 0; while i != self.parts.len() { - if self.parts[i].mimetype != 111 { + if self.parts[i].mimetype != DcMimeType::AcSetupFile { self.parts.remove(i); } else { i += 1; @@ -201,6 +216,9 @@ impl<'a> MimeParser<'a> { } } } + + info!(self.context, "checking message parts: {:?}", &self.parts); + if self.is_send_by_messenger && self.parts.len() == 2 { let need_drop = { let textpart = &self.parts[0]; @@ -302,6 +320,7 @@ impl<'a> MimeParser<'a> { if let Some(dn_field) = self.lookup_field("Chat-Disposition-Notification-To") { if self.get_last_nonmeta().is_some() { let addrs = mailparse::addrparse(&dn_field).unwrap(); + info!(self.context, "last non meta addrs: {:?}", &addrs); if let Some(dn_to_addr) = addrs.first() { if let Some(from_field) = self.lookup_field("From") { @@ -352,6 +371,7 @@ impl<'a> MimeParser<'a> { } fn parse_mime_recursive(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result { + info!(self.context, "parse mime_recursive {:?}", mail.ctype); if mail.ctype.params.get("protected-headers").is_some() { if mail.ctype.mimetype == "text/rfc822-headers" { info!( @@ -361,21 +381,12 @@ impl<'a> MimeParser<'a> { return Ok(false); } - if !self.parsed_header_protected { - // use the most outer protected header - this is typically - // created in sync with the normal, unprotected header - - self.parsed_header_protected = true; + if !self.parsed_protected_headers { self.hash_header(&mail.headers); - } else { - info!( - self.context, - "Protected headers found in MIME header: Will be ignored as we already found an outer one." - ); + self.parsed_protected_headers; } } - // multiple = multipart/ or message/ enum MimeS { Multiple, Single, @@ -422,9 +433,9 @@ impl<'a> MimeParser<'a> { as text/plain and text/html. If we find a multipart/mixed inside mutlipart/alternative, we use this (happens eg in apple mail: "plaintext" as an alternative to "html+PDF attachment") */ - (DC_MIMETYPE_MP_ALTERNATIVE, _) => { + (DcMimeType::MpAlternative, _) => { for cur_data in &mail.subparts { - if mailmime_get_mime_type(cur_data).0 == DC_MIMETYPE_MP_MIXED { + if mailmime_get_mime_type(cur_data).0 == DcMimeType::MpMixed { any_part_added = self.parse_mime_recursive(cur_data)?; break; } @@ -432,7 +443,7 @@ impl<'a> MimeParser<'a> { if !any_part_added { /* search for text/plain and add this */ for cur_data in &mail.subparts { - if mailmime_get_mime_type(cur_data).0 == DC_MIMETYPE_TEXT_PLAIN { + if mailmime_get_mime_type(cur_data).0 == DcMimeType::TextPlain { any_part_added = self.parse_mime_recursive(cur_data)?; break; } @@ -448,7 +459,7 @@ impl<'a> MimeParser<'a> { } } } - (DC_MIMETYPE_MP_RELATED, _) => { + (DcMimeType::MpRelated, _) => { /* add the "root part" - the other parts may be referenced which is not interesting for us (eg. embedded images) we assume he "root part" being the first one, which may not be always true ... @@ -457,7 +468,7 @@ impl<'a> MimeParser<'a> { any_part_added = self.parse_mime_recursive(first)?; } } - (DC_MIMETYPE_MP_NOT_DECRYPTABLE, _) => { + (DcMimeType::MpNotDecryptable, _) => { let mut part = Part::default(); part.typ = Viewtype::Text; let msg_body = self.context.stock_str(StockMessage::CantDecryptMsgBody); @@ -470,7 +481,7 @@ impl<'a> MimeParser<'a> { any_part_added = true; self.decrypting_failed = true; } - (DC_MIMETYPE_MP_SIGNED, _) => { + (DcMimeType::MpSigned, _) => { /* RFC 1847: "The multipart/signed content type contains exactly two body parts. The first body part is the body part over which the digital signature was created [...] @@ -483,12 +494,14 @@ impl<'a> MimeParser<'a> { any_part_added = self.parse_mime_recursive(first)?; } } - (DC_MIMETYPE_MP_REPORT, _) => { + (DcMimeType::MpReport, _) => { + info!(self.context, "got report {}", mail.subparts.len()); /* RFC 6522: the first part is for humans, the second for machines */ if mail.subparts.len() >= 2 { info!(self.context, "report: {:?}", &mail.ctype); if let Some(report_type) = mail.ctype.params.get("report-type") { if report_type == "disposition-notification" { + info!(self.context, "processing report"); if let Some(report) = self.process_report(mail)? { self.reports.push(report); } @@ -503,12 +516,12 @@ impl<'a> MimeParser<'a> { } } _ => { - /* eg. DC_MIMETYPE_MP_MIXED - add all parts (in fact, + /* eg. DcMimeType::MpMixed - add all parts (in fact, AddSinglePartIfKnown() later check if the parts are really supported) HACK: the following lines are a hack for clients who use multipart/mixed instead of multipart/alternative for combined text/html messages (eg. Stock Android "Mail" does so). - So, if we detect such a message below, we skip the HTML + So, if we detect such a message below, we skip the Html part. However, not sure, if there are useful situations to use plain+html in multipart/mixed - if so, we should disable the hack. */ let mut skip_part = -1; @@ -518,10 +531,10 @@ impl<'a> MimeParser<'a> { for (i, cur_data) in mail.subparts.iter().enumerate() { match mailmime_get_mime_type(cur_data) { - (DC_MIMETYPE_TEXT_PLAIN, _) => { + (DcMimeType::TextPlain, _) => { plain_cnt += 1; } - (DC_MIMETYPE_TEXT_HTML, _) => { + (DcMimeType::TextHtml, _) => { html_part = i as isize; html_cnt += 1; } @@ -531,7 +544,7 @@ impl<'a> MimeParser<'a> { if plain_cnt == 1 && html_cnt == 1 { warn!( self.context, - "HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted." + "HACK: multipart/mixed message found with Plain and HTML, we\'ll skip the HTML part as this seems to be unwanted." ); skip_part = html_part; } @@ -554,16 +567,16 @@ impl<'a> MimeParser<'a> { let (mime_type, msg_type) = mailmime_get_mime_type(mail); let raw_mime = mail.ctype.mimetype.to_lowercase(); - if !raw_mime.starts_with("text") { - // MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing - return Ok(false); - } + info!( + self.context, + "got mime type: {:?} ({})", mime_type, raw_mime + ); let old_part_count = self.parts.len(); // regard `Content-Transfer-Encoding:` match mime_type { - DC_MIMETYPE_TEXT_PLAIN | DC_MIMETYPE_TEXT_HTML => { + DcMimeType::TextPlain | DcMimeType::TextHtml => { let decoded_data = match mail.get_body() { Ok(decoded_data) => decoded_data, Err(err) => { @@ -580,7 +593,7 @@ impl<'a> MimeParser<'a> { let simplified_txt = if decoded_data.is_empty() { "".into() } else { - let is_html = mime_type == DC_MIMETYPE_TEXT_HTML; + let is_html = mime_type == DcMimeType::TextHtml; simplifier.simplify(&decoded_data, is_html, is_msgrmsg) }; @@ -597,11 +610,11 @@ impl<'a> MimeParser<'a> { self.is_forwarded = true; } } - DC_MIMETYPE_IMAGE - | DC_MIMETYPE_AUDIO - | DC_MIMETYPE_VIDEO - | DC_MIMETYPE_FILE - | DC_MIMETYPE_AC_SETUP_FILE => { + DcMimeType::Image + | DcMimeType::Audio + | DcMimeType::Video + | DcMimeType::File + | DcMimeType::AcSetupFile => { // try to get file name from // `Content-Disposition: ... filename*=...` // or `Content-Disposition: ... filename*0*=... filename*1*=... filename*2*=...` @@ -650,7 +663,7 @@ impl<'a> MimeParser<'a> { fn do_add_single_file_part( &mut self, msg_type: Viewtype, - mime_type: libc::c_int, + mime_type: DcMimeType, raw_mime: &String, decoded_data: &[u8], filename: &str, @@ -698,7 +711,7 @@ impl<'a> MimeParser<'a> { part.param.set(Param::File, blob.as_name()); part.param.set(Param::MimeType, raw_mime); - if mime_type == DC_MIMETYPE_IMAGE { + if mime_type == DcMimeType::Image { if let Ok((width, height)) = dc_get_filemeta(decoded_data) { part.param.set_int(Param::Width, width as i32); part.param.set_int(Param::Height, height as i32); @@ -809,6 +822,7 @@ impl<'a> MimeParser<'a> { .flatten() .and_then(|v| parse_message_id(&v)) { + info!(self.context, "got report {:?}", original_message_id); return Ok(Some(Report { original_message_id, })); @@ -827,6 +841,7 @@ impl<'a> MimeParser<'a> { server_folder: impl AsRef, server_uid: u32, ) { + info!(self.context, "processing reports {:?}", &self.reports); for report in &self.reports { let mut mdn_consumed = false; @@ -836,6 +851,10 @@ impl<'a> MimeParser<'a> { &report.original_message_id, sent_timestamp, ) { + info!( + self.context, + "found message for report {}", report.original_message_id + ); rr_event_to_send.push((chat_id, msg_id)); mdn_consumed = true; } @@ -863,16 +882,29 @@ fn update_gossip_peerstates( let mut recipients: Option> = None; let mut gossipped_addr: HashSet = Default::default(); + info!( + context, + "Updating gossip peerstates: {:#?}", &gossip_headers + ); for value in &gossip_headers { let gossip_header = value.parse::(); + info!(context, "got gossip header: {:?}", gossip_header); if let Ok(ref header) = gossip_header { if recipients.is_none() { - recipients = Some(get_recipients(mail.headers.iter().map(|v| { - // TODO: error handling - (v.get_key().unwrap(), v.get_value().unwrap()) + recipients = Some(get_recipients(mail.headers.iter().filter_map(|v| { + let key = v.get_key(); + let value = v.get_value(); + if key.is_err() || value.is_err() { + return None; + } + Some((v.get_key().unwrap(), v.get_value().unwrap())) }))); } + + info!(context, "got recipients {:?}", recipients); + info!(context, "looking for addr {:?}", &header.addr); + if recipients.as_ref().unwrap().contains(&header.addr) { let mut peerstate = Peerstate::from_addr(context, &context.sql, &header.addr); if let Some(ref mut peerstate) = peerstate { @@ -929,15 +961,15 @@ fn is_known(key: &str) -> bool { pub struct Part { pub typ: Viewtype, pub is_meta: bool, - pub mimetype: i32, + pub mimetype: DcMimeType, pub msg: Option, pub msg_raw: Option, pub bytes: i32, pub param: Params, } -fn mailmime_get_mime_type(mail: &mailparse::ParsedMail<'_>) -> (libc::c_int, Viewtype) { - let unknown_type = (0, Viewtype::Unknown); +fn mailmime_get_mime_type(mail: &mailparse::ParsedMail<'_>) -> (DcMimeType, Viewtype) { + let unknown_type = (DcMimeType::Unknown, Viewtype::Unknown); let mimetype = mail.ctype.mimetype.to_lowercase(); let mut parts = mimetype.split('/'); @@ -948,41 +980,41 @@ fn mailmime_get_mime_type(mail: &mailparse::ParsedMail<'_>) -> (libc::c_int, Vie "text" => { if !mailmime_is_attachment_disposition(mail) { if subtype == "plain" { - return (DC_MIMETYPE_TEXT_PLAIN, Viewtype::Text); + return (DcMimeType::TextPlain, Viewtype::Text); } if subtype == "html" { - return (DC_MIMETYPE_TEXT_HTML, Viewtype::Text); + return (DcMimeType::TextHtml, Viewtype::Text); } } - (DC_MIMETYPE_FILE, Viewtype::File) + (DcMimeType::File, Viewtype::File) } "image" => { let msg_type = match subtype { "gif" => Viewtype::Gif, "svg+xml" => { - return (DC_MIMETYPE_FILE, Viewtype::File); + return (DcMimeType::File, Viewtype::File); } _ => Viewtype::Image, }; - (DC_MIMETYPE_IMAGE, msg_type) + (DcMimeType::Image, msg_type) } - "audio" => (DC_MIMETYPE_AUDIO, Viewtype::Audio), - "video" => (DC_MIMETYPE_VIDEO, Viewtype::Video), + "audio" => (DcMimeType::Audio, Viewtype::Audio), + "video" => (DcMimeType::Video, Viewtype::Video), "multipart" => { let mime_type = match subtype { - "alternative" => DC_MIMETYPE_MP_ALTERNATIVE, - "related" => DC_MIMETYPE_MP_RELATED, + "alternative" => DcMimeType::MpAlternative, + "related" => DcMimeType::MpRelated, "encrypted" => { // maybe try_decrypt failed to decrypt // or it wasn't in proper Autocrypt format - DC_MIMETYPE_MP_NOT_DECRYPTABLE + DcMimeType::MpNotDecryptable } - "signed" => DC_MIMETYPE_MP_SIGNED, - "mixed" => DC_MIMETYPE_MP_MIXED, - "report" => DC_MIMETYPE_MP_REPORT, - _ => DC_MIMETYPE_MP_OTHER, + "signed" => DcMimeType::MpSigned, + "mixed" => DcMimeType::MpMixed, + "report" => DcMimeType::MpReport, + _ => DcMimeType::MpOther, }; (mime_type, Viewtype::Unknown) @@ -993,16 +1025,16 @@ fn mailmime_get_mime_type(mail: &mailparse::ParsedMail<'_>) -> (libc::c_int, Vie // be handled separatedly. // I've not seen any messages using this, so we do not attach these parts (maybe they're used to attach replies, // which are unwanted at all). - // For now, we skip these parts at all; if desired, we could return DC_MIMETYPE_FILE/DC_MSG_FILE + // For now, we skip these parts at all; if desired, we could return DcMimeType::File/DC_MSG_File // for selected and known subparts. unknown_type } "application" => { if subtype == "autocrypt-setup" { - return (DC_MIMETYPE_AC_SETUP_FILE, Viewtype::File); + return (DcMimeType::AcSetupFile, Viewtype::File); } - (DC_MIMETYPE_FILE, Viewtype::File) + (DcMimeType::File, Viewtype::File) } _ => unknown_type, } diff --git a/src/wrapmime.rs b/src/wrapmime.rs index 4f4b6562d..6021d5eee 100644 --- a/src/wrapmime.rs +++ b/src/wrapmime.rs @@ -18,7 +18,8 @@ pub fn parse_message_id(message_id: &[u8]) -> Result { pub fn get_autocrypt_mime<'a, 'b>(mail: &'a ParsedMail<'b>) -> Result<&'a ParsedMail<'b>, Error> { ensure!( mail.ctype.mimetype == "multipart/encrypted", - "Not a multipart/encrypted message" + "Not a multipart/encrypted message: {}", + mail.ctype.mimetype ); ensure!( mail.subparts.len() == 2, @@ -27,12 +28,14 @@ pub fn get_autocrypt_mime<'a, 'b>(mail: &'a ParsedMail<'b>) -> Result<&'a Parsed ensure!( mail.subparts[0].ctype.mimetype == "application/pgp-encrypted", - "Invalid Autocrypt Level 1 version part" + "Invalid Autocrypt Level 1 version part: {:?}", + mail.subparts[0].ctype, ); ensure!( - mail.subparts[1].ctype.mimetype == "application/octetstream", - "Invalid Autocrypt Level 1 encrypted part" + mail.subparts[1].ctype.mimetype == "application/octet-stream", + "Invalid Autocrypt Level 1 encrypted part: {:?}", + mail.subparts[1].ctype ); Ok(&mail.subparts[1]) From e9858877397d21919db0bc94480f6f10ff33c5e3 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 2 Dec 2019 00:01:37 +0100 Subject: [PATCH 15/20] fix content-type setting and some encryption --- Cargo.lock | 39 +++++++++++++++++++-------------------- Cargo.toml | 1 - src/aheader.rs | 1 - src/dc_receive_imf.rs | 2 +- src/e2ee.rs | 8 ++------ src/error.rs | 1 + src/mimefactory.rs | 24 ++++++++++++++++++++---- src/mimeparser.rs | 32 ++++++++++++++++++++++++++++---- 8 files changed, 71 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b098a71e..7422c1348 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,7 +84,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -549,7 +549,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -631,7 +631,6 @@ dependencies = [ "lettre_email 0.9.2 (git+https://github.com/deltachat/lettre?branch=feat/mail)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "mailparse 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -785,7 +784,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "email" version = "0.0.21" -source = "git+https://github.com/deltachat/rust-email#5fb7dac53e7e0014a8c5715017be3360aa83646c" +source = "git+https://github.com/deltachat/rust-email#265a54a8c31355c506610c032c81112dc0953afb" dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -911,7 +910,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1052,7 +1051,7 @@ dependencies = [ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1398,7 +1397,7 @@ dependencies = [ [[package]] name = "lettre" version = "0.9.2" -source = "git+https://github.com/deltachat/lettre?branch=feat/mail#0f393a3d1d3860183c5df97b4429d0919199344a" +source = "git+https://github.com/deltachat/lettre?branch=feat/mail#db7fe5fc06d4abb4c1cd70534310d1e0b1e79d57" dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1417,7 +1416,7 @@ dependencies = [ [[package]] name = "lettre_email" version = "0.9.2" -source = "git+https://github.com/deltachat/lettre?branch=feat/mail#0f393a3d1d3860183c5df97b4429d0919199344a" +source = "git+https://github.com/deltachat/lettre?branch=feat/mail#db7fe5fc06d4abb4c1cd70534310d1e0b1e79d57" dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "email 0.0.21 (git+https://github.com/deltachat/rust-email)", @@ -1862,7 +1861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1913,7 +1912,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2248,7 +2247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2491,7 +2490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2655,7 +2654,7 @@ dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2695,7 +2694,7 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2718,7 +2717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3139,7 +3138,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3159,7 +3158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3179,7 +3178,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3341,7 +3340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3637,7 +3636,7 @@ dependencies = [ "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f89693ae015201f8de93fd96bde2d065f8bfc3f97ce006d5bc9f900b97c0c7c0" +"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" diff --git a/Cargo.toml b/Cargo.toml index 4b9febc27..9e12520ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,6 @@ rustls = "0.16.0" webpki-roots = "0.18.0" webpki = "0.21.0" mailparse = "0.10.1" -mime = "0.3.14" [dev-dependencies] tempfile = "3.0" diff --git a/src/aheader.rs b/src/aheader.rs index 06ec17b88..22b03102f 100644 --- a/src/aheader.rs +++ b/src/aheader.rs @@ -78,7 +78,6 @@ impl Aheader { Ok(header) => { info!(context, "comparing {} - {}", header.addr, wanted_from); if addr_cmp(&header.addr, wanted_from) { - info!(context, "found header {:?}", header); return Some(header); } } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index bf96b159f..1a6b47c74 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -372,7 +372,7 @@ fn add_parts( // handshake messages must be processed _before_ chats are created // (eg. contacs may be marked as verified) - if let Some(_) = mime_parser.lookup_field("Secure-Join") { + if mime_parser.lookup_field("Secure-Join").is_some() { // avoid discarding by show_emails setting msgrmsg = 1; *chat_id = 0; diff --git a/src/e2ee.rs b/src/e2ee.rs index 7442e7867..e207fa1c3 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; +use mailparse::MailHeaderMap; use num_traits::FromPrimitive; use crate::aheader::*; @@ -121,11 +122,7 @@ pub fn try_decrypt( mail: &mailparse::ParsedMail<'_>, message_time: i64, ) -> Result<(Option>, HashSet)> { - use mailparse::MailHeaderMap; - info!(context, "trying to decrypt: {:?}", mail.get_body()); - for part in &mail.subparts { - info!(context, "trying to decrypt part: {:?}", part.get_body()); - } + info!(context, "trying to decrypt"); let from = mail .headers @@ -137,7 +134,6 @@ pub fn try_decrypt( let mut peerstate = None; let autocryptheader = Aheader::from_headers(context, &from, &mail.headers); - info!(context, "got autocryptheader {:?}", &autocryptheader); if message_time > 0 { peerstate = Peerstate::from_addr(context, &context.sql, &from); diff --git a/src/error.rs b/src/error.rs index 816ba186e..25351bf71 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,5 @@ use failure::Fail; +use lettre_email::mime; #[derive(Debug, Fail)] pub enum Error { diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 8c79c26fc..62b732866 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -1,5 +1,5 @@ use chrono::TimeZone; -use lettre_email::{Address, Header, MimeMultipartType, PartBuilder}; +use lettre_email::{mime, Address, Header, MimeMultipartType, PartBuilder}; use crate::chat::{self, Chat}; use crate::config::Config; @@ -497,15 +497,31 @@ impl<'a, 'b> MimeFactory<'a, 'b> { unprotected_headers.push(Header::new_with_value("From".into(), vec![from]).unwrap()); let outer_message = if is_encrypted { + // Store protected headers in the inner message. for header in protected_headers.into_iter() { message = message.header(header); } + // Set the appropriate Content-Type for the inner message. + let mut existing_ct = message + .get_header("Content-Type".to_string()) + .and_then(|h| h.get_value::().ok()) + .unwrap_or_else(|| "text/plain; charset=utf-8;".to_string()); - let mut outer_message = PartBuilder::new().header(( + if !existing_ct.ends_with(';') { + existing_ct += ";"; + } + message = message.replace_header(Header::new( "Content-Type".to_string(), - "multipart/encrypted; protocol=\"application/pgp-encrypted\"".to_string(), + format!("{} protected-headers=\"v1\";", existing_ct), )); + // Set the appropriate Content-Type for the outer message + let mut outer_message = PartBuilder::new().header(( + "Content-Type".to_string(), + "multipart/encrypted; protocol=\"application/pgp-encrypted\";".to_string(), + )); + + // Store the unprotected headers on the outer message. for header in unprotected_headers.into_iter() { outer_message = outer_message.header(header); } @@ -531,7 +547,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> { .unwrap(), ) .header(("Content-Description", "OpenPGP encrypted message")) - .header(("Content-Disposition", "inline; filename=\"encrypted.asc\"")) + .header(("Content-Disposition", "inline; filename=\"encrypted.asc\";")) .body(encrypted) .build(), ) diff --git a/src/mimeparser.rs b/src/mimeparser.rs index f0a90cfbe..96d788977 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -130,7 +130,10 @@ impl<'a> MimeParser<'a> { if let Some(raw) = raw { mail_raw = raw; + info!(context, "decrypted: {:?}", std::str::from_utf8(&mail_raw)); + let decrypted_mail = mailparse::parse_mail(&mail_raw)?; + // Decrypted the mail decrypted_mail } else { @@ -151,12 +154,13 @@ impl<'a> MimeParser<'a> { } }; + parser.parse_mime_recursive(&mail)?; + // Handle gossip headers let gossip_headers = mail.headers.get_all_values("Autocrypt-Gossip")?; parser.gossipped_addr = update_gossip_peerstates(context, message_time, &mail, gossip_headers)?; - parser.parse_mime_recursive(&mail)?; parser.parse_headers()?; Ok(parser) @@ -372,7 +376,10 @@ impl<'a> MimeParser<'a> { fn parse_mime_recursive(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result { info!(self.context, "parse mime_recursive {:?}", mail.ctype); + if mail.ctype.params.get("protected-headers").is_some() { + info!(self.context, "found protected headers"); + if mail.ctype.mimetype == "text/rfc822-headers" { info!( self.context, @@ -381,9 +388,11 @@ impl<'a> MimeParser<'a> { return Ok(false); } - if !self.parsed_protected_headers { + if self.parsed_protected_headers { + warn!(self.context, "Ignoring nested protected headers"); + } else { self.hash_header(&mail.headers); - self.parsed_protected_headers; + self.parsed_protected_headers = true; } } @@ -884,7 +893,8 @@ fn update_gossip_peerstates( info!( context, - "Updating gossip peerstates: {:#?}", &gossip_headers + "Updating gossip peerstates: {}", + gossip_headers.len() ); for value in &gossip_headers { let gossip_header = value.parse::(); @@ -895,6 +905,7 @@ fn update_gossip_peerstates( recipients = Some(get_recipients(mail.headers.iter().filter_map(|v| { let key = v.get_key(); let value = v.get_value(); + info!(context, "header: {:?} - {:?}", key, value); if key.is_err() || value.is_err() { return None; } @@ -1143,6 +1154,19 @@ mod tests { assert_eq!(mimeparser.get_rfc724_mid(), None); } + #[test] + fn test_mailparse_content_type() { + let ctype = + mailparse::parse_content_type("text/plain; charset=utf-8; protected-headers=v1;"); + + assert_eq!(ctype.mimetype, "text/plain"); + assert_eq!(ctype.charset, "utf-8"); + assert_eq!( + ctype.params.get("protected-headers"), + Some(&"v1".to_string()) + ); + } + #[test] fn test_mimeparser_with_context() { let context = dummy_context(); From 1e7afa9da00a415e3611f2857ee2aae3587194a4 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 2 Dec 2019 00:11:11 +0100 Subject: [PATCH 16/20] fix chat-verified --- Cargo.lock | 4 ++-- src/dc_receive_imf.rs | 2 +- src/message.rs | 2 +- src/mimefactory.rs | 11 +++++++++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7422c1348..12ae271f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1397,7 +1397,7 @@ dependencies = [ [[package]] name = "lettre" version = "0.9.2" -source = "git+https://github.com/deltachat/lettre?branch=feat/mail#db7fe5fc06d4abb4c1cd70534310d1e0b1e79d57" +source = "git+https://github.com/deltachat/lettre?branch=feat/mail#00ba9db544059ddd60048f0b85d5052e4bf605da" dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1416,7 +1416,7 @@ dependencies = [ [[package]] name = "lettre_email" version = "0.9.2" -source = "git+https://github.com/deltachat/lettre?branch=feat/mail#db7fe5fc06d4abb4c1cd70534310d1e0b1e79d57" +source = "git+https://github.com/deltachat/lettre?branch=feat/mail#00ba9db544059ddd60048f0b85d5052e4bf605da" dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "email 0.0.21 (git+https://github.com/deltachat/rust-email)", diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 1a6b47c74..aeef39cbf 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -1272,7 +1272,7 @@ fn create_or_lookup_adhoc_group( context.call_cb(Event::ChatModified(chat_id)); cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked); - return Ok(()); + Ok(()) } fn create_group_record( diff --git a/src/message.rs b/src/message.rs index 555c511b7..f033aea16 100644 --- a/src/message.rs +++ b/src/message.rs @@ -458,7 +458,7 @@ impl Message { }; let contact = if self.from_id != DC_CONTACT_ID_SELF as libc::c_uint - && ((*chat).typ == Chattype::Group || (*chat).typ == Chattype::VerifiedGroup) + && (chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup) { Contact::get_by_id(context, self.from_id).ok() } else { diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 62b732866..dfc3e7143 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -474,9 +474,12 @@ impl<'a, 'b> MimeFactory<'a, 'b> { let is_encrypted = should_encrypt && force_plaintext == 0; // Add gossip headers - info!(self.context, "gossip: {:?}", do_gossip); if do_gossip { - info!(self.context, "Gossip headers: {:?}", &peerstates); + info!( + self.context, + "gossiping headers for {} peerstates", + peerstates.len() + ); for peerstate in peerstates.iter().filter_map(|(state, _)| state.as_ref()) { if peerstate.peek_key(min_verified).is_some() { if let Some(header) = peerstate.render_gossip_header(min_verified) { @@ -604,6 +607,10 @@ impl<'a, 'b> MimeFactory<'a, 'b> { let mut placeholdertext = None; let mut meta_part = None; + if chat.typ == Chattype::VerifiedGroup { + protected_headers.push(Header::new("Chat-Verified".to_string(), "1".to_string())); + } + if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup { protected_headers.push(Header::new("Chat-Group-ID".into(), chat.grpid.clone())); From 43074464ac3aaa1d8fce6bed0c96e1cc6bfe5d3b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 2 Dec 2019 08:44:51 +0100 Subject: [PATCH 17/20] cleanup mimeparser and use `mime` --- src/dc_receive_imf.rs | 25 +++-- src/mimeparser.rs | 246 ++++++++++++++++-------------------------- 2 files changed, 104 insertions(+), 167 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index aeef39cbf..b3d6fa2a6 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -613,17 +613,16 @@ fn add_parts( continue; } - if let Some(ref msg) = part.msg { - if mime_parser.location_kml.is_some() - && icnt == 1 - && (msg == "-location-" || msg.is_empty()) - { - *hidden = 1; - if state == MessageState::InFresh { - state = MessageState::InNoticed; - } + if mime_parser.location_kml.is_some() + && icnt == 1 + && (part.msg == "-location-" || part.msg.is_empty()) + { + *hidden = 1; + if state == MessageState::InFresh { + state = MessageState::InNoticed; } } + if part.typ == Viewtype::Text { let msg_raw = part.msg_raw.as_ref().cloned().unwrap_or_default(); let subject = mime_parser @@ -651,11 +650,11 @@ fn add_parts( part.typ, state, msgrmsg, - part.msg.as_ref().map_or("", String::as_str), + &part.msg, // txt_raw might contain invalid utf8 txt_raw.unwrap_or_default(), part.param.to_string(), - part.bytes, + part.bytes as isize, *hidden, if save_mime_headers { Some(String::from_utf8_lossy(imf_raw)) @@ -1512,9 +1511,9 @@ fn set_better_msg(mime_parser: &mut MimeParser, better_msg: impl AsRef) { if msg.len() > 0 && !mime_parser.parts.is_empty() { let part = &mut mime_parser.parts[0]; if part.typ == Viewtype::Text { - part.msg = Some(msg.to_string()); + part.msg = msg.to_string(); } - }; + } } fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimeParser) -> libc::c_int { diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 96d788977..8c05cb4a5 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -1,6 +1,7 @@ use std::collections::{HashMap, HashSet}; use deltachat_derive::{FromSql, ToSql}; +use lettre_email::mime::{self, Mime}; use mailparse::MailHeaderMap; use crate::aheader::Aheader; @@ -62,30 +63,7 @@ impl Default for SystemMessage { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum DcMimeType { - Unknown, - MpAlternative, - MpRelated, - MpMixed, - MpNotDecryptable, - MpReport, - MpSigned, - MpOther, - TextPlain, - TextHtml, - Image, - Audio, - Video, - File, - AcSetupFile, -} - -impl Default for DcMimeType { - fn default() -> Self { - DcMimeType::Unknown - } -} +const MIME_AC_SETUP_FILE: &str = "application/autocrypt-setup"; impl<'a> MimeParser<'a> { pub fn from_bytes(context: &'a Context, body: &[u8]) -> Result { @@ -176,10 +154,9 @@ impl<'a> MimeParser<'a> { } if let Some(_) = self.lookup_field("Autocrypt-Setup-Message") { - let has_setup_file = self - .parts - .iter() - .any(|p| p.mimetype == DcMimeType::AcSetupFile); + let has_setup_file = self.parts.iter().any(|p| { + p.mimetype.is_some() && p.mimetype.as_ref().unwrap().as_ref() == MIME_AC_SETUP_FILE + }); if has_setup_file { self.is_system_message = SystemMessage::AutocryptSetupMessage; @@ -197,7 +174,10 @@ impl<'a> MimeParser<'a> { let mut i = 0; while i != self.parts.len() { - if self.parts[i].mimetype != DcMimeType::AcSetupFile { + let mimetype = &self.parts[i].mimetype; + if mimetype.is_none() + || mimetype.as_ref().unwrap().as_ref() != MIME_AC_SETUP_FILE + { self.parts.remove(i); } else { i += 1; @@ -242,10 +222,10 @@ impl<'a> MimeParser<'a> { let mut filepart = self.parts.swap_remove(1); // insert new one - filepart.msg = self.parts[0].msg.as_ref().map(|s| s.to_string()); + filepart.msg = self.parts[0].msg.clone(); // forget the one we use now - self.parts[0].msg = None; + self.parts[0].msg = "".to_string(); // swap new with old std::mem::replace(&mut self.parts[0], filepart); @@ -274,12 +254,7 @@ impl<'a> MimeParser<'a> { if !subj.is_empty() { for part in self.parts.iter_mut() { if part.typ == Viewtype::Text { - let new_txt = format!( - "{} – {}", - subj, - part.msg.as_ref().expect("missing msg part") - ); - part.msg = Some(new_txt); + part.msg = format!("{} – {}", subj, part.msg); break; } } @@ -345,18 +320,18 @@ impl<'a> MimeParser<'a> { } } - /* Cleanup - and try to create at least an empty part if there are no parts yet */ + // Cleanup - and try to create at least an empty part if there are no parts yet if self.get_last_nonmeta().is_none() && self.reports.is_empty() { - let mut part_5 = Part::default(); - part_5.typ = Viewtype::Text; - part_5.msg = Some("".into()); + let mut part = Part::default(); + part.typ = Viewtype::Text; if let Some(ref subject) = self.subject { if !self.is_send_by_messenger { - part_5.msg = Some(subject.to_string()) + part.msg = subject.to_string(); } } - self.parts.push(part_5); + + self.parts.push(part); } Ok(()) @@ -437,14 +412,15 @@ impl<'a> MimeParser<'a> { fn handle_multiple(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result { let mut any_part_added = false; - match mailmime_get_mime_type(mail) { + let mimetype = get_mime_type(mail)?.0; + match (mimetype.type_(), mimetype.subtype().as_str()) { /* Most times, mutlipart/alternative contains true alternatives as text/plain and text/html. If we find a multipart/mixed inside mutlipart/alternative, we use this (happens eg in apple mail: "plaintext" as an alternative to "html+PDF attachment") */ - (DcMimeType::MpAlternative, _) => { + (mime::MULTIPART, "alternative") => { for cur_data in &mail.subparts { - if mailmime_get_mime_type(cur_data).0 == DcMimeType::MpMixed { + if get_mime_type(cur_data)?.0 == "multipart/mixed" { any_part_added = self.parse_mime_recursive(cur_data)?; break; } @@ -452,7 +428,7 @@ impl<'a> MimeParser<'a> { if !any_part_added { /* search for text/plain and add this */ for cur_data in &mail.subparts { - if mailmime_get_mime_type(cur_data).0 == DcMimeType::TextPlain { + if get_mime_type(cur_data)?.0.type_() == mime::TEXT { any_part_added = self.parse_mime_recursive(cur_data)?; break; } @@ -468,7 +444,7 @@ impl<'a> MimeParser<'a> { } } } - (DcMimeType::MpRelated, _) => { + (mime::MULTIPART, "related") => { /* add the "root part" - the other parts may be referenced which is not interesting for us (eg. embedded images) we assume he "root part" being the first one, which may not be always true ... @@ -477,20 +453,21 @@ impl<'a> MimeParser<'a> { any_part_added = self.parse_mime_recursive(first)?; } } - (DcMimeType::MpNotDecryptable, _) => { + (mime::MULTIPART, "encrypted") => { + let msg_body = self.context.stock_str(StockMessage::CantDecryptMsgBody); + let txt = format!("[{}]", msg_body); + let mut part = Part::default(); part.typ = Viewtype::Text; - let msg_body = self.context.stock_str(StockMessage::CantDecryptMsgBody); - - let txt = format!("[{}]", msg_body); part.msg_raw = Some(txt.clone()); - part.msg = Some(txt); + part.msg = txt; self.parts.push(part); + any_part_added = true; self.decrypting_failed = true; } - (DcMimeType::MpSigned, _) => { + (mime::MULTIPART, "signed") => { /* RFC 1847: "The multipart/signed content type contains exactly two body parts. The first body part is the body part over which the digital signature was created [...] @@ -503,7 +480,7 @@ impl<'a> MimeParser<'a> { any_part_added = self.parse_mime_recursive(first)?; } } - (DcMimeType::MpReport, _) => { + (mime::MULTIPART, "report") => { info!(self.context, "got report {}", mail.subparts.len()); /* RFC 6522: the first part is for humans, the second for machines */ if mail.subparts.len() >= 2 { @@ -525,25 +502,25 @@ impl<'a> MimeParser<'a> { } } _ => { - /* eg. DcMimeType::MpMixed - add all parts (in fact, - AddSinglePartIfKnown() later check if the parts are really supported) - HACK: the following lines are a hack for clients who use - multipart/mixed instead of multipart/alternative for - combined text/html messages (eg. Stock Android "Mail" does so). - So, if we detect such a message below, we skip the Html - part. However, not sure, if there are useful situations to use - plain+html in multipart/mixed - if so, we should disable the hack. */ + // Add all parts (in fact, + // AddSinglePartIfKnown() later check if the parts are really supported) + // HACK: the following lines are a hack for clients who use + // multipart/mixed instead of multipart/alternative for + // combined text/html messages (eg. Stock Android "Mail" does so). + // So, if we detect such a message below, we skip the Html + // part. However, not sure, if there are useful situations to use + // plain+html in multipart/mixed - if so, we should disable the hack. let mut skip_part = -1; let mut html_part = -1; let mut plain_cnt = 0; let mut html_cnt = 0; for (i, cur_data) in mail.subparts.iter().enumerate() { - match mailmime_get_mime_type(cur_data) { - (DcMimeType::TextPlain, _) => { + match get_mime_type(cur_data)?.0.type_() { + mime::TEXT => { plain_cnt += 1; } - (DcMimeType::TextHtml, _) => { + mime::HTML => { html_part = i as isize; html_cnt += 1; } @@ -559,10 +536,8 @@ impl<'a> MimeParser<'a> { } for (i, cur_data) in mail.subparts.iter().enumerate() { - if i as isize != skip_part { - if self.parse_mime_recursive(cur_data)? { - any_part_added = true; - } + if i as isize != skip_part && self.parse_mime_recursive(cur_data)? { + any_part_added = true; } } } @@ -573,7 +548,7 @@ impl<'a> MimeParser<'a> { fn add_single_part_if_known(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result { // return true if a part was added - let (mime_type, msg_type) = mailmime_get_mime_type(mail); + let (mime_type, msg_type) = get_mime_type(mail)?; let raw_mime = mail.ctype.mimetype.to_lowercase(); info!( @@ -584,8 +559,8 @@ impl<'a> MimeParser<'a> { let old_part_count = self.parts.len(); // regard `Content-Transfer-Encoding:` - match mime_type { - DcMimeType::TextPlain | DcMimeType::TextHtml => { + match mime_type.type_() { + mime::TEXT | mime::HTML => { let decoded_data = match mail.get_body() { Ok(decoded_data) => decoded_data, Err(err) => { @@ -602,15 +577,15 @@ impl<'a> MimeParser<'a> { let simplified_txt = if decoded_data.is_empty() { "".into() } else { - let is_html = mime_type == DcMimeType::TextHtml; + let is_html = mime_type == mime::TEXT_HTML; simplifier.simplify(&decoded_data, is_html, is_msgrmsg) }; if !simplified_txt.is_empty() { let mut part = Part::default(); part.typ = Viewtype::Text; - part.mimetype = mime_type; - part.msg = Some(simplified_txt); + part.mimetype = Some(mime_type); + part.msg = simplified_txt; part.msg_raw = Some(decoded_data); self.do_add_single_part(part); } @@ -619,11 +594,7 @@ impl<'a> MimeParser<'a> { self.is_forwarded = true; } } - DcMimeType::Image - | DcMimeType::Audio - | DcMimeType::Video - | DcMimeType::File - | DcMimeType::AcSetupFile => { + mime::IMAGE | mime::AUDIO | mime::VIDEO | mime::APPLICATION => { // try to get file name from // `Content-Disposition: ... filename*=...` // or `Content-Disposition: ... filename*0*=... filename*1*=... filename*2*=...` @@ -672,7 +643,7 @@ impl<'a> MimeParser<'a> { fn do_add_single_file_part( &mut self, msg_type: Viewtype, - mime_type: DcMimeType, + mime_type: Mime, raw_mime: &String, decoded_data: &[u8], filename: &str, @@ -714,18 +685,19 @@ impl<'a> MimeParser<'a> { /* create and register Mime part referencing the new Blob object */ let mut part = Part::default(); - part.typ = msg_type; - part.mimetype = mime_type; - part.bytes = decoded_data.len() as libc::c_int; - part.param.set(Param::File, blob.as_name()); - part.param.set(Param::MimeType, raw_mime); - - if mime_type == DcMimeType::Image { + if mime_type.type_() == mime::IMAGE { if let Ok((width, height)) = dc_get_filemeta(decoded_data) { part.param.set_int(Param::Width, width as i32); part.param.set_int(Param::Height, height as i32); } } + + part.typ = msg_type; + part.mimetype = Some(mime_type); + part.bytes = decoded_data.len(); + part.param.set(Param::File, blob.as_name()); + part.param.set(Param::MimeType, raw_mime); + self.do_add_single_part(part); } @@ -783,7 +755,7 @@ impl<'a> MimeParser<'a> { let part = &mut self.parts[0]; part.typ = Viewtype::Text; - part.msg = Some(format!("[{}]", error_msg.as_ref())); + part.msg = format!("[{}]", error_msg.as_ref()); self.parts.truncate(1); assert_eq!(self.parts.len(), 1); @@ -968,69 +940,40 @@ fn is_known(key: &str) -> bool { } } -#[derive(Default, Debug, Clone)] +#[derive(Debug, Default, Clone)] pub struct Part { pub typ: Viewtype, pub is_meta: bool, - pub mimetype: DcMimeType, - pub msg: Option, + pub mimetype: Option, + pub msg: String, pub msg_raw: Option, - pub bytes: i32, + pub bytes: usize, pub param: Params, } -fn mailmime_get_mime_type(mail: &mailparse::ParsedMail<'_>) -> (DcMimeType, Viewtype) { - let unknown_type = (DcMimeType::Unknown, Viewtype::Unknown); +fn get_mime_type(mail: &mailparse::ParsedMail<'_>) -> Result<(Mime, Viewtype)> { + let mimetype = mail.ctype.mimetype.parse::()?; - let mimetype = mail.ctype.mimetype.to_lowercase(); - let mut parts = mimetype.split('/'); - let typ = parts.next().expect("invalid mimetype"); - let subtype = parts.next().unwrap_or_default(); - - match typ { - "text" => { + let viewtype = match mimetype.type_() { + mime::TEXT => { if !mailmime_is_attachment_disposition(mail) { - if subtype == "plain" { - return (DcMimeType::TextPlain, Viewtype::Text); - } - if subtype == "html" { - return (DcMimeType::TextHtml, Viewtype::Text); + match mimetype.subtype() { + mime::PLAIN | mime::HTML => Viewtype::Text, + _ => Viewtype::File, } + } else { + Viewtype::File } - - (DcMimeType::File, Viewtype::File) } - "image" => { - let msg_type = match subtype { - "gif" => Viewtype::Gif, - "svg+xml" => { - return (DcMimeType::File, Viewtype::File); - } - _ => Viewtype::Image, - }; - - (DcMimeType::Image, msg_type) - } - "audio" => (DcMimeType::Audio, Viewtype::Audio), - "video" => (DcMimeType::Video, Viewtype::Video), - "multipart" => { - let mime_type = match subtype { - "alternative" => DcMimeType::MpAlternative, - "related" => DcMimeType::MpRelated, - "encrypted" => { - // maybe try_decrypt failed to decrypt - // or it wasn't in proper Autocrypt format - DcMimeType::MpNotDecryptable - } - "signed" => DcMimeType::MpSigned, - "mixed" => DcMimeType::MpMixed, - "report" => DcMimeType::MpReport, - _ => DcMimeType::MpOther, - }; - - (mime_type, Viewtype::Unknown) - } - "message" => { + mime::IMAGE => match mimetype.subtype() { + mime::GIF => Viewtype::Gif, + mime::SVG => Viewtype::File, + _ => Viewtype::Image, + }, + mime::AUDIO => Viewtype::Audio, + mime::VIDEO => Viewtype::Video, + mime::MULTIPART => Viewtype::Unknown, + mime::MESSAGE => { // Enacapsulated messages, see https://www.w3.org/Protocols/rfc1341/7_3_Message.html // Also used as part "message/disposition-notification" of "multipart/report", which, however, will // be handled separatedly. @@ -1038,17 +981,13 @@ fn mailmime_get_mime_type(mail: &mailparse::ParsedMail<'_>) -> (DcMimeType, View // which are unwanted at all). // For now, we skip these parts at all; if desired, we could return DcMimeType::File/DC_MSG_File // for selected and known subparts. - unknown_type + Viewtype::Unknown } - "application" => { - if subtype == "autocrypt-setup" { - return (DcMimeType::AcSetupFile, Viewtype::File); - } + mime::APPLICATION => Viewtype::File, + _ => Viewtype::Unknown, + }; - (DcMimeType::File, Viewtype::File) - } - _ => unknown_type, - } + Ok((mimetype, viewtype)) } fn mailmime_is_attachment_disposition(mail: &mailparse::ParsedMail<'_>) -> bool { @@ -1127,10 +1066,9 @@ mod tests { #[test] fn test_dc_mailmime_parse_crash_fuzzy(data in "[!-~\t ]{2000,}") { let context = dummy_context(); - // parsing should error out for all these random strings - assert!( - MimeParser::from_bytes(&context.ctx, data.as_bytes()).is_err() - ); + + // just don't crash + let _ = MimeParser::from_bytes(&context.ctx, data.as_bytes()); } } From db88212a645e764c6f40ee7ce0e76d250811b422 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 2 Dec 2019 15:29:47 +0100 Subject: [PATCH 18/20] refactor: unsafe, CStr and libc moved out --- Cargo.lock | 1 + deltachat-ffi/Cargo.toml | 1 + deltachat-ffi/src/lib.rs | 6 +- deltachat-ffi/src/providers.rs | 2 +- deltachat-ffi/src/string.rs | 350 +++++++++++++++++++++++++++++ examples/repl/cmdline.rs | 29 +-- examples/repl/main.rs | 4 +- examples/simple.rs | 10 - src/context.rs | 2 +- src/dc_receive_imf.rs | 26 +-- src/dc_tools.rs | 388 +-------------------------------- src/error.rs | 8 - src/job.rs | 2 +- src/location.rs | 2 +- src/message.rs | 16 +- src/mimeparser.rs | 2 +- tests/stress.rs | 8 +- 17 files changed, 398 insertions(+), 459 deletions(-) create mode 100644 deltachat-ffi/src/string.rs diff --git a/Cargo.lock b/Cargo.lock index 12ae271f5..152e9dcb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -686,6 +686,7 @@ version = "1.0.0-beta.8" dependencies = [ "deltachat 1.0.0-beta.8", "deltachat-provider-database 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/deltachat-ffi/Cargo.toml b/deltachat-ffi/Cargo.toml index 39f293366..c154d924a 100644 --- a/deltachat-ffi/Cargo.toml +++ b/deltachat-ffi/Cargo.toml @@ -20,6 +20,7 @@ deltachat-provider-database = "0.2.1" libc = "0.2" human-panic = "1.0.1" num-traits = "0.2.6" +failure = "0.1.6" [features] default = ["vendored", "nightly", "ringbuf"] diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 1a25a84a5..dbd21e068 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -25,13 +25,13 @@ use num_traits::{FromPrimitive, ToPrimitive}; use deltachat::constants::DC_MSG_ID_LAST_SPECIAL; use deltachat::contact::Contact; use deltachat::context::Context; -use deltachat::dc_tools::{ - as_path, dc_strdup, to_opt_string_lossy, to_string_lossy, OsStrExt, StrExt, -}; use deltachat::message::MsgId; use deltachat::stock::StockMessage; use deltachat::*; +mod string; +use self::string::*; + // as C lacks a good and portable error handling, // in general, the C Interface is forgiving wrt to bad parameters. // - objects returned by some functions diff --git a/deltachat-ffi/src/providers.rs b/deltachat-ffi/src/providers.rs index ceaa0d5ae..42c169c77 100644 --- a/deltachat-ffi/src/providers.rs +++ b/deltachat-ffi/src/providers.rs @@ -2,7 +2,7 @@ extern crate deltachat_provider_database; use std::ptr; -use deltachat::dc_tools::{to_string_lossy, StrExt}; +use crate::string::{to_string_lossy, StrExt}; use deltachat_provider_database::StatusState; #[no_mangle] diff --git a/deltachat-ffi/src/string.rs b/deltachat-ffi/src/string.rs new file mode 100644 index 000000000..8baf4d56a --- /dev/null +++ b/deltachat-ffi/src/string.rs @@ -0,0 +1,350 @@ +use failure::Fail; +use std::ffi::{CStr, CString}; + +/// Duplicates a string +/// +/// returns an empty string if NULL is given, never returns NULL (exits on errors) +/// +/// # Examples +/// +/// ```rust,norun +/// use deltachat::dc_tools::{dc_strdup, to_string_lossy}; +/// unsafe { +/// let str_a = b"foobar\x00" as *const u8 as *const libc::c_char; +/// let str_a_copy = dc_strdup(str_a); +/// assert_eq!(to_string_lossy(str_a_copy), "foobar"); +/// assert_ne!(str_a, str_a_copy); +/// } +/// ``` +pub unsafe fn dc_strdup(s: *const libc::c_char) -> *mut libc::c_char { + let ret: *mut libc::c_char; + if !s.is_null() { + ret = libc::strdup(s); + assert!(!ret.is_null()); + } else { + ret = libc::calloc(1, 1) as *mut libc::c_char; + assert!(!ret.is_null()); + } + + ret +} + +/// Error type for the [OsStrExt] trait +#[derive(Debug, Fail, PartialEq)] +pub enum CStringError { + /// The string contains an interior null byte + #[fail(display = "String contains an interior null byte")] + InteriorNullByte, + /// The string is not valid Unicode + #[fail(display = "String is not valid unicode")] + NotUnicode, +} + +/// Extra convenience methods on [std::ffi::OsStr] to work with `*libc::c_char`. +/// +/// The primary function of this trait is to more easily convert +/// [OsStr], [OsString] or [Path] into pointers to C strings. This always +/// allocates a new string since it is very common for the source +/// string not to have the required terminal null byte. +/// +/// It is implemented for `AsRef>` trait, which +/// allows any type which implements this trait to transparently use +/// this. This is how the conversion for [Path] works. +/// +/// [OsStr]: std::ffi::OsStr +/// [OsString]: std::ffi::OsString +/// [Path]: std::path::Path +/// +/// # Example +/// +/// ``` +/// use deltachat::dc_tools::{dc_strdup, OsStrExt}; +/// let path = std::path::Path::new("/some/path"); +/// let path_c = path.to_c_string().unwrap(); +/// unsafe { +/// let mut c_ptr: *mut libc::c_char = dc_strdup(path_c.as_ptr()); +/// } +/// ``` +pub trait OsStrExt { + /// Convert a [std::ffi::OsStr] to an [std::ffi::CString] + /// + /// This is useful to convert e.g. a [std::path::Path] to + /// [*libc::c_char] by using + /// [Path::as_os_str()](std::path::Path::as_os_str) and + /// [CStr::as_ptr()](std::ffi::CStr::as_ptr). + /// + /// This returns [CString] and not [&CStr] because not all [OsStr] + /// slices end with a null byte, particularly those coming from + /// [Path] do not have a null byte and having to handle this as + /// the caller would defeat the point of this function. + /// + /// On Windows this requires that the [OsStr] contains valid + /// unicode, which should normally be the case for a [Path]. + /// + /// [CString]: std::ffi::CString + /// [CStr]: std::ffi::CStr + /// [OsStr]: std::ffi::OsStr + /// [Path]: std::path::Path + /// + /// # Errors + /// + /// Since a C `*char` is terminated by a NULL byte this conversion + /// will fail, when the [OsStr] has an interior null byte. The + /// function will return + /// `[Err]([CStringError::InteriorNullByte])`. When converting + /// from a [Path] it should be safe to + /// [`.unwrap()`](std::result::Result::unwrap) this anyway since a + /// [Path] should not contain interior null bytes. + /// + /// On windows when the string contains invalid Unicode + /// `[Err]([CStringError::NotUnicode])` is returned. + fn to_c_string(&self) -> Result; +} + +impl> OsStrExt for T { + #[cfg(not(target_os = "windows"))] + fn to_c_string(&self) -> Result { + use std::os::unix::ffi::OsStrExt; + CString::new(self.as_ref().as_bytes()).map_err(|err| match err { + std::ffi::NulError { .. } => CStringError::InteriorNullByte, + }) + } + + #[cfg(target_os = "windows")] + fn to_c_string(&self) -> Result { + os_str_to_c_string_unicode(&self) + } +} + +// Implementation for os_str_to_c_string on windows. +#[allow(dead_code)] +fn os_str_to_c_string_unicode( + os_str: &dyn AsRef, +) -> Result { + match os_str.as_ref().to_str() { + Some(val) => CString::new(val.as_bytes()).map_err(|err| match err { + std::ffi::NulError { .. } => CStringError::InteriorNullByte, + }), + None => Err(CStringError::NotUnicode), + } +} + +/// Convenience methods/associated functions for working with [CString] +/// +/// This is helps transitioning from unsafe code. +pub trait CStringExt { + /// Create a new [CString], yolo style + /// + /// This unwrap the result, panicking when there are embedded NULL + /// bytes. + fn yolo>>(t: T) -> CString { + CString::new(t).expect("String contains null byte, can not be CString") + } +} + +impl CStringExt for CString {} + +/// Convenience methods to make transitioning from raw C strings easier. +/// +/// To interact with (legacy) C APIs we often need to convert from +/// Rust strings to raw C strings. This can be clumsy to do correctly +/// and the compiler sometimes allows it in an unsafe way. These +/// methods make it more succinct and help you get it right. +pub trait StrExt { + /// Allocate a new raw C `*char` version of this string. + /// + /// This allocates a new raw C string which must be freed using + /// `free`. It takes care of some common pitfalls with using + /// [CString.as_ptr]. + /// + /// [CString.as_ptr]: std::ffi::CString.as_ptr + /// + /// # Panics + /// + /// This function will panic when the original string contains an + /// interior null byte as this can not be represented in raw C + /// strings. + unsafe fn strdup(&self) -> *mut libc::c_char; +} + +impl> StrExt for T { + unsafe fn strdup(&self) -> *mut libc::c_char { + let tmp = CString::yolo(self.as_ref()); + dc_strdup(tmp.as_ptr()) + } +} + +pub fn to_string_lossy(s: *const libc::c_char) -> String { + if s.is_null() { + return "".into(); + } + + let cstr = unsafe { CStr::from_ptr(s) }; + + cstr.to_string_lossy().to_string() +} + +pub fn to_opt_string_lossy(s: *const libc::c_char) -> Option { + if s.is_null() { + return None; + } + + Some(to_string_lossy(s)) +} + +/// Convert a C `*char` pointer to a [std::path::Path] slice. +/// +/// This converts a `*libc::c_char` pointer to a [Path] slice. This +/// essentially has to convert the pointer to [std::ffi::OsStr] to do +/// so and thus is the inverse of [OsStrExt::to_c_string]. Just like +/// [OsStrExt::to_c_string] requires valid Unicode on Windows, this +/// requires that the pointer contains valid UTF-8 on Windows. +/// +/// Because this returns a reference the [Path] silce can not outlive +/// the original pointer. +/// +/// [Path]: std::path::Path +#[cfg(not(target_os = "windows"))] +pub fn as_path<'a>(s: *const libc::c_char) -> &'a std::path::Path { + assert!(!s.is_null(), "cannot be used on null pointers"); + use std::os::unix::ffi::OsStrExt; + unsafe { + let c_str = std::ffi::CStr::from_ptr(s).to_bytes(); + let os_str = std::ffi::OsStr::from_bytes(c_str); + std::path::Path::new(os_str) + } +} + +// as_path() implementation for windows, documented above. +#[cfg(target_os = "windows")] +pub fn as_path<'a>(s: *const libc::c_char) -> &'a std::path::Path { + as_path_unicode(s) +} + +// Implementation for as_path() on Windows. +// +// Having this as a separate function means it can be tested on unix +// too. +#[allow(dead_code)] +fn as_path_unicode<'a>(s: *const libc::c_char) -> &'a std::path::Path { + assert!(!s.is_null(), "cannot be used on null pointers"); + + let cstr = unsafe { CStr::from_ptr(s) }; + let str = cstr.to_str().unwrap_or_else(|err| panic!("{}", err)); + + std::path::Path::new(str) +} + +#[cfg(test)] +mod tests { + use super::*; + use libc::{free, strcmp}; + + #[test] + fn test_os_str_to_c_string_cwd() { + let some_dir = std::env::current_dir().unwrap(); + some_dir.as_os_str().to_c_string().unwrap(); + } + + #[test] + fn test_os_str_to_c_string_unicode() { + let some_str = String::from("/some/valid/utf8"); + let some_dir = std::path::Path::new(&some_str); + assert_eq!( + some_dir.as_os_str().to_c_string().unwrap(), + CString::new("/some/valid/utf8").unwrap() + ); + } + + #[test] + fn test_os_str_to_c_string_nul() { + let some_str = std::ffi::OsString::from("foo\x00bar"); + assert_eq!( + some_str.to_c_string().err().unwrap(), + CStringError::InteriorNullByte + ) + } + + #[test] + fn test_path_to_c_string_cwd() { + let some_dir = std::env::current_dir().unwrap(); + some_dir.to_c_string().unwrap(); + } + + #[test] + fn test_path_to_c_string_unicode() { + let some_str = String::from("/some/valid/utf8"); + let some_dir = std::path::Path::new(&some_str); + assert_eq!( + some_dir.as_os_str().to_c_string().unwrap(), + CString::new("/some/valid/utf8").unwrap() + ); + } + + #[test] + fn test_os_str_to_c_string_unicode_fn() { + let some_str = std::ffi::OsString::from("foo"); + assert_eq!( + os_str_to_c_string_unicode(&some_str).unwrap(), + CString::new("foo").unwrap() + ); + } + + #[test] + fn test_path_to_c_string_unicode_fn() { + let some_str = String::from("/some/path"); + let some_path = std::path::Path::new(&some_str); + assert_eq!( + os_str_to_c_string_unicode(&some_path).unwrap(), + CString::new("/some/path").unwrap() + ); + } + + #[test] + fn test_os_str_to_c_string_unicode_fn_nul() { + let some_str = std::ffi::OsString::from("fooz\x00bar"); + assert_eq!( + os_str_to_c_string_unicode(&some_str).err().unwrap(), + CStringError::InteriorNullByte + ); + } + + #[test] + fn test_as_path() { + let some_path = CString::new("/some/path").unwrap(); + let ptr = some_path.as_ptr(); + assert_eq!(as_path(ptr), std::ffi::OsString::from("/some/path")) + } + + #[test] + fn test_as_path_unicode_fn() { + let some_path = CString::new("/some/path").unwrap(); + let ptr = some_path.as_ptr(); + assert_eq!(as_path_unicode(ptr), std::ffi::OsString::from("/some/path")); + } + + #[test] + fn test_cstring_yolo() { + assert_eq!(CString::new("hello").unwrap(), CString::yolo("hello")); + } + + #[test] + fn test_strdup_str() { + unsafe { + let s = "hello".strdup(); + let cmp = strcmp(s, b"hello\x00" as *const u8 as *const libc::c_char); + free(s as *mut libc::c_void); + assert_eq!(cmp, 0); + } + } + + #[test] + fn test_strdup_string() { + unsafe { + let s = String::from("hello").strdup(); + let cmp = strcmp(s, b"hello\x00" as *const u8 as *const libc::c_char); + free(s as *mut libc::c_void); + assert_eq!(cmp, 0); + } + } +} diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index a90ac0785..2e465aca1 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -19,12 +19,11 @@ use deltachat::peerstate::*; use deltachat::qr::*; use deltachat::sql; use deltachat::Event; -use libc::free; /// Reset database tables. This function is called from Core cmdline. /// Argument is a bitmask, executing single or multiple actions in one call. /// e.g. bitmask 7 triggers actions definded with bits 1, 2 and 4. -pub unsafe fn dc_reset_tables(context: &Context, bits: i32) -> i32 { +pub fn dc_reset_tables(context: &Context, bits: i32) -> i32 { info!(context, "Resetting tables ({})...", bits); if 0 != bits & 1 { sql::execute(context, &context.sql, "DELETE FROM jobs;", params![]).unwrap(); @@ -107,18 +106,19 @@ fn dc_poke_eml_file(context: &Context, filename: impl AsRef) -> Result<(), /// @param context The context as created by dc_context_new(). /// @param spec The file or directory to import. NULL for the last command. /// @return 1=success, 0=error. -fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int { +fn poke_spec(context: &Context, spec: Option<&str>) -> libc::c_int { if !context.sql.is_open() { error!(context, "Import: Database not opened."); return 0; } - let real_spec: String; let mut read_cnt = 0; + let real_spec: String; + /* if `spec` is given, remember it for later usage; if it is not given, try to use the last one */ - if !spec.is_null() { - real_spec = to_string_lossy(spec); + if let Some(spec) = spec { + real_spec = spec.to_string(); context .sql .set_raw_config(context, "import_spec", Some(&real_spec)) @@ -174,7 +174,7 @@ fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int { 1 } -unsafe fn log_msg(context: &Context, prefix: impl AsRef, msg: &Message) { +fn log_msg(context: &Context, prefix: impl AsRef, msg: &Message) { let contact = Contact::get_by_id(context, msg.get_from_id()).expect("invalid contact"); let contact_name = contact.get_name(); let contact_id = contact.get_id(); @@ -219,7 +219,7 @@ unsafe fn log_msg(context: &Context, prefix: impl AsRef, msg: &Message) { ); } -unsafe fn log_msglist(context: &Context, msglist: &Vec) -> Result<(), Error> { +fn log_msglist(context: &Context, msglist: &Vec) -> Result<(), Error> { let mut lines_out = 0; for &msg_id in msglist { if msg_id.is_daymarker() { @@ -250,7 +250,7 @@ unsafe fn log_msglist(context: &Context, msglist: &Vec) -> Result<(), Err Ok(()) } -unsafe fn log_contactlist(context: &Context, contacts: &Vec) { +fn log_contactlist(context: &Context, contacts: &Vec) { let mut contacts = contacts.clone(); if !contacts.contains(&1) { contacts.push(1); @@ -302,7 +302,7 @@ fn chat_prefix(chat: &Chat) -> &'static str { chat.typ.into() } -pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::Error> { +pub fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::Error> { let chat_id = *context.cmdline_sel_chat_id.read().unwrap(); let mut sel_chat = if chat_id > 0 { Chat::load_from_db(context, chat_id).ok() @@ -313,11 +313,6 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E let mut args = line.splitn(3, ' '); let arg0 = args.next().unwrap_or_default(); let arg1 = args.next().unwrap_or_default(); - let arg1_c = if arg1.is_empty() { - std::ptr::null() - } else { - arg1.strdup() as *const _ - }; let arg2 = args.next().unwrap_or_default(); let blobdir = context.get_blobdir(); @@ -467,7 +462,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E ); } "poke" => { - ensure!(0 != poke_spec(context, arg1_c), "Poke failed"); + ensure!(0 != poke_spec(context, Some(arg1)), "Poke failed"); } "reset" => { ensure!(!arg1.is_empty(), "Argument missing: 1=jobs, 2=peerstates, 4=private keys, 8=rest but server config"); @@ -1008,7 +1003,5 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E _ => bail!("Unknown command: \"{}\" type ? for help.", arg0), } - free(arg1_c as *mut _); - Ok(()) } diff --git a/examples/repl/main.rs b/examples/repl/main.rs index bc7528c5d..178f4fb0d 100644 --- a/examples/repl/main.rs +++ b/examples/repl/main.rs @@ -403,7 +403,7 @@ fn main_0(args: Vec) -> Result<(), failure::Error> { // TODO: ignore "set mail_pw" rl.add_history_entry(line.as_str()); let ctx = ctx.clone(); - match unsafe { handle_cmd(line.trim(), ctx) } { + match handle_cmd(line.trim(), ctx) { Ok(ExitResult::Continue) => {} Ok(ExitResult::Exit) => break, Err(err) => println!("Error: {}", err), @@ -434,7 +434,7 @@ enum ExitResult { Exit, } -unsafe fn handle_cmd(line: &str, ctx: Arc>) -> Result { +fn handle_cmd(line: &str, ctx: Arc>) -> Result { let mut args = line.splitn(2, ' '); let arg0 = args.next().unwrap_or_default(); let arg1 = args.next().unwrap_or_default(); diff --git a/examples/simple.rs b/examples/simple.rs index 67c8fbbc7..71917e7c1 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -101,16 +101,6 @@ fn main() { thread::sleep(duration); - // let msglist = dc_get_chat_msgs(&ctx, chat_id, 0, 0); - // for i in 0..dc_array_get_cnt(msglist) { - // let msg_id = dc_array_get_id(msglist, i); - // let msg = dc_get_msg(context, msg_id); - // let text = CStr::from_ptr(dc_msg_get_text(msg)).unwrap(); - // println!("Message {}: {}\n", i + 1, text.to_str().unwrap()); - // dc_msg_unref(msg); - // } - // dc_array_unref(msglist); - println!("stopping threads"); *running.write().unwrap() = false; diff --git a/src/context.rs b/src/context.rs index 6515b1842..711e34be1 100644 --- a/src/context.rs +++ b/src/context.rs @@ -86,7 +86,7 @@ pub fn get_info() -> HashMap<&'static str, String> { ); res.insert( "arch", - (::std::mem::size_of::<*mut libc::c_void>()) + (std::mem::size_of::<*mut libc::c_void>()) .wrapping_mul(8) .to_string(), ); diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index b3d6fa2a6..ad559bb57 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -286,7 +286,7 @@ fn add_parts( sent_timestamp: &mut i64, from_id: &mut u32, from_id_blocked: i32, - hidden: &mut libc::c_int, + hidden: &mut i32, chat_id: &mut u32, to_id: &mut u32, flags: u32, @@ -297,7 +297,7 @@ fn add_parts( create_event_to_send: &mut Option, ) -> Result<()> { let mut state: MessageState; - let mut msgrmsg: libc::c_int; + let mut msgrmsg: i32; let mut chat_id_blocked = Blocked::Not; let mut sort_timestamp = 0; let mut rcvd_timestamp = 0; @@ -640,10 +640,10 @@ fn add_parts( stmt.execute(params![ rfc724_mid, server_folder.as_ref(), - server_uid as libc::c_int, - *chat_id as libc::c_int, - *from_id as libc::c_int, - *to_id as libc::c_int, + server_uid as i32, + *chat_id as i32, + *from_id as i32, + *to_id as i32, sort_timestamp, *sent_timestamp, rcvd_timestamp, @@ -754,7 +754,7 @@ fn calc_timestamps( chat_id: u32, from_id: u32, message_timestamp: i64, - is_fresh_msg: libc::c_int, + is_fresh_msg: i32, sort_timestamp: &mut i64, sent_timestamp: &mut i64, rcvd_timestamp: &mut i64, @@ -799,7 +799,7 @@ fn calc_timestamps( fn create_or_lookup_group( context: &Context, mime_parser: &mut MimeParser, - allow_creation: libc::c_int, + allow_creation: i32, create_blocked: Blocked, from_id: u32, to_ids: &mut Vec, @@ -889,7 +889,7 @@ fn create_or_lookup_group( 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()) - == from_id as u32) as libc::c_int; + == from_id as u32) as i32; better_msg = context.stock_system_msg( if 0 != left_group { StockMessage::MsgGroupLeft @@ -1167,7 +1167,7 @@ fn create_or_lookup_group( fn create_or_lookup_adhoc_group( context: &Context, mime_parser: &MimeParser, - allow_creation: libc::c_int, + allow_creation: i32, create_blocked: Blocked, from_id: u32, to_ids: &mut Vec, @@ -1252,7 +1252,7 @@ fn create_or_lookup_adhoc_group( let grpname = if let Some(subject) = mime_parser.subject.as_ref().filter(|s| !s.is_empty()) { subject.to_string() } else { - context.stock_string_repl_int(StockMessage::Member, member_ids.len() as libc::c_int) + context.stock_string_repl_int(StockMessage::Member, member_ids.len() as i32) }; // create group record @@ -1516,7 +1516,7 @@ fn set_better_msg(mime_parser: &mut MimeParser, better_msg: impl AsRef) { } } -fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimeParser) -> libc::c_int { +fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimeParser) -> i32 { /* 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) */ @@ -1566,7 +1566,7 @@ fn is_known_rfc724_mid(context: &Context, rfc724_mid: &mailparse::MailAddr) -> b .unwrap_or_default() } -fn dc_is_reply_to_messenger_message(context: &Context, mime_parser: &MimeParser) -> libc::c_int { +fn dc_is_reply_to_messenger_message(context: &Context, mime_parser: &MimeParser) -> i32 { /* 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 - checks also if any of the referenced IDs are send by a messenger diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 0e58b2a88..08f58296c 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -3,52 +3,22 @@ use core::cmp::{max, min}; use std::borrow::Cow; -use std::ffi::{CStr, CString}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::time::SystemTime; use std::{fmt, fs}; use chrono::{Local, TimeZone}; -use libc::{memcpy, strlen}; use rand::{thread_rng, Rng}; use crate::context::Context; use crate::error::Error; use crate::events::Event; -pub(crate) fn dc_exactly_one_bit_set(v: libc::c_int) -> bool { +pub(crate) fn dc_exactly_one_bit_set(v: i32) -> bool { 0 != v && 0 == v & (v - 1) } -/// Duplicates a string -/// -/// returns an empty string if NULL is given, never returns NULL (exits on errors) -/// -/// # Examples -/// -/// ``` -/// use deltachat::dc_tools::{dc_strdup, to_string_lossy}; -/// unsafe { -/// let str_a = b"foobar\x00" as *const u8 as *const libc::c_char; -/// let str_a_copy = dc_strdup(str_a); -/// assert_eq!(to_string_lossy(str_a_copy), "foobar"); -/// assert_ne!(str_a, str_a_copy); -/// } -/// ``` -pub unsafe fn dc_strdup(s: *const libc::c_char) -> *mut libc::c_char { - let ret: *mut libc::c_char; - if !s.is_null() { - ret = strdup(s); - assert!(!ret.is_null()); - } else { - ret = libc::calloc(1, 1) as *mut libc::c_char; - assert!(!ret.is_null()); - } - - ret -} - /// Shortens a string to a specified length and adds "..." or "[...]" to the end of /// the shortened string. pub(crate) fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Cow { @@ -532,212 +502,6 @@ pub(crate) fn dc_get_next_backup_path( bail!("could not create backup file, disk full?"); } -/// Error type for the [OsStrExt] trait -#[derive(Debug, Fail, PartialEq)] -pub enum CStringError { - /// The string contains an interior null byte - #[fail(display = "String contains an interior null byte")] - InteriorNullByte, - /// The string is not valid Unicode - #[fail(display = "String is not valid unicode")] - NotUnicode, -} - -/// Extra convenience methods on [std::ffi::OsStr] to work with `*libc::c_char`. -/// -/// The primary function of this trait is to more easily convert -/// [OsStr], [OsString] or [Path] into pointers to C strings. This always -/// allocates a new string since it is very common for the source -/// string not to have the required terminal null byte. -/// -/// It is implemented for `AsRef>` trait, which -/// allows any type which implements this trait to transparently use -/// this. This is how the conversion for [Path] works. -/// -/// [OsStr]: std::ffi::OsStr -/// [OsString]: std::ffi::OsString -/// [Path]: std::path::Path -/// -/// # Example -/// -/// ``` -/// use deltachat::dc_tools::{dc_strdup, OsStrExt}; -/// let path = std::path::Path::new("/some/path"); -/// let path_c = path.to_c_string().unwrap(); -/// unsafe { -/// let mut c_ptr: *mut libc::c_char = dc_strdup(path_c.as_ptr()); -/// } -/// ``` -pub trait OsStrExt { - /// Convert a [std::ffi::OsStr] to an [std::ffi::CString] - /// - /// This is useful to convert e.g. a [std::path::Path] to - /// [*libc::c_char] by using - /// [Path::as_os_str()](std::path::Path::as_os_str) and - /// [CStr::as_ptr()](std::ffi::CStr::as_ptr). - /// - /// This returns [CString] and not [&CStr] because not all [OsStr] - /// slices end with a null byte, particularly those coming from - /// [Path] do not have a null byte and having to handle this as - /// the caller would defeat the point of this function. - /// - /// On Windows this requires that the [OsStr] contains valid - /// unicode, which should normally be the case for a [Path]. - /// - /// [CString]: std::ffi::CString - /// [CStr]: std::ffi::CStr - /// [OsStr]: std::ffi::OsStr - /// [Path]: std::path::Path - /// - /// # Errors - /// - /// Since a C `*char` is terminated by a NULL byte this conversion - /// will fail, when the [OsStr] has an interior null byte. The - /// function will return - /// `[Err]([CStringError::InteriorNullByte])`. When converting - /// from a [Path] it should be safe to - /// [`.unwrap()`](std::result::Result::unwrap) this anyway since a - /// [Path] should not contain interior null bytes. - /// - /// On windows when the string contains invalid Unicode - /// `[Err]([CStringError::NotUnicode])` is returned. - fn to_c_string(&self) -> Result; -} - -impl> OsStrExt for T { - #[cfg(not(target_os = "windows"))] - fn to_c_string(&self) -> Result { - use std::os::unix::ffi::OsStrExt; - CString::new(self.as_ref().as_bytes()).map_err(|err| match err { - std::ffi::NulError { .. } => CStringError::InteriorNullByte, - }) - } - - #[cfg(target_os = "windows")] - fn to_c_string(&self) -> Result { - os_str_to_c_string_unicode(&self) - } -} - -// Implementation for os_str_to_c_string on windows. -#[allow(dead_code)] -fn os_str_to_c_string_unicode( - os_str: &dyn AsRef, -) -> Result { - match os_str.as_ref().to_str() { - Some(val) => CString::new(val.as_bytes()).map_err(|err| match err { - std::ffi::NulError { .. } => CStringError::InteriorNullByte, - }), - None => Err(CStringError::NotUnicode), - } -} - -/// Convenience methods/associated functions for working with [CString] -/// -/// This is helps transitioning from unsafe code. -pub trait CStringExt { - /// Create a new [CString], yolo style - /// - /// This unwrap the result, panicking when there are embedded NULL - /// bytes. - fn yolo>>(t: T) -> CString { - CString::new(t).expect("String contains null byte, can not be CString") - } -} - -impl CStringExt for CString {} - -/// Convenience methods to make transitioning from raw C strings easier. -/// -/// To interact with (legacy) C APIs we often need to convert from -/// Rust strings to raw C strings. This can be clumsy to do correctly -/// and the compiler sometimes allows it in an unsafe way. These -/// methods make it more succinct and help you get it right. -pub trait StrExt { - /// Allocate a new raw C `*char` version of this string. - /// - /// This allocates a new raw C string which must be freed using - /// `free`. It takes care of some common pitfalls with using - /// [CString.as_ptr]. - /// - /// [CString.as_ptr]: std::ffi::CString.as_ptr - /// - /// # Panics - /// - /// This function will panic when the original string contains an - /// interior null byte as this can not be represented in raw C - /// strings. - unsafe fn strdup(&self) -> *mut libc::c_char; -} - -impl> StrExt for T { - unsafe fn strdup(&self) -> *mut libc::c_char { - let tmp = CString::yolo(self.as_ref()); - dc_strdup(tmp.as_ptr()) - } -} - -pub fn to_string_lossy(s: *const libc::c_char) -> String { - if s.is_null() { - return "".into(); - } - - let cstr = unsafe { CStr::from_ptr(s) }; - - cstr.to_string_lossy().to_string() -} - -pub fn to_opt_string_lossy(s: *const libc::c_char) -> Option { - if s.is_null() { - return None; - } - - Some(to_string_lossy(s)) -} - -/// Convert a C `*char` pointer to a [std::path::Path] slice. -/// -/// This converts a `*libc::c_char` pointer to a [Path] slice. This -/// essentially has to convert the pointer to [std::ffi::OsStr] to do -/// so and thus is the inverse of [OsStrExt::to_c_string]. Just like -/// [OsStrExt::to_c_string] requires valid Unicode on Windows, this -/// requires that the pointer contains valid UTF-8 on Windows. -/// -/// Because this returns a reference the [Path] silce can not outlive -/// the original pointer. -/// -/// [Path]: std::path::Path -#[cfg(not(target_os = "windows"))] -pub fn as_path<'a>(s: *const libc::c_char) -> &'a std::path::Path { - assert!(!s.is_null(), "cannot be used on null pointers"); - use std::os::unix::ffi::OsStrExt; - unsafe { - let c_str = std::ffi::CStr::from_ptr(s).to_bytes(); - let os_str = std::ffi::OsStr::from_bytes(c_str); - std::path::Path::new(os_str) - } -} - -// as_path() implementation for windows, documented above. -#[cfg(target_os = "windows")] -pub fn as_path<'a>(s: *const libc::c_char) -> &'a std::path::Path { - as_path_unicode(s) -} - -// Implementation for as_path() on Windows. -// -// Having this as a separate function means it can be tested on unix -// too. -#[allow(dead_code)] -fn as_path_unicode<'a>(s: *const libc::c_char) -> &'a std::path::Path { - assert!(!s.is_null(), "cannot be used on null pointers"); - - let cstr = unsafe { CStr::from_ptr(s) }; - let str = cstr.to_str().unwrap_or_else(|err| panic!("{}", err)); - - std::path::Path::new(str) -} - pub(crate) fn time() -> i64 { SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) @@ -815,57 +579,14 @@ pub(crate) fn listflags_has(listflags: u32, bitindex: usize) -> bool { (listflags & bitindex) == bitindex } -pub(crate) unsafe fn strdup(s: *const libc::c_char) -> *mut libc::c_char { - if s.is_null() { - return std::ptr::null_mut(); - } - - let slen = strlen(s); - let result = libc::malloc(slen + 1); - if result.is_null() { - return std::ptr::null_mut(); - } - - memcpy(result, s as *const _, slen + 1); - result as *mut _ -} - #[cfg(test)] mod tests { use super::*; - - use libc::{free, strcmp}; use std::convert::TryInto; - use std::ffi::CStr; use crate::constants::*; use crate::test_utils::*; - #[test] - fn test_dc_strdup() { - unsafe { - let str_a = b"foobar\x00" as *const u8 as *const libc::c_char; - let str_a_copy = dc_strdup(str_a); - - // Value of str_a_copy should equal foobar - assert_eq!( - CStr::from_ptr(str_a_copy), - CString::new("foobar").unwrap().as_c_str() - ); - // Address of str_a should be different from str_a_copy - assert_ne!(str_a, str_a_copy); - - let str_a = std::ptr::null() as *const libc::c_char; - let str_a_copy = dc_strdup(str_a); - // Value of str_a_copy should equal "" - assert_eq!( - CStr::from_ptr(str_a_copy), - CString::new("").unwrap().as_c_str() - ); - assert_ne!(str_a, str_a_copy); - } - } - #[test] fn test_rust_ftoa() { assert_eq!("1.22", format!("{}", 1.22)); @@ -953,113 +674,6 @@ mod tests { } #[test] - fn test_os_str_to_c_string_cwd() { - let some_dir = std::env::current_dir().unwrap(); - some_dir.as_os_str().to_c_string().unwrap(); - } - - #[test] - fn test_os_str_to_c_string_unicode() { - let some_str = String::from("/some/valid/utf8"); - let some_dir = std::path::Path::new(&some_str); - assert_eq!( - some_dir.as_os_str().to_c_string().unwrap(), - CString::new("/some/valid/utf8").unwrap() - ); - } - - #[test] - fn test_os_str_to_c_string_nul() { - let some_str = std::ffi::OsString::from("foo\x00bar"); - assert_eq!( - some_str.to_c_string().err().unwrap(), - CStringError::InteriorNullByte - ) - } - - #[test] - fn test_path_to_c_string_cwd() { - let some_dir = std::env::current_dir().unwrap(); - some_dir.to_c_string().unwrap(); - } - - #[test] - fn test_path_to_c_string_unicode() { - let some_str = String::from("/some/valid/utf8"); - let some_dir = std::path::Path::new(&some_str); - assert_eq!( - some_dir.as_os_str().to_c_string().unwrap(), - CString::new("/some/valid/utf8").unwrap() - ); - } - - #[test] - fn test_os_str_to_c_string_unicode_fn() { - let some_str = std::ffi::OsString::from("foo"); - assert_eq!( - os_str_to_c_string_unicode(&some_str).unwrap(), - CString::new("foo").unwrap() - ); - } - - #[test] - fn test_path_to_c_string_unicode_fn() { - let some_str = String::from("/some/path"); - let some_path = std::path::Path::new(&some_str); - assert_eq!( - os_str_to_c_string_unicode(&some_path).unwrap(), - CString::new("/some/path").unwrap() - ); - } - - #[test] - fn test_os_str_to_c_string_unicode_fn_nul() { - let some_str = std::ffi::OsString::from("fooz\x00bar"); - assert_eq!( - os_str_to_c_string_unicode(&some_str).err().unwrap(), - CStringError::InteriorNullByte - ); - } - - #[test] - fn test_as_path() { - let some_path = CString::new("/some/path").unwrap(); - let ptr = some_path.as_ptr(); - assert_eq!(as_path(ptr), std::ffi::OsString::from("/some/path")) - } - - #[test] - fn test_as_path_unicode_fn() { - let some_path = CString::new("/some/path").unwrap(); - let ptr = some_path.as_ptr(); - assert_eq!(as_path_unicode(ptr), std::ffi::OsString::from("/some/path")); - } - - #[test] - fn test_cstring_yolo() { - assert_eq!(CString::new("hello").unwrap(), CString::yolo("hello")); - } - - #[test] - fn test_strdup_str() { - unsafe { - let s = "hello".strdup(); - let cmp = strcmp(s, b"hello\x00" as *const u8 as *const libc::c_char); - free(s as *mut libc::c_void); - assert_eq!(cmp, 0); - } - } - - #[test] - fn test_strdup_string() { - unsafe { - let s = String::from("hello").strdup(); - let cmp = strcmp(s, b"hello\x00" as *const u8 as *const libc::c_char); - free(s as *mut libc::c_void); - assert_eq!(cmp, 0); - } - } - #[test] fn test_dc_extract_grpid_from_rfc724_mid() { // Should return None if we pass invalid mid diff --git a/src/error.rs b/src/error.rs index 25351bf71..588117f45 100644 --- a/src/error.rs +++ b/src/error.rs @@ -15,8 +15,6 @@ pub enum Error { Image(image_meta::ImageError), #[fail(display = "{:?}", _0)] Utf8(std::str::Utf8Error), - #[fail(display = "{:?}", _0)] - CStringError(crate::dc_tools::CStringError), #[fail(display = "PGP: {:?}", _0)] Pgp(pgp::errors::Error), #[fail(display = "Base64Decode: {:?}", _0)] @@ -75,12 +73,6 @@ impl From for Error { } } -impl From for Error { - fn from(err: crate::dc_tools::CStringError) -> Error { - Error::CStringError(err) - } -} - impl From for Error { fn from(err: pgp::errors::Error) -> Error { Error::Pgp(err) diff --git a/src/job.rs b/src/job.rs index 63b8e1063..a01add23c 100644 --- a/src/job.rs +++ b/src/job.rs @@ -898,7 +898,7 @@ fn add_smtp_job( pub fn job_add( context: &Context, action: Action, - foreign_id: libc::c_int, + foreign_id: i32, param: Params, delay_seconds: i64, ) { diff --git a/src/location.rs b/src/location.rs index 357349d89..35bee16da 100644 --- a/src/location.rs +++ b/src/location.rs @@ -229,7 +229,7 @@ pub fn send_locations_to_chat(context: &Context, chat_id: u32, seconds: i64) { job_add( context, Action::MaybeSendLocationsEnded, - chat_id as libc::c_int, + chat_id as i32, Params::new(), seconds + 1, ); diff --git a/src/message.rs b/src/message.rs index f033aea16..bf1cb1d97 100644 --- a/src/message.rs +++ b/src/message.rs @@ -457,7 +457,7 @@ impl Message { return ret; }; - let contact = if self.from_id != DC_CONTACT_ID_SELF as libc::c_uint + let contact = if self.from_id != DC_CONTACT_ID_SELF as u32 && (chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup) { Contact::get_by_id(context, self.from_id).ok() @@ -502,8 +502,8 @@ impl Message { pub fn is_info(&self) -> bool { let cmd = self.param.get_cmd(); - self.from_id == DC_CONTACT_ID_INFO as libc::c_uint - || self.to_id == DC_CONTACT_ID_INFO as libc::c_uint + self.from_id == DC_CONTACT_ID_INFO as u32 + || self.to_id == DC_CONTACT_ID_INFO as u32 || cmd != SystemMessage::Unknown && cmd != SystemMessage::AutocryptSetupMessage } @@ -730,7 +730,7 @@ pub fn get_msg_info(context: &Context, msg_id: MsgId) -> String { ret += &format!(" by {}", name); ret += "\n"; - if msg.from_id != DC_CONTACT_ID_SELF as libc::c_uint { + if msg.from_id != DC_CONTACT_ID_SELF as u32 { let s = dc_timestamp_to_str(if 0 != msg.timestamp_rcvd { msg.timestamp_rcvd } else { @@ -1227,7 +1227,7 @@ pub fn mdn_from_ext( } /// The number of messages assigned to real chat (!=deaddrop, !=trash) -pub fn get_real_msg_cnt(context: &Context) -> libc::c_int { +pub fn get_real_msg_cnt(context: &Context) -> i32 { match context.sql.query_row( "SELECT COUNT(*) \ FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id \ @@ -1243,7 +1243,7 @@ pub fn get_real_msg_cnt(context: &Context) -> libc::c_int { } } -pub fn get_deaddrop_msg_cnt(context: &Context) -> libc::size_t { +pub fn get_deaddrop_msg_cnt(context: &Context) -> usize { match context.sql.query_row( "SELECT COUNT(*) \ FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id \ @@ -1251,7 +1251,7 @@ pub fn get_deaddrop_msg_cnt(context: &Context) -> libc::size_t { rusqlite::NO_PARAMS, |row| row.get::<_, isize>(0), ) { - Ok(res) => res as libc::size_t, + Ok(res) => res as usize, Err(err) => { error!(context, "dc_get_deaddrop_msg_cnt() failed. {}", err); 0 @@ -1259,7 +1259,7 @@ pub fn get_deaddrop_msg_cnt(context: &Context) -> libc::size_t { } } -pub fn rfc724_mid_cnt(context: &Context, rfc724_mid: &str) -> libc::c_int { +pub fn rfc724_mid_cnt(context: &Context, rfc724_mid: &str) -> i32 { // check the number of messages with the same rfc724_mid match context.sql.query_row( "SELECT COUNT(*) FROM msgs WHERE rfc724_mid=?;", diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 8c05cb4a5..8fe8deadd 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -232,7 +232,7 @@ impl<'a> MimeParser<'a> { } } if let Some(ref subject) = self.subject { - let mut prepend_subject: libc::c_int = 1i32; + let mut prepend_subject = 1i32; if !self.decrypting_failed { let colon = subject.find(':'); if colon == Some(2) diff --git a/tests/stress.rs b/tests/stress.rs index f03c9e2c8..9939766e1 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -14,7 +14,7 @@ use tempfile::{tempdir, TempDir}; /* some data used for testing ******************************************************************************/ -unsafe fn stress_functions(context: &Context) { +fn stress_functions(context: &Context) { let res = context.get_config(config::Config::SysConfigKeys).unwrap(); assert!(!res.contains(" probably_never_a_key ")); @@ -224,10 +224,8 @@ fn create_test_context() -> TestContext { #[test] fn test_stress_tests() { - unsafe { - let context = create_test_context(); - stress_functions(&context.ctx); - } + let context = create_test_context(); + stress_functions(&context.ctx); } #[test] From 1c5a3e6698634e71de0c8122ad120032f1f71f45 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 3 Dec 2019 10:59:30 +0100 Subject: [PATCH 19/20] remove debug logging and fix update_gossip_headers location --- src/mimefactory.rs | 5 ----- src/mimeparser.rs | 52 ++++++++-------------------------------------- 2 files changed, 9 insertions(+), 48 deletions(-) diff --git a/src/mimefactory.rs b/src/mimefactory.rs index dfc3e7143..113475f1e 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -475,11 +475,6 @@ impl<'a, 'b> MimeFactory<'a, 'b> { // Add gossip headers if do_gossip { - info!( - self.context, - "gossiping headers for {} peerstates", - peerstates.len() - ); for peerstate in peerstates.iter().filter_map(|(state, _)| state.as_ref()) { if peerstate.peek_key(min_verified).is_some() { if let Some(header) = peerstate.render_gossip_header(min_verified) { diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 8fe8deadd..31085ce5c 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -108,11 +108,15 @@ impl<'a> MimeParser<'a> { if let Some(raw) = raw { mail_raw = raw; - info!(context, "decrypted: {:?}", std::str::from_utf8(&mail_raw)); - let decrypted_mail = mailparse::parse_mail(&mail_raw)?; - // Decrypted the mail + // Handle any gossip headers if the mail was encrypted. See section + // "3.6 Key Gossip" of https://autocrypt.org/autocrypt-spec-1.1.0.pdf + let gossip_headers = + decrypted_mail.headers.get_all_values("Autocrypt-Gossip")?; + parser.gossipped_addr = + update_gossip_peerstates(context, message_time, &mail, gossip_headers)?; + decrypted_mail } else { // Message was not encrypted @@ -134,11 +138,6 @@ impl<'a> MimeParser<'a> { parser.parse_mime_recursive(&mail)?; - // Handle gossip headers - let gossip_headers = mail.headers.get_all_values("Autocrypt-Gossip")?; - parser.gossipped_addr = - update_gossip_peerstates(context, message_time, &mail, gossip_headers)?; - parser.parse_headers()?; Ok(parser) @@ -201,8 +200,6 @@ impl<'a> MimeParser<'a> { } } - info!(self.context, "checking message parts: {:?}", &self.parts); - if self.is_send_by_messenger && self.parts.len() == 2 { let need_drop = { let textpart = &self.parts[0]; @@ -299,15 +296,12 @@ impl<'a> MimeParser<'a> { if let Some(dn_field) = self.lookup_field("Chat-Disposition-Notification-To") { if self.get_last_nonmeta().is_some() { let addrs = mailparse::addrparse(&dn_field).unwrap(); - info!(self.context, "last non meta addrs: {:?}", &addrs); if let Some(dn_to_addr) = addrs.first() { if let Some(from_field) = self.lookup_field("From") { - info!(self.context, "From {:?}", from_field); let from_addrs = mailparse::addrparse(&from_field).unwrap(); if let Some(from_addr) = from_addrs.first() { - info!(self.context, "comparing {:?} - {:?}", from_addr, dn_to_addr); if compare_addrs(from_addr, dn_to_addr) { if let Some(part_4) = self.get_last_nonmeta_mut() { part_4.param.set_int(Param::WantsMdn, 1); @@ -350,13 +344,9 @@ impl<'a> MimeParser<'a> { } fn parse_mime_recursive(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result { - info!(self.context, "parse mime_recursive {:?}", mail.ctype); - if mail.ctype.params.get("protected-headers").is_some() { - info!(self.context, "found protected headers"); - if mail.ctype.mimetype == "text/rfc822-headers" { - info!( + warn!( self.context, "Protected headers found in text/rfc822-headers attachment: Will be ignored.", ); @@ -481,13 +471,10 @@ impl<'a> MimeParser<'a> { } } (mime::MULTIPART, "report") => { - info!(self.context, "got report {}", mail.subparts.len()); /* RFC 6522: the first part is for humans, the second for machines */ if mail.subparts.len() >= 2 { - info!(self.context, "report: {:?}", &mail.ctype); if let Some(report_type) = mail.ctype.params.get("report-type") { if report_type == "disposition-notification" { - info!(self.context, "processing report"); if let Some(report) = self.process_report(mail)? { self.reports.push(report); } @@ -551,11 +538,6 @@ impl<'a> MimeParser<'a> { let (mime_type, msg_type) = get_mime_type(mail)?; let raw_mime = mail.ctype.mimetype.to_lowercase(); - info!( - self.context, - "got mime type: {:?} ({})", mime_type, raw_mime - ); - let old_part_count = self.parts.len(); // regard `Content-Transfer-Encoding:` @@ -803,7 +785,6 @@ impl<'a> MimeParser<'a> { .flatten() .and_then(|v| parse_message_id(&v)) { - info!(self.context, "got report {:?}", original_message_id); return Ok(Some(Report { original_message_id, })); @@ -822,7 +803,6 @@ impl<'a> MimeParser<'a> { server_folder: impl AsRef, server_uid: u32, ) { - info!(self.context, "processing reports {:?}", &self.reports); for report in &self.reports { let mut mdn_consumed = false; @@ -832,10 +812,6 @@ impl<'a> MimeParser<'a> { &report.original_message_id, sent_timestamp, ) { - info!( - self.context, - "found message for report {}", report.original_message_id - ); rr_event_to_send.push((chat_id, msg_id)); mdn_consumed = true; } @@ -863,21 +839,14 @@ fn update_gossip_peerstates( let mut recipients: Option> = None; let mut gossipped_addr: HashSet = Default::default(); - info!( - context, - "Updating gossip peerstates: {}", - gossip_headers.len() - ); for value in &gossip_headers { let gossip_header = value.parse::(); - info!(context, "got gossip header: {:?}", gossip_header); if let Ok(ref header) = gossip_header { if recipients.is_none() { recipients = Some(get_recipients(mail.headers.iter().filter_map(|v| { let key = v.get_key(); let value = v.get_value(); - info!(context, "header: {:?} - {:?}", key, value); if key.is_err() || value.is_err() { return None; } @@ -885,9 +854,6 @@ fn update_gossip_peerstates( }))); } - info!(context, "got recipients {:?}", recipients); - info!(context, "looking for addr {:?}", &header.addr); - if recipients.as_ref().unwrap().contains(&header.addr) { let mut peerstate = Peerstate::from_addr(context, &context.sql, &header.addr); if let Some(ref mut peerstate) = peerstate { @@ -906,7 +872,7 @@ fn update_gossip_peerstates( gossipped_addr.insert(header.addr.clone()); } else { - info!( + warn!( context, "Ignoring gossipped \"{}\" as the address is not in To/Cc list.", &header.addr, ); From affdf7241f6b616bfea7bf764e2b93d29ef6e4e5 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Tue, 3 Dec 2019 12:26:27 +0100 Subject: [PATCH 20/20] fixup: remove double mimefactory --- src/job.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/job.rs b/src/job.rs index a01add23c..6bdcba296 100644 --- a/src/job.rs +++ b/src/job.rs @@ -607,8 +607,6 @@ pub fn job_send_msg(context: &Context, msg_id: MsgId) -> Result<(), Error> { let mut msg = Message::load_from_db(context, msg_id)?; msg.try_calc_and_set_dimensions(context).ok(); - let mut mimefactory = MimeFactory::from_msg(context, &msg)?; - /* create message */ let needs_encryption = msg.param.get_int(Param::GuaranteeE2ee).unwrap_or_default();