mirror of
https://github.com/chatmail/core.git
synced 2026-04-28 02:46:29 +03:00
refactor: cleanup config values and move to their own file
This commit is contained in:
@@ -39,6 +39,8 @@ rusqlite = { version = "0.19", features = ["bundled"] }
|
||||
addr = "0.2.0"
|
||||
r2d2_sqlite = "0.11.0"
|
||||
r2d2 = "0.8.5"
|
||||
strum = "0.15.0"
|
||||
strum_macros = "0.15.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.0"
|
||||
|
||||
@@ -91,7 +91,7 @@ pub unsafe extern "C" fn dc_set_config(
|
||||
assert!(!key.is_null(), "invalid key");
|
||||
let context = &*context;
|
||||
|
||||
context::dc_set_config(context, dc_tools::as_str(key), as_opt_str(value))
|
||||
config::set(context, dc_tools::as_str(key), as_opt_str(value))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -103,7 +103,7 @@ pub unsafe extern "C" fn dc_get_config(
|
||||
assert!(!key.is_null(), "invalid key");
|
||||
let context = &*context;
|
||||
|
||||
into_cstring(context::dc_get_config(context, dc_tools::as_str(key)))
|
||||
into_cstring(config::get(context, dc_tools::as_str(key)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use deltachat::config;
|
||||
use deltachat::constants::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_array::*;
|
||||
@@ -481,7 +482,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
},
|
||||
"auth" => {
|
||||
if 0 == S_IS_AUTH {
|
||||
let is_pw = dc_get_config(context, "mail_pw");
|
||||
let is_pw = config::get(context, "mail_pw");
|
||||
if arg1 == is_pw {
|
||||
S_IS_AUTH = 1;
|
||||
} else {
|
||||
@@ -602,13 +603,13 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
"set" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <key> missing.");
|
||||
ensure!(
|
||||
0 != dc_set_config(context, &arg1, Some(&arg2)),
|
||||
0 != config::set(context, &arg1, Some(&arg2)),
|
||||
"Set config failed"
|
||||
);
|
||||
}
|
||||
"get" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <key> missing.");
|
||||
let val = dc_get_config(context, &arg1);
|
||||
let val = config::get(context, &arg1);
|
||||
println!("{}={}", arg1, val);
|
||||
}
|
||||
"info" => {
|
||||
|
||||
@@ -17,6 +17,7 @@ use std::borrow::Cow::{self, Borrowed, Owned};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
use deltachat::config;
|
||||
use deltachat::constants::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_configure::*;
|
||||
@@ -514,7 +515,7 @@ unsafe fn handle_cmd(line: &str, ctx: Arc<RwLock<Context>>) -> Result<ExitResult
|
||||
dc_configure(&ctx.read().unwrap());
|
||||
}
|
||||
"oauth2" => {
|
||||
let addr = dc_get_config(&ctx.read().unwrap(), "addr");
|
||||
let addr = config::get(&ctx.read().unwrap(), "addr");
|
||||
if addr.is_empty() {
|
||||
println!("oauth2: set addr first.");
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::sync::{Arc, RwLock};
|
||||
use std::{thread, time};
|
||||
use tempfile::tempdir;
|
||||
|
||||
use deltachat::config;
|
||||
use deltachat::constants::Event;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_chat::*;
|
||||
@@ -85,8 +86,8 @@ fn main() {
|
||||
let args = std::env::args().collect::<Vec<String>>();
|
||||
assert_eq!(args.len(), 2, "missing password");
|
||||
let pw = args[1].clone();
|
||||
dc_set_config(&ctx, "addr", Some("d@testrun.org"));
|
||||
dc_set_config(&ctx, "mail_pw", Some(&pw));
|
||||
config::set(&ctx, "addr", Some("d@testrun.org"));
|
||||
config::set(&ctx, "mail_pw", Some(&pw));
|
||||
dc_configure(&ctx);
|
||||
|
||||
thread::sleep(duration);
|
||||
|
||||
212
src/config.rs
Normal file
212
src/config.rs
Normal file
@@ -0,0 +1,212 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use strum::{EnumProperty, IntoEnumIterator};
|
||||
use strum_macros::{AsRefStr, Display, EnumIter, EnumProperty, EnumString};
|
||||
|
||||
use crate::constants::DC_VERSION_STR;
|
||||
use crate::context::Context;
|
||||
use crate::dc_job::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::sql;
|
||||
use crate::x::*;
|
||||
|
||||
/// The available configuration keys.
|
||||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, Eq, Display, EnumString, AsRefStr, EnumIter, EnumProperty,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum Config {
|
||||
Addr,
|
||||
MailServer,
|
||||
MailUser,
|
||||
MailPw,
|
||||
MailPort,
|
||||
SendServer,
|
||||
SendUser,
|
||||
SendPw,
|
||||
SendPort,
|
||||
ServerFlags,
|
||||
#[strum(props(default = "INBOX"))]
|
||||
ImapFolder,
|
||||
Displayname,
|
||||
Selfstatus,
|
||||
Selfavatar,
|
||||
#[strum(props(default = "1"))]
|
||||
E2eeEnabled,
|
||||
#[strum(props(default = "1"))]
|
||||
MdnsEnabled,
|
||||
InboxWatch,
|
||||
#[strum(props(default = "1"))]
|
||||
SentboxWatch,
|
||||
#[strum(props(default = "1"))]
|
||||
MvboxWatch,
|
||||
#[strum(props(default = "1"))]
|
||||
MvboxMove,
|
||||
#[strum(props(default = "0"))]
|
||||
ShowEmails,
|
||||
SaveMimeHeaders,
|
||||
ConfiguredAddr,
|
||||
ConfiguredMailServer,
|
||||
ConfiguredMailUser,
|
||||
ConfiguredMailPw,
|
||||
ConfiguredMailPort,
|
||||
ConfiguredSendServer,
|
||||
ConfiguredSendUser,
|
||||
ConfiguredSendPw,
|
||||
ConfiguredSendPort,
|
||||
ConfiguredServerFlags,
|
||||
Configured,
|
||||
}
|
||||
|
||||
// deprecated
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumString, AsRefStr, EnumIter)]
|
||||
pub enum SysConfig {
|
||||
#[strum(serialize = "sys.version")]
|
||||
Version,
|
||||
#[strum(serialize = "sys.msgsize_max_recommended")]
|
||||
MsgsizeMaxRecommended,
|
||||
#[strum(serialize = "sys.config_keys")]
|
||||
ConfigKeys,
|
||||
}
|
||||
|
||||
/// Get a configuration key.
|
||||
/// Returns "" when the key is invalid, or no default was found.
|
||||
pub fn get(context: &Context, key: impl AsRef<str>) -> String {
|
||||
let key = key.as_ref();
|
||||
|
||||
if key.starts_with("sys.") {
|
||||
return get_sys_config_str(key);
|
||||
}
|
||||
|
||||
match Config::from_str(key) {
|
||||
Ok(config_key) => {
|
||||
let value = match config_key {
|
||||
Config::Selfavatar => {
|
||||
let rel_path = sql::get_config(context, &context.sql, key, None);
|
||||
rel_path.map(|p| {
|
||||
let v = unsafe { dc_get_abs_path(context, to_cstring(p).as_ptr()) };
|
||||
let r = to_string(v);
|
||||
unsafe { free(v as *mut _) };
|
||||
r
|
||||
})
|
||||
}
|
||||
_ => sql::get_config(context, &context.sql, key, None),
|
||||
};
|
||||
|
||||
if value.is_some() {
|
||||
return value.unwrap();
|
||||
}
|
||||
|
||||
// Default values
|
||||
match config_key {
|
||||
Config::Selfstatus => {
|
||||
let s = unsafe { dc_stock_str(context, 13) };
|
||||
let res = to_string(s);
|
||||
unsafe { free(s as *mut _) };
|
||||
res
|
||||
}
|
||||
_ => config_key
|
||||
.get_str("default")
|
||||
.unwrap_or_default()
|
||||
.to_string(),
|
||||
}
|
||||
}
|
||||
Err(_) => "".into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_sys_config_str(key: impl AsRef<str>) -> String {
|
||||
match SysConfig::from_str(key.as_ref()) {
|
||||
Ok(SysConfig::Version) => std::str::from_utf8(DC_VERSION_STR).unwrap().into(),
|
||||
Ok(SysConfig::MsgsizeMaxRecommended) => format!("{}", 24 * 1024 * 1024 / 4 * 3),
|
||||
Ok(SysConfig::ConfigKeys) => get_config_keys_str(),
|
||||
Err(_) => "".into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_config_keys_str() -> String {
|
||||
let keys = Config::iter().fold(String::new(), |mut acc, key| {
|
||||
acc += key.as_ref();
|
||||
acc += " ";
|
||||
acc
|
||||
});
|
||||
|
||||
let sys_keys = SysConfig::iter().fold(String::new(), |mut acc, key| {
|
||||
acc += key.as_ref();
|
||||
acc += " ";
|
||||
acc
|
||||
});
|
||||
|
||||
format!(" {} {} ", keys, sys_keys)
|
||||
}
|
||||
|
||||
/// Set the given config key.
|
||||
/// Returns `1` on success and `0` on failure.
|
||||
pub fn set(context: &Context, key: impl AsRef<str>, value: Option<&str>) -> libc::c_int {
|
||||
let mut ret = 0;
|
||||
|
||||
// regular keys
|
||||
match Config::from_str(key.as_ref()) {
|
||||
Ok(Config::Selfavatar) if value.is_some() => {
|
||||
let mut rel_path = unsafe { dc_strdup(to_cstring(value.unwrap()).as_ptr()) };
|
||||
if 0 != unsafe { dc_make_rel_and_copy(context, &mut rel_path) } {
|
||||
ret = sql::set_config(context, &context.sql, key, Some(as_str(rel_path)));
|
||||
}
|
||||
unsafe { free(rel_path as *mut libc::c_void) };
|
||||
}
|
||||
Ok(Config::InboxWatch) => {
|
||||
ret = sql::set_config(context, &context.sql, key, value);
|
||||
unsafe { dc_interrupt_imap_idle(context) };
|
||||
}
|
||||
Ok(Config::SentboxWatch) => {
|
||||
ret = sql::set_config(context, &context.sql, key, value);
|
||||
unsafe { dc_interrupt_sentbox_idle(context) };
|
||||
}
|
||||
Ok(Config::MvboxWatch) => {
|
||||
ret = sql::set_config(context, &context.sql, key, value);
|
||||
unsafe { dc_interrupt_mvbox_idle(context) };
|
||||
}
|
||||
Ok(Config::Selfstatus) => {
|
||||
let def = unsafe { dc_stock_str(context, 13) };
|
||||
let val = if value.is_none() || value.unwrap() == as_str(def) {
|
||||
None
|
||||
} else {
|
||||
value
|
||||
};
|
||||
|
||||
ret = sql::set_config(context, &context.sql, key, val);
|
||||
unsafe { free(def as *mut libc::c_void) };
|
||||
}
|
||||
Ok(_) => {
|
||||
ret = sql::set_config(context, &context.sql, key, value);
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use std::str::FromStr;
|
||||
use std::string::ToString;
|
||||
|
||||
#[test]
|
||||
fn test_to_string() {
|
||||
assert_eq!(Config::MailServer.to_string(), "mail_server");
|
||||
assert_eq!(Config::from_str("mail_server"), Ok(Config::MailServer));
|
||||
|
||||
assert_eq!(SysConfig::ConfigKeys.to_string(), "sys.config_keys");
|
||||
assert_eq!(
|
||||
SysConfig::from_str("sys.config_keys"),
|
||||
Ok(SysConfig::ConfigKeys)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_prop() {
|
||||
assert_eq!(Config::ImapFolder.get_str("default"), Some("INBOX"));
|
||||
}
|
||||
}
|
||||
163
src/context.rs
163
src/context.rs
@@ -11,7 +11,6 @@ use crate::dc_lot::dc_lot_t;
|
||||
use crate::dc_move::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_receive_imf::*;
|
||||
use crate::dc_stock::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::imap::*;
|
||||
use crate::key::*;
|
||||
@@ -20,49 +19,6 @@ use crate::sql::{self, Sql};
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
const CONFIG_KEYS: [&'static str; 33] = [
|
||||
"addr",
|
||||
"mail_server",
|
||||
"mail_user",
|
||||
"mail_pw",
|
||||
"mail_port",
|
||||
"send_server",
|
||||
"send_user",
|
||||
"send_pw",
|
||||
"send_port",
|
||||
"server_flags",
|
||||
"imap_folder",
|
||||
"displayname",
|
||||
"selfstatus",
|
||||
"selfavatar",
|
||||
"e2ee_enabled",
|
||||
"mdns_enabled",
|
||||
"inbox_watch",
|
||||
"sentbox_watch",
|
||||
"mvbox_watch",
|
||||
"mvbox_move",
|
||||
"show_emails",
|
||||
"save_mime_headers",
|
||||
"configured_addr",
|
||||
"configured_mail_server",
|
||||
"configured_mail_user",
|
||||
"configured_mail_pw",
|
||||
"configured_mail_port",
|
||||
"configured_send_server",
|
||||
"configured_send_user",
|
||||
"configured_send_pw",
|
||||
"configured_send_port",
|
||||
"configured_server_flags",
|
||||
"configured",
|
||||
];
|
||||
|
||||
// deprecated
|
||||
const SYS_CONFIG_KEYS: [&'static str; 3] = [
|
||||
"sys.version",
|
||||
"sys.msgsize_max_recommended",
|
||||
"sys.config_keys",
|
||||
];
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Context {
|
||||
pub userdata: *mut libc::c_void,
|
||||
@@ -412,129 +368,10 @@ pub unsafe fn dc_get_blobdir(context: &Context) -> *mut libc::c_char {
|
||||
dc_strdup(*context.blobdir.clone().read().unwrap())
|
||||
}
|
||||
|
||||
pub fn dc_set_config(context: &Context, key: impl AsRef<str>, value: Option<&str>) -> libc::c_int {
|
||||
let mut ret = 0;
|
||||
|
||||
if !is_settable_config_key(key.as_ref()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
match key.as_ref() {
|
||||
"selfavatar" if value.is_some() => {
|
||||
let mut rel_path = unsafe { dc_strdup(to_cstring(value.unwrap()).as_ptr()) };
|
||||
if 0 != unsafe { dc_make_rel_and_copy(context, &mut rel_path) } {
|
||||
ret = sql::set_config(context, &context.sql, key, Some(as_str(rel_path)));
|
||||
}
|
||||
unsafe { free(rel_path as *mut libc::c_void) };
|
||||
}
|
||||
"inbox_watch" => {
|
||||
ret = sql::set_config(context, &context.sql, key, value);
|
||||
unsafe { dc_interrupt_imap_idle(context) };
|
||||
}
|
||||
"sentbox_watch" => {
|
||||
ret = sql::set_config(context, &context.sql, key, value);
|
||||
unsafe { dc_interrupt_sentbox_idle(context) };
|
||||
}
|
||||
"mvbox_watch" => {
|
||||
ret = sql::set_config(context, &context.sql, key, value);
|
||||
unsafe { dc_interrupt_mvbox_idle(context) };
|
||||
}
|
||||
"selfstatus" => {
|
||||
let def = unsafe { dc_stock_str(context, 13) };
|
||||
let val = if value.is_none() || value.unwrap() == as_str(def) {
|
||||
None
|
||||
} else {
|
||||
value
|
||||
};
|
||||
|
||||
ret = sql::set_config(context, &context.sql, key, val);
|
||||
unsafe { free(def as *mut libc::c_void) };
|
||||
}
|
||||
_ => {
|
||||
ret = sql::set_config(context, &context.sql, key, value);
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
/* ******************************************************************************
|
||||
* INI-handling, Information
|
||||
******************************************************************************/
|
||||
|
||||
fn is_settable_config_key(key: impl AsRef<str>) -> bool {
|
||||
CONFIG_KEYS
|
||||
.into_iter()
|
||||
.find(|c| **c == key.as_ref())
|
||||
.is_some()
|
||||
}
|
||||
|
||||
pub fn dc_get_config(context: &Context, key: impl AsRef<str>) -> String {
|
||||
if key.as_ref().starts_with("sys") {
|
||||
return get_sys_config_str(key.as_ref());
|
||||
}
|
||||
|
||||
if !is_gettable_config_key(key.as_ref()) {
|
||||
return "".into();
|
||||
}
|
||||
|
||||
let value = match key.as_ref() {
|
||||
"selfavatar" => {
|
||||
let rel_path = sql::get_config(context, &context.sql, key.as_ref(), None);
|
||||
rel_path.map(|p| {
|
||||
let v = unsafe { dc_get_abs_path(context, to_cstring(p).as_ptr()) };
|
||||
let r = to_string(v);
|
||||
unsafe { free(v as *mut _) };
|
||||
r
|
||||
})
|
||||
}
|
||||
_ => sql::get_config(context, &context.sql, key.as_ref(), None),
|
||||
};
|
||||
|
||||
if value.is_some() {
|
||||
return value.unwrap();
|
||||
}
|
||||
|
||||
match key.as_ref() {
|
||||
"e2ee_enabled" => "1".into(),
|
||||
"mdns_enabled" => "1".into(),
|
||||
"imap_folder" => "INBOX".into(),
|
||||
"inbox_watch" => "1".into(),
|
||||
"sentbox_watch" | "mvbox_watch" | "mvbox_move" => "1".into(),
|
||||
"show_emails" => "0".into(),
|
||||
"selfstatus" => {
|
||||
let s = unsafe { dc_stock_str(context, 13) };
|
||||
let res = to_string(s);
|
||||
unsafe { free(s as *mut _) };
|
||||
res
|
||||
}
|
||||
_ => "".into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_gettable_config_key(key: impl AsRef<str>) -> bool {
|
||||
SYS_CONFIG_KEYS
|
||||
.into_iter()
|
||||
.find(|c| **c == key.as_ref())
|
||||
.is_some()
|
||||
|| is_settable_config_key(key)
|
||||
}
|
||||
|
||||
fn get_sys_config_str(key: impl AsRef<str>) -> String {
|
||||
match key.as_ref() {
|
||||
"sys.version" => std::str::from_utf8(DC_VERSION_STR).unwrap().into(),
|
||||
"sys.msgsize_max_recommended" => format!("{}", 24 * 1024 * 1024 / 4 * 3),
|
||||
"sys.config_keys" => get_config_keys_str(),
|
||||
_ => "".into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_config_keys_str() -> String {
|
||||
let keys = &CONFIG_KEYS[..].join(" ");
|
||||
let sys_keys = &SYS_CONFIG_KEYS[..].join(" ");
|
||||
|
||||
format!(" {} {} ", keys, sys_keys)
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char {
|
||||
let unset = "0";
|
||||
let l = dc_loginparam_read(context, &context.sql, "");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::aheader::EncryptPreference;
|
||||
use crate::config;
|
||||
use crate::constants::Event;
|
||||
use crate::context::Context;
|
||||
use crate::context::*;
|
||||
use crate::dc_array::*;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_loginparam::*;
|
||||
@@ -882,7 +882,7 @@ pub fn dc_contact_get_profile_image(contact: *const dc_contact_t) -> *mut libc::
|
||||
}
|
||||
|
||||
if unsafe { (*contact).id } == 1 {
|
||||
let avatar = dc_get_config(unsafe { (*contact).context }, "selfavatar");
|
||||
let avatar = config::get(unsafe { (*contact).context }, "selfavatar");
|
||||
if !avatar.is_empty() {
|
||||
image_abs = unsafe { dc_strdup(to_cstring(avatar).as_ptr()) };
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ extern crate rusqlite;
|
||||
mod log;
|
||||
|
||||
pub mod aheader;
|
||||
pub mod config;
|
||||
pub mod constants;
|
||||
pub mod context;
|
||||
pub mod error;
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::ffi::CString;
|
||||
use mmime::mailimf_types::*;
|
||||
use tempfile::{tempdir, TempDir};
|
||||
|
||||
use deltachat::config;
|
||||
use deltachat::constants::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_array::*;
|
||||
@@ -247,7 +248,7 @@ unsafe fn stress_functions(context: &Context) {
|
||||
free(fn1 as *mut libc::c_void);
|
||||
}
|
||||
|
||||
let res = dc_get_config(context, "sys.config_keys");
|
||||
let res = config::get(context, "sys.config_keys");
|
||||
|
||||
assert!(!res.contains(" probably_never_a_key "));
|
||||
assert!(res.contains(" addr "));
|
||||
|
||||
Reference in New Issue
Block a user