From f930a50805a03ae36b928421873d361f51f2703d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Wed, 26 Jun 2013 13:36:50 +0200 Subject: [PATCH] Fix for #3318 Fixes https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3318 It seems fixing this in the htaccess file(s) isn't going to work even though a url rewriting based solution was more clean. On the plus side this works for any web server. If a url is called with "index.php" in it then the CakeRequest swallows this part and fixes the path. Any linked url from the requested page will have a clean url. Thus after following one of these urls this problem is gone anyway. Some code docblock improvements to CakeRequestTest.php Added test case for fix Also now you can call just index.php even if you have url rewriting enabled --- lib/Cake/Network/CakeRequest.php | 17 +- .../Test/Case/Network/CakeRequestTest.php | 169 +++++++++++++----- 2 files changed, 139 insertions(+), 47 deletions(-) diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index 16871ad3933..f7d745f82bf 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -257,7 +257,12 @@ protected function _url() { list($uri) = explode('?', $uri, 2); } if (empty($uri) || $uri === '/' || $uri === '//' || $uri === '/index.php') { - return '/'; + $uri = '/'; + } + $endsWithIndex = '/webroot/index.php'; + $endsWithLength = strlen($endsWithIndex); + if (strlen($uri) >= $endsWithLength && substr_compare($uri, $endsWithIndex, -$endsWithLength, $endsWithLength) === 0) { + $uri = '/'; } return $uri; } @@ -265,7 +270,12 @@ protected function _url() { /** * Returns a base URL and sets the proper webroot * + * If CakePHP is called with index.php in the URL even though + * URL Rewriting is activated (and thus not needed) it swallows + * the unnecessary part from $base to prevent issue #3318. + * * @return string Base URL + * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3318 */ protected function _base() { $dir = $webroot = null; @@ -283,6 +293,10 @@ protected function _base() { if (!$baseUrl) { $base = dirname(env('PHP_SELF')); + $indexPos = strpos($base, '/webroot/index.php'); + if ($indexPos !== false) { + $base = substr($base, 0, $indexPos) . '/webroot'; + } if ($webroot === 'webroot' && $webroot === basename($base)) { $base = dirname($base); } @@ -295,6 +309,7 @@ protected function _base() { } $base = implode('/', array_map('rawurlencode', explode('/', $base))); $this->webroot = $base . '/'; + return $this->base = $base; } diff --git a/lib/Cake/Test/Case/Network/CakeRequestTest.php b/lib/Cake/Test/Case/Network/CakeRequestTest.php index a96bdbb7b0c..8bdf6b56485 100644 --- a/lib/Cake/Test/Case/Network/CakeRequestTest.php +++ b/lib/Cake/Test/Case/Network/CakeRequestTest.php @@ -29,6 +29,12 @@ */ class TestCakeRequest extends CakeRequest { +/** + * reConstruct method + * + * @param string $url + * @param bool $parseEnvironment + */ public function reConstruct($url = 'some/path', $parseEnvironment = true) { $this->_base(); if (empty($url)) { @@ -49,10 +55,13 @@ public function reConstruct($url = 'some/path', $parseEnvironment = true) { } +/** + * Class CakeRequestTest + */ class CakeRequestTest extends CakeTestCase { /** - * setup callback + * Setup callback * * @return void */ @@ -69,7 +78,7 @@ public function setUp() { } /** - * tearDown + * TearDown * * @return void */ @@ -82,7 +91,7 @@ public function tearDown() { } /** - * test that the autoparse = false constructor works. + * Test that the autoparse = false constructor works. * * @return void */ @@ -95,7 +104,7 @@ public function testNoAutoParseConstruction() { } /** - * test construction + * Test construction * * @return void */ @@ -153,7 +162,7 @@ public function testQueryStringAndNamedParams() { } /** - * test addParams() method + * Test addParams() method * * @return void */ @@ -170,7 +179,7 @@ public function testAddParams() { } /** - * test splicing in paths. + * Test splicing in paths. * * @return void */ @@ -190,7 +199,7 @@ public function testAddPaths() { } /** - * test parsing POST data into the object. + * Test parsing POST data into the object. * * @return void */ @@ -241,7 +250,7 @@ public function testPostParsing() { } /** - * test parsing PUT data into the object. + * Test parsing PUT data into the object. * * @return void */ @@ -315,7 +324,7 @@ public function testPutParsing() { } /** - * test parsing json PUT data into the object. + * Test parsing json PUT data into the object. * * @return void */ @@ -332,7 +341,7 @@ public function testPutParsingJSON() { } /** - * test parsing of FILES array + * Test parsing of FILES array * * @return void */ @@ -621,7 +630,7 @@ public function testFilesZeroithIndex() { } /** - * test method overrides coming in from POST data. + * Test method overrides coming in from POST data. * * @return void */ @@ -640,7 +649,7 @@ public function testMethodOverrides() { } /** - * test the clientIp method. + * Test the clientIp method. * * @return void */ @@ -663,7 +672,7 @@ public function testclientIp() { } /** - * test the referer function. + * Test the referrer function. * * @return void */ @@ -748,7 +757,7 @@ public function testIsHttpMethods() { } /** - * test the method() method. + * Test the method() method. * * @return void */ @@ -760,7 +769,7 @@ public function testMethod() { } /** - * test host retrieval. + * Test host retrieval. * * @return void */ @@ -772,7 +781,7 @@ public function testHost() { } /** - * test domain retrieval. + * Test domain retrieval. * * @return void */ @@ -787,7 +796,7 @@ public function testDomain() { } /** - * test getting subdomains for a host. + * Test getting subdomains for a host. * * @return void */ @@ -808,7 +817,7 @@ public function testSubdomain() { } /** - * test ajax, flash and friends + * Test ajax, flash and friends * * @return void */ @@ -842,7 +851,7 @@ public function testisAjaxFlashAndFriends() { } /** - * test __call expcetions + * Test __call exceptions * * @expectedException CakeException * @return void @@ -853,7 +862,7 @@ public function testMagicCallExceptionOnUnknownMethod() { } /** - * test is(ssl) + * Test is(ssl) * * @return void */ @@ -886,7 +895,7 @@ public function testIsSsl() { } /** - * test getting request params with object properties. + * Test getting request params with object properties. * * @return void */ @@ -921,7 +930,7 @@ public function testMagicisset() { } /** - * test the array access implementation + * Test the array access implementation * * @return void */ @@ -952,7 +961,7 @@ public function testArrayAccess() { } /** - * test adding detectors and having them work. + * Test adding detectors and having them work. * * @return void */ @@ -1009,16 +1018,17 @@ public function testAddDetector() { } /** - * helper function for testing callbacks. + * Helper function for testing callbacks. * - * @return void + * @param $request + * @return bool */ public function detectCallback($request) { return (bool)$request->return; } /** - * test getting headers + * Test getting headers * * @return void */ @@ -1032,7 +1042,7 @@ public function testHeader() { } /** - * test accepts() with and without parameters + * Test accepts() with and without parameters * * @return void */ @@ -1117,7 +1127,7 @@ public function testParseAcceptNoQValues() { } /** - * testBaseUrlAndWebrootWithModRewrite method + * Test baseUrl and webroot with ModRewrite * * @return void */ @@ -1186,7 +1196,7 @@ public function testBaseUrlAndWebrootWithModRewrite() { } /** - * testBaseUrlwithModRewriteAlias method + * Test baseUrl with ModRewrite alias * * @return void */ @@ -1214,7 +1224,71 @@ public function testBaseUrlwithModRewriteAlias() { } /** - * test base, webroot, and url parsing when there is no url rewriting + * Test base, webroot, url and here parsing when there is url rewriting but + * CakePHP gets called with index.php in url nonetheless. + * + * Tests uri with + * - index.php/ + * - index.php/ + * - index.php/apples/ + * - index.php/bananas/eat/tasty_banana + * + * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3318 + */ + public function testBaseUrlWithModRewriteAndIndexPhp() { + $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php'; + $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php'; + unset($_SERVER['PATH_INFO']); + $request = new CakeRequest(); + + $this->assertEquals('/cakephp', $request->base); + $this->assertEquals('/cakephp/', $request->webroot); + $this->assertEquals('', $request->url); + $this->assertEquals('/cakephp/', $request->here); + + $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php/'; + $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php/'; + $_SERVER['PATH_INFO'] = '/'; + $request = new CakeRequest(); + + $this->assertEquals('/cakephp', $request->base); + $this->assertEquals('/cakephp/', $request->webroot); + $this->assertEquals('', $request->url); + $this->assertEquals('/cakephp/', $request->here); + + $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php/apples'; + $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php/apples'; + $_SERVER['PATH_INFO'] = '/apples'; + $request = new CakeRequest(); + + $this->assertEquals('/cakephp', $request->base); + $this->assertEquals('/cakephp/', $request->webroot); + $this->assertEquals('apples', $request->url); + $this->assertEquals('/cakephp/apples', $request->here); + + $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php/melons/share/'; + $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php/melons/share/'; + $_SERVER['PATH_INFO'] = '/melons/share/'; + $request = new CakeRequest(); + + $this->assertEquals('/cakephp', $request->base); + $this->assertEquals('/cakephp/', $request->webroot); + $this->assertEquals('melons/share/', $request->url); + $this->assertEquals('/cakephp/melons/share/', $request->here); + + $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php/bananas/eat/tasty_banana'; + $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php/bananas/eat/tasty_banana'; + $_SERVER['PATH_INFO'] = '/bananas/eat/tasty_banana'; + $request = new CakeRequest(); + + $this->assertEquals('/cakephp', $request->base); + $this->assertEquals('/cakephp/', $request->webroot); + $this->assertEquals('bananas/eat/tasty_banana', $request->url); + $this->assertEquals('/cakephp/bananas/eat/tasty_banana', $request->here); + } + +/** + * Test base, webroot, and url parsing when there is no url rewriting * * @return void */ @@ -1237,8 +1311,8 @@ public function testBaseUrlWithNoModRewrite() { $this->assertEquals('posts/index', $request->url); } -/** - * testBaseUrlAndWebrootWithBaseUrl method + /** + * Test baseUrl and webroot with baseUrl * * @return void */ @@ -1287,7 +1361,7 @@ public function testBaseUrlAndWebrootWithBaseUrl() { } /** - * test baseUrl with no rewrite and using the top level index.php. + * Test baseUrl with no rewrite and using the top level index.php. * * @return void */ @@ -1325,7 +1399,7 @@ public function testBaseUrlWithAppAndWebrootInDirname() { } /** - * test baseUrl with no rewrite, and using the app/webroot/index.php file as is normal with virtual hosts. + * Test baseUrl with no rewrite, and using the app/webroot/index.php file as is normal with virtual hosts. * * @return void */ @@ -1371,9 +1445,9 @@ public function testGetParamWithUrlencodedElement() { } /** - * generator for environment configurations + * Generator for environment configurations * - * @return void + * @return array Environment array */ public static function environmentGenerator() { return array( @@ -1745,9 +1819,12 @@ public static function environmentGenerator() { } /** - * testEnvironmentDetection method + * Test environment detection * * @dataProvider environmentGenerator + * @param $name + * @param $env + * @param $expected * @return void */ public function testEnvironmentDetection($name, $env, $expected) { @@ -1764,7 +1841,7 @@ public function testEnvironmentDetection($name, $env, $expected) { } /** - * test the query() method + * Test the query() method * * @return void */ @@ -1782,7 +1859,7 @@ public function testQuery() { } /** - * test the query() method with arrays passed via $_GET + * Test the query() method with arrays passed via $_GET * * @return void */ @@ -1803,7 +1880,7 @@ public function testQueryWithArray() { } /** - * test the data() method reading + * Test the data() method reading * * @return void */ @@ -1822,7 +1899,7 @@ public function testDataReading() { } /** - * test writing with data() + * Test writing with data() * * @return void */ @@ -1844,7 +1921,7 @@ public function testDataWriting() { } /** - * test writing falsey values. + * Test writing falsey values. * * @return void */ @@ -1865,7 +1942,7 @@ public function testDataWritingFalsey() { } /** - * test accept language + * Test accept language * * @return void */ @@ -1908,7 +1985,7 @@ public function testAcceptLanguage() { } /** - * test the here() method + * Test the here() method * * @return void */ @@ -2011,7 +2088,7 @@ public function testIsRequested() { } /** - * TestOnlyAllow + * Test onlyAllow method * * @return void */ @@ -2026,7 +2103,7 @@ public function testOnlyAllow() { } /** - * TestOnlyAllow throwing exception + * Test onlyAllow throwing exception * */ public function testOnlyAllowException() {