diff --git a/src/configure/auto_mozilla.rs b/src/configure/auto_mozilla.rs index 2aa1a1af1..3d034fbe7 100644 --- a/src/configure/auto_mozilla.rs +++ b/src/configure/auto_mozilla.rs @@ -2,7 +2,7 @@ use quick_xml; use quick_xml::events::{BytesEnd, BytesStart, BytesText}; use crate::context::Context; -use crate::dc_loginparam::*; +use crate::dc_loginparam::LoginParam; use crate::dc_tools::*; use crate::x::*; @@ -13,10 +13,10 @@ use super::read_autoconf_file; /* documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Autoconfiguration */ #[repr(C)] struct moz_autoconfigure_t<'a> { - pub in_0: &'a dc_loginparam_t, + pub in_0: &'a LoginParam, pub in_emaildomain: &'a str, pub in_emaillocalpart: &'a str, - pub out: dc_loginparam_t, + pub out: LoginParam, pub out_imap_set: libc::c_int, pub out_smtp_set: libc::c_int, pub tag_server: libc::c_int, @@ -26,8 +26,8 @@ struct moz_autoconfigure_t<'a> { pub unsafe fn moz_autoconfigure( context: &Context, url: &str, - param_in: &dc_loginparam_t, -) -> Option { + param_in: &LoginParam, +) -> Option { let xml_raw = read_autoconf_file(context, url); if xml_raw.is_null() { return None; @@ -51,7 +51,7 @@ pub unsafe fn moz_autoconfigure( in_0: param_in, in_emaildomain, in_emaillocalpart, - out: dc_loginparam_new(), + out: LoginParam::new(), out_imap_set: 0, out_smtp_set: 0, tag_server: 0, @@ -86,7 +86,7 @@ pub unsafe fn moz_autoconfigure( || moz_ac.out.send_server.is_empty() || moz_ac.out.send_port == 0 { - let r = dc_loginparam_get_readable(&moz_ac.out); + let r = moz_ac.out.to_string(); warn!(context, 0, "Bad or incomplete autoconfig: {}", r,); free(xml_raw as *mut libc::c_void); return None; diff --git a/src/configure/auto_outlook.rs b/src/configure/auto_outlook.rs index b69c1cb50..d350ff6e8 100644 --- a/src/configure/auto_outlook.rs +++ b/src/configure/auto_outlook.rs @@ -2,7 +2,7 @@ use quick_xml; use quick_xml::events::{BytesEnd, BytesStart, BytesText}; use crate::context::Context; -use crate::dc_loginparam::*; +use crate::dc_loginparam::LoginParam; use crate::dc_tools::*; use crate::x::*; use std::ptr; @@ -13,8 +13,8 @@ use super::read_autoconf_file; ******************************************************************************/ #[repr(C)] struct outlk_autodiscover_t<'a> { - pub in_0: &'a dc_loginparam_t, - pub out: dc_loginparam_t, + pub in_0: &'a LoginParam, + pub out: LoginParam, pub out_imap_set: libc::c_int, pub out_smtp_set: libc::c_int, pub tag_config: libc::c_int, @@ -25,13 +25,13 @@ struct outlk_autodiscover_t<'a> { pub unsafe fn outlk_autodiscover( context: &Context, url__: &str, - param_in: &dc_loginparam_t, -) -> Option { + param_in: &LoginParam, +) -> Option { let mut xml_raw: *mut libc::c_char = ptr::null_mut(); let mut url = url__.strdup(); let mut outlk_ad = outlk_autodiscover_t { in_0: param_in, - out: dc_loginparam_new(), + out: LoginParam::new(), out_imap_set: 0, out_smtp_set: 0, tag_config: 0, @@ -108,7 +108,7 @@ pub unsafe fn outlk_autodiscover( || outlk_ad.out.send_server.is_empty() || outlk_ad.out.send_port == 0 { - let r = dc_loginparam_get_readable(&outlk_ad.out); + let r = outlk_ad.out.to_string(); warn!(context, 0, "Bad or incomplete autoconfig: {}", r,); free(url as *mut libc::c_void); free(xml_raw as *mut libc::c_void); diff --git a/src/configure/mod.rs b/src/configure/mod.rs index f4e5d5fbb..dc152dd4b 100644 --- a/src/configure/mod.rs +++ b/src/configure/mod.rs @@ -3,7 +3,7 @@ use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use crate::constants::Event; use crate::constants::DC_CREATE_MVBOX; use crate::context::Context; -use crate::dc_loginparam::*; +use crate::dc_loginparam::LoginParam; use crate::dc_tools::*; use crate::e2ee; use crate::imap::*; @@ -69,7 +69,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { let mut smtp_connected_here = false; let mut ongoing_allocated_here = false; - let mut param_autoconfig: Option = None; + let mut param_autoconfig: Option = None; if dc_alloc_ongoing(context) { ongoing_allocated_here = true; if !context.sql.is_open() { @@ -95,7 +95,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { let s = s_a.read().unwrap(); // Variables that are shared between steps: - let mut param: dc_loginparam_t = dc_loginparam_read(context, &context.sql, ""); + let mut param = LoginParam::from_database(context, ""); // need all vars here to be mutable because rust thinks the same step could be called multiple times // and also initialize, because otherwise rust thinks it's used while unitilized, even if thats not the case as the loop goes only forward let mut param_domain = "undefined.undefined".to_owned(); @@ -256,8 +256,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { 12 => { progress!(context, 500); if let Some(ref cfg) = param_autoconfig { - let r = dc_loginparam_get_readable(cfg); - info!(context, 0, "Got autoconfig: {}", r); + info!(context, 0, "Got autoconfig: {}", &cfg); if !cfg.mail_user.is_empty() { param.mail_user = cfg.mail_user.clone(); } @@ -358,8 +357,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { ok_to_continue8 = true; break; } - let r_0 = dc_loginparam_get_readable(¶m); - info!(context, 0, "Trying: {}", r_0,); + info!(context, 0, "Trying: {}", ¶m); if context.inbox.read().unwrap().connect(context, ¶m) { ok_to_continue8 = true; @@ -377,8 +375,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { progress!(context, 650 + username_variation * 30); param.server_flags &= !(0x100 | 0x200 | 0x400); param.server_flags |= 0x100; - let r_1 = dc_loginparam_get_readable(¶m); - info!(context, 0, "Trying: {}", r_1,); + info!(context, 0, "Trying: {}", ¶m); if context.inbox.read().unwrap().connect(context, ¶m) { ok_to_continue8 = true; @@ -391,8 +388,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { } progress!(context, 660 + username_variation * 30); param.mail_port = 143; - let r_2 = dc_loginparam_get_readable(¶m); - info!(context, 0, "Trying: {}", r_2,); + info!(context, 0, "Trying: {}", ¶m); if context.inbox.read().unwrap().connect(context, ¶m) { ok_to_continue8 = true; @@ -447,8 +443,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { param.server_flags &= !(0x10000 | 0x20000 | 0x40000); param.server_flags |= 0x10000; param.send_port = 587; - let r_3 = dc_loginparam_get_readable(¶m); - info!(context, 0, "Trying: {}", r_3,); + info!(context, 0, "Trying: {}", ¶m); if !context .smtp @@ -464,8 +459,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { param.server_flags &= !(0x10000 | 0x20000 | 0x40000); param.server_flags |= 0x10000; param.send_port = 25; - let r_4 = dc_loginparam_get_readable(¶m); - info!(context, 0, "Trying: {}", r_4); + info!(context, 0, "Trying: {}", ¶m); if !context .smtp @@ -517,12 +511,13 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { 17 => { progress!(context, 910); /* configuration success - write back the configured parameters with the "configured_" prefix; also write the "configured"-flag */ - dc_loginparam_write( - context, - ¶m, - &context.sql, - "configured_", /*the trailing underscore is correct*/ - ); + param + .save_to_database( + context, + "configured_", /*the trailing underscore is correct*/ + ) + .ok(); + context.sql.set_config_int(context, "configured", 1).ok(); true } @@ -635,7 +630,7 @@ pub fn dc_connect_to_configured_imap(context: &Context, imap: &Imap) -> libc::c_ { warn!(context, 0, "Not configured, cannot connect.",); } else { - let param = dc_loginparam_read(context, &context.sql, "configured_"); + let param = LoginParam::from_database(context, "configured_"); // the trailing underscore is correct if imap.connect(context, ¶m) { diff --git a/src/contact.rs b/src/contact.rs index 0e7371ae5..8f58bdb9c 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -6,7 +6,7 @@ use crate::aheader::EncryptPreference; use crate::config::Config; use crate::constants::*; use crate::context::Context; -use crate::dc_loginparam::*; +use crate::dc_loginparam::LoginParam; use crate::dc_tools::*; use crate::e2ee; use crate::error::Result; @@ -576,7 +576,7 @@ impl<'a> Contact<'a> { if let Ok(contact) = Contact::load_from_db(context, contact_id) { let peerstate = Peerstate::from_addr(context, &context.sql, &contact.addr); - let loginparam = dc_loginparam_read(context, &context.sql, "configured_"); + let loginparam = LoginParam::from_database(context, "configured_"); let mut self_key = Key::from_self_public(context, &loginparam.addr, &context.sql); diff --git a/src/context.rs b/src/context.rs index 104db486b..9fe93093e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -3,7 +3,7 @@ use std::sync::{Arc, Condvar, Mutex, RwLock}; use crate::chat::*; use crate::constants::*; use crate::contact::*; -use crate::dc_loginparam::*; +use crate::dc_loginparam::LoginParam; use crate::dc_receive_imf::*; use crate::dc_tools::*; use crate::imap::*; @@ -331,8 +331,8 @@ pub unsafe fn dc_get_blobdir(context: &Context) -> *mut libc::c_char { pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char { let unset = "0"; - let l = dc_loginparam_read(context, &context.sql, ""); - let l2 = dc_loginparam_read(context, &context.sql, "configured_"); + let l = LoginParam::from_database(context, ""); + let l2 = LoginParam::from_database(context, "configured_"); let displayname = context.sql.get_config(context, "displayname"); let chats = get_chat_cnt(context) as usize; let real_msgs = dc_get_real_msg_cnt(context) as usize; @@ -376,8 +376,6 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char { "".into() }; - let l_readable_str = dc_loginparam_get_readable(&l); - let l2_readable_str = dc_loginparam_get_readable(&l2); let inbox_watch = context .sql .get_config_int(context, "inbox_watch") @@ -457,8 +455,8 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char { }, displayname.unwrap_or_else(|| unset.into()), is_configured, - l_readable_str, - l2_readable_str, + l, + l2, inbox_watch, sentbox_watch, mvbox_watch, diff --git a/src/dc_loginparam.rs b/src/dc_loginparam.rs index 0cf5b0b53..87ecd3886 100644 --- a/src/dc_loginparam.rs +++ b/src/dc_loginparam.rs @@ -1,11 +1,11 @@ use std::borrow::Cow; +use std::fmt; use crate::context::Context; -use crate::sql::Sql; +use crate::error::Error; #[derive(Default, Debug)] -#[allow(non_camel_case_types)] -pub struct dc_loginparam_t { +pub struct LoginParam { pub addr: String, pub mail_server: String, pub mail_user: String, @@ -18,113 +18,134 @@ pub struct dc_loginparam_t { pub server_flags: i32, } -impl dc_loginparam_t { +impl LoginParam { + /// Create a new `LoginParam` with default values. + pub fn new() -> Self { + Default::default() + } + + /// Read the login parameters from the database. + pub fn from_database(context: &Context, prefix: impl AsRef) -> Self { + let prefix = prefix.as_ref(); + let sql = &context.sql; + + let key = format!("{}addr", prefix); + let addr = sql + .get_config(context, key) + .unwrap_or_default() + .trim() + .to_string(); + + let key = format!("{}mail_server", prefix); + let mail_server = sql.get_config(context, key).unwrap_or_default(); + + let key = format!("{}mail_port", prefix); + let mail_port = sql.get_config_int(context, key).unwrap_or_default(); + + let key = format!("{}mail_user", prefix); + let mail_user = sql.get_config(context, key).unwrap_or_default(); + + let key = format!("{}mail_pw", prefix); + let mail_pw = sql.get_config(context, key).unwrap_or_default(); + + let key = format!("{}send_server", prefix); + let send_server = sql.get_config(context, key).unwrap_or_default(); + + let key = format!("{}send_port", prefix); + let send_port = sql.get_config_int(context, key).unwrap_or_default(); + + let key = format!("{}send_user", prefix); + let send_user = sql.get_config(context, key).unwrap_or_default(); + + let key = format!("{}send_pw", prefix); + let send_pw = sql.get_config(context, key).unwrap_or_default(); + + let key = format!("{}server_flags", prefix); + let server_flags = sql.get_config_int(context, key).unwrap_or_default(); + + LoginParam { + addr: addr.to_string(), + mail_server, + mail_user, + mail_pw, + mail_port, + send_server, + send_user, + send_pw, + send_port, + server_flags, + } + } + pub fn addr_str(&self) -> &str { self.addr.as_str() } -} -pub fn dc_loginparam_new() -> dc_loginparam_t { - Default::default() -} + /// Save this loginparam to the database. + pub fn save_to_database( + &self, + context: &Context, + prefix: impl AsRef, + ) -> Result<(), Error> { + let prefix = prefix.as_ref(); + let sql = &context.sql; -pub fn dc_loginparam_read( - context: &Context, - sql: &Sql, - prefix: impl AsRef, -) -> dc_loginparam_t { - let prefix = prefix.as_ref(); + let key = format!("{}addr", prefix); + sql.set_config(context, key, Some(&self.addr))?; - let key = format!("{}addr", prefix); - let addr = sql - .get_config(context, key) - .unwrap_or_default() - .trim() - .to_string(); + let key = format!("{}mail_server", prefix); + sql.set_config(context, key, Some(&self.mail_server))?; - let key = format!("{}mail_server", prefix); - let mail_server = sql.get_config(context, key).unwrap_or_default(); + let key = format!("{}mail_port", prefix); + sql.set_config_int(context, key, self.mail_port)?; - let key = format!("{}mail_port", prefix); - let mail_port = sql.get_config_int(context, key).unwrap_or_default(); + let key = format!("{}mail_user", prefix); + sql.set_config(context, key, Some(&self.mail_user))?; - let key = format!("{}mail_user", prefix); - let mail_user = sql.get_config(context, key).unwrap_or_default(); + let key = format!("{}mail_pw", prefix); + sql.set_config(context, key, Some(&self.mail_pw))?; - let key = format!("{}mail_pw", prefix); - let mail_pw = sql.get_config(context, key).unwrap_or_default(); + let key = format!("{}send_server", prefix); + sql.set_config(context, key, Some(&self.send_server))?; - let key = format!("{}send_server", prefix); - let send_server = sql.get_config(context, key).unwrap_or_default(); + let key = format!("{}send_port", prefix); + sql.set_config_int(context, key, self.send_port)?; - let key = format!("{}send_port", prefix); - let send_port = sql.get_config_int(context, key).unwrap_or_default(); + let key = format!("{}send_user", prefix); + sql.set_config(context, key, Some(&self.send_user))?; - let key = format!("{}send_user", prefix); - let send_user = sql.get_config(context, key).unwrap_or_default(); + let key = format!("{}send_pw", prefix); + sql.set_config(context, key, Some(&self.send_pw))?; - let key = format!("{}send_pw", prefix); - let send_pw = sql.get_config(context, key).unwrap_or_default(); + let key = format!("{}server_flags", prefix); + sql.set_config_int(context, key, self.server_flags)?; - let key = format!("{}server_flags", prefix); - let server_flags = sql.get_config_int(context, key).unwrap_or_default(); - - dc_loginparam_t { - addr: addr.to_string(), - mail_server, - mail_user, - mail_pw, - mail_port, - send_server, - send_user, - send_pw, - send_port, - server_flags, + Ok(()) } } -pub fn dc_loginparam_write( - context: &Context, - loginparam: &dc_loginparam_t, - sql: &Sql, - prefix: impl AsRef, -) { - let prefix = prefix.as_ref(); +impl fmt::Display for LoginParam { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let unset = "0"; + let pw = "***"; - let key = format!("{}addr", prefix); - sql.set_config(context, key, Some(&loginparam.addr)).ok(); + let flags_readable = get_readable_flags(self.server_flags); - let key = format!("{}mail_server", prefix); - sql.set_config(context, key, Some(&loginparam.mail_server)) - .ok(); - - let key = format!("{}mail_port", prefix); - sql.set_config_int(context, key, loginparam.mail_port).ok(); - - let key = format!("{}mail_user", prefix); - sql.set_config(context, key, Some(&loginparam.mail_user)) - .ok(); - - let key = format!("{}mail_pw", prefix); - sql.set_config(context, key, Some(&loginparam.mail_pw)).ok(); - - let key = format!("{}send_server", prefix); - sql.set_config(context, key, Some(&loginparam.send_server)) - .ok(); - - let key = format!("{}send_port", prefix); - sql.set_config_int(context, key, loginparam.send_port).ok(); - - let key = format!("{}send_user", prefix); - sql.set_config(context, key, Some(&loginparam.send_user)) - .ok(); - - let key = format!("{}send_pw", prefix); - sql.set_config(context, key, Some(&loginparam.send_pw)).ok(); - - let key = format!("{}server_flags", prefix); - sql.set_config_int(context, key, loginparam.server_flags) - .ok(); + write!( + f, + "{} {}:{}:{}:{} {}:{}:{}:{} {}", + unset_empty(&self.addr), + unset_empty(&self.mail_user), + if !self.mail_pw.is_empty() { pw } else { unset }, + unset_empty(&self.mail_server), + self.mail_port, + unset_empty(&self.send_user), + if !self.send_pw.is_empty() { pw } else { unset }, + unset_empty(&self.send_server), + self.send_port, + flags_readable, + ) + } } fn unset_empty(s: &String) -> Cow { @@ -135,35 +156,6 @@ fn unset_empty(s: &String) -> Cow { } } -pub fn dc_loginparam_get_readable(loginparam: &dc_loginparam_t) -> String { - let unset = "0"; - let pw = "***"; - - let flags_readable = get_readable_flags(loginparam.server_flags); - - format!( - "{} {}:{}:{}:{} {}:{}:{}:{} {}", - unset_empty(&loginparam.addr), - unset_empty(&loginparam.mail_user), - if !loginparam.mail_pw.is_empty() { - pw - } else { - unset - }, - unset_empty(&loginparam.mail_server), - loginparam.mail_port, - unset_empty(&loginparam.send_user), - if !loginparam.send_pw.is_empty() { - pw - } else { - unset - }, - unset_empty(&loginparam.send_server), - loginparam.send_port, - flags_readable, - ) -} - fn get_readable_flags(flags: i32) -> String { let mut res = String::new(); for bit in 0..31 { diff --git a/src/imap.rs b/src/imap.rs index 52c7ca788..d5d74f6c6 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -8,7 +8,7 @@ use std::time::{Duration, SystemTime}; use crate::constants::*; use crate::context::Context; -use crate::dc_loginparam::*; +use crate::dc_loginparam::LoginParam; use crate::dc_tools::CStringExt; use crate::oauth2::dc_get_oauth2_access_token; use crate::types::*; @@ -516,7 +516,7 @@ impl Imap { cfg.watch_folder = None; } - pub fn connect(&self, context: &Context, lp: &dc_loginparam_t) -> bool { + pub fn connect(&self, context: &Context, lp: &LoginParam) -> bool { if lp.mail_server.is_empty() || lp.mail_user.is_empty() || lp.mail_pw.is_empty() { return false; } diff --git a/src/job.rs b/src/job.rs index d92494a7a..542a61934 100644 --- a/src/job.rs +++ b/src/job.rs @@ -10,7 +10,7 @@ use crate::configure::*; use crate::constants::*; use crate::context::Context; use crate::dc_imex::*; -use crate::dc_loginparam::*; +use crate::dc_loginparam::LoginParam; use crate::dc_mimefactory::*; use crate::dc_tools::*; use crate::imap::*; @@ -130,7 +130,7 @@ impl Job { fn do_DC_JOB_SEND(&mut self, context: &Context) { /* connect to SMTP server, if not yet done */ if !context.smtp.lock().unwrap().is_connected() { - let loginparam = dc_loginparam_read(context, &context.sql, "configured_"); + let loginparam = LoginParam::from_database(context, "configured_"); let connected = context.smtp.lock().unwrap().connect(context, &loginparam); if !connected { diff --git a/src/smtp.rs b/src/smtp.rs index a1dc96789..d4f8eddc8 100644 --- a/src/smtp.rs +++ b/src/smtp.rs @@ -4,7 +4,7 @@ use lettre::*; use crate::constants::Event; use crate::constants::*; use crate::context::Context; -use crate::dc_loginparam::*; +use crate::dc_loginparam::LoginParam; use crate::oauth2::*; pub struct Smtp { @@ -43,7 +43,7 @@ impl Smtp { } /// Connect using the provided login params - pub fn connect(&mut self, context: &Context, lp: &dc_loginparam_t) -> bool { + pub fn connect(&mut self, context: &Context, lp: &LoginParam) -> bool { if self.is_connected() { warn!(context, 0, "SMTP already connected."); return true;