Skip to content

Commit

Permalink
Fixed base URL detection when request URI contains encoded chars
Browse files Browse the repository at this point in the history
Signed-off-by: Victor Berchet <victor@suumit.com>
  • Loading branch information
arnaud-lb authored and vicb committed Apr 10, 2012
1 parent 127cff0 commit d17ba0e
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 15 deletions.
38 changes: 31 additions & 7 deletions src/Symfony/Component/HttpFoundation/Request.php
Expand Up @@ -1301,14 +1301,14 @@ protected function prepareBaseUrl()
// Does the baseUrl have anything in common with the request_uri?
$requestUri = $this->getRequestUri();

if ($baseUrl && 0 === strpos($requestUri, $baseUrl)) {
if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) {
// full $baseUrl matches
return $baseUrl;
return $prefix;
}

if ($baseUrl && 0 === strpos($requestUri, dirname($baseUrl))) {
if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl))) {
// directory portion of $baseUrl matches
return rtrim(dirname($baseUrl), '/');
return rtrim($prefix, '/');
}

$truncatedRequestUri = $requestUri;
Expand All @@ -1317,7 +1317,7 @@ protected function prepareBaseUrl()
}

$basename = basename($baseUrl);
if (empty($basename) || !strpos($truncatedRequestUri, $basename)) {
if (empty($basename) || !strpos(urldecode($truncatedRequestUri), $basename)) {
// no match whatsoever; set it blank
return '';
}
Expand Down Expand Up @@ -1378,14 +1378,14 @@ protected function preparePathInfo()
$requestUri = substr($requestUri, 0, $pos);
}

if ((null !== $baseUrl) && (false === ($pathInfo = substr(urldecode($requestUri), strlen(urldecode($baseUrl)))))) {
if ((null !== $baseUrl) && (false === ($pathInfo = substr($requestUri, strlen($baseUrl))))) {
// If substr() returns false then PATH_INFO is set to an empty string
return '/';
} elseif (null === $baseUrl) {
return $requestUri;
}

return (string) $pathInfo;
return rawurldecode((string) $pathInfo);
}

/**
Expand Down Expand Up @@ -1423,4 +1423,28 @@ private function setPhpDefaultLocale($locale)
} catch (\Exception $e) {
}
}

/*
* Returns the prefix as encoded in the string when the string starts with
* the given prefix, false otherwise.
*
* @param string $string The urlencoded string
* @param string $prefix The prefix not encoded
*
* @return string|false The prefix as it is encoded in $string, or false
*/
private function getUrlencodedPrefix($string, $prefix)
{
if (0 !== strpos(rawurldecode($string), $prefix)) {
return false;
}

$len = strlen($prefix);

if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) {
return $match[0];
}

return false;
}
}
103 changes: 95 additions & 8 deletions src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
Expand Up @@ -751,18 +751,11 @@ public function testGetPathInfo()

$this->assertEquals('/path/info', $request->getPathInfo());

$server = array();
$server['REQUEST_URI'] = '/path test/info';
$request->initialize(array(), array(), array(), array(), array(), $server);

$this->assertEquals('/path test/info', $request->getPathInfo());

$server = array();
$server['REQUEST_URI'] = '/path%20test/info';
$request->initialize(array(), array(), array(), array(), array(), $server);

$this->assertEquals('/path test/info', $request->getPathInfo());

$this->assertEquals('/path%20test/info', $request->getPathInfo());
}

public function testGetPreferredLanguage()
Expand Down Expand Up @@ -946,6 +939,100 @@ private function startTrustingProxyData()
Request::trustProxyData();
}

/**
* @dataProvider getBaseUrlData
*/
public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo)
{
$request = Request::create($uri, 'GET', array(), array(), array(), $server);

$this->assertSame($expectedBaseUrl, $request->getBaseUrl(), 'baseUrl');
$this->assertSame($expectedPathInfo, $request->getPathInfo(), 'pathInfo');
}

public function getBaseUrlData()
{
return array(
array(
'/foo%20bar',
array(
'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
'SCRIPT_NAME' => '/foo bar/app.php',
'PHP_SELF' => '/foo bar/app.php',
),
'/foo%20bar',
'/',
),
array(
'/foo%20bar/home',
array(
'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
'SCRIPT_NAME' => '/foo bar/app.php',
'PHP_SELF' => '/foo bar/app.php',
),
'/foo%20bar',
'/home',
),
array(
'/foo%20bar/app.php/home',
array(
'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
'SCRIPT_NAME' => '/foo bar/app.php',
'PHP_SELF' => '/foo bar/app.php',
),
'/foo%20bar/app.php',
'/home',
),
array(
'/foo%20bar/app.php/home%2Fbaz',
array(
'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
'SCRIPT_NAME' => '/foo bar/app.php',
'PHP_SELF' => '/foo bar/app.php',
),
'/foo%20bar/app.php',
'/home%2Fbaz',
),
array(
'/foo/bar+baz',
array(
'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo/app.php',
'SCRIPT_NAME' => '/foo/app.php',
'PHP_SELF' => '/foo/app.php',
),
'/foo',
'/bar+baz',
),
);
}

/**
* @dataProvider urlencodedStringPrefixData
*/
public function testUrlencodedStringPrefix($string, $prefix, $expect)
{
$request = new Request;

$me = new \ReflectionMethod($request, 'getUrlencodedPrefix');
$me->setAccessible(true);

$this->assertSame($expect, $me->invoke($request, $string, $prefix));
}

public function urlencodedStringPrefixData()
{
return array(
array('foo', 'foo', 'foo'),
array('fo%6f', 'foo', 'fo%6f'),
array('foo/bar', 'foo', 'foo'),
array('fo%6f/bar', 'foo', 'fo%6f'),
array('f%6f%6f/bar', 'foo', 'f%6f%6f'),
array('%66%6F%6F/bar', 'foo', '%66%6F%6F'),
array('fo+o/bar', 'fo+o', 'fo+o'),
array('fo%2Bo/bar', 'fo+o', 'fo%2Bo'),
);
}

private function stopTrustingProxyData()
{
$class = new \ReflectionClass('Symfony\\Component\\HttpFoundation\\Request');
Expand Down

0 comments on commit d17ba0e

Please sign in to comment.