diff --git a/src/configure/auto_outlook.rs b/src/configure/auto_outlook.rs index b2577c171..ff6a4bc61 100644 --- a/src/configure/auto_outlook.rs +++ b/src/configure/auto_outlook.rs @@ -1,55 +1,42 @@ -use std::ptr; - -use libc::free; use quick_xml; -use quick_xml::events::{BytesEnd, BytesStart, BytesText}; +use quick_xml::events::BytesEnd; use crate::constants::*; use crate::context::Context; -use crate::dc_tools::*; use crate::login_param::LoginParam; use super::read_autoconf_file; -/* ****************************************************************************** - * Outlook's Autodiscover - ******************************************************************************/ -#[repr(C)] -struct outlk_autodiscover_t { + +/// Outlook's Autodiscover +struct OutlookAutodiscover { pub out: LoginParam, - pub out_imap_set: libc::c_int, - pub out_smtp_set: libc::c_int, - pub tag_config: libc::c_int, - pub config: [*mut libc::c_char; 6], + pub out_imap_set: bool, + pub out_smtp_set: bool, + pub config_type: Option, + pub config_server: String, + pub config_port: i32, + pub config_ssl: String, + pub config_redirecturl: Option, } -pub unsafe fn outlk_autodiscover( +pub fn outlk_autodiscover( context: &Context, - url__: &str, + url: &str, _param_in: &LoginParam, ) -> Option { - let mut url = url__.to_string(); - let mut outlk_ad = outlk_autodiscover_t { - out: LoginParam::new(), - out_imap_set: 0, - out_smtp_set: 0, - tag_config: 0, - config: [ptr::null_mut(); 6], - }; - let mut out_null = true; - let ok_to_continue; - let mut i = 0; - loop { - /* Follow up to 10 xml-redirects (http-redirects are followed in read_autoconf_file() */ - if i >= 10 { - ok_to_continue = true; - break; - } - - libc::memset( - &mut outlk_ad as *mut outlk_autodiscover_t as *mut libc::c_void, - 0, - ::std::mem::size_of::(), - ); + let mut url = url.to_string(); + /* Follow up to 10 xml-redirects (http-redirects are followed in read_autoconf_file() */ + for _i in 0..10 { + let mut outlk_ad = OutlookAutodiscover { + out: LoginParam::new(), + out_imap_set: false, + out_smtp_set: false, + config_type: None, + config_server: String::new(), + config_port: 0, + config_ssl: String::new(), + config_redirecturl: None, + }; if let Some(xml_raw) = read_autoconf_file(context, &url) { let mut reader = quick_xml::Reader::from_str(&xml_raw); @@ -57,16 +44,46 @@ pub unsafe fn outlk_autodiscover( let mut buf = Vec::new(); + let mut current_tag: Option = None; + loop { match reader.read_event(&mut buf) { Ok(quick_xml::events::Event::Start(ref e)) => { - outlk_autodiscover_starttag_cb(e, &mut outlk_ad) + let tag = String::from_utf8_lossy(e.name()).trim().to_lowercase(); + + if tag == "protocol" { + outlk_ad.config_type = None; + outlk_ad.config_server = String::new(); + outlk_ad.config_port = 0; + outlk_ad.config_ssl = String::new(); + outlk_ad.config_redirecturl = None; + + current_tag = None; + } else { + current_tag = Some(tag); + } } Ok(quick_xml::events::Event::End(ref e)) => { - outlk_autodiscover_endtag_cb(e, &mut outlk_ad) + outlk_autodiscover_endtag_cb(e, &mut outlk_ad); + current_tag = None; } Ok(quick_xml::events::Event::Text(ref e)) => { - outlk_autodiscover_text_cb(e, &mut outlk_ad, &reader) + let val = e.unescape_and_decode(&reader).unwrap_or_default(); + + if let Some(ref tag) = current_tag { + match tag.as_str() { + "type" => outlk_ad.config_type = Some(val.trim().to_string()), + "server" => outlk_ad.config_server = val.trim().to_string(), + "port" => { + outlk_ad.config_port = val.trim().parse().unwrap_or_default() + } + "ssl" => outlk_ad.config_ssl = val.trim().to_string(), + "redirecturl" => { + outlk_ad.config_redirecturl = Some(val.trim().to_string()) + } + _ => {} + }; + } } Err(e) => { error!( @@ -83,129 +100,58 @@ pub unsafe fn outlk_autodiscover( } // XML redirect via redirecturl - if !(!outlk_ad.config[5].is_null() - && 0 != *outlk_ad.config[5usize].offset(0isize) as libc::c_int) + if outlk_ad.config_redirecturl.is_none() + || outlk_ad.config_redirecturl.as_ref().unwrap().is_empty() { - out_null = false; - ok_to_continue = true; - break; + if outlk_ad.out.mail_server.is_empty() + || outlk_ad.out.mail_port == 0 + || outlk_ad.out.send_server.is_empty() + || outlk_ad.out.send_port == 0 + { + let r = outlk_ad.out.to_string(); + warn!(context, "Bad or incomplete autoconfig: {}", r,); + return None; + } + return Some(outlk_ad.out); + } else { + url = outlk_ad.config_redirecturl.unwrap(); } - url = as_str(outlk_ad.config[5usize]).to_string(); - - outlk_clean_config(&mut outlk_ad); - i += 1; } else { - ok_to_continue = false; - break; - } - } - - if ok_to_continue { - if outlk_ad.out.mail_server.is_empty() - || outlk_ad.out.mail_port == 0 - || outlk_ad.out.send_server.is_empty() - || outlk_ad.out.send_port == 0 - { - let r = outlk_ad.out.to_string(); - warn!(context, "Bad or incomplete autoconfig: {}", r,); - outlk_clean_config(&mut outlk_ad); - return None; } } - outlk_clean_config(&mut outlk_ad); - if out_null { - None - } else { - Some(outlk_ad.out) - } + None } -unsafe fn outlk_clean_config(mut outlk_ad: *mut outlk_autodiscover_t) { - for i in 0..6 { - free((*outlk_ad).config[i] as *mut libc::c_void); - (*outlk_ad).config[i] = ptr::null_mut(); - } -} - -fn outlk_autodiscover_text_cb( - event: &BytesText, - outlk_ad: &mut outlk_autodiscover_t, - reader: &quick_xml::Reader, -) { - let val = event.unescape_and_decode(reader).unwrap_or_default(); - - unsafe { - free(outlk_ad.config[outlk_ad.tag_config as usize].cast()); - outlk_ad.config[outlk_ad.tag_config as usize] = val.trim().strdup(); - } -} - -unsafe fn outlk_autodiscover_endtag_cb(event: &BytesEnd, outlk_ad: &mut outlk_autodiscover_t) { +fn outlk_autodiscover_endtag_cb(event: &BytesEnd, outlk_ad: &mut OutlookAutodiscover) { let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase(); if tag == "protocol" { - if !outlk_ad.config[1].is_null() { - let port = dc_atoi_null_is_0(outlk_ad.config[3]); - let ssl_on = (!outlk_ad.config[4].is_null() - && strcasecmp( - outlk_ad.config[4], - b"on\x00" as *const u8 as *const libc::c_char, - ) == 0) as libc::c_int; - let ssl_off = (!outlk_ad.config[4].is_null() - && strcasecmp( - outlk_ad.config[4], - b"off\x00" as *const u8 as *const libc::c_char, - ) == 0) as libc::c_int; - if strcasecmp( - outlk_ad.config[1], - b"imap\x00" as *const u8 as *const libc::c_char, - ) == 0 - && outlk_ad.out_imap_set == 0 - { - outlk_ad.out.mail_server = to_string_lossy(outlk_ad.config[2]); + if let Some(type_) = &outlk_ad.config_type { + let port = outlk_ad.config_port; + let ssl_on = outlk_ad.config_ssl == "on"; + let ssl_off = outlk_ad.config_ssl == "off"; + if type_ == "imap" && !outlk_ad.out_imap_set { + outlk_ad.out.mail_server = + std::mem::replace(&mut outlk_ad.config_server, String::new()); outlk_ad.out.mail_port = port; - if 0 != ssl_on { + if ssl_on { outlk_ad.out.server_flags |= DC_LP_IMAP_SOCKET_SSL as i32 - } else if 0 != ssl_off { + } else if ssl_off { outlk_ad.out.server_flags |= DC_LP_IMAP_SOCKET_PLAIN as i32 } - outlk_ad.out_imap_set = 1 - } else if strcasecmp( - outlk_ad.config[1usize], - b"smtp\x00" as *const u8 as *const libc::c_char, - ) == 0 - && outlk_ad.out_smtp_set == 0 - { - outlk_ad.out.send_server = to_string_lossy(outlk_ad.config[2]); - outlk_ad.out.send_port = port; - if 0 != ssl_on { + outlk_ad.out_imap_set = true + } else if type_ == "smtp" && !outlk_ad.out_smtp_set { + outlk_ad.out.send_server = + std::mem::replace(&mut outlk_ad.config_server, String::new()); + outlk_ad.out.send_port = outlk_ad.config_port; + if ssl_on { outlk_ad.out.server_flags |= DC_LP_SMTP_SOCKET_SSL as i32 - } else if 0 != ssl_off { + } else if ssl_off { outlk_ad.out.server_flags |= DC_LP_SMTP_SOCKET_PLAIN as i32 } - outlk_ad.out_smtp_set = 1 + outlk_ad.out_smtp_set = true } } - outlk_clean_config(outlk_ad); } - outlk_ad.tag_config = 0; -} - -fn outlk_autodiscover_starttag_cb(event: &BytesStart, outlk_ad: &mut outlk_autodiscover_t) { - let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase(); - - if tag == "protocol" { - unsafe { outlk_clean_config(outlk_ad) }; - } else if tag == "type" { - outlk_ad.tag_config = 1 - } else if tag == "server" { - outlk_ad.tag_config = 2 - } else if tag == "port" { - outlk_ad.tag_config = 3 - } else if tag == "ssl" { - outlk_ad.tag_config = 4 - } else if tag == "redirecturl" { - outlk_ad.tag_config = 5 - }; } diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 366dca072..6a0362c95 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -51,14 +51,6 @@ pub unsafe fn dc_strdup(s: *const libc::c_char) -> *mut libc::c_char { ret } -pub(crate) fn dc_atoi_null_is_0(s: *const libc::c_char) -> libc::c_int { - if !s.is_null() { - as_str(s).parse().unwrap_or_default() - } else { - 0 - } -} - unsafe fn dc_ltrim(buf: *mut libc::c_char) { let mut len: libc::size_t; let mut cur: *const libc::c_uchar;