]> OzVa Git service - ozva-cloud/commitdiff
feat: improve hidden to support glob (#108)
authorsigoden <sigoden@gmail.com>
Tue, 19 Jul 2022 12:37:14 +0000 (20:37 +0800)
committerGitHub <noreply@github.com>
Tue, 19 Jul 2022 12:37:14 +0000 (20:37 +0800)
src/args.rs
src/server.rs
src/utils.rs

index bb0672085999366c7b681d765885a9c6d00f31ca..ac33fa267c6a1347d65108f4d28df34718495bf1 100644 (file)
@@ -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<String>,
     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<String> = 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
index 456ed3dfb525188bf37b84748be3a47c2271d432..fb1f6a000e1389bc5ea0706d09ab317b6c50392e 100644 (file)
@@ -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<PathItem> = 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<W: AsyncWrite + Unpin>(
     writer: &mut W,
     dir: &Path,
-    hidden: &str,
+    hidden: &[String],
     running: Arc<AtomicBool>,
 ) -> 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) {
index 6a27b65641d9663c812af6d77cfd1270d66c0277..ca951fa9da62853be5d5aa9d893bd2cf6cc4f04c 100644 (file)
@@ -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<char> = 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"));
+}