summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--it_html.class32
-rw-r--r--tests/U_tests.json10
2 files changed, 22 insertions, 20 deletions
diff --git a/it_html.class b/it_html.class
index 670054c..1f705fb 100644
--- a/it_html.class
+++ b/it_html.class
@@ -538,7 +538,6 @@ static function U(/* ... */)
if (!($u = @parse_url($base)))
list($u['path'], $u['query']) = explode("?", $base, 2);
- $u['params'] = it_url::parse_str($u['query']);
$u['host'] = preg_match('/[^-_.0-9a-z]/i', $u['host']) && function_exists('idn_to_ascii') && ($idnahost = idn_to_ascii($GLOBALS['it_html']->p['charset'] == "iso-8859-1" ? utf8_encode($u['host']) : $u['host'])) ? $idnahost : $u['host']; # Punycode hostname to include into webpage
$u['host'] = preg_replace_callback('/[^-_.0-9a-z\x80-\xff]/i', function($m) { return rawurlencode($m[0]); }, $u['host']); # Encode garbage chars in host
@@ -551,26 +550,29 @@ static function U(/* ... */)
$schemepart = $hostpart ? ($u['scheme'] ? $u['scheme'] . ":" : "") . "//$hostpart" : ($u['scheme'] == "mailto" ? $u['scheme'] . ":" : "");
-
- # 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];
-
+ # sanitize path and fragment
$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]
- );
+ foreach (['path', 'query', 'fragment'] as $key)
+ $u[$key] = preg_replace_callback('/[^-a-z0-9_.+!*(),:?@&=\/~$%#]|%(?![0-9a-f]{2})/i', function($m) { return rawurlencode($m[0]); }, $u[$key]);
+ # convert empty http url path to /
if (!$u['path'] && $hostpart && preg_match('/^(https?)?$/', $u['scheme']))
$u['path'] = '/';
- $queryparams = it_url::params($u['params'] + $params);
+ # if we supplied params, add/replace them in the existing url, removing empty existing params such as foo=&bar
+ if ($params)
+ {
+ $u['params'] = it_url::parse_str($u['query']);
+
+ # 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];
+
+ $u['query'] = it_url::params($u['params'] + $params);
+ }
- return $schemepart . $u['path'] . ($queryparams ? "?" . $queryparams : "") . ($u['fragment'] ? "#" . $u['fragment'] : "");;
+ return $schemepart . $u['path'] . ($u['query'] ? "?" . $u['query'] : "") . ($u['fragment'] ? "#" . $u['fragment'] : "");
}
diff --git a/tests/U_tests.json b/tests/U_tests.json
index 5614cbb..a8ad63d 100644
--- a/tests/U_tests.json
+++ b/tests/U_tests.json
@@ -43,14 +43,14 @@
{
"args": ["/foo.html?bar="],
- "exp": "/foo.html",
- "name": "U() empty parameter in base removed (1)"
+ "exp": "/foo.html?bar=",
+ "name": "U() empty parameter with = in base must stay"
},
{
- "args": ["/foo.html?bar"],
- "exp": "/foo.html",
- "name": "U() empty parameter in base removed (2)"
+ "args": ["/foo.html?foo=bar&qux"],
+ "exp": "/foo.html?foo=bar&qux",
+ "name": "U() empty parameter in base without = must stay"
},
{