diff --git a/src/constants.rs b/src/constants.rs index e2c2e5cc5..688f91821 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -509,3 +509,10 @@ pub const DC_STR_MSGLOCATIONENABLED: usize = 64; pub const DC_STR_MSGLOCATIONDISABLED: usize = 65; pub const DC_STR_LOCATION: usize = 66; pub const DC_STR_COUNT: usize = 66; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)] +#[repr(u8)] +pub enum Key { + Public = 0, + Private = 1, +} diff --git a/src/dc_aheader.rs b/src/dc_aheader.rs index c9b0ebdcb..f42ed6d33 100644 --- a/src/dc_aheader.rs +++ b/src/dc_aheader.rs @@ -1,283 +1,318 @@ -use mmime::mailimf_types::*; +use std::collections::BTreeMap; +use std::ffi::{CStr, CString}; +use std::str::FromStr; +use std::{fmt, str}; +use mmime::mailimf_types::*; +use num_traits::ToPrimitive; + +use crate::constants::*; use crate::dc_contact::*; use crate::dc_key::*; -use crate::dc_strbuilder::*; -use crate::dc_tools::*; -use crate::types::*; -use crate::x::*; + +/// Possible values for encryption preference +#[derive(PartialEq, Eq, Debug, Clone, Copy, FromPrimitive, ToPrimitive)] +#[repr(u8)] +pub enum EncryptPreference { + NoPreference = 0, + Mutual = 1, + Reset = 20, +} + +impl Default for EncryptPreference { + fn default() -> Self { + EncryptPreference::NoPreference + } +} + +impl fmt::Display for EncryptPreference { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + EncryptPreference::Mutual => write!(fmt, "mutual"), + EncryptPreference::NoPreference => write!(fmt, "nopreference"), + EncryptPreference::Reset => write!(fmt, "reset"), + } + } +} + +impl str::FromStr for EncryptPreference { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "mutual" => Ok(EncryptPreference::Mutual), + "reset" => Ok(EncryptPreference::Reset), + _ => Ok(EncryptPreference::NoPreference), + } + } +} /// Parse and create [Autocrypt-headers](https://autocrypt.org/en/latest/level1.html#the-autocrypt-header). -#[derive(Copy, Clone)] -#[repr(C)] -pub struct dc_aheader_t { - pub addr: *mut libc::c_char, +pub struct Aheader { + pub addr: String, pub public_key: *mut dc_key_t, - pub prefer_encrypt: libc::c_int, + pub prefer_encrypt: EncryptPreference, } -/// the returned pointer is ref'd and must be unref'd after usage -pub unsafe fn dc_aheader_new() -> *mut dc_aheader_t { - let mut aheader = calloc(1, ::std::mem::size_of::()) as *mut dc_aheader_t; - - if aheader.is_null() { - // TODO replace with enum (hardcoded in deltachat-core) /rtn - exit(37); +impl Aheader { + pub fn new(addr: String, public_key: *mut dc_key_t, prefer_encrypt: EncryptPreference) -> Self { + Aheader { + addr, + public_key, + prefer_encrypt, + } } - (*aheader).public_key = dc_key_new(); + pub fn from_imffields( + wanted_from: *const libc::c_char, + header: *const mailimf_fields, + ) -> Option { + if wanted_from.is_null() || header.is_null() { + return None; + } - aheader -} + let mut fine_header = None; + let mut cur = unsafe { (*(*header).fld_list).first }; -pub unsafe fn dc_aheader_new_from_imffields( - wanted_from: *const libc::c_char, - header: *const mailimf_fields, -) -> *mut dc_aheader_t { - let mut cur; - let mut fine_header = 0 as *mut dc_aheader_t; - - if wanted_from.is_null() || header.is_null() { - return 0 as *mut dc_aheader_t; - } - - cur = (*(*header).fld_list).first; - while !cur.is_null() { - let field = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimf_field; - - if !field.is_null() && (*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() - && !(*optional_field).fld_name.is_null() - && strcasecmp( - (*optional_field).fld_name, - b"Autocrypt\x00" as *const u8 as *const libc::c_char, - ) == 0 + 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 mut test = dc_aheader_new(); - if 0 == dc_aheader_set_from_string(test, (*optional_field).fld_value) - || dc_addr_cmp((*test).addr, wanted_from) != 0 + 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_str().unwrap() } + == "Autocrypt" { - dc_aheader_unref(test); - test = 0 as *mut dc_aheader_t - } - if fine_header.is_null() { - fine_header = test - } else if !test.is_null() { - dc_aheader_unref(fine_header); - dc_aheader_unref(test); - return 0 as *mut dc_aheader_t; + let value = unsafe { + CStr::from_ptr((*optional_field).fld_value) + .to_str() + .unwrap() + }; + + match Self::from_str(value) { + Ok(test) => { + // TODO: implement rust-safe version of dc_addr_cmp + let addr = CString::new(test.addr.clone()).unwrap(); + if unsafe { dc_addr_cmp(addr.as_ptr(), wanted_from) } == 0 { + if fine_header.is_none() { + fine_header = Some(test); + } else { + // TODO: figure out what kind of error case this is + return None; + } + } + } + _ => {} + } } } + + cur = unsafe { (*cur).next }; } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell - } - } - - fine_header -} - -pub unsafe fn dc_aheader_unref(aheader: *mut dc_aheader_t) { - if aheader.is_null() { - return; - } - free((*aheader).addr as *mut libc::c_void); - dc_key_unref((*aheader).public_key); - free(aheader as *mut libc::c_void); -} - -pub unsafe fn dc_aheader_set_from_string( - mut aheader: *mut dc_aheader_t, - header_str__: *const libc::c_char, -) -> libc::c_int { - let current_block: u64; - /* according to RFC 5322 (Internet Message Format), the given string may contain `\r\n` before any whitespace. - we can ignore this issue as - (a) no key or value is expected to contain spaces, - (b) for the key, non-base64-characters are ignored and - (c) for parsing, we ignore `\r\n` as well as tabs for spaces */ - let mut header_str = 0 as *mut libc::c_char; - let mut p; - let mut beg_attr_name; - let mut after_attr_name; - let mut beg_attr_value; - let mut success: libc::c_int = 0; - - dc_aheader_empty(aheader); - if !(aheader.is_null() || header_str__.is_null()) { - (*aheader).prefer_encrypt = 0; - header_str = dc_strdup(header_str__); - p = header_str; - loop { - if !(0 != *p) { - current_block = 5689316957504528238; - break; - } - p = p.offset(strspn(p, b"\t\r\n =;\x00" as *const u8 as *const libc::c_char) as isize); - beg_attr_name = p; - beg_attr_value = 0 as *mut libc::c_char; - p = p.offset(strcspn(p, b"\t\r\n =;\x00" as *const u8 as *const libc::c_char) as isize); - if !(p != beg_attr_name) { - continue; - } - after_attr_name = p; - p = p.offset(strspn(p, b"\t\r\n \x00" as *const u8 as *const libc::c_char) as isize); - if *p as libc::c_int == '=' as i32 { - p = p.offset( - strspn(p, b"\t\r\n =\x00" as *const u8 as *const libc::c_char) as isize, - ); - beg_attr_value = p; - p = p.offset(strcspn(p, b";\x00" as *const u8 as *const libc::c_char) as isize); - if *p as libc::c_int != '\u{0}' as i32 { - *p = '\u{0}' as i32 as libc::c_char; - p = p.offset(1isize) - } - dc_trim(beg_attr_value); - } else { - p = p - .offset(strspn(p, b"\t\r\n ;\x00" as *const u8 as *const libc::c_char) as isize) - } - *after_attr_name = '\u{0}' as i32 as libc::c_char; - if !(0 == add_attribute(aheader, beg_attr_name, beg_attr_value)) { - continue; - } - /* a bad attribute makes the whole header invalid */ - current_block = 9271062167157603455; - break; - } - match current_block { - 9271062167157603455 => {} - _ => { - if !(*aheader).addr.is_null() && !(*(*aheader).public_key).binary.is_null() { - success = 1 - } - } - } - } - free(header_str as *mut libc::c_void); - if 0 == success { - dc_aheader_empty(aheader); - } - - success -} - -pub unsafe fn dc_aheader_empty(mut aheader: *mut dc_aheader_t) { - if aheader.is_null() { - return; - } - (*aheader).prefer_encrypt = 0; - free((*aheader).addr as *mut libc::c_void); - (*aheader).addr = 0 as *mut libc::c_char; - - if !(*(*aheader).public_key).binary.is_null() { - dc_key_unref((*aheader).public_key); - (*aheader).public_key = dc_key_new() + fine_header } } -/* ****************************************************************************** - * Parse Autocrypt Header - ******************************************************************************/ - -unsafe fn add_attribute( - mut aheader: *mut dc_aheader_t, - name: *const libc::c_char, - value: *const libc::c_char, -) -> libc::c_int { - if strcasecmp(name, b"addr\x00" as *const u8 as *const libc::c_char) == 0 { - if value.is_null() || !dc_may_be_valid_addr(value) || !(*aheader).addr.is_null() { - return 0; - } - (*aheader).addr = dc_addr_normalize(value); - return 1; - } else { - if strcasecmp( - name, - b"prefer-encrypt\x00" as *const u8 as *const libc::c_char, - ) == 0 - { - if !value.is_null() - && strcasecmp(value, b"mutual\x00" as *const u8 as *const libc::c_char) == 0 - { - (*aheader).prefer_encrypt = 1; - return 1; - } - return 1; - } else { - if strcasecmp(name, b"keydata\x00" as *const u8 as *const libc::c_char) == 0 { - if value.is_null() - || !(*(*aheader).public_key).binary.is_null() - || 0 != (*(*aheader).public_key).bytes - { - return 0; - } - return dc_key_set_from_base64((*aheader).public_key, value, 0); - } else { - if *name.offset(0isize) as libc::c_int == '_' as i32 { - return 1; - } - } - } - } - - 0 -} - -pub unsafe fn dc_aheader_render(aheader: *const dc_aheader_t) -> *mut libc::c_char { - let mut success: bool = false; - let mut keybase64_wrapped: *mut libc::c_char = 0 as *mut libc::c_char; - let mut ret: dc_strbuilder_t = dc_strbuilder_t { - buf: 0 as *mut libc::c_char, - allocated: 0, - free: 0, - eos: 0 as *mut libc::c_char, - }; - dc_strbuilder_init(&mut ret, 0); - if !(aheader.is_null() - || (*aheader).addr.is_null() - || (*(*aheader).public_key).binary.is_null() - || (*(*aheader).public_key).type_0 != 0) - { - dc_strbuilder_cat(&mut ret, b"addr=\x00" as *const u8 as *const libc::c_char); - dc_strbuilder_cat(&mut ret, (*aheader).addr); - dc_strbuilder_cat(&mut ret, b"; \x00" as *const u8 as *const libc::c_char); - if (*aheader).prefer_encrypt == 1 { - dc_strbuilder_cat( - &mut ret, - b"prefer-encrypt=mutual; \x00" as *const u8 as *const libc::c_char, - ); - } - dc_strbuilder_cat( - &mut ret, - b"keydata= \x00" as *const u8 as *const libc::c_char, - ); +impl fmt::Display for Aheader { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { // TODO replace 78 with enum /rtn - /* adds a whitespace every 78 characters, this allows libEtPan to wrap the lines according to RFC 5322 - (which may insert a linebreak before every whitespace) */ - keybase64_wrapped = dc_key_render_base64((*aheader).public_key, 78); - - if !keybase64_wrapped.is_null() { - /*no checksum*/ - dc_strbuilder_cat(&mut ret, keybase64_wrapped); - success = true; - } + // adds a whitespace every 78 characters, this allows libEtPan to + // wrap the lines according to RFC 5322 + // (which may insert a linebreak before every whitespace) + let keydata = dc_key_render_base64_string(self.public_key, 78); + write!( + fmt, + "addr={}; prefer-encrypt={}; keydata={}", + self.addr, self.prefer_encrypt, keydata + ) + } +} + +impl str::FromStr for Aheader { + type Err = (); + + fn from_str(s: &str) -> Result { + let mut attributes: BTreeMap = s + .split(";") + .filter_map(|a| { + let attribute: Vec<&str> = a.trim().splitn(2, "=").collect(); + if attribute.len() < 2 { + return None; + } + + Some(( + attribute[0].trim().to_string(), + attribute[1].trim().to_string(), + )) + }) + .collect(); + + let addr = match attributes.remove("addr") { + Some(addr) => addr, + None => { + return Err(()); + } + }; + + let public_key = match attributes.remove("keydata") { + Some(raw) => { + let key = unsafe { dc_key_new() }; + unsafe { + dc_key_set_from_base64( + key, + CString::new(raw).unwrap().as_ptr(), + Key::Public.to_i32().unwrap(), + ) + }; + key + } + None => { + return Err(()); + } + }; + + let prefer_encrypt = match attributes + .remove("prefer-encrypt") + .and_then(|raw| raw.parse().ok()) + { + Some(pref) => pref, + None => EncryptPreference::NoPreference, + }; + + // Autocrypt-Level0: unknown attributes starting with an underscore can be safely ignored + // Autocrypt-Level0: unknown attribute, treat the header as invalid + if attributes.keys().find(|k| !k.starts_with("_")).is_some() { + return Err(()); + } + + Ok(Aheader { + addr, + public_key, + prefer_encrypt, + }) + } +} + +impl Drop for Aheader { + fn drop(&mut self) { + unsafe { + dc_key_unref(self.public_key); + } + self.public_key = std::ptr::null_mut(); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::pgp as rpgp; + + fn rawkey() -> String { + "mDMEWFUX7RYJKwYBBAHaRw8BAQdACHq6FkRGsHqBMsNpD7d+aQ2jtxVwTO+Y4NhBaQyHaMj+0HWFsaWNlQHRlc3RzdWl0ZS5hdXRvY3J5cHQub3JniJAEExYIADgWIQQmqmdR/XZoxC+kkkr8dE2p/nPD1AUCWFUX7QIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRD8dE2p/nPD1EqOAP0WUDKwko001X7XTSYbWGWmXfR9P1Aw6917EnkVQMsp3gEA86Ii8ArL3jd+E2qS5JSysx/qiVhuTSwWzmC5K6zKdg+4OARYVRfuEgorBgEEAZdVAQUBAQdAv1A88FoCfwz0zSh6NNnUuKuz1p3ctJ3kXMGotsVYjA0DAQgHiHgEGBYIACAWIQQmqmdR/XZoxC+kkkr8dE2p/nPD1AUCWFUX7gIbDAAKCRD8dE2p/nPD1FTOAP4nS14sX7a/nBXBKWAh/oX8iVtkhmZqjy9tG21BcNqb+wEAq73H4+1ncnkscR3Nu4GYzNRSD3NXq68tEESK28kYvw4=".into() + } + + #[test] + fn test_from_str() { + let h: Aheader = format!( + "addr=me@mail.com; prefer-encrypt=mutual; keydata={}", + rawkey() + ) + .parse() + .expect("failed to parse"); + + assert_eq!(h.addr, "me@mail.com"); + assert_eq!(h.prefer_encrypt, EncryptPreference::Mutual); + assert!(!h.public_key.is_null()); + } + + #[test] + fn test_from_str_non_critical() { + let raw = format!("addr=me@mail.com; _foo=one; _bar=two; keydata={}", rawkey()); + let h: Aheader = raw.parse().expect("failed to parse"); + + assert_eq!(h.addr, "me@mail.com"); + assert_eq!(h.prefer_encrypt, EncryptPreference::NoPreference); + assert!(!h.public_key.is_null()); + } + + #[test] + fn test_from_str_superflous_critical() { + let raw = format!( + "addr=me@mail.com; _foo=one; _bar=two; other=me; keydata={}", + rawkey() + ); + assert!(raw.parse::().is_err()); + } + + #[test] + fn test_good_headers() { + let fixed_header = "addr=a@b.example.org; prefer-encrypt=mutual; keydata=xsBNBFzG3j0BCAC6iNhT8zydvCXi8LI/gFnkadMbfmSE/rTJskRRra/utGbLyDta/yTrJgWL7O3y/g 4HdDW/dN2z26Y6W13IMzx9gLInn1KQZChtqWAcr/ReUucXcymwcfg1mdkBGk3TSLeLihN6CJx8Wsv8 ig+kgAzte4f5rqEEAJVQ9WZHuti7UiYs6oRzqTo06CRe9owVXxzdMf0VDQtf7ZFm9dpzKKbhH7Lu88 80iiotQ9/yRCkDGp9fNThsrLdZiK6OIAcIBAqi2rI89aS1dAmnRbktQieCx5izzyYkR1KvVL3gTTll HOzfKVEC2asmtWu2e4se/+O4WMIS1eGrn7GeWVb0Vwc5ABEBAAHNETxhQEBiLmV4YW1wbGUuZGU+ws CJBBABCAAzAhkBBQJcxt5FAhsDBAsJCAcGFQgJCgsCAxYCARYhBI4xxYKBgH3ANh5cufaKrc9mtiML AAoJEPaKrc9mtiML938H/18F+3Wf9/JaAy/8hCO1v4S2PVBhxaKCokaNFtkfaMRne2l087LscCFPiF Nyb4mv6Z3YeK8Xpxlp2sI0ecvdiqLUOGfnxS6tQrj+83EjtIrZ/hXOk1h121QFWH9Zg2VNHtODXjAg dLDC0NWUrclR0ZOqEDQHeo0ibTILdokVfXFN25wakPmGaYJP2y729cb1ve7RzvIvwn+Dddfxo3ao72 rBfLi7l4NQ4S0KsY4cw+/6l5bRCKYCP77wZtvCwUvfVVosLdT43agtSiBI49+ayqvZ8OCvSJa61i+v 81brTiEy9GBod4eAp45Ibsuemkw+gon4ZOvUXHTjwFB+h63MrozOwE0EXMbePQEIAL/vauf1zK8JgC u3V+G+SOX0iWw5xUlCPX+ERpBbWfwu3uAqn4wYXD3JDE/fVAF668xiV4eTPtlSUd5h0mn+G7uXMMOt kb+20SoEt50f8zw8TrL9t+ZsV11GKZWJpCar5AhXWsn6EEi8I2hLL5vn55ZZmHuGgN4jjmkRl3ToKC LhaXwTBjCJem7N5EH7F75wErEITa55v4Lb4Nfca7vnvtYrI1OA446xa8gHra0SINelTD09/JM/Fw4s WVPBaRZmJK/Tnu79N23No9XBUubmFPv1pNexZsQclicnTpt/BEWhiun7d6lfGB63K1aoHRTR1pcrWv BuALuuz0gqar2zlI0AEQEAAcLAdgQYAQgAIAUCXMbeRQIbDBYhBI4xxYKBgH3ANh5cufaKrc9mtiML AAoJEPaKrc9mtiMLKSEIAIyLCRO2OyZ0IYRvRPpMn4p7E+7Pfcz/0mSkOy+1hshgJnqivXurm8zwGr wdMqeV4eslKR9H1RUdWGUQJNbtwmmjrt5DHpIhYHl5t3FpCBaGbV20Omo00Q38lBl9MtrmZkZw+ktE k6X+0xCKssMF+2MADkSOIufbR5HrDVB89VZOHCO9DeXvCUUAw2hyJiL/LHmLzJ40zYoTmb+F//f0k0 j+tRdbkefyRoCmwG7YGiT+2hnCdgcezswnzah5J3ZKlrg7jOGo1LxtbvNUzxNBbC6S/aNgwm6qxo7x egRhmEl5uZ16zwyj4qz+xkjGy25Of5mWfUDoNw7OT7sjUbHOOMc="; + + let ah = Aheader::from_str(fixed_header).expect("failed to parse"); + assert_eq!(ah.addr, "a@b.example.org"); + // assert_eq!(unsafe { (*ah.public_key).bytes }, 1212); + assert!(valid_key(ah.public_key as *const _)); + assert_eq!(ah.prefer_encrypt, EncryptPreference::Mutual); + + let rendered = ah.to_string(); + assert_eq!(rendered, fixed_header); + + let ah = Aheader::from_str(" _foo; __FOO=BAR ;;; addr = a@b.example.org ;\r\n prefer-encrypt = mutual ; keydata = RG VsdGEgQ\r\n2hhdA==").expect("failed to parse"); + assert_eq!(ah.addr, "a@b.example.org"); + assert_eq!(unsafe { (*ah.public_key).bytes }, 10); + assert_eq!(ah.prefer_encrypt, EncryptPreference::Mutual); + assert_eq!( + unsafe { + CStr::from_ptr((*ah.public_key).binary as *const _) + .to_str() + .unwrap() + }, + "Delta Chat" + ); + + Aheader::from_str( + "addr=a@b.example.org; prefer-encrypt=ignoreUnknownValues; keydata=RGVsdGEgQ2hhdA==", + ) + .expect("failed to parse"); + + Aheader::from_str("addr=a@b.example.org; keydata=RGVsdGEgQ2hhdA==") + .expect("failed to parse"); + } + + #[test] + fn test_bad_headers() { + assert!(Aheader::from_str("").is_err()); + assert!(Aheader::from_str("foo").is_err()); + assert!(Aheader::from_str("\n\n\n").is_err()); + assert!(Aheader::from_str(" ;;").is_err()); + assert!(Aheader::from_str("addr=a@t.de; unknwon=1; keydata=jau").is_err()); + } + + fn valid_key(raw_key: *const dc_key_t) -> bool { + let mut key_is_valid = false; + unsafe { + if !(raw_key.is_null() || (*raw_key).binary.is_null() || (*raw_key).bytes <= 0i32) { + let key = rpgp::rpgp_key_from_bytes( + (*raw_key).binary as *const _, + (*raw_key).bytes as usize, + ); + + if (*raw_key).type_0 == 0i32 && 0 != rpgp::rpgp_key_is_public(key) as libc::c_int { + key_is_valid = true; + } else if (*raw_key).type_0 == 1i32 + && 0 != rpgp::rpgp_key_is_secret(key) as libc::c_int + { + key_is_valid = true; + } + if !key.is_null() { + rpgp::rpgp_key_drop(key); + } + } + } + + key_is_valid } - - if !success { - free(ret.buf as *mut libc::c_void); - ret.buf = 0 as *mut libc::c_char - } - - free(keybase64_wrapped as *mut libc::c_void); - - ret.buf } diff --git a/src/dc_apeerstate.rs b/src/dc_apeerstate.rs index d46477dbf..29758bffb 100644 --- a/src/dc_apeerstate.rs +++ b/src/dc_apeerstate.rs @@ -1,3 +1,7 @@ +use std::ffi::{CStr, CString}; + +use num_traits::ToPrimitive; + use crate::dc_aheader::*; use crate::dc_chat::*; use crate::dc_context::dc_context_t; @@ -81,20 +85,20 @@ unsafe fn dc_apeerstate_empty(mut peerstate: *mut dc_apeerstate_t) { // TODO should return bool /rtn pub unsafe fn dc_apeerstate_init_from_header( mut peerstate: *mut dc_apeerstate_t, - header: *const dc_aheader_t, + header: &Aheader, message_time: time_t, ) -> libc::c_int { - if peerstate.is_null() || header.is_null() { + if peerstate.is_null() { return 0i32; } dc_apeerstate_empty(peerstate); - (*peerstate).addr = dc_strdup((*header).addr); + (*peerstate).addr = dc_strdup(CString::new(header.addr.clone()).unwrap().as_ptr()); (*peerstate).last_seen = message_time; (*peerstate).last_seen_autocrypt = message_time; (*peerstate).to_save |= 0x2i32; - (*peerstate).prefer_encrypt = (*header).prefer_encrypt; + (*peerstate).prefer_encrypt = header.prefer_encrypt.to_i32().unwrap(); (*peerstate).public_key = dc_key_new(); - dc_key_set_from_key((*peerstate).public_key, (*header).public_key); + dc_key_set_from_key((*peerstate).public_key, header.public_key); dc_apeerstate_recalc_fingerprint(peerstate); 1 @@ -152,20 +156,20 @@ pub unsafe fn dc_apeerstate_recalc_fingerprint(mut peerstate: *mut dc_apeerstate } // TODO should return bool /rtn -pub unsafe extern "C" fn dc_apeerstate_init_from_gossip( +pub unsafe fn dc_apeerstate_init_from_gossip( mut peerstate: *mut dc_apeerstate_t, - gossip_header: *const dc_aheader_t, + gossip_header: &Aheader, message_time: time_t, ) -> libc::c_int { - if peerstate.is_null() || gossip_header.is_null() { + if peerstate.is_null() { return 0i32; } dc_apeerstate_empty(peerstate); - (*peerstate).addr = dc_strdup((*gossip_header).addr); + (*peerstate).addr = dc_strdup(CString::new(gossip_header.addr.clone()).unwrap().as_ptr()); (*peerstate).gossip_timestamp = message_time; (*peerstate).to_save |= 0x2i32; (*peerstate).gossip_key = dc_key_new(); - dc_key_set_from_key((*peerstate).gossip_key, (*gossip_header).public_key); + dc_key_set_from_key((*peerstate).gossip_key, gossip_header.public_key); dc_apeerstate_recalc_fingerprint(peerstate); 1 @@ -191,15 +195,17 @@ pub unsafe fn dc_apeerstate_degrade_encryption( pub unsafe fn dc_apeerstate_apply_header( mut peerstate: *mut dc_apeerstate_t, - header: *const dc_aheader_t, + header: &Aheader, message_time: time_t, ) { if peerstate.is_null() - || header.is_null() || (*peerstate).addr.is_null() - || (*header).addr.is_null() - || (*(*header).public_key).binary.is_null() - || strcasecmp((*peerstate).addr, (*header).addr) != 0i32 + || (*header.public_key).binary.is_null() + || CStr::from_ptr((*peerstate).addr) + .to_str() + .unwrap() + .to_lowercase() + != header.addr.to_lowercase() { return; } @@ -207,13 +213,16 @@ pub unsafe fn dc_apeerstate_apply_header( (*peerstate).last_seen = message_time; (*peerstate).last_seen_autocrypt = message_time; (*peerstate).to_save |= 0x1i32; - if ((*header).prefer_encrypt == 1i32 || (*header).prefer_encrypt == 0i32) - && (*header).prefer_encrypt != (*peerstate).prefer_encrypt + if (header.prefer_encrypt == EncryptPreference::Mutual + || header.prefer_encrypt == EncryptPreference::NoPreference) + && header.prefer_encrypt.to_i32().unwrap() != (*peerstate).prefer_encrypt { - if (*peerstate).prefer_encrypt == 1i32 && (*header).prefer_encrypt != 1i32 { + if (*peerstate).prefer_encrypt == 1i32 + && header.prefer_encrypt != EncryptPreference::Mutual + { (*peerstate).degrade_event |= 0x1i32 } - (*peerstate).prefer_encrypt = (*header).prefer_encrypt; + (*peerstate).prefer_encrypt = header.prefer_encrypt.to_i32().unwrap(); (*peerstate).to_save |= 0x2i32 } if (*peerstate).public_key.is_null() { @@ -229,15 +238,17 @@ pub unsafe fn dc_apeerstate_apply_header( pub unsafe fn dc_apeerstate_apply_gossip( mut peerstate: *mut dc_apeerstate_t, - gossip_header: *const dc_aheader_t, + gossip_header: &Aheader, message_time: time_t, ) { if peerstate.is_null() - || gossip_header.is_null() || (*peerstate).addr.is_null() - || (*gossip_header).addr.is_null() || (*(*gossip_header).public_key).binary.is_null() - || strcasecmp((*peerstate).addr, (*gossip_header).addr) != 0i32 + || CStr::from_ptr((*peerstate).addr) + .to_str() + .unwrap() + .to_lowercase() + != gossip_header.addr.to_lowercase() { return; } @@ -259,16 +270,17 @@ pub unsafe fn dc_apeerstate_render_gossip_header( peerstate: *const dc_apeerstate_t, min_verified: libc::c_int, ) -> *mut libc::c_char { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; - let mut autocryptheader: *mut dc_aheader_t = dc_aheader_new(); if !(peerstate.is_null() || (*peerstate).addr.is_null()) { - (*autocryptheader).prefer_encrypt = 0i32; - (*autocryptheader).addr = dc_strdup((*peerstate).addr); - (*autocryptheader).public_key = dc_key_ref(dc_apeerstate_peek_key(peerstate, min_verified)); - ret = dc_aheader_render(autocryptheader) + let addr = CStr::from_ptr((*peerstate).addr).to_str().unwrap().into(); + let key = dc_key_ref(dc_apeerstate_peek_key(peerstate, min_verified)); + let header = Aheader::new(addr, key, EncryptPreference::NoPreference); + let rendered = header.to_string(); + let rendered_c = CString::new(rendered).unwrap(); + + libc::strdup(rendered_c.as_ptr()) + } else { + std::ptr::null_mut() } - dc_aheader_unref(autocryptheader); - ret } pub unsafe fn dc_apeerstate_peek_key( diff --git a/src/dc_array.rs b/src/dc_array.rs index 79323b991..442d88def 100644 --- a/src/dc_array.rs +++ b/src/dc_array.rs @@ -263,10 +263,7 @@ pub unsafe fn dc_array_new(initsize: size_t) -> *mut dc_array_t { dc_array_new_typed(0, initsize) } -pub unsafe extern "C" fn dc_array_new_typed( - type_0: libc::c_int, - initsize: size_t, -) -> *mut dc_array_t { +pub unsafe fn dc_array_new_typed(type_0: libc::c_int, initsize: size_t) -> *mut dc_array_t { let mut array: *mut dc_array_t; array = calloc(1, ::std::mem::size_of::()) as *mut dc_array_t; if array.is_null() { diff --git a/src/dc_chat.rs b/src/dc_chat.rs index 8741ab87c..29cdbbb9b 100644 --- a/src/dc_chat.rs +++ b/src/dc_chat.rs @@ -2279,7 +2279,7 @@ pub unsafe fn dc_chat_get_name(chat: *const dc_chat_t) -> *mut libc::c_char { dc_strdup((*chat).name) } -pub unsafe extern "C" fn dc_chat_get_subtitle(chat: *const dc_chat_t) -> *mut libc::c_char { +pub unsafe fn dc_chat_get_subtitle(chat: *const dc_chat_t) -> *mut libc::c_char { /* returns either the address or the number of chat members */ let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { diff --git a/src/dc_contact.rs b/src/dc_contact.rs index f5e4aa169..f786a3f72 100644 --- a/src/dc_contact.rs +++ b/src/dc_contact.rs @@ -46,7 +46,7 @@ pub unsafe fn dc_marknoticed_contact(context: &dc_context_t, contact_id: uint32_ } // handle contacts -pub unsafe extern "C" fn dc_may_be_valid_addr(addr: *const libc::c_char) -> bool { +pub unsafe fn dc_may_be_valid_addr(addr: *const libc::c_char) -> bool { if addr.is_null() { return false; } diff --git a/src/dc_e2ee.rs b/src/dc_e2ee.rs index 2e1241653..2ef64a25c 100644 --- a/src/dc_e2ee.rs +++ b/src/dc_e2ee.rs @@ -1,3 +1,6 @@ +use std::ffi::{CStr, CString}; +use std::str::FromStr; + use mmime::clist::*; use mmime::mailimf::*; use mmime::mailimf_types::*; @@ -53,11 +56,9 @@ pub unsafe fn dc_e2ee_encrypt( mut in_out_message: *mut mailmime, mut helper: *mut dc_e2ee_helper_t, ) { - let p_0: *mut libc::c_char; let current_block: u64; let mut col: libc::c_int = 0i32; let mut do_encrypt: libc::c_int = 0i32; - let mut autocryptheader: *mut dc_aheader_t = dc_aheader_new(); /*just a pointer into mailmime structure, must not be freed*/ let imffields_unprotected: *mut mailimf_fields; let keyring: *mut dc_keyring_t = dc_keyring_new(); @@ -73,42 +74,40 @@ pub unsafe fn dc_e2ee_encrypt( ::std::mem::size_of::(), ); } + if !(recipients_addr.is_null() || in_out_message.is_null() || !(*in_out_message).mm_parent.is_null() - || autocryptheader.is_null() || keyring.is_null() || sign_key.is_null() || plain.is_null() || helper.is_null()) { /* libEtPan's pgp_encrypt_mime() takes the parent as the new root. We just expect the root as being given to this function. */ - (*autocryptheader).prefer_encrypt = 0i32; - if 0 != dc_sqlite3_get_config_int( - context, - &context.sql.clone().read().unwrap(), - b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, - 1i32, - ) { - (*autocryptheader).prefer_encrypt = 1i32 - } - (*autocryptheader).addr = dc_sqlite3_get_config( + let prefer_encrypt = if 0 + != dc_sqlite3_get_config_int( + context, + &context.sql.clone().read().unwrap(), + b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, + 1, + ) { + EncryptPreference::Mutual + } else { + EncryptPreference::NoPreference + }; + + let addr = dc_sqlite3_get_config( context, &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); - if !(*autocryptheader).addr.is_null() { - if !(0 - == load_or_generate_self_public_key( - context, - (*autocryptheader).public_key, - (*autocryptheader).addr, - in_out_message, - )) - { + + let public_key = dc_key_new(); + if !addr.is_null() { + if 0 != load_or_generate_self_public_key(context, public_key, addr, in_out_message) { /*only for random-seed*/ - if (*autocryptheader).prefer_encrypt == 1i32 || 0 != e2ee_guaranteed { + if prefer_encrypt == EncryptPreference::Mutual || 0 != e2ee_guaranteed { do_encrypt = 1i32; let mut iter1: *mut clistiter; iter1 = (*recipients_addr).first; @@ -121,7 +120,7 @@ pub unsafe fn dc_e2ee_encrypt( as *const libc::c_char; let peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); let mut key_to_use: *mut dc_key_t = 0 as *mut dc_key_t; - if !(strcasecmp(recipient_addr, (*autocryptheader).addr) == 0i32) { + if !(strcasecmp(recipient_addr, addr) == 0i32) { if 0 != dc_apeerstate_load_by_addr( peerstate, &context.sql.clone().read().unwrap(), @@ -148,11 +147,11 @@ pub unsafe fn dc_e2ee_encrypt( } } if 0 != do_encrypt { - dc_keyring_add(keyring, (*autocryptheader).public_key); + dc_keyring_add(keyring, public_key); if 0 == dc_key_load_self_private( context, sign_key, - (*autocryptheader).addr, + addr, &context.sql.clone().read().unwrap(), ) { do_encrypt = 0i32 @@ -371,25 +370,24 @@ pub unsafe fn dc_e2ee_encrypt( match current_block { 14181132614457621749 => {} _ => { - p_0 = dc_aheader_render(autocryptheader); - if !p_0.is_null() { - mailimf_fields_add( - imffields_unprotected, - mailimf_field_new_custom( - strdup( - b"Autocrypt\x00" as *const u8 as *const libc::c_char, - ), - p_0, - ), - ); - } + let addr = CStr::from_ptr(addr).to_str().unwrap(); + let aheader = Aheader::new(addr.into(), public_key, prefer_encrypt); + let rendered = CString::new(aheader.to_string()).unwrap(); + + mailimf_fields_add( + imffields_unprotected, + mailimf_field_new_custom( + strdup(b"Autocrypt\x00" as *const u8 as *const libc::c_char), + libc::strdup(rendered.as_ptr()), + ), + ); } } } } } } - dc_aheader_unref(autocryptheader); + dc_keyring_unref(keyring); dc_key_unref(sign_key); if !plain.is_null() { @@ -645,7 +643,6 @@ pub unsafe fn dc_e2ee_decrypt( (to detect parts that could not be decrypted, simply look for left "multipart/encrypted" MIME types */ /*just a pointer into mailmime structure, must not be freed*/ let imffields: *mut mailimf_fields = mailmime_find_mailimf_fields(in_out_message); - let mut autocryptheader: *mut dc_aheader_t = 0 as *mut dc_aheader_t; let mut message_time: time_t = 0i32 as time_t; let peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); let mut from: *mut libc::c_char = 0 as *mut libc::c_char; @@ -680,11 +677,10 @@ pub unsafe fn dc_e2ee_decrypt( } } } - autocryptheader = dc_aheader_new_from_imffields(from, imffields); - if !autocryptheader.is_null() { - if 0 == dc_pgp_is_valid_key(context, (*autocryptheader).public_key) { - dc_aheader_unref(autocryptheader); - autocryptheader = 0 as *mut dc_aheader_t + let mut autocryptheader = Aheader::from_imffields(from, imffields); + if let Some(ref header) = autocryptheader { + if 0 == dc_pgp_is_valid_key(context, header.public_key) { + autocryptheader = None; } } if message_time > 0i32 as libc::c_long && !from.is_null() { @@ -693,8 +689,8 @@ pub unsafe fn dc_e2ee_decrypt( &context.sql.clone().read().unwrap(), from, ) { - if !autocryptheader.is_null() { - dc_apeerstate_apply_header(peerstate, autocryptheader, message_time); + if let Some(ref header) = autocryptheader { + dc_apeerstate_apply_header(peerstate, header, message_time); dc_apeerstate_save_to_db(peerstate, &context.sql.clone().read().unwrap(), 0i32); } else if message_time > (*peerstate).last_seen_autocrypt && 0 == contains_report(in_out_message) @@ -702,8 +698,8 @@ pub unsafe fn dc_e2ee_decrypt( dc_apeerstate_degrade_encryption(peerstate, message_time); dc_apeerstate_save_to_db(peerstate, &context.sql.clone().read().unwrap(), 0i32); } - } else if !autocryptheader.is_null() { - dc_apeerstate_init_from_header(peerstate, autocryptheader, message_time); + } else if let Some(ref header) = autocryptheader { + dc_apeerstate_init_from_header(peerstate, header, message_time); dc_apeerstate_save_to_db(peerstate, &context.sql.clone().read().unwrap(), 1i32); } } @@ -767,7 +763,7 @@ pub unsafe fn dc_e2ee_decrypt( if !gossip_headers.is_null() { mailimf_fields_free(gossip_headers); } - dc_aheader_unref(autocryptheader); + dc_apeerstate_unref(peerstate); dc_keyring_unref(private_keyring); dc_keyring_unref(public_keyring_for_validate); @@ -801,66 +797,70 @@ unsafe fn update_gossip_peerstates( b"Autocrypt-Gossip\x00" as *const u8 as *const libc::c_char, ) == 0i32 { - let gossip_header: *mut dc_aheader_t = dc_aheader_new(); - if 0 != dc_aheader_set_from_string(gossip_header, (*optional_field).fld_value) - && 0 != dc_pgp_is_valid_key(context, (*gossip_header).public_key) - { - if recipients.is_null() { - recipients = mailimf_get_recipients(imffields) - } - if !dc_hash_find( - recipients, - (*gossip_header).addr as *const libc::c_void, - strlen((*gossip_header).addr) as libc::c_int, - ) - .is_null() - { - let peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); - if 0 == dc_apeerstate_load_by_addr( - peerstate, - &context.sql.clone().read().unwrap(), - (*gossip_header).addr, - ) { - dc_apeerstate_init_from_gossip(peerstate, gossip_header, message_time); - dc_apeerstate_save_to_db( + let value = CStr::from_ptr((*optional_field).fld_value) + .to_str() + .unwrap(); + let gossip_header = Aheader::from_str(value); + if let Ok(ref header) = gossip_header { + if 0 != dc_pgp_is_valid_key(context, header.public_key) { + if recipients.is_null() { + recipients = mailimf_get_recipients(imffields) + } + if !dc_hash_find( + recipients, + CString::new(header.addr.clone()).unwrap().as_ptr() + as *const libc::c_void, + header.addr.len() as i32, + ) + .is_null() + { + let peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); + if 0 == dc_apeerstate_load_by_addr( peerstate, &context.sql.clone().read().unwrap(), - 1i32, + CString::new(header.addr.clone()).unwrap().as_ptr(), + ) { + dc_apeerstate_init_from_gossip(peerstate, header, message_time); + dc_apeerstate_save_to_db( + peerstate, + &context.sql.clone().read().unwrap(), + 1i32, + ); + } else { + dc_apeerstate_apply_gossip(peerstate, header, message_time); + dc_apeerstate_save_to_db( + peerstate, + &context.sql.clone().read().unwrap(), + 0i32, + ); + } + if 0 != (*peerstate).degrade_event { + dc_handle_degrade_event(context, peerstate); + } + dc_apeerstate_unref(peerstate); + if gossipped_addr.is_null() { + gossipped_addr = + malloc(::std::mem::size_of::()) as *mut dc_hash_t; + dc_hash_init(gossipped_addr, 3i32, 1i32); + } + dc_hash_insert( + gossipped_addr, + CString::new(header.addr.clone()).unwrap().as_ptr() + as *const libc::c_void, + header.addr.len() as libc::c_int, + 1i32 as *mut libc::c_void, ); } else { - dc_apeerstate_apply_gossip(peerstate, gossip_header, message_time); - dc_apeerstate_save_to_db( - peerstate, - &context.sql.clone().read().unwrap(), + dc_log_info( + context, 0i32, + b"Ignoring gossipped \"%s\" as the address is not in To/Cc list.\x00" + as *const u8 as *const libc::c_char, + CString::new(header.addr.clone()).unwrap().as_ptr(), ); } - if 0 != (*peerstate).degrade_event { - dc_handle_degrade_event(context, peerstate); - } - dc_apeerstate_unref(peerstate); - if gossipped_addr.is_null() { - gossipped_addr = - malloc(::std::mem::size_of::()) as *mut dc_hash_t; - dc_hash_init(gossipped_addr, 3i32, 1i32); - } - dc_hash_insert( - gossipped_addr, - (*gossip_header).addr as *const libc::c_void, - strlen((*gossip_header).addr) as libc::c_int, - 1i32 as *mut libc::c_void, - ); - } else { - dc_log_info( - context, - 0i32, - b"Ignoring gossipped \"%s\" as the address is not in To/Cc list.\x00" - as *const u8 as *const libc::c_char, - (*gossip_header).addr, - ); } } - dc_aheader_unref(gossip_header); } } cur1 = if !cur1.is_null() { diff --git a/src/dc_hash.rs b/src/dc_hash.rs index d1ae2e4b9..e63c94b7b 100644 --- a/src/dc_hash.rs +++ b/src/dc_hash.rs @@ -224,7 +224,7 @@ pub unsafe fn dc_hash_insert( /* Link an element into the hash table */ -unsafe extern "C" fn insertElement( +unsafe fn insertElement( mut pH: *mut dc_hash_t, mut pEntry: *mut _ht, mut pNew: *mut dc_hashelem_t, diff --git a/src/dc_job.rs b/src/dc_job.rs index 854e881e2..49029d0d1 100644 --- a/src/dc_job.rs +++ b/src/dc_job.rs @@ -303,7 +303,7 @@ unsafe fn dc_suspend_smtp_thread(context: &dc_context_t, suspend: libc::c_int) { } } } -unsafe extern "C" fn dc_job_do_DC_JOB_SEND(context: &dc_context_t, job: &mut dc_job_t) { +unsafe fn dc_job_do_DC_JOB_SEND(context: &dc_context_t, job: &mut dc_job_t) { let mut current_block: u64; let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; let mut buf: *mut libc::c_void = 0 as *mut libc::c_void; diff --git a/src/dc_jobthread.rs b/src/dc_jobthread.rs index 42cd573c0..9059784b7 100644 --- a/src/dc_jobthread.rs +++ b/src/dc_jobthread.rs @@ -86,10 +86,7 @@ pub unsafe fn dc_jobthread_suspend( } } -pub unsafe extern "C" fn dc_jobthread_interrupt_idle( - context: &dc_context_t, - jobthread: &dc_jobthread_t, -) { +pub unsafe fn dc_jobthread_interrupt_idle(context: &dc_context_t, jobthread: &dc_jobthread_t) { { jobthread.state.clone().0.lock().unwrap().jobs_needed = 1; } diff --git a/src/dc_key.rs b/src/dc_key.rs index b6865a722..3d91fbe5b 100644 --- a/src/dc_key.rs +++ b/src/dc_key.rs @@ -118,7 +118,7 @@ pub unsafe fn dc_key_set_from_key(key: *mut dc_key_t, o: *const dc_key_t) -> lib } // TODO should return bool /rtn -pub unsafe extern "C" fn dc_key_set_from_stmt( +pub unsafe fn dc_key_set_from_stmt( key: *mut dc_key_t, stmt: *mut sqlite3_stmt, index: libc::c_int, @@ -297,11 +297,8 @@ pub unsafe fn dc_key_load_self_private( success } -/* the result must be freed */ -pub fn dc_key_render_base64(key: *const dc_key_t, break_every: usize) -> *mut libc::c_char { - if key.is_null() { - return std::ptr::null_mut(); - } +pub fn dc_key_render_base64_string(key: *const dc_key_t, break_every: usize) -> String { + assert!(!key.is_null(), "missing key"); let key = unsafe { *key }; let bytes = unsafe { slice::from_raw_parts(key.binary as *const u8, key.bytes as usize) }; @@ -318,7 +315,7 @@ pub fn dc_key_render_base64(key: *const dc_key_t, break_every: usize) -> *mut li }; let encoded = base64::encode(&buf); - let res = encoded + encoded .as_bytes() .chunks(break_every) .fold(String::new(), |mut res, buf| { @@ -326,8 +323,14 @@ pub fn dc_key_render_base64(key: *const dc_key_t, break_every: usize) -> *mut li res += unsafe { std::str::from_utf8_unchecked(buf) }; res += " "; res - }); + }) + .trim() + .to_string() +} +/* the result must be freed */ +pub fn dc_key_render_base64(key: *const dc_key_t, break_every: usize) -> *mut libc::c_char { + let res = dc_key_render_base64_string(key, break_every); let res_c = CString::new(res.trim()).unwrap(); // need to use strdup to allocate the result with malloc diff --git a/src/dc_location.rs b/src/dc_location.rs index 03fe5db12..67d76188a 100644 --- a/src/dc_location.rs +++ b/src/dc_location.rs @@ -129,7 +129,7 @@ unsafe fn schedule_MAYBE_SEND_LOCATIONS(context: &dc_context_t, flags: libc::c_i }; } -pub unsafe extern "C" fn dc_is_sending_locations_to_chat( +pub unsafe fn dc_is_sending_locations_to_chat( context: &dc_context_t, chat_id: uint32_t, ) -> libc::c_int { diff --git a/src/dc_oauth2.rs b/src/dc_oauth2.rs index 7ed5f0294..c63e663bd 100644 --- a/src/dc_oauth2.rs +++ b/src/dc_oauth2.rs @@ -469,7 +469,7 @@ unsafe fn jsondup(json: *const libc::c_char, tok: *mut jsmntok_t) -> *mut libc:: strdup(b"\x00" as *const u8 as *const libc::c_char) } -unsafe extern "C" fn jsoneq( +unsafe fn jsoneq( json: *const libc::c_char, tok: *mut jsmntok_t, s: *const libc::c_char, diff --git a/src/dc_saxparser.rs b/src/dc_saxparser.rs index 31897b536..af6c60a3a 100644 --- a/src/dc_saxparser.rs +++ b/src/dc_saxparser.rs @@ -20,10 +20,7 @@ pub type dc_saxparser_starttag_cb_t = Option< unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: *mut *mut libc::c_char) -> (), >; -pub unsafe extern "C" fn dc_saxparser_init( - mut saxparser: *mut dc_saxparser_t, - userdata: *mut libc::c_void, -) { +pub unsafe fn dc_saxparser_init(mut saxparser: *mut dc_saxparser_t, userdata: *mut libc::c_void) { (*saxparser).userdata = userdata; (*saxparser).starttag_cb = Some(def_starttag_cb); (*saxparser).endtag_cb = Some(def_endtag_cb); diff --git a/src/dc_strencode.rs b/src/dc_strencode.rs index 95a845fbb..bc5ad7164 100644 --- a/src/dc_strencode.rs +++ b/src/dc_strencode.rs @@ -24,7 +24,7 @@ pub fn isdigit(mut _c: libc::c_int) -> libc::c_int { } } -pub unsafe extern "C" fn dc_urlencode(to_encode: *const libc::c_char) -> *mut libc::c_char { +pub unsafe fn dc_urlencode(to_encode: *const libc::c_char) -> *mut libc::c_char { let mut pstr: *const libc::c_char = to_encode; if to_encode.is_null() { return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); diff --git a/src/dc_tools.rs b/src/dc_tools.rs index a2e427161..9075578d9 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -266,7 +266,7 @@ pub unsafe fn dc_binary_to_uc_hex(buf: *const uint8_t, bytes: size_t) -> *mut li } /* remove all \r characters from string */ -pub unsafe extern "C" fn dc_remove_cr_chars(buf: *mut libc::c_char) { +pub unsafe fn dc_remove_cr_chars(buf: *mut libc::c_char) { /* search for first `\r` */ let mut p1: *const libc::c_char = buf; while 0 != *p1 { diff --git a/tests/stress.rs b/tests/stress.rs index 7a2384281..9e21446bb 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -9,7 +9,6 @@ use mmime::other::*; use tempfile::tempdir; use deltachat::constants::*; -use deltachat::dc_aheader::*; use deltachat::dc_array::*; use deltachat::dc_configure::*; use deltachat::dc_contact::*; @@ -45,7 +44,7 @@ static mut S_EM_SETUPFILE: *const libc::c_char = b"-----BEGIN PGP MESSAGE-----\nPassphrase-Format: numeric9x4\nPassphrase-Begin: 17\n\n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\nmngm1QCMMw2v/j8=\n=9sJE\n-----END PGP MESSAGE-----\n\x00" as *const u8 as *const libc::c_char; -unsafe extern "C" fn stress_functions(context: &dc_context_t) { +unsafe fn stress_functions(context: &dc_context_t) { let mut saxparser: dc_saxparser_t = dc_saxparser_t { starttag_cb: None, endtag_cb: None, @@ -3175,216 +3174,7 @@ unsafe extern "C" fn stress_functions(context: &dc_context_t) { } else { }; free(keys as *mut libc::c_void); - let ah: *mut dc_aheader_t = dc_aheader_new(); - let rendered: *mut libc::c_char; - let mut ah_ok: libc::c_int; - let fixed_header = b"addr=a@b.example.org; prefer-encrypt=mutual; keydata= xsBNBFzG3j0BCAC6iNhT8zydvCXi8LI/gFnkadMbfmSE/rTJskRRra/utGbLyDta/yTrJgWL7O3y/g 4HdDW/dN2z26Y6W13IMzx9gLInn1KQZChtqWAcr/ReUucXcymwcfg1mdkBGk3TSLeLihN6CJx8Wsv8 ig+kgAzte4f5rqEEAJVQ9WZHuti7UiYs6oRzqTo06CRe9owVXxzdMf0VDQtf7ZFm9dpzKKbhH7Lu88 80iiotQ9/yRCkDGp9fNThsrLdZiK6OIAcIBAqi2rI89aS1dAmnRbktQieCx5izzyYkR1KvVL3gTTll HOzfKVEC2asmtWu2e4se/+O4WMIS1eGrn7GeWVb0Vwc5ABEBAAHNETxhQEBiLmV4YW1wbGUuZGU+ws CJBBABCAAzAhkBBQJcxt5FAhsDBAsJCAcGFQgJCgsCAxYCARYhBI4xxYKBgH3ANh5cufaKrc9mtiML AAoJEPaKrc9mtiML938H/18F+3Wf9/JaAy/8hCO1v4S2PVBhxaKCokaNFtkfaMRne2l087LscCFPiF Nyb4mv6Z3YeK8Xpxlp2sI0ecvdiqLUOGfnxS6tQrj+83EjtIrZ/hXOk1h121QFWH9Zg2VNHtODXjAg dLDC0NWUrclR0ZOqEDQHeo0ibTILdokVfXFN25wakPmGaYJP2y729cb1ve7RzvIvwn+Dddfxo3ao72 rBfLi7l4NQ4S0KsY4cw+/6l5bRCKYCP77wZtvCwUvfVVosLdT43agtSiBI49+ayqvZ8OCvSJa61i+v 81brTiEy9GBod4eAp45Ibsuemkw+gon4ZOvUXHTjwFB+h63MrozOwE0EXMbePQEIAL/vauf1zK8JgC u3V+G+SOX0iWw5xUlCPX+ERpBbWfwu3uAqn4wYXD3JDE/fVAF668xiV4eTPtlSUd5h0mn+G7uXMMOt kb+20SoEt50f8zw8TrL9t+ZsV11GKZWJpCar5AhXWsn6EEi8I2hLL5vn55ZZmHuGgN4jjmkRl3ToKC LhaXwTBjCJem7N5EH7F75wErEITa55v4Lb4Nfca7vnvtYrI1OA446xa8gHra0SINelTD09/JM/Fw4s WVPBaRZmJK/Tnu79N23No9XBUubmFPv1pNexZsQclicnTpt/BEWhiun7d6lfGB63K1aoHRTR1pcrWv BuALuuz0gqar2zlI0AEQEAAcLAdgQYAQgAIAUCXMbeRQIbDBYhBI4xxYKBgH3ANh5cufaKrc9mtiML AAoJEPaKrc9mtiMLKSEIAIyLCRO2OyZ0IYRvRPpMn4p7E+7Pfcz/0mSkOy+1hshgJnqivXurm8zwGr wdMqeV4eslKR9H1RUdWGUQJNbtwmmjrt5DHpIhYHl5t3FpCBaGbV20Omo00Q38lBl9MtrmZkZw+ktE k6X+0xCKssMF+2MADkSOIufbR5HrDVB89VZOHCO9DeXvCUUAw2hyJiL/LHmLzJ40zYoTmb+F//f0k0 j+tRdbkefyRoCmwG7YGiT+2hnCdgcezswnzah5J3ZKlrg7jOGo1LxtbvNUzxNBbC6S/aNgwm6qxo7x egRhmEl5uZ16zwyj4qz+xkjGy25Of5mWfUDoNw7OT7sjUbHOOMc="; - ah_ok = dc_aheader_set_from_string(ah, fixed_header as *const u8 as *const libc::c_char); - if 0 != !(ah_ok == 1i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 769i32, - b"ah_ok == 1\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - if 0 != !(!(*ah).addr.is_null() - && strcmp( - (*ah).addr, - b"a@b.example.org\x00" as *const u8 as *const libc::c_char, - ) == 0i32) as libc::c_int as libc::c_long - { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 770i32, - b"ah->addr && strcmp(ah->addr, \"a@b.example.org\")==0\x00" as *const u8 - as *const libc::c_char, - ); - } else { - }; - assert_eq!((*(*ah).public_key).bytes, 1212); - - if 0 != !((*ah).prefer_encrypt == 1i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 772i32, - b"ah->prefer_encrypt==DC_PE_MUTUAL\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - - rendered = dc_aheader_render(ah); - - assert!(!rendered.is_null()); - assert_eq!( - std::ffi::CStr::from_ptr(rendered).to_str().unwrap(), - std::str::from_utf8(fixed_header).unwrap() - ); - - ah_ok = - dc_aheader_set_from_string(ah, - b" _foo; __FOO=BAR ;;; addr = a@b.example.org ;\r\n prefer-encrypt = mutual ; keydata = RG VsdGEgQ\r\n2hhdA==\x00" - as *const u8 as *const libc::c_char); - if 0 != !(ah_ok == 1i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 778i32, - b"ah_ok == 1\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - if 0 != !(!(*ah).addr.is_null() - && strcmp( - (*ah).addr, - b"a@b.example.org\x00" as *const u8 as *const libc::c_char, - ) == 0i32) as libc::c_int as libc::c_long - { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 779i32, - b"ah->addr && strcmp(ah->addr, \"a@b.example.org\")==0\x00" as *const u8 - as *const libc::c_char, - ); - } else { - }; - - if 0 != !((*(*ah).public_key).bytes == 10i32 - && strncmp( - (*(*ah).public_key).binary as *mut libc::c_char, - b"Delta Chat\x00" as *const u8 as *const libc::c_char, - 10, - ) == 0i32) as libc::c_int as libc::c_long - { - __assert_rtn((*::std::mem::transmute::<&[u8; 17], - &[libc::c_char; 17]>(b"stress_functions\x00")).as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as - *const libc::c_char, 780i32, - b"ah->public_key->bytes==10 && strncmp((char*)ah->public_key->binary, \"Delta Chat\", 10)==0\x00" - as *const u8 as *const libc::c_char); - } else { - }; - if 0 != !((*ah).prefer_encrypt == 1i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 781i32, - b"ah->prefer_encrypt==DC_PE_MUTUAL\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - ah_ok = dc_aheader_set_from_string( - ah, - b"addr=a@b.example.org; prefer-encrypt=ignoreUnknownValues; keydata=RGVsdGEgQ2hhdA==\x00" - as *const u8 as *const libc::c_char, - ); - if 0 != !(ah_ok == 1i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 784i32, - b"ah_ok == 1\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - ah_ok = dc_aheader_set_from_string( - ah, - b"addr=a@b.example.org; keydata=RGVsdGEgQ2hhdA==\x00" as *const u8 as *const libc::c_char, - ); - if 0 != !(ah_ok == 1i32 && (*ah).prefer_encrypt == 0i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 787i32, - b"ah_ok == 1 && ah->prefer_encrypt==DC_PE_NOPREFERENCE\x00" as *const u8 - as *const libc::c_char, - ); - } else { - }; - ah_ok = dc_aheader_set_from_string(ah, b"\x00" as *const u8 as *const libc::c_char); - if 0 != !(ah_ok == 0i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 790i32, - b"ah_ok == 0\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - ah_ok = dc_aheader_set_from_string(ah, b";\x00" as *const u8 as *const libc::c_char); - if 0 != !(ah_ok == 0i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 793i32, - b"ah_ok == 0\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - ah_ok = dc_aheader_set_from_string(ah, b"foo\x00" as *const u8 as *const libc::c_char); - if 0 != !(ah_ok == 0i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 796i32, - b"ah_ok == 0\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - ah_ok = dc_aheader_set_from_string(ah, b"\n\n\n\x00" as *const u8 as *const libc::c_char); - if 0 != !(ah_ok == 0i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 799i32, - b"ah_ok == 0\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - ah_ok = dc_aheader_set_from_string(ah, b" ;;\x00" as *const u8 as *const libc::c_char); - if 0 != !(ah_ok == 0i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 802i32, - b"ah_ok == 0\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - ah_ok = dc_aheader_set_from_string( - ah, - b"addr=a@t.de; unknwon=1; keydata=jau\x00" as *const u8 as *const libc::c_char, - ); - if 0 != !(ah_ok == 0i32) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 805i32, - b"ah_ok == 0\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - dc_aheader_unref(ah); - free(rendered as *mut libc::c_void); let mut ok: libc::c_int; let mut buf_0: *mut libc::c_char; let mut headerline: *const libc::c_char = 0 as *const libc::c_char;