diff --git a/core/Constants.php b/core/Constants.php
index cded92297..b02c31c20 100644
--- a/core/Constants.php
+++ b/core/Constants.php
@@ -54,6 +54,13 @@ do {
///////////////////////////////////////////////////////////////////////////////
// GLOBALS AND DEFINE SETTING
+function stripslashes_recursively(&$array) {
+ foreach($array as $k => $v) {
+ if(is_array($v)) stripslashes_recursively($array[$k]);
+ else $array[$k] = stripslashes($v);
+ }
+}
+
/**
* A blank HTTP_HOST value is used to detect command-line execution.
* We update the $_SERVER variable to contain data consistent with the rest of the application.
diff --git a/core/Core.php b/core/Core.php
index 9071c0557..5347439b3 100644
--- a/core/Core.php
+++ b/core/Core.php
@@ -164,13 +164,6 @@ function project() {
return $project;
}
-function stripslashes_recursively(&$array) {
- foreach($array as $k => $v) {
- if(is_array($v)) stripslashes_recursively($array[$k]);
- else $array[$k] = stripslashes($v);
- }
-}
-
/**
* @see i18n::_t()
*/
diff --git a/core/startup/ErrorControlChain.php b/core/startup/ErrorControlChain.php
index dc32257e7..4ac510cbb 100644
--- a/core/startup/ErrorControlChain.php
+++ b/core/startup/ErrorControlChain.php
@@ -74,9 +74,33 @@ class ErrorControlChain {
return $error && ($error['type'] & self::$fatal_errors) != 0;
}
+ protected function lastErrorWasMemoryExhaustion() {
+ $error = error_get_last();
+ $message = $error ? $error['message'] : '';
+ return stripos($message, 'memory') !== false && stripos($message, 'exhausted') !== false;
+ }
+
+ static $transtable = array(
+ 'k' => 1024,
+ 'm' => 1048576,
+ 'g' => 1073741824
+ );
+
+ protected function translateMemstring($memString) {
+ $char = strtolower(substr($memString, -1));
+ $fact = isset(self::$transtable[$char]) ? self::$transtable[$char] : 1;
+ return ((int)$memString) * $fact;
+ }
+
public function handleFatalError() {
if ($this->handleFatalErrors && $this->suppression) {
if ($this->lastErrorWasFatal()) {
+ if ($this->lastErrorWasMemoryExhaustion()) {
+ // Bump up memory limit by an arbitrary 10% / 10MB (whichever is bigger) since we've run out
+ $cur = $this->translateMemstring(ini_get('memory_limit'));
+ if ($cur != -1) ini_set('memory_limit', $cur + max(round($cur*0.1), 10000000));
+ }
+
$this->error = true;
$this->step();
}
diff --git a/core/startup/ParameterConfirmationToken.php b/core/startup/ParameterConfirmationToken.php
index 21364f871..288488b6b 100644
--- a/core/startup/ParameterConfirmationToken.php
+++ b/core/startup/ParameterConfirmationToken.php
@@ -91,10 +91,17 @@ class ParameterConfirmationToken {
unset($params['url']);
// Join them all together into the original URL
- $location = "$proto://" . $host . BASE_URL . $url . ($params ? '?'.http_build_query($params) : '');
+ $location = "$proto://" . $host . '/' . ltrim(BASE_URL, '/') . $url . ($params ? '?'.http_build_query($params) : '');
// And redirect
- header('location: '.$location, true, 302);
+ if (headers_sent()) {
+ echo "
+
+
+You are being redirected. If you are not redirected soon, click here to continue the flush
+";
+ }
+ else header('location: '.$location, true, 302);
die;
}
}
diff --git a/dev/install/install.php5 b/dev/install/install.php5
index 890250e7c..33c124d67 100644
--- a/dev/install/install.php5
+++ b/dev/install/install.php5
@@ -1222,8 +1222,12 @@ PHP
$this->statusMessage("Checking that friendly URLs work...");
$this->checkRewrite();
} else {
+ require_once 'core/startup/ParameterConfirmationToken.php';
+ $token = new ParameterConfirmationToken('flush');
+ $params = http_build_query($token->params());
+
$destinationURL = 'index.php/' .
- ($this->checkModuleExists('cms') ? 'home/successfullyinstalled?flush=1' : '?flush=1');
+ ($this->checkModuleExists('cms') ? "home/successfullyinstalled?$params" : "?$params");
echo <<SilverStripe successfully installed; I am now redirecting you to your SilverStripe site...
@@ -1361,8 +1365,12 @@ TEXT;
}
function checkRewrite() {
+ require_once 'core/startup/ParameterConfirmationToken.php';
+ $token = new ParameterConfirmationToken('flush');
+ $params = http_build_query($token->params());
+
$destinationURL = str_replace('install.php', '', $_SERVER['SCRIPT_NAME']) .
- ($this->checkModuleExists('cms') ? 'home/successfullyinstalled?flush=1' : '?flush=1');
+ ($this->checkModuleExists('cms') ? "home/successfullyinstalled?$params" : "?$params");
echo <<Testing...
diff --git a/tests/core/startup/ErrorControlChainTest.php b/tests/core/startup/ErrorControlChainTest.php
index 8b5a1d622..b715bbe3b 100644
--- a/tests/core/startup/ErrorControlChainTest.php
+++ b/tests/core/startup/ErrorControlChainTest.php
@@ -8,6 +8,11 @@
*/
class ErrorControlChainTest_Chain extends ErrorControlChain {
+ // Change function visibility to be testable directly
+ public function translateMemstring($memstring) {
+ return parent::translateMemstring($memstring);
+ }
+
function executeInSubprocess() {
// Get the path to the ErrorControlChain class
$classpath = SS_ClassLoader::instance()->getItemPath('ErrorControlChain');
@@ -114,6 +119,23 @@ class ErrorControlChainTest extends SapphireTest {
->executeInSubprocess();
$this->assertEquals('Done', $out);
+
+ // Memory exhaustion
+
+ $chain = new ErrorControlChainTest_Chain();
+
+ list($out, $code) = $chain
+ ->then(function(){
+ ini_set('memory_limit', '10M');
+ $a = array();
+ while(1) $a[] = 1;
+ })
+ ->thenIfErrored(function(){
+ echo "Done";
+ })
+ ->executeInSubprocess();
+
+ $this->assertEquals('Done', $out);
}
function testExceptionSuppression() {
@@ -238,4 +260,23 @@ class ErrorControlChainTest extends SapphireTest {
$this->assertContains("Good", $out);
}
+
+ function testMemoryConversion() {
+ $chain = new ErrorControlChainTest_Chain();
+
+ $this->assertEquals(200, $chain->translateMemstring('200'));
+ $this->assertEquals(300, $chain->translateMemstring('300'));
+
+ $this->assertEquals(2 * 1024, $chain->translateMemstring('2k'));
+ $this->assertEquals(3 * 1024, $chain->translateMemstring('3K'));
+
+ $this->assertEquals(2 * 1024 * 1024, $chain->translateMemstring('2m'));
+ $this->assertEquals(3 * 1024 * 1024, $chain->translateMemstring('3M'));
+
+ $this->assertEquals(2 * 1024 * 1024 * 1024, $chain->translateMemstring('2g'));
+ $this->assertEquals(3 * 1024 * 1024 * 1024, $chain->translateMemstring('3G'));
+
+ $this->assertEquals(200, $chain->translateMemstring('200foo'));
+ $this->assertEquals(300, $chain->translateMemstring('300foo'));
+ }
}
\ No newline at end of file