diff options
-rw-r--r-- | it_html.class | 20 | ||||
-rw-r--r-- | tests/U_tests.json | 95 |
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" } ] |