CH-J Toolsgestione server su SSH
Menu
Sorgente pubblicata

CH-J Tools

Sfoglia directory e file per una specifica release di applicazioni.

Scarica sorgente ZIP
CH-J / Server Manager 1704 file
0.1.2-beta Aggiunto: · Costruito:
settings.rs Aggiunto: Data non registrata 6,6 KB · 163 righe
Codice Scarica file
1//! Helper settings in `<data>/standby-helper.json`, written by the application (Settings → Standby Helper).
2//! The file holds only switches; no secrets. A missing or broken file means "everything off".
3use serde_json::{json, Value};
4use std::path::{Path, PathBuf};
6pub const FILE: &str = "standby-helper.json";
7const APP_DIRECTORY_NAME: &str = "CH-J Tools";
8/// Folder of the application before its rename; the application moves it to `APP_DIRECTORY_NAME` at its first start.
9const LEGACY_APP_DIRECTORY_NAME: &str = "CH-J Server Manager";
11/// Same resolution as the application's `AppPaths::resolve`, so both always use the same data folder: the new folder,
12/// or the old one while the application has not moved it yet (the helper never moves it itself).
13pub fn data_dir() -> PathBuf {
14 for var in ["CHJ_USER_DATA_DIR", "CHJ_BUILD_SMOKE_USER_DATA_DIR"] {
15 if let Some(path) = std::env::var_os(var).map(PathBuf::from).filter(|p| p.is_absolute()) {
16 return path;
17 }
18 }
19 choose(&config_dir())
22fn choose(base: &Path) -> PathBuf {
23 let target = base.join(APP_DIRECTORY_NAME);
24 let legacy = base.join(LEGACY_APP_DIRECTORY_NAME);
25 let usable = |path: &Path| std::fs::read_dir(path).map(|mut entries| entries.next().is_some()).unwrap_or(false);
26 if !usable(&target) && legacy.is_dir() {
27 legacy
28 } else {
29 target
30 }
33pub fn home() -> PathBuf {
34 std::env::var_os(if cfg!(windows) { "USERPROFILE" } else { "HOME" }).map(PathBuf::from).unwrap_or_default()
37fn config_dir() -> PathBuf {
38 if cfg!(target_os = "macos") {
39 home().join("Library").join("Application Support")
40 } else if cfg!(windows) {
41 std::env::var_os("APPDATA").map(PathBuf::from).unwrap_or_else(|| home().join("AppData").join("Roaming"))
42 } else {
43 std::env::var_os("XDG_CONFIG_HOME").map(PathBuf::from).filter(|p| p.is_absolute()).unwrap_or_else(|| home().join(".config"))
44 }
47#[derive(Clone, Debug, PartialEq, Eq)]
48pub struct Settings {
49 /// Master switch: off removes every system entry and stops the background process.
50 pub enabled: bool,
51 /// Start the background process at login.
52 pub start_at_login: bool,
53 /// Context-menu entries of the system file manager.
54 pub menu_verify: bool,
55 pub menu_sign: bool,
58impl Default for Settings {
59 fn default() -> Self {
60 Self { enabled: false, start_at_login: true, menu_verify: true, menu_sign: true }
61 }
64impl Settings {
65 pub fn from_json(value: &Value) -> Self {
66 let flag = |key: &str, default: bool| value.get(key).and_then(Value::as_bool).unwrap_or(default);
67 let d = Self::default();
68 Self {
69 enabled: flag("enabled", d.enabled),
70 start_at_login: flag("startAtLogin", d.start_at_login),
71 menu_verify: value.get("menu").and_then(|m| m.get("verify")).and_then(Value::as_bool).unwrap_or(d.menu_verify),
72 menu_sign: value.get("menu").and_then(|m| m.get("sign")).and_then(Value::as_bool).unwrap_or(d.menu_sign),
73 }
74 }
75 pub fn to_json(&self) -> Value {
76 json!({"enabled": self.enabled, "startAtLogin": self.start_at_login, "menu": {"verify": self.menu_verify, "sign": self.menu_sign}})
77 }
78 pub fn wants_login(&self) -> bool {
79 self.enabled && self.start_at_login
80 }
81 pub fn wants_verify(&self) -> bool {
82 self.enabled && self.menu_verify
83 }
84 pub fn wants_sign(&self) -> bool {
85 self.enabled && self.menu_sign
86 }
89pub fn load(data: &Path) -> Settings {
90 std::fs::read(data.join(FILE)).ok().and_then(|b| serde_json::from_slice::<Value>(&b).ok()).map(|v| Settings::from_json(&v)).unwrap_or_default()
93/// UI language of the application (`config/config.json` → `ui.language`), reduced to the helper's CS/DE/EN.
94pub fn language(data: &Path) -> &'static str {
95 let code = std::fs::read(data.join("config").join("config.json"))
96 .ok()
97 .and_then(|b| serde_json::from_slice::<Value>(&b).ok())
98 .and_then(|v| v["ui"]["language"].as_str().map(str::to_string))
99 .unwrap_or_default();
100 match code.get(..2) {
101 Some("cs") | Some("sk") => "cs",
102 Some("de") => "de",
103 _ => "en",
104 }
107/// Everything the integration needs: where the user's folders are and what the menu entries say.
108pub struct Context {
109 pub home: PathBuf,
110 pub helper: PathBuf,
111 /// Icon of the Windows menu entries.
112 #[cfg_attr(not(windows), allow(dead_code))]
113 pub app: PathBuf,
114 pub language: &'static str,
117impl Context {
118 pub fn new(data: &Path) -> Self {
119 Self { home: home(), helper: crate::helper_binary(), app: crate::app_binary(), language: language(data) }
120 }
121 pub fn label(&self, action: &str) -> &'static str {
122 match (self.language, action) {
123 ("cs", "verify") => "CH-J – Ověřit podpis",
124 ("cs", _) => "CH-J – Podepsat (OpenPGP)",
125 ("de", "verify") => "CH-J – Signatur prüfen",
126 ("de", _) => "CH-J – Signieren (OpenPGP)",
127 (_, "verify") => "CH-J – Verify signature",
128 _ => "CH-J – Sign (OpenPGP)",
129 }
130 }
133#[cfg(test)]
134mod tests {
135 #[test]
136 fn data_folder_follows_the_rename() {
137 let base = tempfile::tempdir().unwrap();
138 assert_eq!(super::choose(base.path()), base.path().join("CH-J Tools"));
139 std::fs::create_dir_all(base.path().join("CH-J Server Manager").join("vault")).unwrap();
140 assert_eq!(super::choose(base.path()), base.path().join("CH-J Server Manager"));
141 std::fs::create_dir_all(base.path().join("CH-J Tools")).unwrap();
142 assert_eq!(super::choose(base.path()), base.path().join("CH-J Server Manager"), "an empty new folder is not the data yet");
143 std::fs::write(base.path().join("CH-J Tools").join("config.json"), b"{}").unwrap();
144 assert_eq!(super::choose(base.path()), base.path().join("CH-J Tools"));
145 }
147 use super::*;
149 #[test]
150 fn missing_or_broken_settings_mean_off() {
151 let dir = std::env::temp_dir().join(format!("chj-standby-settings-{}", std::process::id()));
152 std::fs::create_dir_all(&dir).unwrap();
153 assert_eq!(load(&dir), Settings::default());
154 assert!(!load(&dir).wants_verify());
155 std::fs::write(dir.join(FILE), "{broken").unwrap();
156 assert_eq!(load(&dir), Settings::default());
157 std::fs::write(dir.join(FILE), r#"{"enabled":true,"startAtLogin":false,"menu":{"sign":false}}"#).unwrap();
158 let s = load(&dir);
159 assert!(s.wants_verify() && !s.wants_sign() && !s.wants_login());
160 assert_eq!(Settings::from_json(&s.to_json()), s);
161 std::fs::remove_dir_all(&dir).unwrap();
162 }
SHA-2561cf707e94731cedb585ee1fe73f3f5c579a7020da7cf16a751b84f95dc743edc

CH-J Proprietary Software License 1.14 · La sorgente è fornita sotto CH-J Proprietary Software License 1.14. La sua disponibilità non modifica i termini di licenza o concede diritti aggiuntivi.

Archivio SHA-256ac8fe790f4ba60fc098f8c985fc2656cfcc6cdc21fb34b30e308a2b54e62258f
File