diff --git a/src/lib.rs b/src/lib.rs index 9378318b..fe871a47 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1419,11 +1419,31 @@ fn file_url_segments_to_pathbuf(segments: str::Split) -> Result) -> Result { let first = try!(segments.next().ok_or(())); - if first.len() != 2 || !first.starts_with(parser::ascii_alpha) - || first.as_bytes()[1] != b':' { - return Err(()) - } - let mut string = first.to_owned(); + + let mut string = match first.len() { + 2 => { + if !first.starts_with(parser::ascii_alpha) || first.as_bytes()[1] != b':' { + return Err(()) + } + + first.to_owned() + }, + + 4 => { + if !first.starts_with(parser::ascii_alpha) { + return Err(()) + } + let bytes = first.as_bytes(); + if bytes[1] != b'%' || bytes[2] != b'3' || (bytes[3] != b'a' && bytes[3] != b'A') { + return Err(()) + } + + first[0..1].to_owned() + ":" + }, + + _ => return Err(()), + }; + for segment in segments { string.push('\\'); diff --git a/tests/unit.rs b/tests/unit.rs index 7cea1000..08cf75d5 100644 --- a/tests/unit.rs +++ b/tests/unit.rs @@ -70,6 +70,10 @@ fn new_path_windows_fun() { // test windows canonicalized path let path = PathBuf::from(r"\\?\C:\foo\bar"); assert!(Url::from_file_path(path).is_ok()); + + // Percent-encoded drive letter + let url = Url::parse("file:///C%3A/foo/bar").unwrap(); + assert_eq!(url.to_file_path(), Ok(PathBuf::from(r"C:\foo\bar"))); } }