diff --git a/src/main.rs b/src/main.rs index 425fb30f..ba281b30 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod cli; mod manifest; mod missing; mod path; +mod registry; mod resource; mod schema; mod steam; diff --git a/src/path.rs b/src/path.rs index aa774aa4..8dd3d350 100644 --- a/src/path.rs +++ b/src/path.rs @@ -50,7 +50,7 @@ pub fn normalize(path: &str) -> String { path } -pub fn too_broad(path: &str) -> bool { +fn too_broad(path: &str) -> bool { use placeholder::{BASE, HOME, ROOT, STORE_USER_ID, WIN_APP_DATA, WIN_DIR, WIN_DOCUMENTS, XDG_CONFIG, XDG_DATA}; for item in placeholder::ALL { diff --git a/src/registry.rs b/src/registry.rs new file mode 100644 index 00000000..ed209863 --- /dev/null +++ b/src/registry.rs @@ -0,0 +1,54 @@ +use once_cell::sync::Lazy; +use regex::Regex; + +pub fn normalize(path: &str) -> String { + let mut path = path.trim().trim_end_matches(['/', '\\']).replace('\\', "/"); + + static CONSECUTIVE_SLASHES: Lazy = Lazy::new(|| Regex::new(r"/{2,}").unwrap()); + static UNNECESSARY_DOUBLE_STAR_1: Lazy = Lazy::new(|| Regex::new(r"([^/*])\*{2,}").unwrap()); + static UNNECESSARY_DOUBLE_STAR_2: Lazy = Lazy::new(|| Regex::new(r"\*{2,}([^/*])").unwrap()); + static ENDING_WILDCARD: Lazy = Lazy::new(|| Regex::new(r"(/\*)+$").unwrap()); + static ENDING_DOT: Lazy = Lazy::new(|| Regex::new(r"(/\.)$").unwrap()); + static INTERMEDIATE_DOT: Lazy = Lazy::new(|| Regex::new(r"(/\./)").unwrap()); + + for (pattern, replacement) in [ + (&CONSECUTIVE_SLASHES, "/"), + (&UNNECESSARY_DOUBLE_STAR_1, "${1}*"), + (&UNNECESSARY_DOUBLE_STAR_2, "*${1}"), + (&ENDING_WILDCARD, ""), + (&ENDING_DOT, ""), + (&INTERMEDIATE_DOT, "/"), + ] { + path = pattern.replace_all(&path, replacement).to_string(); + } + + path +} + +fn too_broad(path: &str) -> bool { + let path = path.to_lowercase(); + + let valid = &["hkey_current_user", "hkey_local_machine"]; + if !valid.iter().any(|x| path.starts_with(x)) { + return true; + } + + for item in [ + "hkey_current_user", + "hkey_current_user/software", + "hkey_current_user/software/wow6432node", + "hkey_local_machine", + "hkey_local_machine/software", + "hkey_local_machine/software/wow6432node", + ] { + if path == item { + return true; + } + } + + false +} + +pub fn usable(path: &str) -> bool { + !path.is_empty() && !path.contains("{{") && !too_broad(path) +} diff --git a/src/wiki.rs b/src/wiki.rs index 80bbbf8c..8c6fd0fa 100644 --- a/src/wiki.rs +++ b/src/wiki.rs @@ -6,7 +6,7 @@ use wikitext_parser::{Attribute, TextPiece}; use crate::{ manifest::{placeholder, Os, Store, Tag}, - path, + path, registry, resource::ResourceFile, should_cancel, Error, Regularity, State, }; @@ -625,7 +625,10 @@ impl WikiPath { } pub fn normalize(mut self) -> Self { - self.composite = path::normalize(&self.composite); + self.composite = match self.kind { + None | Some(PathKind::File) => path::normalize(&self.composite), + Some(PathKind::Registry) => registry::normalize(&self.composite), + }; if self.kind.is_none() { self.kind = Some(PathKind::File); @@ -692,7 +695,10 @@ impl WikiPath { } pub fn usable(&self) -> bool { - path::usable(&self.composite) && !self.irregular() + match self.kind { + None | Some(PathKind::File) => path::usable(&self.composite) && !self.irregular(), + Some(PathKind::Registry) => registry::usable(&self.composite) && !self.irregular(), + } } }