feat: improve hidden to support glob (#108)
This commit is contained in:
parent
f148817c52
commit
b791549ec7
3 changed files with 69 additions and 10 deletions
|
@ -159,7 +159,7 @@ pub struct Args {
|
||||||
pub path_is_file: bool,
|
pub path_is_file: bool,
|
||||||
pub path_prefix: String,
|
pub path_prefix: String,
|
||||||
pub uri_prefix: String,
|
pub uri_prefix: String,
|
||||||
pub hidden: String,
|
pub hidden: Vec<String>,
|
||||||
pub auth_method: AuthMethod,
|
pub auth_method: AuthMethod,
|
||||||
pub auth: AccessControl,
|
pub auth: AccessControl,
|
||||||
pub allow_upload: bool,
|
pub allow_upload: bool,
|
||||||
|
@ -199,9 +199,9 @@ impl Args {
|
||||||
} else {
|
} else {
|
||||||
format!("/{}/", &encode_uri(&path_prefix))
|
format!("/{}/", &encode_uri(&path_prefix))
|
||||||
};
|
};
|
||||||
let hidden: String = matches
|
let hidden: Vec<String> = matches
|
||||||
.value_of("hidden")
|
.value_of("hidden")
|
||||||
.map(|v| format!(",{},", v))
|
.map(|v| v.split(',').map(|x| x.to_string()).collect())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let enable_cors = matches.is_present("enable-cors");
|
let enable_cors = matches.is_present("enable-cors");
|
||||||
let auth: Vec<&str> = matches
|
let auth: Vec<&str> = matches
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::streamer::Streamer;
|
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 crate::{Args, BoxResult};
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
use xml::escape::escape_str_pcdata;
|
use xml::escape::escape_str_pcdata;
|
||||||
|
@ -366,7 +366,8 @@ impl Server {
|
||||||
) -> BoxResult<()> {
|
) -> BoxResult<()> {
|
||||||
let mut paths: Vec<PathItem> = vec![];
|
let mut paths: Vec<PathItem> = vec![];
|
||||||
let path_buf = path.to_path_buf();
|
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 running = self.running.clone();
|
||||||
let search = search.to_lowercase();
|
let search = search.to_lowercase();
|
||||||
let search_paths = tokio::task::spawn_blocking(move || {
|
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>(
|
async fn zip_dir<W: AsyncWrite + Unpin>(
|
||||||
writer: &mut W,
|
writer: &mut W,
|
||||||
dir: &Path,
|
dir: &Path,
|
||||||
hidden: &str,
|
hidden: &[String],
|
||||||
running: Arc<AtomicBool>,
|
running: Arc<AtomicBool>,
|
||||||
) -> BoxResult<()> {
|
) -> BoxResult<()> {
|
||||||
let mut writer = ZipFileWriter::new(writer);
|
let mut writer = ZipFileWriter::new(writer);
|
||||||
let hidden = Arc::new(hidden.to_string());
|
let hidden = Arc::new(hidden.to_vec());
|
||||||
let hidden = hidden.to_string();
|
let hidden = hidden.clone();
|
||||||
let dir_path_buf = dir.to_path_buf();
|
let dir_path_buf = dir.to_path_buf();
|
||||||
let zip_paths = tokio::task::spawn_blocking(move || {
|
let zip_paths = tokio::task::spawn_blocking(move || {
|
||||||
let mut it = WalkDir::new(&dir_path_buf).into_iter();
|
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;
|
*res.status_mut() = StatusCode::NO_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_hidden(hidden: &str, file_name: &str) -> bool {
|
fn is_hidden(hidden: &[String], file_name: &str) -> bool {
|
||||||
hidden.contains(&format!(",{},", file_name))
|
hidden.iter().any(|v| glob(v, file_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_webdav_headers(res: &mut Response) {
|
fn set_webdav_headers(res: &mut Response) {
|
||||||
|
|
58
src/utils.rs
58
src/utils.rs
|
@ -23,3 +23,61 @@ pub fn try_get_file_name(path: &Path) -> BoxResult<&str> {
|
||||||
.and_then(|v| v.to_str())
|
.and_then(|v| v.to_str())
|
||||||
.ok_or_else(|| format!("Failed to get file name of `{}`", path.display()).into())
|
.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"));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue