allow subpaths inside zipfiles
This commit is contained in:
parent
76a16e6ba6
commit
b7185bc313
2 changed files with 32 additions and 9 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::HashSet, fs::File, io::Write};
|
||||
use std::{collections::HashSet, fs::File, io::Write, path::Path, path::Component};
|
||||
|
||||
use actix::{fut::future::ActorFutureExt, Actor, ActorContext, AsyncContext, StreamHandler};
|
||||
use actix_http::ws::{CloseReason, Item};
|
||||
|
@ -22,20 +22,42 @@ const MAX_FILES: usize = 256;
|
|||
const FILENAME_DATE_FORMAT: &[time::format_description::FormatItem] =
|
||||
time::macros::format_description!("[year]-[month]-[day]-[hour][minute][second]");
|
||||
|
||||
/// Sanitises a filename after performing unicode normalization,
|
||||
/// Sanitises a file or directory name after performing unicode normalization,
|
||||
/// optionally reducing the length limit to leave space for an
|
||||
/// extension yet to be added.
|
||||
fn sanitise(name: &str, extension_length: usize) -> String {
|
||||
fn sanitise_path_component(name: &str, extension_length: usize) -> String {
|
||||
let name = name.nfd().collect::<String>();
|
||||
sanitise_with_options(
|
||||
&name,
|
||||
&SanOptions {
|
||||
length_limit: SanOptions::DEFAULT.length_limit - extension_length,
|
||||
length_limit: SanOptions::DEFAULT.length_limit.saturating_sub(extension_length),
|
||||
..SanOptions::DEFAULT
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn sanitise_path(path: &str) -> String {
|
||||
let mut san_path = Path::new(path).components().rfold(String::new(), |subpath, c| {
|
||||
if subpath.len() >= SanOptions::DEFAULT.length_limit*8 {
|
||||
return subpath;
|
||||
}
|
||||
if let Component::Normal(s) = c {
|
||||
let mut component = sanitise_path_component(&s.to_string_lossy(), 0);
|
||||
if !subpath.is_empty() {
|
||||
component.push('/');
|
||||
component.push_str(&subpath);
|
||||
}
|
||||
component
|
||||
} else {
|
||||
subpath
|
||||
}
|
||||
});
|
||||
if san_path.is_empty() {
|
||||
san_path.push('_');
|
||||
}
|
||||
san_path
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
enum Error {
|
||||
#[error("Failed to parse file metadata")]
|
||||
|
@ -114,7 +136,7 @@ pub use crate::state::v1::UploadedFile;
|
|||
impl UploadedFile {
|
||||
fn new(name: &str, size: u64, modtime: OffsetDateTime) -> Self {
|
||||
Self {
|
||||
name: sanitise(name, 0),
|
||||
name: sanitise_path(name),
|
||||
size,
|
||||
modtime,
|
||||
}
|
||||
|
@ -285,7 +307,7 @@ impl Uploader {
|
|||
info!("Wrapping in zipfile generator");
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let collection_name =
|
||||
collection_name.map(|f| sanitise(&f, 4)).unwrap_or_else(|| {
|
||||
collection_name.map(|f| sanitise_path_component(&f, 4)).unwrap_or_else(|| {
|
||||
super::APP_NAME.to_owned()
|
||||
+ &now.format(FILENAME_DATE_FORMAT).unwrap()
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue