From b791549ec777d506265cd24d547d286d067e50c9 Mon Sep 17 00:00:00 2001 From: sigoden Date: Tue, 19 Jul 2022 20:37:14 +0800 Subject: [PATCH] feat: improve hidden to support glob (#108) --- src/args.rs | 6 +++--- src/server.rs | 15 ++++++------- src/utils.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/args.rs b/src/args.rs index bb06720..ac33fa2 100644 --- a/src/args.rs +++ b/src/args.rs @@ -159,7 +159,7 @@ pub struct Args { pub path_is_file: bool, pub path_prefix: String, pub uri_prefix: String, - pub hidden: String, + pub hidden: Vec, pub auth_method: AuthMethod, pub auth: AccessControl, pub allow_upload: bool, @@ -199,9 +199,9 @@ impl Args { } else { format!("/{}/", &encode_uri(&path_prefix)) }; - let hidden: String = matches + let hidden: Vec = matches .value_of("hidden") - .map(|v| format!(",{},", v)) + .map(|v| v.split(',').map(|x| x.to_string()).collect()) .unwrap_or_default(); let enable_cors = matches.is_present("enable-cors"); let auth: Vec<&str> = matches diff --git a/src/server.rs b/src/server.rs index 456ed3d..fb1f6a0 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,5 +1,5 @@ use crate::streamer::Streamer; -use crate::utils::{decode_uri, encode_uri, get_file_name, try_get_file_name}; +use crate::utils::{decode_uri, encode_uri, get_file_name, glob, try_get_file_name}; use crate::{Args, BoxResult}; use walkdir::WalkDir; use xml::escape::escape_str_pcdata; @@ -366,7 +366,8 @@ impl Server { ) -> BoxResult<()> { let mut paths: Vec = vec![]; let path_buf = path.to_path_buf(); - let hidden = self.args.hidden.to_string(); + let hidden = Arc::new(self.args.hidden.to_vec()); + let hidden = hidden.clone(); let running = self.running.clone(); let search = search.to_lowercase(); let search_paths = tokio::task::spawn_blocking(move || { @@ -1065,12 +1066,12 @@ fn res_multistatus(res: &mut Response, content: &str) { async fn zip_dir( writer: &mut W, dir: &Path, - hidden: &str, + hidden: &[String], running: Arc, ) -> BoxResult<()> { let mut writer = ZipFileWriter::new(writer); - let hidden = Arc::new(hidden.to_string()); - let hidden = hidden.to_string(); + let hidden = Arc::new(hidden.to_vec()); + let hidden = hidden.clone(); let dir_path_buf = dir.to_path_buf(); let zip_paths = tokio::task::spawn_blocking(move || { let mut it = WalkDir::new(&dir_path_buf).into_iter(); @@ -1170,8 +1171,8 @@ fn status_no_content(res: &mut Response) { *res.status_mut() = StatusCode::NO_CONTENT; } -fn is_hidden(hidden: &str, file_name: &str) -> bool { - hidden.contains(&format!(",{},", file_name)) +fn is_hidden(hidden: &[String], file_name: &str) -> bool { + hidden.iter().any(|v| glob(v, file_name)) } fn set_webdav_headers(res: &mut Response) { diff --git a/src/utils.rs b/src/utils.rs index 6a27b65..ca951fa 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -23,3 +23,61 @@ pub fn try_get_file_name(path: &Path) -> BoxResult<&str> { .and_then(|v| v.to_str()) .ok_or_else(|| format!("Failed to get file name of `{}`", path.display()).into()) } + +pub fn glob(source: &str, target: &str) -> bool { + let ss: Vec = source.chars().collect(); + let mut iter = target.chars(); + let mut i = 0; + 'outer: while i < ss.len() { + let s = ss[i]; + match s { + '*' => match ss.get(i + 1) { + Some(s_next) => { + for t in iter.by_ref() { + if t == *s_next { + i += 2; + continue 'outer; + } + } + return true; + } + None => return true, + }, + '?' => match iter.next() { + Some(_) => { + i += 1; + continue; + } + None => return false, + }, + _ => match iter.next() { + Some(t) => { + if s == t { + i += 1; + continue; + } + return false; + } + None => return false, + }, + } + } + iter.next().is_none() +} + +#[test] +fn test_glob_key() { + assert!(glob("", "")); + assert!(glob(".*", ".git")); + assert!(glob("abc", "abc")); + assert!(glob("a*c", "abc")); + assert!(glob("a?c", "abc")); + assert!(glob("a*c", "abbc")); + assert!(glob("*c", "abc")); + assert!(glob("a*", "abc")); + assert!(glob("?c", "bc")); + assert!(glob("a?", "ab")); + assert!(!glob("abc", "adc")); + assert!(!glob("abc", "abcd")); + assert!(!glob("a?c", "abbc")); +}