summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--it_html.class20
-rw-r--r--tests/U_tests.json95
2 files changed, 108 insertions, 7 deletions
diff --git a/it_html.class b/it_html.class
index c7105b7..c75f05e 100644
--- a/it_html.class
+++ b/it_html.class
@@ -538,7 +538,7 @@ static function U(/* ... */)
if (!isset($base))
$base = preg_replace('/\?.*/', '', $_SERVER['REQUEST_URI']);
- $base = preg_replace(array('|\0|', '/\\\\/'), array('', '/'), $base); # kill null chars, turn \ to /
+ $base = preg_replace('|\0|', '', $base); # kill null chars
if (!($u = @parse_url($base)))
list($u['path'], $u['query']) = explode("?", $base, 2);
@@ -555,20 +555,26 @@ static function U(/* ... */)
$schemepart = $hostpart ? ($u['scheme'] ? $u['scheme'] . ":" : "") . "//$hostpart" : ($u['scheme'] == "mailto" ? $u['scheme'] . ":" : "");
- # hack: encode % if not followed by two hex digits
- $path = preg_replace('/%(?![0-9a-f]{2})/i', '%25', $u['path']);
# if params replace url parameters that are present in base, replace them but keep their order
foreach ($u['params'] as $key => $dummy)
if (isset($params[$key]))
$u['params'][$key] = $params[$key];
- $path = preg_replace_callback('|[^-a-z0-9_.+!*(),:?@&=/~$%#]|i', function($m) { return rawurlencode($m[0]); }, $path);
- $path = preg_replace('|^([a-z0-9_]+:)?//[^/]*$|', '$0/', $path); # Add slash if absolute url without a path, e.g. http://gna.ch
+ $u['path'] = preg_replace('|\\\\|', '/', $u['path']); # turn \ to /
+ foreach (['path', 'fragment'] as $key)
+ $u[$key] = preg_replace_callback(
+ '/[^-a-z0-9_.+!*(),:?@&=\/~$%#]|%(?![0-9a-f]{2})/i',
+ function($m) { return rawurlencode($m[0]); },
+ $u[$key]
+ );
+
+ if (!$u['path'] && $hostpart)
+ $u['path'] = '/';
+
$queryparams = it_url::params($u['params'] + $params);
- $separator = strpos($path, "?") === false ? "?" : "&";
- return $schemepart . $path . ($queryparams ? "$separator$queryparams" : "") . ($u['fragment'] ? "#" . $u['fragment'] : "");;
+ return $schemepart . $u['path'] . ($queryparams ? "?" . $queryparams : "") . ($u['fragment'] ? "#" . $u['fragment'] : "");;
}
diff --git a/tests/U_tests.json b/tests/U_tests.json
index a8b5688..3e1d092 100644
--- a/tests/U_tests.json
+++ b/tests/U_tests.json
@@ -1,4 +1,39 @@
[
+ {
+ "args": ["/Zürich"],
+ "exp": "/Z%C3%BCrich",
+ "name": "U() with utf8 umlaut"
+ },
+
+ {
+ "args": ["/path#Zürich"],
+ "exp": "/path#Z%C3%BCrich",
+ "name": "U() with utf8 umlaut in fragment"
+ },
+
+ {
+ "args": ["/foo.html?"],
+ "exp": "/foo.html",
+ "name": "U() removes ? at end"
+ },
+
+ {
+ "args": ["/foo.html#"],
+ "exp": "/foo.html",
+ "name": "U() removes # at end"
+ },
+
+ {
+ "args": ["/foo.html?#"],
+ "exp": "/foo.html",
+ "name": "U() removes ?# at end"
+ },
+
+ {
+ "args": ["/foo.html#?"],
+ "exp": "/foo.html#?",
+ "name": "U() keeps #? at end"
+ },
{
"args": ["/foo.html", {"bar": {"gna": 42, "qux": {"quux": "<Zürich>", "gnöp": "fasel"}}}],
@@ -7,12 +42,30 @@
},
{
+ "args": ["/foo.html?", {"foo" : "bar[qux][gnöp]=fasel"}],
+ "exp": "/foo.html?foo=bar%5Bqux%5D%5Bgn%C3%B6p%5D%3Dfasel",
+ "name": "U() with array syntax in value and ? at end of base"
+ },
+
+ {
"args": ["/foo.html?a=b&bar=qux&c=d", {"bar": "baz"}],
"exp": "/foo.html?a=b&bar=baz&c=d",
"name": "U() args override get params in base url"
},
{
+ "args": ["/foo.html?a=b&bar=qux&c=d", {"bar": "baz", "gna": "gnaber"}],
+ "exp": "/foo.html?a=b&bar=baz&c=d&gna=gnaber",
+ "name": "U() args override get params in base url and appends remaining params"
+ },
+
+ {
+ "args": ["/foo.html?gna=g&a=b&bar=qux&c=d", {"bar": "baz", "gna": "gnaber"}],
+ "exp": "/foo.html?gna=gnaber&a=b&bar=baz&c=d",
+ "name": "U() args override get params in base url keeping same order"
+ },
+
+ {
"args": ["/foo.html?bar.qux=a.b", {"c.d": "e.f", "g h": "i j"}],
"exp": "/foo.html?bar.qux=a.b&c.d=e.f&g+h=i+j",
"name": "U() dots and spaces in arg names are preserved"
@@ -43,8 +96,50 @@
},
{
+ "args": ["path#%% %1%x %1x%x1%xx%11%ff%FF%0f%0F %"],
+ "exp": "path#%25%25%20%251%25x%20%251x%25x1%25xx%11%ff%FF%0f%0F%20%25",
+ "name": "U() quoting of % if not followed by 2 hex digits in fragment"
+ },
+
+ {
"args": ["a\\b"],
"exp": "a/b",
"name": "U() converting of \\ to /"
+ },
+
+ {
+ "args": ["path/#a\\b"],
+ "exp": "path/#a%5Cb",
+ "name": "U() encode \\ in fragment"
+ },
+
+ {
+ "args": ["foo.html?bar=\\gna"],
+ "exp": "foo.html?bar=%5Cgna",
+ "name": "U() encode \\ in url parameter"
+ },
+
+ {
+ "args": ["path/#?a=b"],
+ "exp": "path/#?a=b",
+ "name": "U() keep query syntax in fragment"
+ },
+
+ {
+ "args": ["path/#Jet d'eau"],
+ "exp": "path/#Jet%20d%27eau",
+ "name": "U() with single quotes in fragment"
+ },
+
+ {
+ "args": ["//gna.ch"],
+ "exp": "//gna.ch/",
+ "name": "U() add / for absolute url without path"
+ },
+
+ {
+ "args": ["http://gna.ch"],
+ "exp": "http://gna.ch/",
+ "name": "U() add / for absolute http url without path"
}
]