From 442e258888efcc87d6b1aa8843a49324bf8e2388 Mon Sep 17 00:00:00 2001 From: Hugo David Farji Date: Fri, 24 Jul 2020 21:10:01 -0300 Subject: [PATCH 1/2] fix(static_file_handler): Support for blank spaces and percent encoding in path --- Cargo.toml | 1 + src/lib.rs | 1 + src/static_files_handler.rs | 10 ++++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 743feb05ea..c2ce88caf1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ serde_json = "1.0" time = "0.1" typemap = "0.3" url = "1.0" +percent-encoding = "1.0.0" [dev-dependencies] serde_derive = "1.0" diff --git a/src/lib.rs b/src/lib.rs index 2ecb9b1f14..dea0e68c1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ extern crate url; extern crate mustache; extern crate groupable; extern crate modifier; +extern crate percent_encoding; #[macro_use] extern crate log; #[macro_use] extern crate lazy_static; diff --git a/src/static_files_handler.rs b/src/static_files_handler.rs index bebd4223ab..5fc388b832 100644 --- a/src/static_files_handler.rs +++ b/src/static_files_handler.rs @@ -45,13 +45,15 @@ impl StaticFilesHandler { } } - fn extract_path<'a, D>(&self, req: &'a mut Request) -> Option<&'a str> { + fn extract_path<'a, D>(&self, req: &'a mut Request) -> Option { req.path_without_query().map(|path| { - debug!("{:?} {:?}{:?}", req.origin.method, self.root_path.display(), path); + let percent_decoded_path = percent_encoding::percent_decode(path.as_bytes()).decode_utf8().unwrap(); + + debug!("{:?} {:?}{:?}", req.origin.method, self.root_path.display(), percent_decoded_path); match path { - "/" => "index.html", - path => &path[1..], + "/" => String::from("index.html"), + path => percent_decoded_path[1..].to_string(), } }) } From 8e7401e0f85d60cd86ec301decf429521628e8f2 Mon Sep 17 00:00:00 2001 From: Hugo David Farji Date: Sun, 26 Jul 2020 20:42:23 -0300 Subject: [PATCH 2/2] fix(static_file_handler): Added specs for percent decode in static files handler --- src/static_files_handler.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/static_files_handler.rs b/src/static_files_handler.rs index 5fc388b832..338b0b2dfd 100644 --- a/src/static_files_handler.rs +++ b/src/static_files_handler.rs @@ -1,6 +1,8 @@ use std::path::{Path, PathBuf}; use std::io::ErrorKind::NotFound; use std::fs; +use std::borrow::Cow; +use std::str::Utf8Error; use hyper::method::Method::{Get, Head}; @@ -47,13 +49,13 @@ impl StaticFilesHandler { fn extract_path<'a, D>(&self, req: &'a mut Request) -> Option { req.path_without_query().map(|path| { - let percent_decoded_path = percent_encoding::percent_decode(path.as_bytes()).decode_utf8().unwrap(); + let percent_decoded_path = percent_decode_path(path).unwrap(); debug!("{:?} {:?}{:?}", req.origin.method, self.root_path.display(), percent_decoded_path); match path { "/" => String::from("index.html"), - path => percent_decoded_path[1..].to_string(), + _path => percent_decoded_path[1..].to_string(), } }) } @@ -94,6 +96,10 @@ fn safe_path>(path: P) -> bool { }) } +fn percent_decode_path(path: &str) -> Result, Utf8Error> { + percent_encoding::percent_decode(path.as_bytes()).decode_utf8() +} + #[test] fn bad_paths() { let bad_paths = &[ @@ -123,3 +129,18 @@ fn valid_paths() { assert!(safe_path(path), "expected {:?} to not be suspicious", path); } } + +#[test] +fn percent_decoded_paths() { + let paths_to_match = &[ + ("file-without-percent", "file-without-percent"), + ("file%20with%20percent", "file with percent"), + ("folder%20with%20percent/file", "folder with percent/file"), + ("folder%20with%20percent/file%20with%20percent", "folder with percent/file with percent"), + ("folder-without-percent/file%20with%20percent", "folder-without-percent/file with percent"), + ]; + + for &path in paths_to_match { + assert_eq!(percent_decode_path(path.0).unwrap(), path.1, "expected {:?} to be decoded to {:?}", path.0, path.1); + } +} \ No newline at end of file