Skip to content

Commit 8ea2685

Browse files
committed
deduplicate full_path construction logic by creating helper build_storage_key()
Signed-off-by: Denys Fedoryshchenko <denys.f@collabora.com>
1 parent 4225893 commit 8ea2685

1 file changed

Lines changed: 25 additions & 34 deletions

File tree

src/main.rs

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,25 @@ fn validate_path(path: &str) -> Result<(), String> {
513513
Ok(())
514514
}
515515

516+
/// Build a normalized, validated storage key from the upload path and filename.
517+
/// Strips trailing slashes from `path`, joins with `filename`, strips leading slashes,
518+
/// and validates against path traversal.
519+
fn build_storage_key(path: &mut String, filename: &str) -> Result<String, String> {
520+
// Remove trailing slash
521+
if path.ends_with('/') {
522+
path.pop();
523+
}
524+
let full_path = if path.is_empty() {
525+
filename.to_string()
526+
} else {
527+
format!("{}/{}", path, filename)
528+
};
529+
// Normalize: strip leading slashes so the path is always relative
530+
let full_path = full_path.trim_start_matches('/').to_string();
531+
validate_path(&full_path)?;
532+
Ok(full_path)
533+
}
534+
516535
fn verify_upload_permissions(owner: &str, path: &str) -> Result<(), String> {
517536
let cfg_content = get_config_content();
518537
let cfg: Table = toml::from_str(&cfg_content).unwrap();
@@ -682,28 +701,13 @@ async fn ax_post_file(
682701
}
683702

684703
// FAST PATH: path already set, stream directly
685-
// if path ends on /, remove it
686-
if path.ends_with("/") {
687-
debug_log!("Removing trailing /, workaround");
688-
path.pop();
689-
}
690-
691-
let full_path = if path.is_empty() {
692-
file0_filename.clone()
693-
} else {
694-
format!("{}/{}", path, file0_filename)
695-
};
696-
// Normalize: strip leading slashes so the path is always relative
697-
let full_path = full_path.trim_start_matches('/').to_string();
698-
699-
// validate path for traversal
700-
match validate_path(&full_path) {
701-
Ok(_) => (),
704+
let full_path = match build_storage_key(&mut path, &file0_filename) {
705+
Ok(p) => p,
702706
Err(e) => {
703707
upload_result = Some((StatusCode::BAD_REQUEST, e.into_bytes()));
704708
break;
705709
}
706-
}
710+
};
707711

708712
// verify upload permissions
709713
match verify_upload_permissions(&owner, &path) {
@@ -820,25 +824,12 @@ async fn ax_post_file(
820824
// Handle buffered file0 case (file0 arrived before path)
821825
if upload_result.is_none() {
822826
if let Some(tmp) = buffered_file {
823-
if path.ends_with("/") {
824-
debug_log!("Removing trailing /, workaround");
825-
path.pop();
826-
}
827-
828-
let full_path = if path.is_empty() {
829-
file0_filename.clone()
830-
} else {
831-
format!("{}/{}", path, file0_filename)
832-
};
833-
// Normalize: strip leading slashes so the path is always relative
834-
let full_path = full_path.trim_start_matches('/').to_string();
835-
836-
match validate_path(&full_path) {
837-
Ok(_) => (),
827+
let full_path = match build_storage_key(&mut path, &file0_filename) {
828+
Ok(p) => p,
838829
Err(e) => {
839830
return (StatusCode::BAD_REQUEST, e.into_bytes());
840831
}
841-
}
832+
};
842833

843834
match verify_upload_permissions(&owner, &path) {
844835
Ok(_) => (),

0 commit comments

Comments
 (0)