description("Canonicalization of paths."); cases = [ ["/././foo", "/foo"], ["/./.foo", "/.foo"], ["/foo/.", "/foo/"], ["/foo/./", "/foo/"], // double dots followed by a slash or the end of the string count ["/foo/bar/..", "/foo/"], ["/foo/bar/../", "/foo/"], // don't count double dots when they aren't followed by a slash ["/foo/..bar", "/foo/..bar"], // some in the middle ["/foo/bar/../ton", "/foo/ton"], ["/foo/bar/../ton/../../a", "/a"], // we should not be able to go above the root ["/foo/../../..", "/"], ["/foo/../../../ton", "/ton"], // escaped dots should be unescaped and treated the same as dots ["/foo/%2e", "/foo/"], ["/foo/%2e%2", "/foo/.%2"], ["/foo/%2e./%2e%2e/.%2e/%2e.bar", "/..bar"], // Multiple slashes in a row should be preserved and treated like empty // directory names. ["////../..", "//"], ["/foo/bar//../..", "/foo/"], ["/foo/bar//..", "/foo/bar/"], ["/foo/bar/..", "/foo/"], // ----- escaping tests ----- ["/foo", "/foo"], // Valid escape sequence ["/%20foo", "/%20foo"], // Invalid escape sequence we should pass through unchanged. ["/foo%", "/foo%"], ["/foo%2", "/foo%2"], // Invalid escape sequence: bad characters should be treated the same as // the sourrounding text, not as escaped (in this case, UTF-8). ["/foo%2zbar", "/foo%2zbar"], // (Disabled because requires UTF8) // ["/foo%2\xc2\xa9zbar", "/foo%2%C2%A9zbar"], ["/foo%2\u00c2\u00a9zbar", "/foo%2%C3%82%C2%A9zbar"], // Regular characters that are escaped should be unescaped ["/foo%41%7a", "/fooAz"], // Funny characters that are unescaped should be escaped ["/foo\u0009\u0091%91", "/foo%09%C2%91%91"], // Invalid characters that are escaped should cause a failure. ["/foo%00%51", "/foo%00Q"], // Some characters should be passed through unchanged regardless of esc. ["/(%28:%3A%29)", "/(%28:%3A%29)"], // Characters that are properly escaped should not have the case changed // of hex letters. ["/%3A%3a%3C%3c", "/%3A%3a%3C%3c"], // Funny characters that are unescaped should be escaped ["/foo\tbar", "/foo%09bar"], // Backslashes should get converted to forward slashes ["\\\\foo\\\\bar", "/foo/bar"], // Hashes found in paths (possibly only when the caller explicitly sets // the path on an already-parsed URL) should be escaped. // (Disabled because requires ability to set path directly.) // ["/foo#bar", "/foo%23bar"], // %7f should be allowed and %3D should not be unescaped (these were wrong // in a previous version). ["/%7Ffp3%3Eju%3Dduvgw%3Dd", "/%7Ffp3%3Eju%3Dduvgw%3Dd"], // @ should be passed through unchanged (escaped or unescaped). ["/@asdf%40", "/@asdf%40"], // ----- encoding tests ----- // Basic conversions ["/\u4f60\u597d\u4f60\u597d", "/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD"], // Invalid unicode characters should fail. We only do validation on // UTF-16 input, so this doesn't happen on 8-bit. ["/\ufdd0zyx", "/%EF%BF%BDzyx"], ]; for (var i = 0; i < cases.length; ++i) { test_vector = cases[i][0]; expected_result = cases[i][1]; shouldBe("canonicalize('http://example.com" + test_vector + "')", "'http://example.com" + expected_result + "'"); } var successfullyParsed = true;