diff --git a/core/HTTP.php b/core/HTTP.php index ae4f6ab6a..1c4a6b6c7 100644 --- a/core/HTTP.php +++ b/core/HTTP.php @@ -112,29 +112,31 @@ class HTTP { if(isset($parts['query'])) parse_str($parts['query'], $params); $params[$varname] = $varvalue; - // Recompile Uri - $newUri = $parts['scheme'] . '://' . ( - isset($parts['user']) && $parts['user'] != '' && isset($parts['pass']) - ? $parts['user'] . ':' . $parts['pass'] . '@' - : '' - ) . - $parts['host'] . ( - isset($parts['path']) && $parts['path'] != '' - ? $parts['path'] - : '' - ) . ( - ($params) - // XHTML compliant by default - ? '?' . http_build_query($params, null, '&') - : '' - ) . ( - isset($parts['fragment']) && $parts['fragment'] != '' - ? '#' . $parts['fragment'] - : '' - ); + // Generate URI segments and formatting + $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http'; + $user = (isset($parts['user']) && $parts['user'] != '') ? $parts['user'] : ''; + + if($user != '') { + // format in either user:pass@host.com or user@host.com + $user .= (isset($parts['pass']) && $parts['pass'] != '') ? ':' . $parts['pass'] . '@' : '@'; + } + $host = (isset($parts['host'])) ? $parts['host'] : ''; + $port = (isset($parts['port']) && $parts['port'] != '') ? ':'.$parts['port'] : ''; + $path = (isset($parts['path']) && $parts['path'] != '') ? $parts['path'] : ''; + + // handle URL params which are existing / new + $params = ($params) ? '?' . http_build_query($params, null, '&') : ''; + + // keep fragments (anchors) intact. + $fragment = (isset($parts['fragment']) && $parts['fragment'] != '') ? '#'.$parts['fragment'] : ''; + + // Recompile URI segments + $newUri = $scheme . '://' . $user . $host . $port . $path . $params . $fragment; + if($isRelative) return Director::makeRelative($newUri); - else return $newUri; + + return $newUri; } static function RAW_setGetVar($varname, $varvalue, $currentURL = null) { diff --git a/tests/HTTPTest.php b/tests/HTTPTest.php index 1fe874df5..eb1955e30 100644 --- a/tests/HTTPTest.php +++ b/tests/HTTPTest.php @@ -83,13 +83,30 @@ class HTTPTest extends SapphireTest { HTTP::setGetVar('foo', 'new', 'http://test.com/?foo=&foo=old'), 'Absolute URL and empty query param' ); - + // http_build_query() escapes angular brackets, they should be correctly urldecoded by the browser client $this->assertEquals( - // http_build_query() escapes angular brackets, they should be correctly urldecoded by the browser client 'http://test.com/?foo%5Btest%5D=one&foo%5Btest%5D=two', HTTP::setGetVar('foo[test]', 'two', 'http://test.com/?foo[test]=one'), 'Absolute URL and PHP array query string notation' ); + + $urls = array( + 'http://www.test.com:8080', + 'http://test.com:3000/', + 'http://test.com:3030/baz/', + 'http://baz:foo@test.com', + 'http://baz@test.com/', + 'http://baz:foo@test.com:8080', + 'http://baz@test.com:8080' + ); + + foreach($urls as $testURL) { + $this->assertEquals( + $testURL .'?foo=bar', + HTTP::setGetVar('foo', 'bar', $testURL), + 'Absolute URL and Port Number' + ); + } } }