add basic provider-functions

This commit is contained in:
B. Petersen
2020-01-22 20:59:07 +01:00
parent 0f172595d7
commit 748e54d4c2
6 changed files with 165 additions and 73 deletions

View File

@@ -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);
/**

View File

@@ -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<T, E> {
fn unwrap_or_log_default(self, context: &context::Context, message: &str) -> T;
fn log_err(self, context: &context::Context, message: &str) -> Result<T, E>;
@@ -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.
}

View File

@@ -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?

View File

@@ -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 [<chat-id>]\n\
getbadqr\n\
checkqr <qr-content>\n\
providerinfo <addr>\n\
event <event-id to test>\n\
fileinfo <file>\n\
emptyserver <flags> (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 <addr> 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 <id> missing.");

View File

@@ -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;

80
src/provider.rs Normal file
View File

@@ -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
}