diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index ac0fbfedc..2958eae66 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Fix handling of special characters in filenames. + ## 0.6.4 - Fix handling of newlines in filenames. diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 8ceb59bef..5b1f14eed 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -569,18 +569,20 @@ mod tests { } #[actix_rt::test] - async fn test_static_files_with_newlines() { + async fn test_static_files_with_special_characters() { // Create the file we want to test against ad-hoc. We can't check it in as otherwise // Windows can't even checkout this repository. let temp_dir = tempfile::tempdir().unwrap(); - let file_with_newlines = temp_dir.path().join("test\nnewline.text"); + let file_with_newlines = temp_dir.path().join("test\n\x0B\x0C\rnewline.text"); fs::write(&file_with_newlines, "Look at my newlines").unwrap(); let srv = test::init_service( App::new().service(Files::new("/", temp_dir.path()).index_file("Cargo.toml")), ) .await; - let request = TestRequest::get().uri("/test%0Anewline.text").to_request(); + let request = TestRequest::get() + .uri("/test%0A%0B%0C%0Dnewline.text") + .to_request(); let response = test::call_service(&srv, request).await; assert_eq!(response.status(), StatusCode::OK); diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index 02dc701ea..9e4a37737 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -139,8 +139,12 @@ impl NamedFile { _ => DispositionType::Attachment, }; - // Replace newlines in filenames which could occur on some filesystems. - let filename_s = filename.replace('\n', "%0A"); + // replace special characters in filenames which could occur on some filesystems + let filename_s = filename + .replace('\n', "%0A") // \n line break + .replace('\x0B', "%0B") // \v vertical tab + .replace('\x0C', "%0C") // \f form feed + .replace('\r', "%0D"); // \r carriage return let mut parameters = vec![DispositionParam::Filename(filename_s)]; if !filename.is_ascii() {