//! All config settings. Mirrors legacy/lib/config.php; every value has the //! original default and can be overridden in `config.toml`. use std::path::{Path, PathBuf}; use serde::Deserialize; #[derive(Debug, Clone, Deserialize)] #[serde(default)] pub struct Config { // Server pub bind: String, pub data_dir: PathBuf, pub database: PathBuf, /// Set when served over HTTPS, adds the `Secure` flag to cookies. pub secure_cookies: bool, /// Take the client IP from `X-Forwarded-For` (only behind a trusted reverse proxy). pub trust_proxy: bool, // Names and URLs for your installation pub frontend_path: String, pub site_name: String, pub site_title: String, // Spam protection pub upload_lock_time: i64, pub max_num_uploads: i64, // User score pub post_score: i64, pub tag_score_per_char: f64, pub tag_score_max: f64, // Misc settings pub users_per_page: i64, pub thumbs_per_page: i64, pub color_search_dev: i64, pub max_random_thumbs: i64, pub min_random_score: f64, pub max_download: usize, pub jpeg_quality: u8, /// User ids that see the HoF/Ban admin links (was hardcoded `$user->id == "1"`). pub superadmins: Vec, /// User ids that see the "Unblock" link on /manage (was `id == 11 || id == 1`). pub unblockers: Vec, /// Optional iframe targets for /chat, /forum and /shop. Empty = placeholder. pub chat_url: String, pub forum_url: String, pub shop_url: String, } impl Default for Config { fn default() -> Self { Self { bind: "127.0.0.1:8080".into(), data_dir: "data".into(), database: "data/4ducky.db".into(), secure_cookies: false, trust_proxy: false, frontend_path: "http://www.4ducky.com/".into(), site_name: "4ducky".into(), site_title: "4ducky.com - fol witzik".into(), upload_lock_time: 7200, max_num_uploads: 50, post_score: 10, tag_score_per_char: 0.5, tag_score_max: 20.0, users_per_page: 100, thumbs_per_page: 125, color_search_dev: 50, max_random_thumbs: 10, min_random_score: 10.0, max_download: 8_097_152, jpeg_quality: 100, superadmins: vec![1], unblockers: vec![1, 11], chat_url: String::new(), forum_url: String::new(), shop_url: String::new(), } } } impl Config { pub fn load(path: &Path) -> anyhow::Result { let mut cfg: Config = if path.exists() { toml::from_str(&std::fs::read_to_string(path)?)? } else { Config::default() }; if !cfg.frontend_path.ends_with('/') { cfg.frontend_path.push('/'); } Ok(cfg) } pub fn is_superadmin(&self, id: i64) -> bool { self.superadmins.contains(&id) } } /// Grid solver settings (`Config::$gridView`). Not configurable, the CSS depends on them. pub const GRID_SIZE: i64 = 64; pub const GRID_WIDTH: usize = 12; pub const BORDER_WIDTH: u32 = 2; pub struct ThumbClass { pub class: &'static str, pub width: usize, pub height: usize, pub percentage: f64, pub dir: &'static str, } /// Definition of all Thumbnail classes, in the original order. pub const THUMB_CLASSES: [ThumbClass; 3] = [ ThumbClass { class: "b2", width: 1, height: 1, percentage: 0.6, dir: "64x64" }, ThumbClass { class: "b1", width: 2, height: 2, percentage: 0.35, dir: "128x128" }, ThumbClass { class: "b0", width: 3, height: 3, percentage: 0.05, dir: "192x192" }, ]; pub fn thumb_class(class: &str) -> &'static ThumbClass { THUMB_CLASSES.iter().find(|c| c.class == class).unwrap_or(&THUMB_CLASSES[0]) }