diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 02ac41380..ee4dc5422 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -3692,12 +3692,13 @@ int dc_contact_is_verified (dc_contact_t* contact); * The provider is extracted from the email address and it's information is returned. * * @memberof dc_provider_t + * @param context The context object as created by dc_context_new(). * @param email The user's email address to extract the provider info form. * @return a dc_provider_t struct which can be used with the dc_provider_get_* * accessor functions. If no provider info is found, NULL will be * returned. */ -dc_provider_t* dc_provider_new_from_email (const char* email); +dc_provider_t* dc_provider_new_from_email (const dc_context_t*, const char* email); /** @@ -3724,7 +3725,7 @@ char* dc_provider_get_overview_page (const dc_provider_t* prov * @param provider The dc_provider_t struct. * @return A string which must be released using dc_str_unref(). */ -char* dc_provider_get_before_login_hints (const dc_provider_t* provider); +char* dc_provider_get_before_login_hint (const dc_provider_t* provider); /** @@ -3746,7 +3747,7 @@ int dc_provider_get_status (const dc_provider_t* prov * @memberof dc_provider_t * @param provider The dc_provider_t struct. */ -void dc_provider_unref (const dc_provider_t* provider); +void dc_provider_unref (dc_provider_t* provider); /** diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 1eb0bf9cc..98ff0a577 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -3156,8 +3156,6 @@ pub unsafe extern "C" fn dc_str_unref(s: *mut libc::c_char) { libc::free(s as *mut _) } -pub mod providers; - pub trait ResultExt { fn unwrap_or_log_default(self, context: &context::Context, message: &str) -> T; fn log_err(self, context: &context::Context, message: &str) -> Result; @@ -3212,3 +3210,68 @@ fn convert_and_prune_message_ids(msg_ids: *const u32, msg_cnt: libc::c_int) -> V msg_ids } + +// dc_provider_t + +#[no_mangle] +pub type dc_provider_t = provider::Provider; + +#[no_mangle] +pub unsafe extern "C" fn dc_provider_new_from_email( + context: *const dc_context_t, + addr: *const libc::c_char, +) -> *const dc_provider_t { + if context.is_null() || addr.is_null() { + eprintln!("ignoring careless call to dc_provider_new_from_email()"); + return ptr::null(); + } + let addr = to_string_lossy(addr); + match provider::get_provider_info(addr.as_str()) { + Some(provider) => provider, + None => ptr::null_mut(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn dc_provider_get_overview_page( + provider: *const dc_provider_t, +) -> *mut libc::c_char { + if provider.is_null() { + eprintln!("ignoring careless call to dc_provider_get_overview_page()"); + return "".strdup(); + } + let provider = &*provider; + provider.overview_page.strdup() +} + +#[no_mangle] +pub unsafe extern "C" fn dc_provider_get_before_login_hint( + provider: *const dc_provider_t, +) -> *mut libc::c_char { + if provider.is_null() { + eprintln!("ignoring careless call to dc_provider_get_before_login_hint()"); + return "".strdup(); + } + let provider = &*provider; + provider.before_login_hint.strdup() +} + +#[no_mangle] +pub unsafe extern "C" fn dc_provider_get_status(provider: *const dc_provider_t) -> libc::c_int { + if provider.is_null() { + eprintln!("ignoring careless call to dc_provider_get_status()"); + return 0; + } + let provider = &*provider; + provider.status as libc::c_int +} + +#[no_mangle] +pub unsafe extern "C" fn dc_provider_unref(provider: *mut dc_provider_t) { + if provider.is_null() { + eprintln!("ignoring careless call to dc_provider_unref()"); + return; + } + // currently, there is nothing to free, the provider info is a static object. + // this may change once we start localizing string. +} diff --git a/deltachat-ffi/src/providers.rs b/deltachat-ffi/src/providers.rs deleted file mode 100644 index d6b10a2f1..000000000 --- a/deltachat-ffi/src/providers.rs +++ /dev/null @@ -1,67 +0,0 @@ -extern crate deltachat_provider_database; - -use std::ptr; - -use crate::string::{to_string_lossy, StrExt}; -use deltachat_provider_database::StatusState; - -#[no_mangle] -pub type dc_provider_t = deltachat_provider_database::Provider; - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_new_from_email( - email: *const libc::c_char, -) -> *const dc_provider_t { - let email = to_string_lossy(email); - let domain = deltachat_provider_database::get_domain_from_email(&email); - match deltachat_provider_database::get_provider_info(domain) { - Some(provider) => provider, - None => ptr::null(), - } -} - -macro_rules! null_guard { - ($context:tt) => { - if $context.is_null() { - return ptr::null_mut() as *mut libc::c_char; - } - }; -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_get_overview_page( - provider: *const dc_provider_t, -) -> *mut libc::c_char { - null_guard!(provider); - format!( - "{}/{}", - deltachat_provider_database::PROVIDER_OVERVIEW_URL, - (*provider).overview_page - ) - .strdup() -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_get_before_login_hints( - provider: *const dc_provider_t, -) -> *mut libc::c_char { - null_guard!(provider); - (*provider).markdown.strdup() -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_get_status(provider: *const dc_provider_t) -> u32 { - if provider.is_null() { - return 0; - } - match (*provider).status.state { - StatusState::OK => 1, - StatusState::PREPARATION => 2, - StatusState::BROKEN => 3, - } -} - -#[no_mangle] -pub unsafe extern "C" fn dc_provider_unref(_provider: *const dc_provider_t) {} - -// TODO expose general provider overview url? diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index adefb5926..39ce23066 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -3,7 +3,6 @@ use std::str::FromStr; use deltachat::chat::{self, Chat, ChatId}; use deltachat::chatlist::*; -use deltachat::config; use deltachat::constants::*; use deltachat::contact::*; use deltachat::context::*; @@ -19,6 +18,7 @@ use deltachat::peerstate::*; use deltachat::qr::*; use deltachat::sql; use deltachat::Event; +use deltachat::{config, provider}; /// Reset database tables. /// Argument is a bitmask, executing single or multiple actions in one call. @@ -392,6 +392,7 @@ pub fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::Error> { getqr []\n\ getbadqr\n\ checkqr \n\ + providerinfo \n\ event \n\ fileinfo \n\ emptyserver (1=MVBOX 2=INBOX)\n\ @@ -966,6 +967,19 @@ pub fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::Error> { res.get_text2() ); } + "providerinfo" => { + ensure!(!arg1.is_empty(), "Argument missing."); + match provider::get_provider_info(arg1) { + Some(info) => { + println!("Information for provider belonging to {}:", arg1); + println!("status: {}", info.status as u32); + println!("before_login_hint: {}", info.before_login_hint); + } + None => { + println!("No information for provider belonging to {} found.", arg1); + } + } + } // TODO: implement this again, unclear how to match this through though, without writing a parser. // "event" => { // ensure!(!arg1.is_empty(), "Argument missing."); diff --git a/src/lib.rs b/src/lib.rs index 06f676298..1f6edf406 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,6 +54,7 @@ pub mod oauth2; mod param; pub mod peerstate; pub mod pgp; +pub mod provider; pub mod qr; pub mod securejoin; mod simplify; diff --git a/src/provider.rs b/src/provider.rs new file mode 100644 index 000000000..532314581 --- /dev/null +++ b/src/provider.rs @@ -0,0 +1,80 @@ +use crate::dc_tools::EmailAddress; + +#[derive(Debug, Copy, Clone, PartialEq, ToPrimitive)] +#[repr(u8)] +pub enum Status { + OK = 1, + PREPARATION = 2, + BROKEN = 3, +} + +#[derive(Debug)] +#[repr(u8)] +pub enum ServerType { + SMTP = 1, + IMAP = 2, +} + +#[derive(Debug)] +#[repr(u8)] +pub enum ServerSocket { + STARTTLS = 1, + SSL = 2, +} + +#[derive(Debug)] +pub struct Server { + pub stype: ServerType, + pub socket: ServerSocket, + pub port: u16, + pub server: &'static str, + pub username: &'static str, +} + +#[derive(Debug, PartialEq)] +pub struct Provider { + pub domains: &'static str, + pub status: Status, + pub before_login_hint: &'static str, + pub overview_page: &'static str, +} + +// TODO: the database will be auto-generated from the provider-db +const DATABASE: [Provider; 3] = [ + Provider { + domains: "nauta.cu", + status: Status::OK, + before_login_hint: "", + overview_page: "", + }, + Provider { + domains: "outlook.com live.com", + status: Status::BROKEN, + before_login_hint: "this provider is broken, sorry :(", + overview_page: "https://provider.delta.chat/outlook.com", + }, + Provider { + domains: "gmail.com", + status: Status::PREPARATION, + before_login_hint: "please enable less-secure-apps", + overview_page: "https://provider.delta.chat/gmail.com", + }, +]; + +pub fn get_provider_info(addr: &str) -> Option<&Provider> { + let domain = match EmailAddress::new(addr) { + Ok(addr) => addr.domain, + Err(_err) => return None, + } + .to_lowercase(); + + for record in &DATABASE { + for record_domain in record.domains.split(" ") { + if record_domain == domain { + return Some(record); + } + } + } + + None +}