diff --git a/libraries/joomla/application/web.php b/libraries/joomla/application/web.php index 76ae9b064251b..b7762d5f0bf59 100644 --- a/libraries/joomla/application/web.php +++ b/libraries/joomla/application/web.php @@ -539,7 +539,7 @@ public function redirect($url, $status = 303) } else { - // Check if we have a boolean for the status variable for compatability with old $move parameter + // Check if we have a boolean for the status variable for compatibility with old $move parameter // @deprecated 4.0 if (is_bool($status)) { @@ -553,6 +553,19 @@ public function redirect($url, $status = 303) $status = 303; } + // Prevent browser / proxy caching for the case of 303 redirect + if ($status == 303) + { + // HTTP 1.1 + $this->header('Cache-Control: no-cache, no-store, must-revalidate'); + + // HTTP 1.0 + $this->header('Pragma: no-cache'); + + // Proxies + $this->header('Expires: 0'); + } + // All other cases use the more efficient HTTP header for redirection. $this->header($this->responseMap[$status]); $this->header('Location: ' . $url); @@ -560,6 +573,9 @@ public function redirect($url, $status = 303) } } + // Close the session after the redirect to prevent session issues on slow handlers + $this->session->close(); + // Close the application after the redirect. $this->close(); } diff --git a/tests/unit/suites/libraries/cms/application/JApplicationCmsTest.php b/tests/unit/suites/libraries/cms/application/JApplicationCmsTest.php index 62b0b055fc5e0..e0d31e8aa31d2 100644 --- a/tests/unit/suites/libraries/cms/application/JApplicationCmsTest.php +++ b/tests/unit/suites/libraries/cms/application/JApplicationCmsTest.php @@ -208,7 +208,7 @@ public function testExecuteWithoutDocument() // Register all the methods so that we can track if they have been fired. $this->class->registerEvent('JWebDoExecute', 'JWebTestExecute-JWebDoExecute') - ->registerEvent('onAfterRespond', 'JWebTestExecute-onAfterRespond'); + ->registerEvent('onAfterRespond', 'JWebTestExecute-onAfterRespond'); $this->class->execute(); @@ -237,9 +237,9 @@ public function testExecuteWithDocument() // Register all the methods so that we can track if they have been fired. $this->class->registerEvent('JWebDoExecute', 'JWebTestExecute-JWebDoExecute') - ->registerEvent('onBeforeRender', 'JWebTestExecute-onBeforeRender') - ->registerEvent('onAfterRender', 'JWebTestExecute-onAfterRender') - ->registerEvent('onAfterRespond', 'JWebTestExecute-onAfterRespond'); + ->registerEvent('onBeforeRender', 'JWebTestExecute-onBeforeRender') + ->registerEvent('onAfterRender', 'JWebTestExecute-onAfterRender') + ->registerEvent('onAfterRespond', 'JWebTestExecute-onAfterRespond'); // Buffer the execution. ob_start(); @@ -389,11 +389,15 @@ public function testRedirect() $config->set('uri.base.full', $base); TestReflection::setValue($this->class, 'config', $config); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); $this->class->redirect($url, false); $this->assertEquals( array( + array('Cache-Control: no-cache, no-store, must-revalidate', true, null), + array('Pragma: no-cache', true, null), + array('Expires: 0', true, null), array('HTTP/1.1 303 See other', true, null), array('Location: ' . $base . $url, true, null), array('Content-Type: text/html; charset=utf-8', true, null), @@ -428,6 +432,7 @@ public function testRedirectLegacy() $config->set('uri.base.full', $base); TestReflection::setValue($this->class, 'config', $config); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); $this->class->redirect($url, 'Test Message', 'message', false); @@ -443,6 +448,9 @@ public function testRedirectLegacy() $this->assertEquals( array( + array('Cache-Control: no-cache, no-store, must-revalidate', true, null), + array('Pragma: no-cache', true, null), + array('Expires: 0', true, null), array('HTTP/1.1 303 See other', true, null), array('Location: ' . $base . $url, true, null), array('Content-Type: text/html; charset=utf-8', true, null), @@ -477,6 +485,7 @@ public function testRedirectLegacyWithEmptyMessageAndEmptyStatus() $config->set('uri.base.full', $base); TestReflection::setValue($this->class, 'config', $config); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); $this->class->redirect($url, '', 'message'); @@ -488,6 +497,9 @@ public function testRedirectLegacyWithEmptyMessageAndEmptyStatus() // The redirect gives a 303 error code $this->assertEquals( array( + array('Cache-Control: no-cache, no-store, must-revalidate', true, null), + array('Pragma: no-cache', true, null), + array('Expires: 0', true, null), array('HTTP/1.1 303 See other', true, null), array('Location: ' . $base . $url, true, null), array('Content-Type: text/html; charset=utf-8', true, null), @@ -516,6 +528,7 @@ public function testRedirectWithHeadersSent() $config->set('uri.base.full', $base); TestReflection::setValue($this->class, 'config', $config); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); // Capture the output for this test. ob_start(); @@ -546,6 +559,8 @@ public function testRedirectWithJavascriptRedirect() ) ); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); + // Capture the output for this test. ob_start(); $this->class->redirect($url); @@ -579,6 +594,8 @@ public function testRedirectWithMoved() ) ); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); + $this->class->redirect($url, true); $this->assertEquals( @@ -621,10 +638,11 @@ public function testRedirectWithUrl($url, $base, $request, $expected) $config->set('uri.request', $request); TestReflection::setValue($this->class, 'config', $config); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); $this->class->redirect($url, false); - $this->assertEquals('Location: ' . $expected, $this->class->headers[1][0]); + $this->assertEquals('Location: ' . $expected, $this->class->headers[4][0]); } /** diff --git a/tests/unit/suites/libraries/joomla/application/JApplicationWebTest.php b/tests/unit/suites/libraries/joomla/application/JApplicationWebTest.php index 9b624cce097e8..399dafe9a19d3 100644 --- a/tests/unit/suites/libraries/joomla/application/JApplicationWebTest.php +++ b/tests/unit/suites/libraries/joomla/application/JApplicationWebTest.php @@ -1045,11 +1045,15 @@ public function testRedirect() $config->set('uri.base.full', $base); TestReflection::setValue($this->class, 'config', $config); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); $this->class->redirect($url, false); $this->assertEquals( array( + array('Cache-Control: no-cache, no-store, must-revalidate', true, null), + array('Pragma: no-cache', true, null), + array('Expires: 0', true, null), array('HTTP/1.1 303 See other', true, null), array('Location: ' . $base . $url, true, null), array('Content-Type: text/html; charset=utf-8', true, null), @@ -1078,6 +1082,7 @@ public function testRedirectWithHeadersSent() $config->set('uri.base.full', $base); TestReflection::setValue($this->class, 'config', $config); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); // Capture the output for this test. ob_start(); @@ -1107,6 +1112,8 @@ public function testRedirectWithJavascriptRedirect() ) ); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); + // Capture the output for this test. ob_start(); $this->class->redirect($url); @@ -1138,6 +1145,8 @@ public function testRedirectWithMoved() ) ); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); + $this->class->redirect($url, true); $this->assertEquals( @@ -1180,10 +1189,11 @@ public function testRedirectWithUrl($url, $base, $request, $expected) $config->set('uri.request', $request); TestReflection::setValue($this->class, 'config', $config); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); $this->class->redirect($url, false); - $this->assertEquals('Location: ' . $expected, $this->class->headers[1][0]); + $this->assertEquals('Location: ' . $expected, $this->class->headers[4][0]); } /** @@ -1265,6 +1275,7 @@ public function testSet() $config = new Registry(array('foo' => 'bar')); TestReflection::setValue($this->class, 'config', $config); + TestReflection::setValue($this->class, 'session', $this->getMockSession()); $this->assertEquals('bar', $this->class->set('foo', 'car'));