Browse Source

Auto merge of #231 - Arnavion:fix-230, r=SimonSapin

Teach to_file_path to understand percent-encoded drive letters on Windows.

Fixes #230

---

I thought about using `percent_encoded` instead of matching `%3a` bytes individually, but I figured it would be overkill. If you think otherwise I'm happy to change it.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-url/231)
<!-- Reviewable:end -->
bors-servo 10 years ago
parent
commit
99d3b1b022
2 changed files with 29 additions and 5 deletions
  1. 25 5
      src/lib.rs
  2. 4 0
      tests/unit.rs

+ 25 - 5
src/lib.rs

@@ -1419,11 +1419,31 @@ fn file_url_segments_to_pathbuf(segments: str::Split<char>) -> Result<PathBuf, (
 #[cfg_attr(not(windows), allow(dead_code))]
 fn file_url_segments_to_pathbuf_windows(mut segments: str::Split<char>) -> Result<PathBuf, ()> {
     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('\\');
 

+ 4 - 0
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")));
     }
 }