From 873fd8c5bc03a848aae84f39b7d73af67b661798 Mon Sep 17 00:00:00 2001 From: Daniel Hensby Date: Mon, 30 Jan 2017 15:33:56 +0000 Subject: [PATCH 1/3] NEW replace _ss_environment.php with .env and environment vars --- cli-script.php | 17 ++- composer.json | 3 +- main.php | 3 +- .../Flysystem/ProtectedAssetAdapter.php | 9 +- src/Control/Director.php | 2 +- src/Control/HTTPRequest.php | 2 +- src/Core/Constants.php | 68 ++++------- src/Core/Manifest/ClassManifest.php | 2 +- src/Core/Manifest/ConfigManifest.php | 6 +- .../Startup/ParameterConfirmationToken.php | 2 +- src/Dev/Deprecation.php | 5 +- src/Dev/Install/client/dist/js/install.js | 2 +- src/Dev/Install/config-form.html | 14 +-- src/Dev/Install/install.php5 | 35 +++--- src/Dev/SapphireTest.php | 6 +- src/ORM/DB.php | 2 +- src/Security/BasicAuth.php | 4 +- src/View/ThemeManifest.php | 5 +- src/conf/ConfigureFromEnv.php | 115 +++++++++--------- tests/bootstrap/environment.php | 37 +++--- .../php/Core/Manifest/ConfigManifestTest.php | 12 +- tests/php/ORM/DBTest.php | 2 +- 22 files changed, 161 insertions(+), 192 deletions(-) diff --git a/cli-script.php b/cli-script.php index 5a1d9b737..e3b2ac16a 100755 --- a/cli-script.php +++ b/cli-script.php @@ -82,23 +82,20 @@ $_SESSION = null; // Connect to database if(!isset($databaseConfig) || !isset($databaseConfig['database']) || !$databaseConfig['database']) { echo "\nPlease configure your database connection details. You can do this by creating a file -called _ss_environment.php in either of the following locations:\n\n"; - echo " - " . BASE_PATH . DIRECTORY_SEPARATOR . "_ss_environment.php\n - "; - echo dirname(BASE_PATH) . DIRECTORY_SEPARATOR . "_ss_environment.php\n\n"; +called .env in " . BASE_PATH; echo <<'); -define('SS_DATABASE_PASSWORD', ''); -define('SS_DATABASE_NAME', ''); +SS_DATABASE_SERVER="localhost" +SS_DATABASE_USERNAME="" +SS_DATABASE_PASSWORD="" +SS_DATABASE_NAME="" -------------------------------------------------- Once you have done that, run 'composer install' or './framework/sake dev/build' to create diff --git a/composer.json b/composer.json index 185e092cd..dc47dfea3 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ "embed/embed": "^2.6", "swiftmailer/swiftmailer": "~5.4", "symfony/config": "^2.8|^3", - "symfony/translation": "^2.8|^3" + "symfony/translation": "^2.8|^3", + "vlucas/phpdotenv": "^2.4" }, "require-dev": { "phpunit/PHPUnit": "~4.8", diff --git a/main.php b/main.php index cc6576478..c1b121b11 100644 --- a/main.php +++ b/main.php @@ -32,8 +32,7 @@ if (version_compare(phpversion(), '5.5.0', '<')) { * * The main.php does a number of set-up activities for the request. * - * - Includes the first one of the following files that it finds: (root)/_ss_environment.php, - * (root)/../_ss_environment.php, or (root)/../../_ss_environment.php + * - Includes the .env file in your webroot * - Gets an up-to-date manifest from {@link ManifestBuilder} * - Sets up error handlers with {@link Debug::loadErrorHandlers()} * - Calls {@link DB::connect()}, passing it the global variable $databaseConfig that should diff --git a/src/Assets/Flysystem/ProtectedAssetAdapter.php b/src/Assets/Flysystem/ProtectedAssetAdapter.php index 5ed034a0f..7a47ff759 100644 --- a/src/Assets/Flysystem/ProtectedAssetAdapter.php +++ b/src/Assets/Flysystem/ProtectedAssetAdapter.php @@ -35,13 +35,8 @@ class ProtectedAssetAdapter extends AssetAdapter implements ProtectedAdapter return parent::findRoot($root); } - // Use environment defined path - if (defined('SS_PROTECTED_ASSETS_PATH')) { - return SS_PROTECTED_ASSETS_PATH; - } - - // Default location is under assets - return ASSETS_PATH . '/' . Config::inst()->get(get_class($this), 'secure_folder'); + // Use environment defined path or default location is under assets + return getenv('SS_PROTECTED_ASSETS_PATH') ?: ASSETS_PATH . '/' . Config::inst()->get(get_class($this), 'secure_folder'); } /** diff --git a/src/Control/Director.php b/src/Control/Director.php index 8ab5863b7..b9c6e0366 100644 --- a/src/Control/Director.php +++ b/src/Control/Director.php @@ -607,7 +607,7 @@ class Director implements TemplateGlobalProvider // See https://support.microsoft.com/en-us/kb/307347 $headerOverride = false; if (TRUSTED_PROXY) { - $headers = (defined('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(SS_TRUSTED_PROXY_PROTOCOL_HEADER) : null; + $headers = (getenv('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(getenv('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) : null; if (!$headers) { // Backwards compatible defaults $headers = array('HTTP_X_FORWARDED_PROTO', 'HTTP_X_FORWARDED_PROTOCOL', 'HTTP_FRONT_END_HTTPS'); diff --git a/src/Control/HTTPRequest.php b/src/Control/HTTPRequest.php index b91eb3fc3..b3b7d76f6 100644 --- a/src/Control/HTTPRequest.php +++ b/src/Control/HTTPRequest.php @@ -768,7 +768,7 @@ class HTTPRequest implements ArrayAccess { $headerOverrideIP = null; if (TRUSTED_PROXY) { - $headers = (defined('SS_TRUSTED_PROXY_IP_HEADER')) ? array(SS_TRUSTED_PROXY_IP_HEADER) : null; + $headers = (getenv('SS_TRUSTED_PROXY_IP_HEADER')) ? array(getenv('SS_TRUSTED_PROXY_IP_HEADER')) : null; if (!$headers) { // Backwards compatible defaults $headers = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR'); diff --git a/src/Core/Constants.php b/src/Core/Constants.php index bc5789a8d..fb1188815 100644 --- a/src/Core/Constants.php +++ b/src/Core/Constants.php @@ -3,7 +3,6 @@ * This file is the Framework constants bootstrap. It will prepare some basic common constants. * * It takes care of: - * - Including _ss_environment.php * - Normalisation of $_SERVER values * - Initialisation of necessary constants (mostly paths) * @@ -30,48 +29,6 @@ /////////////////////////////////////////////////////////////////////////////// // ENVIRONMENT CONFIG -/** - * Include _ss_environment.php file - */ -//define the name of the environment file -$envFile = '_ss_environment.php'; -//define the dirs to start scanning from (have to add the trailing slash) -// we're going to check the realpath AND the path as the script sees it -$dirsToCheck = array( - realpath('.'), - dirname($_SERVER['SCRIPT_FILENAME']) -); -//if they are the same, remove one of them -if ($dirsToCheck[0] == $dirsToCheck[1]) { - unset($dirsToCheck[1]); -} -foreach ($dirsToCheck as $dir) { - //check this dir and every parent dir (until we hit the base of the drive) - // or until we hit a dir we can't read - while (true) { - //if it's readable, go ahead - if (@is_readable($dir)) { - //if the file exists, then we include it, set relevant vars and break out - if (file_exists($dir . DIRECTORY_SEPARATOR . $envFile)) { - define('SS_ENVIRONMENT_FILE', $dir . DIRECTORY_SEPARATOR . $envFile); - include_once(SS_ENVIRONMENT_FILE); - //break out of BOTH loops because we found the $envFile - break(2); - } - } else { - //break out of the while loop, we can't read the dir - break; - } - if (dirname($dir) == $dir) { - // here we need to check that the path of the last dir and the next one are - // not the same, if they are, we have hit the root of the drive - break; - } - //go up a directory - $dir = dirname($dir); - } -} - /** * Validate whether the request comes directly from a trusted server or not * This is necessary to validate whether or not the values of X-Forwarded- @@ -82,18 +39,18 @@ if (!defined('TRUSTED_PROXY')) { if (getenv('BlockUntrustedProxyHeaders') // Legacy setting (reverted from documentation) || getenv('BlockUntrustedIPs') // Documented setting - || defined('SS_TRUSTED_PROXY_IPS') + || getenv('SS_TRUSTED_PROXY_IPS') ) { $trusted = false; - if (defined('SS_TRUSTED_PROXY_IPS') && SS_TRUSTED_PROXY_IPS !== 'none') { - if (SS_TRUSTED_PROXY_IPS === '*') { + if (getenv('SS_TRUSTED_PROXY_IPS') !== 'none') { + if (getenv('SS_TRUSTED_PROXY_IPS') === '*') { $trusted = true; } elseif (isset($_SERVER['REMOTE_ADDR'])) { if (!class_exists('SilverStripe\\Control\\Util\\IPUtils')) { require_once 'Control/IPUtils.php'; }; - $trusted = SilverStripe\Control\Util\IPUtils::checkIP($_SERVER['REMOTE_ADDR'], explode(',', SS_TRUSTED_PROXY_IPS)); + $trusted = SilverStripe\Control\Util\IPUtils::checkIP($_SERVER['REMOTE_ADDR'], explode(',', getenv('SS_TRUSTED_PROXY_IPS'))); } } } @@ -202,6 +159,23 @@ if (!defined('BASE_PATH')) { } define('BASE_PATH', $candidateBasePath); } + +// Allow a first class env var to be set that disables .env file loading +if (!getenv('SS_IGNORE_DOT_ENV')) { + foreach (array( + BASE_PATH, + dirname(BASE_PATH), + ) as $path) { + try { + (new \Dotenv\Dotenv($path))->load(); + } catch (\Dotenv\Exception\InvalidPathException $e) { + // no .env found - no big deal + continue; + } + break; + } +} + if (!defined('BASE_URL')) { // Determine the base URL by comparing SCRIPT_NAME to SCRIPT_FILENAME and getting common elements $path = realpath($_SERVER['SCRIPT_FILENAME']); diff --git a/src/Core/Manifest/ClassManifest.php b/src/Core/Manifest/ClassManifest.php index 4c2854995..51a689791 100644 --- a/src/Core/Manifest/ClassManifest.php +++ b/src/Core/Manifest/ClassManifest.php @@ -176,7 +176,7 @@ class ClassManifest $this->base = $base; $this->tests = $includeTests; - $cacheClass = defined('SS_MANIFESTCACHE') ? SS_MANIFESTCACHE : 'SilverStripe\\Core\\Manifest\\ManifestCache_File'; + $cacheClass = getenv('SS_MANIFESTCACHE') ?: 'SilverStripe\\Core\\Manifest\\ManifestCache_File'; $this->cache = new $cacheClass('classmanifest'.($includeTests ? '_tests' : '')); $this->cacheKey = 'manifest'; diff --git a/src/Core/Manifest/ConfigManifest.php b/src/Core/Manifest/ConfigManifest.php index b5f1c1aaa..48a4f09ab 100644 --- a/src/Core/Manifest/ConfigManifest.php +++ b/src/Core/Manifest/ConfigManifest.php @@ -210,7 +210,7 @@ class ConfigManifest if (isset($key['envvars'])) { foreach ($key['envvars'] as $variable => $foo) { - $key['envvars'][$variable] = isset($_ENV[$variable]) ? $_ENV[$variable] : null; + $key['envvars'][$variable] = getenv($variable) ?: null; } } @@ -726,7 +726,7 @@ class ConfigManifest break; case 'envvarset': - $matches = $matches && isset($_ENV[$v]); + $matches = $matches && getenv($v); break; case 'constantdefined': @@ -735,7 +735,7 @@ class ConfigManifest default: $matches = $matches && ( - (isset($_ENV[$k]) && $_ENV[$k] == $v) || + getenv($k) == $v || (defined($k) && constant($k) == $v) ); break; diff --git a/src/Core/Startup/ParameterConfirmationToken.php b/src/Core/Startup/ParameterConfirmationToken.php index 0e4076320..b9075614a 100644 --- a/src/Core/Startup/ParameterConfirmationToken.php +++ b/src/Core/Startup/ParameterConfirmationToken.php @@ -179,7 +179,7 @@ class ParameterConfirmationToken // See https://support.microsoft.com/en-us/kb/307347 $headerOverride = false; if (TRUSTED_PROXY) { - $headers = (defined('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(SS_TRUSTED_PROXY_PROTOCOL_HEADER) : null; + $headers = (getenv('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(getenv('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) : null; if (!$headers) { // Backwards compatible defaults $headers = array('HTTP_X_FORWARDED_PROTO', 'HTTP_X_FORWARDED_PROTOCOL', 'HTTP_FRONT_END_HTTPS'); diff --git a/src/Dev/Deprecation.php b/src/Dev/Deprecation.php index d7de927ee..6af497ced 100644 --- a/src/Dev/Deprecation.php +++ b/src/Dev/Deprecation.php @@ -152,10 +152,7 @@ class Deprecation if (isset(self::$enabled)) { return self::$enabled; } - if (defined('SS_DEPRECATION_ENABLED')) { - return SS_DEPRECATION_ENABLED; - } - return true; + return getenv('SS_DEPRECATION_ENABLED') ?: true; } /** diff --git a/src/Dev/Install/client/dist/js/install.js b/src/Dev/Install/client/dist/js/install.js index d347f281c..2bd164d0e 100644 --- a/src/Dev/Install/client/dist/js/install.js +++ b/src/Dev/Install/client/dist/js/install.js @@ -2,7 +2,7 @@ $(document).ready(function () { /** * Toggle field readonly modes, if check configuration comes from - * _ss_environment (values populated on reload). + * environment variables (values populated on reload). */ $('#use_environment').click(function (e) { if (!$(this).is(':checked')) { diff --git a/src/Dev/Install/config-form.html b/src/Dev/Install/config-form.html index dbf514c25..0e64707f0 100644 --- a/src/Dev/Install/config-form.html +++ b/src/Dev/Install/config-form.html @@ -101,7 +101,7 @@ // All are disabled by default when environment is used $disabled = 'disabled="disabled"'; // If SS_DATABASE_CLASS is specified, check the database in the list - if(defined('SS_DATABASE_CLASS') && SS_DATABASE_CLASS == $class) { + if(getenv('SS_DATABASE_CLASS') == $class) { $checked = ' checked="checked"'; } } else { @@ -135,8 +135,8 @@ $fieldType = ($fieldName == 'password') ? 'password' : 'text'; // values $defaultValue = (isset($fieldSpec['default'])) ? $fieldSpec['default'] : null; - if($usingEnv && isset($fieldSpec['envVar']) && defined($fieldSpec['envVar'])) { - $value = constant($fieldSpec['envVar']); + if($usingEnv && isset($fieldSpec['envVar']) && $envVar = getenv($fieldSpec['envVar'])) { + $value = $envVar; } else { $value = (isset($databaseConfig[$fieldName]) && $databaseConfig['type'] == $class) ? $databaseConfig[$fieldName] : $defaultValue; } @@ -149,7 +149,7 @@ 'name' => "db[$class][$fieldName]", 'value' => $value, ); - if($usingEnv && isset($fieldSpec['envVar']) && defined($fieldSpec['envVar'])) { + if($usingEnv && isset($fieldSpec['envVar']) && getenv($fieldSpec['envVar'])) { $attrs['disabled'] = 'disabled'; } if(isset($fieldSpec['envVar'])) { @@ -177,7 +177,7 @@
> - +
@@ -202,14 +202,14 @@
- > + >
- > + >
diff --git a/src/Dev/Install/install.php5 b/src/Dev/Install/install.php5 index 22fe22bf1..848eee34c 100755 --- a/src/Dev/Install/install.php5 +++ b/src/Dev/Install/install.php5 @@ -60,8 +60,7 @@ if (!$included) { exit(1); } -$envFileExists = defined('SS_ENVIRONMENT_FILE'); -$usingEnv = $envFileExists && !empty($_REQUEST['useEnv']); +$usingEnv = !empty($_REQUEST['useEnv']); require_once __DIR__ . '/DatabaseConfigurationHelper.php'; require_once __DIR__ . '/DatabaseAdapterRegistry.php'; @@ -142,8 +141,8 @@ if(isset($_REQUEST['db'])) { if(isset($_REQUEST['db']['type'])) { $type = $_REQUEST['db']['type']; } else { - if( defined('SS_DATABASE_CLASS') ){ - $type = $_REQUEST['db']['type'] = SS_DATABASE_CLASS; + if ($type = getenv('SS_DATABASE_CLASS')) { + $_REQUEST['db']['type'] = $type; } elseif( $databaseClasses['MySQLPDODatabase']['supported'] ) { $type = $_REQUEST['db']['type'] = 'MySQLPDODatabase'; } elseif( $databaseClasses['MySQLDatabase']['supported'] ) { @@ -156,10 +155,10 @@ if(isset($_REQUEST['db'])) { // Disabled inputs don't submit anything - we need to use the environment (except the database name) if($usingEnv) { $_REQUEST['db'][$type] = $databaseConfig = array( - "type" => defined('SS_DATABASE_CLASS') ? SS_DATABASE_CLASS : $type, - "server" => defined('SS_DATABASE_SERVER') ? SS_DATABASE_SERVER : "localhost", - "username" => defined('SS_DATABASE_USERNAME') ? SS_DATABASE_USERNAME : "root", - "password" => defined('SS_DATABASE_PASSWORD') ? SS_DATABASE_PASSWORD : "", + "type" => getenv('SS_DATABASE_CLASS') ?: $type, + "server" => getenv('SS_DATABASE_SERVER') ?: "localhost", + "username" => getenv('SS_DATABASE_USERNAME') ?: "root", + "password" => getenv('SS_DATABASE_PASSWORD') ?: "", "database" => $_REQUEST['db'][$type]['database'], ); @@ -169,8 +168,8 @@ if(isset($_REQUEST['db'])) { $databaseConfig['type'] = $type; } } else { - if( defined('SS_DATABASE_CLASS') ){ - $type = $_REQUEST['db']['type'] = SS_DATABASE_CLASS; + if($type = getenv('SS_DATABASE_CLASS')) { + $_REQUEST['db']['type'] = $type; } elseif( $databaseClasses['MySQLPDODatabase']['supported'] ) { $type = $_REQUEST['db']['type'] = 'MySQLPDODatabase'; } elseif( $databaseClasses['MySQLDatabase']['supported'] ) { @@ -180,9 +179,9 @@ if(isset($_REQUEST['db'])) { } $_REQUEST['db'][$type] = $databaseConfig = array( "type" => $type, - "server" => defined('SS_DATABASE_SERVER') ? SS_DATABASE_SERVER : "localhost", - "username" => defined('SS_DATABASE_USERNAME') ? SS_DATABASE_USERNAME : "root", - "password" => defined('SS_DATABASE_PASSWORD') ? SS_DATABASE_PASSWORD : "", + "server" => getenv('SS_DATABASE_SERVER') ?: "localhost", + "username" => getenv('SS_DATABASE_USERNAME') ?: "root", + "password" => getenv('SS_DATABASE_PASSWORD') ?: "", "database" => isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : "SS_mysite", ); } @@ -191,16 +190,16 @@ if(isset($_REQUEST['admin'])) { // Disabled inputs don't submit anything - we need to use the environment (except the database name) if($usingEnv) { $_REQUEST['admin'] = $adminConfig = array( - 'username' => defined('SS_DEFAULT_ADMIN_USERNAME') ? SS_DEFAULT_ADMIN_USERNAME : 'admin', - 'password' => defined('SS_DEFAULT_ADMIN_PASSWORD') ? SS_DEFAULT_ADMIN_PASSWORD : '', + 'username' => getenv('SS_DEFAULT_ADMIN_USERNAME') ?: 'admin', + 'password' => getenv('SS_DEFAULT_ADMIN_PASSWORD') ?: '', ); } else { $adminConfig = $_REQUEST['admin']; } } else { $_REQUEST['admin'] = $adminConfig = array( - 'username' => defined('SS_DEFAULT_ADMIN_USERNAME') ? SS_DEFAULT_ADMIN_USERNAME : 'admin', - 'password' => defined('SS_DEFAULT_ADMIN_PASSWORD') ? SS_DEFAULT_ADMIN_PASSWORD : '', + 'username' => getenv('SS_DEFAULT_ADMIN_USERNAME') ?: 'admin', + 'password' => getenv('SS_DEFAULT_ADMIN_PASSWORD') ?: '', ); } @@ -1402,7 +1401,7 @@ class Installer extends InstallRequirements { // Write the config file global $usingEnv; if($usingEnv) { - $this->statusMessage("Setting up 'mysite/_config.php' for use with _ss_environment.php..."); + $this->statusMessage("Setting up 'mysite/_config.php' for use with environment variables..."); $this->writeToFile("mysite/_config.php", <<getSelectedDatabase(), 0, strlen($prefix) + 5) == strtolower(sprintf('%stmpdb', $prefix))); } @@ -1083,7 +1083,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase $databaseConfig['timezone'] = '+0:00'; DB::connect($databaseConfig); $dbConn = DB::get_conn(); - $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; + $prefix = getenv('SS_DATABASE_PREFIX') ?: 'ss_'; $dbname = strtolower(sprintf('%stmpdb', $prefix)) . rand(1000000, 9999999); while (!$dbname || $dbConn->databaseExists($dbname)) { $dbname = strtolower(sprintf('%stmpdb', $prefix)) . rand(1000000, 9999999); @@ -1103,7 +1103,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase public static function delete_all_temp_dbs() { - $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; + $prefix = getenv('SS_DATABASE_PREFIX') ?: 'ss_'; foreach (DB::get_schema()->databaseList() as $dbName) { if (preg_match(sprintf('/^%stmpdb[0-9]+$/', $prefix), $dbName)) { DB::get_schema()->dropDatabase($dbName); diff --git a/src/ORM/DB.php b/src/ORM/DB.php index ba2c51e4b..fc1b7593f 100644 --- a/src/ORM/DB.php +++ b/src/ORM/DB.php @@ -241,7 +241,7 @@ class DB return false; } - $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; + $prefix = getenv('SS_DATABASE_PREFIX') ?: 'ss_'; $pattern = strtolower(sprintf('/^%stmpdb\d{7}$/', $prefix)); return (bool)preg_match($pattern, $name); } diff --git a/src/Security/BasicAuth.php b/src/Security/BasicAuth.php index 2ad56ac34..fb00fdc0e 100644 --- a/src/Security/BasicAuth.php +++ b/src/Security/BasicAuth.php @@ -134,9 +134,9 @@ class BasicAuth * away from prying eyes, but still be able to test the regular log-in features of the site. * * If you are including conf/ConfigureFromEnv.php in your _config.php file, you can also enable - * this feature by adding this line to your _ss_environment.php: + * this feature by adding this line to your .env: * - * define('SS_USE_BASIC_AUTH', true); + * SS_USE_BASIC_AUTH=1 * * @param boolean $protect Set this to false to disable protection. * @param string $code {@link Permission} code that is required from the user. diff --git a/src/View/ThemeManifest.php b/src/View/ThemeManifest.php index 31bc3f547..f577154ab 100644 --- a/src/View/ThemeManifest.php +++ b/src/View/ThemeManifest.php @@ -72,9 +72,8 @@ class ThemeManifest implements ThemeList $this->project = $project; - $cacheClass = defined('SS_MANIFESTCACHE') - ? SS_MANIFESTCACHE - : 'SilverStripe\\Core\\Manifest\\ManifestCache_File'; + $cacheClass = getenv('SS_MANIFESTCACHE') + ?: 'SilverStripe\\Core\\Manifest\\ManifestCache_File'; $this->cache = new $cacheClass('thememanifest'.($includeTests ? '_tests' : '')); $this->cacheKey = $this->getCacheKey(); diff --git a/src/conf/ConfigureFromEnv.php b/src/conf/ConfigureFromEnv.php index f360653c7..71e140a77 100644 --- a/src/conf/ConfigureFromEnv.php +++ b/src/conf/ConfigureFromEnv.php @@ -1,9 +1,9 @@ environment_type = SS_ENVIRONMENT_TYPE; +if ($envType = getenv('SS_ENVIRONMENT_TYPE')) { + Director::config()->environment_type = $envType; } global $database; // No database provided if (!isset($database) || !$database) { - if (defined('SS_DATABASE_NAME')) { - $database = SS_DATABASE_NAME; - } elseif (defined('SS_DATABASE_CHOOSE_NAME') && SS_DATABASE_CHOOSE_NAME) { - $loopCount = (int)SS_DATABASE_CHOOSE_NAME; + if (!($database = getenv('SS_DATABASE_NAME')) && $chooseName = getenv('SS_DATABASE_CHOOSE_NAME')) { + $loopCount = (int)$chooseName; $databaseDir = BASE_PATH; - for ($i=0; $i<$loopCount-1; - $i++) { + for ($i=0; $i<$loopCount-1; $i++) { $databaseDir = dirname($databaseDir); } - $database = "SS_" . basename($databaseDir); + $database = getenv('SS_DATABASE_PREFIX') ?: 'SS_'; + $database .= basename($databaseDir); $database = str_replace('.', '', $database); } } -if (defined('SS_DATABASE_USERNAME') && defined('SS_DATABASE_PASSWORD')) { +if ($dbUser = getenv('SS_DATABASE_USERNAME')) { global $databaseConfig; // Checks if the database global is defined (if present, wraps with prefix and suffix) @@ -105,69 +83,69 @@ if (defined('SS_DATABASE_USERNAME') && defined('SS_DATABASE_PASSWORD')) { if (!$name) { return ''; } else { - return (defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : '') + return (getenv('SS_DATABASE_PREFIX') ?: '') . $name - . (defined('SS_DATABASE_SUFFIX') ? SS_DATABASE_SUFFIX : ''); + . (getenv('SS_DATABASE_SUFFIX') ?: ''); } }; /** @skipUpgrade */ $databaseConfig = array( - "type" => defined('SS_DATABASE_CLASS') ? SS_DATABASE_CLASS : 'MySQLDatabase', - "server" => defined('SS_DATABASE_SERVER') ? SS_DATABASE_SERVER : 'localhost', - "username" => SS_DATABASE_USERNAME, - "password" => SS_DATABASE_PASSWORD, + "type" => getenv('SS_DATABASE_CLASS') ?: 'MySQLDatabase', + "server" => getenv('SS_DATABASE_SERVER') ?: 'localhost', + "username" => $dbUser, + "password" => getenv('SS_DATABASE_PASSWORD'), "database" => $databaseNameWrapper($database), ); // Set the port if called for - if (defined('SS_DATABASE_PORT')) { - $databaseConfig['port'] = SS_DATABASE_PORT; + if ($dbPort = getenv('SS_DATABASE_PORT')) { + $databaseConfig['port'] = $dbPort; } // Set the timezone if called for - if (defined('SS_DATABASE_TIMEZONE')) { - $databaseConfig['timezone'] = SS_DATABASE_TIMEZONE; + if ($dbTZ = getenv('SS_DATABASE_TIMEZONE')) { + $databaseConfig['timezone'] = $dbTZ; } // For schema enabled drivers: - if (defined('SS_DATABASE_SCHEMA')) { - $databaseConfig["schema"] = SS_DATABASE_SCHEMA; + if ($dbSchema = getenv('SS_DATABASE_SCHEMA')) { + $databaseConfig["schema"] = $dbSchema; } // For SQlite3 memory databases (mainly for testing purposes) - if (defined('SS_DATABASE_MEMORY')) { - $databaseConfig["memory"] = SS_DATABASE_MEMORY; + if ($dbMemory = getenv('SS_DATABASE_MEMORY')) { + $databaseConfig["memory"] = $dbMemory; } } -if (defined('SS_SEND_ALL_EMAILS_TO')) { - Email::config()->send_all_emails_to = SS_SEND_ALL_EMAILS_TO; +if ($sendAllEmailsTo = getenv('SS_SEND_ALL_EMAILS_TO')) { + Email::config()->send_all_emails_to = $sendAllEmailsTo; } -if (defined('SS_SEND_ALL_EMAILS_FROM')) { - Email::config()->send_all_emails_from = SS_SEND_ALL_EMAILS_FROM; +if ($sendAllEmailsFrom = getenv('SS_SEND_ALL_EMAILS_FROM')) { + Email::config()->send_all_emails_from = $sendAllEmailsFrom; } -if (defined('SS_DEFAULT_ADMIN_USERNAME')) { - if (!defined('SS_DEFAULT_ADMIN_PASSWORD')) { +if ($defaultAdminUser = getenv('SS_DEFAULT_ADMIN_USERNAME')) { + if (!$defaultAdminPass = getenv('SS_DEFAULT_ADMIN_PASSWORD')) { user_error( - "SS_DEFAULT_ADMIN_PASSWORD must be defined in your _ss_environment.php," + "SS_DEFAULT_ADMIN_PASSWORD must be defined in your environment," . "if SS_DEFAULT_ADMIN_USERNAME is defined. See " . "http://doc.silverstripe.org/framework/en/topics/environment-management for more information", E_USER_ERROR ); } else { - Security::setDefaultAdmin(SS_DEFAULT_ADMIN_USERNAME, SS_DEFAULT_ADMIN_PASSWORD); + Security::setDefaultAdmin($defaultAdminUser, $defaultAdminPass); } } -if (defined('SS_USE_BASIC_AUTH') && SS_USE_BASIC_AUTH) { - BasicAuth::config()->entire_site_protected = SS_USE_BASIC_AUTH; +if ($useBasicAuth = getenv('SS_USE_BASIC_AUTH')) { + BasicAuth::config()->entire_site_protected = $useBasicAuth; } -if (defined('SS_ERROR_LOG')) { +if ($errorLog = getenv('SS_ERROR_LOG')) { $logger = Injector::inst()->get('Logger'); if ($logger instanceof Logger) { - $logger->pushHandler(new StreamHandler(BASE_PATH . '/' . SS_ERROR_LOG, Logger::WARNING)); + $logger->pushHandler(new StreamHandler(BASE_PATH . '/' . $errorLog, Logger::WARNING)); } else { user_error("SS_ERROR_LOG setting only works with Monolog, you are using another logger", E_USER_WARNING); } @@ -175,3 +153,24 @@ if (defined('SS_ERROR_LOG')) { // Allow database adapters to handle their own configuration DatabaseAdapterRegistry::autoconfigure(); + +unset( + $envType, + $chooseName, + $loopCount, + $databaseDir, + $i, + $databaseNameWrapper, + $dbUser, + $dbPort, + $dbTZ, + $dbSchema, + $dbMemory, + $sendAllEmailsTo, + $sendAllEmailsFrom, + $defaultAdminUser, + $defaultAdminPass, + $useBasicAuth, + $errorLog, + $logger +); diff --git a/tests/bootstrap/environment.php b/tests/bootstrap/environment.php index 997f5e1a5..eb6abdb60 100644 --- a/tests/bootstrap/environment.php +++ b/tests/bootstrap/environment.php @@ -1,34 +1,37 @@ setEnvironmentVariable('SS_ENVIRONMENT_TYPE', 'dev'); } -if (!defined('SS_DATABASE_CLASS') && !defined('SS_DATABASE_USERNAME')) { +if (!getenv('SS_DATABASE_CLASS') && !getenv('SS_DATABASE_USERNAME')) { // The default settings let us define the database config via environment vars // Database connection, including PDO and legacy ORM support switch (getenv('DB')) { case "PGSQL"; - define('SS_DATABASE_CLASS', getenv('PDO') ? 'PostgrePDODatabase' : 'PostgreSQLDatabase'); - define('SS_DATABASE_USERNAME', 'postgres'); - define('SS_DATABASE_PASSWORD', ''); - break; + $loader->setEnvironmentVariable('SS_DATABASE_CLASS', getenv('PDO') ? 'PostgrePDODatabase' : 'PostgreSQLDatabase'); + $loader->setEnvironmentVariable('SS_DATABASE_USERNAME', 'postgres'); + $loader->setEnvironmentVariable('SS_DATABASE_PASSWORD', ''); + break; case "SQLITE": - define('SS_DATABASE_CLASS', getenv('PDO') ? 'SQLite3PDODatabase' : 'SQLite3Database'); - define('SS_DATABASE_USERNAME', 'root'); - define('SS_DATABASE_PASSWORD', ''); - define('SS_SQLITE_DATABASE_PATH', ':memory:'); + $loader->setEnvironmentVariable('SS_DATABASE_CLASS', getenv('PDO') ? 'SQLite3PDODatabase' : 'SQLite3Database'); + $loader->setEnvironmentVariable('SS_DATABASE_USERNAME', 'root'); + $loader->setEnvironmentVariable('SS_DATABASE_PASSWORD', ''); + $loader->setEnvironmentVariable('SS_SQLITE_DATABASE_PATH', ':memory:'); break; default: - define('SS_DATABASE_CLASS', getenv('PDO') ? 'MySQLPDODatabase' : 'MySQLDatabase'); - define('SS_DATABASE_USERNAME', 'root'); - define('SS_DATABASE_PASSWORD', ''); + $loader->setEnvironmentVariable('SS_DATABASE_CLASS', getenv('PDO') ? 'MySQLPDODatabase' : 'MySQLDatabase'); + $loader->setEnvironmentVariable('SS_DATABASE_USERNAME', 'root'); + $loader->setEnvironmentVariable('SS_DATABASE_PASSWORD', ''); } - define('SS_DATABASE_SERVER', '127.0.0.1'); - define('SS_DATABASE_CHOOSE_NAME', true); + $loader->setEnvironmentVariable('SS_DATABASE_SERVER', '127.0.0.1'); + $loader->setEnvironmentVariable('SS_DATABASE_CHOOSE_NAME', true); } diff --git a/tests/php/Core/Manifest/ConfigManifestTest.php b/tests/php/Core/Manifest/ConfigManifestTest.php index d8d5e6f20..e6e7f5d01 100644 --- a/tests/php/Core/Manifest/ConfigManifestTest.php +++ b/tests/php/Core/Manifest/ConfigManifestTest.php @@ -427,7 +427,9 @@ class ConfigManifestTest extends SapphireTest public function testEnvVarSetRules() { - $_ENV['ENVVARSET_FOO'] = 1; + $loader = new \Dotenv\Loader(null); + + $loader->setEnvironmentVariable('ENVVARSET_FOO', 1); $config = $this->getConfigFixtureValue('EnvVarSet'); $this->assertEquals( @@ -463,7 +465,9 @@ class ConfigManifestTest extends SapphireTest public function testEnvOrConstantMatchesValueRules() { - $_ENV['ENVORCONSTANTMATCHESVALUE_FOO'] = 'Foo'; + $loader = new \Dotenv\Loader(null); + + $loader->setEnvironmentVariable('ENVORCONSTANTMATCHESVALUE_FOO', 'Foo'); define('ENVORCONSTANTMATCHESVALUE_BAR', 'Bar'); $config = $this->getConfigFixtureValue('EnvOrConstantMatchesValue'); @@ -537,7 +541,9 @@ class ConfigManifestTest extends SapphireTest public function testMultipleRules() { - $_ENV['MULTIPLERULES_ENVVARIABLESET'] = 1; + $loader = new \Dotenv\Loader(null); + + $loader->setEnvironmentVariable('MULTIPLERULES_ENVVARIABLESET', 1); define('MULTIPLERULES_DEFINEDCONSTANT', 'defined'); $config = $this->getConfigFixtureValue('MultipleRules'); diff --git a/tests/php/ORM/DBTest.php b/tests/php/ORM/DBTest.php index a5eb5dfdf..7590a3cf2 100644 --- a/tests/php/ORM/DBTest.php +++ b/tests/php/ORM/DBTest.php @@ -12,7 +12,7 @@ class DBTest extends SapphireTest public function testValidAlternativeDatabaseName() { - $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; + $prefix = getenv('SS_DATABASE_PREFIX') ?: 'ss_'; Director::config()->update('environment_type', 'dev'); $this->assertTrue(DB::valid_alternative_database_name($prefix.'tmpdb1234567')); From 6e096f6172bf6075805ded6fa47d4d30fb9adf80 Mon Sep 17 00:00:00 2001 From: Daniel Hensby Date: Mon, 30 Jan 2017 15:34:55 +0000 Subject: [PATCH 2/3] DOCS Updated environment management docs to use .env file --- .../01_Installation/03_Windows.md | 2 +- .../Windows_IIS7.md | 25 ++-- docs/en/00_Getting_Started/02_Composer.md | 26 ++-- .../03_Environment_Management.md | 136 +++++++----------- .../03_Environment_Variables.md | 9 +- .../07_Debugging/00_Environment_Types.md | 5 +- .../09_Security/03_Authentication.md | 11 +- .../09_Security/04_Secure_Coding.md | 23 ++- .../14_Files/03_File_Security.md | 5 +- .../16_Execution_Pipeline/02_Manifests.md | 2 +- .../16_Execution_Pipeline/index.md | 7 +- docs/en/04_Changelogs/4.0.0.md | 19 ++- docs/en/05_Contributing/04_Release_Process.md | 7 +- .../05_Making_A_SilverStripe_Core_Release.md | 36 +++-- 14 files changed, 139 insertions(+), 174 deletions(-) diff --git a/docs/en/00_Getting_Started/01_Installation/03_Windows.md b/docs/en/00_Getting_Started/01_Installation/03_Windows.md index ed9bf0b45..739e441e2 100644 --- a/docs/en/00_Getting_Started/01_Installation/03_Windows.md +++ b/docs/en/00_Getting_Started/01_Installation/03_Windows.md @@ -38,7 +38,7 @@ $ composer create-project silverstripe/installer ./silverstripe * Rename the unpacked directory from `C:\wamp\www\silverstripe-vX.X.X` to `C:\wamp\www\silverstripe` ## Install and configure -* Option 1: Environment file - Set up a file named _ss_environment.php either in the webroot or a directory above webroot and setup as per the [Environment Management process](/getting_started/environment_management). +* Option 1: Environment file - Set up a file named `.env` file either in the webroot and setup as per the [Environment Management process](/getting_started/environment_management). * Option 2: Installer - Visit `http://localhost/silverstripe` - you will see SilverStripe's installation screen. * You should be able to click "Install SilverStripe" and the installer will do its thing. It takes a minute or two. diff --git a/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_IIS7.md b/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_IIS7.md index 1fa32603e..40ba16355 100644 --- a/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_IIS7.md +++ b/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_IIS7.md @@ -160,22 +160,21 @@ You will need to give **Modify** permission to **IUSR** user. To do it right cli Now that we've got the backend server software sorted out, it's time to install the SilverStripe CMS/framework. -Create a new file called **_ss_environment.php** in **C:\inetpub\wwwroot** +Create a new file called `.env` in **C:\inetpub\wwwroot\ss** This file tells SilverStripe projects installed on this machine which database server and credentials, as well as anything environment specific. -Inside the newly created _ss_environment.php file, insert the following code: +Inside the newly created `.env` file, insert the following code: - load(); +} catch (\Dotenv\Exception\InvalidPathException $e) { + // no file found +} +``` - :::php - '); - - // This sets a prefix, which is prepended to the $database variable. This is - // helpful mainly on shared hosts, when every database has a prefix. - define('SS_DATABASE_PREFIX', 'simon_'); - - // These two lines are a bit complicated. If I'm connecting to the server from - // 127.0.0.1 or MyIP and I'm using a browser with a + in the UserAgent, the site - // is put in dev mode, otherwise it is put in live mode. Most sites would only - // need to put the site in either dev or live mode, thus wont need the IP checks - if(isset($_SERVER['REMOTE_ADDR']) && ($_SERVER['REMOTE_ADDR'] == '127.0.0.1' || ($_SERVER['REMOTE_ADDR'] == '' - && strpos($_SERVER['HTTP_USER_AGENT'], '+') !== false))) - define('SS_ENVIRONMENT_TYPE', 'dev'); - else - define('SS_ENVIRONMENT_TYPE', 'live'); - - // These two defines sets a default login which, when used, will always log - // you in as an admin, even creating one if none exist. - define('SS_DEFAULT_ADMIN_USERNAME', ''); - define('SS_DEFAULT_ADMIN_PASSWORD', ''); - - // This causes errors to be written to the BASE_PATH/silverstripe.log file. - // Path must be relative to BASE_PATH - define('SS_ERROR_LOG', 'silverstripe.log'); - - // This is used by sake to know which directory points to which URL - global $_FILE_TO_URL_MAPPING; - $_FILE_TO_URL_MAPPING['/var/www'] = 'http://simon.geek.nz'; +## Core environment variables -## Available Constants +SilverStripe core environment variables are listed here, though you're free to define any you need for your application. | Name | Description | | ---- | ----------- | -| `TEMP_FOLDER` | Absolute file path to store temporary files such as cached templates or the class manifest. Needs to be writeable by the webserver user. Defaults to *silverstripe-cache* in the webroot, and falls back to *sys_get_temp_dir()*. See *getTempFolder()* in *framework/core/TempPath.php*.| | `SS_DATABASE_CLASS` | The database class to use, MySQLPDODatabase, MySQLDatabase, MSSQLDatabase, etc. defaults to MySQLDatabase.| | `SS_DATABASE_SERVER`| The database server to use, defaulting to localhost.| | `SS_DATABASE_USERNAME`| The database username (mandatory).| @@ -125,3 +78,12 @@ This is my `_ss_environment.php` file. I have it placed in `/var`, as each of th | `SS_SEND_ALL_EMAILS_TO`| If you define this constant, all emails will be redirected to this address.| | `SS_SEND_ALL_EMAILS_FROM`| If you define this constant, all emails will be sent from this address.| | `SS_ERROR_LOG` | Relative path to the log file. | +| `SS_PROTECTED_ASSETS_PATH` | Path to secured assets - defaults to ASSET_PATH/.protected | +| `SS_DATABASE_MEMORY` | Used for SQLite3 DBs | +| `SS_TRUSTED_PROXY_PROTOCOL_HEADER` | Used to define the proxy header to be used to determine HTTPS status | +| `SS_TRUSTED_PROXY_IP_HEADER` | Used to define the proxy header to be used to determine request IPs | +| `SS_TRUSTED_PROXY_HOST_HEADER` | Used to define the proxy header to be used to determine the requested host name | +| `SS_TRUSTED_PROXY_IPS` | IP address or CIDR range to trust proxy headers from | +| `SS_ALLOWED_HOSTS` | A comma deliminated list of hostnames the site is allowed to respond to | +| `SS_MANIFESTCACHE` | The manifest cache to use (defaults to file based caching) | +| `SS_IGNORE_DOT_ENV` | If set the .env file will be ignored. This is good for live to mitigate any performance implications of loading the .env file | diff --git a/docs/en/02_Developer_Guides/04_Configuration/03_Environment_Variables.md b/docs/en/02_Developer_Guides/04_Configuration/03_Environment_Variables.md index 99c8ca188..3bf84b7cd 100644 --- a/docs/en/02_Developer_Guides/04_Configuration/03_Environment_Variables.md +++ b/docs/en/02_Developer_Guides/04_Configuration/03_Environment_Variables.md @@ -4,11 +4,10 @@ summary: Site configuration variables such as database connection details, envir # Environment Variables Environment specific variables like database connection details, API keys and other server configuration should be kept -outside the application code in a separate `_ss_environment.php` file. This file is stored outside the web root and -version control for security reasons. +outside the application code in a separate `.env` file. This file is stored in the web root and +kept out of version control for security reasons. -For more information on the environment file, see the [Environment Management](../../getting_started/environment_management/) -documentation. +For more information see our docs on [Environment Management](../../getting_started/environment_management/). Data which isn't sensitive that can be in version control but is mostly static such as constants is best suited to be -included through the [Configuration API](configuration) based on the standard environment types (dev / test / live). \ No newline at end of file +included through the [Configuration API](configuration) based on the standard environment types (dev / test / live). diff --git a/docs/en/02_Developer_Guides/07_Debugging/00_Environment_Types.md b/docs/en/02_Developer_Guides/07_Debugging/00_Environment_Types.md index 65d5b42f9..fd72a44d6 100644 --- a/docs/en/02_Developer_Guides/07_Debugging/00_Environment_Types.md +++ b/docs/en/02_Developer_Guides/07_Debugging/00_Environment_Types.md @@ -13,10 +13,9 @@ The definition of setting an environment type in a `mysite/_config/app.yml` look SilverStripe\Control\Director: environment_type: 'dev' -The definition of setting an environment type in a `_ss_environment.php` file looks like +The definition of setting an environment type in a `.env` file looks like - :::php - define('SS_ENVIRONMENT_TYPE', 'dev'); + SS_ENVIRONMENT_TYPE="dev" The three environment types you can set are `dev`, `test` and `live`. diff --git a/docs/en/02_Developer_Guides/09_Security/03_Authentication.md b/docs/en/02_Developer_Guides/09_Security/03_Authentication.md index 8e4d8f7f3..dc2598661 100644 --- a/docs/en/02_Developer_Guides/09_Security/03_Authentication.md +++ b/docs/en/02_Developer_Guides/09_Security/03_Authentication.md @@ -37,13 +37,12 @@ When a new SilverStripe site is created for the first time, it may be necessary CMS access for the first time. SilverStripe provides a default admin configuration system, which allows a username and password to be configured for a single special user outside of the normal membership system. -It is advisable to configure this user in your `_ss_environment.php` file outside of the web root, as below: +It is advisable to configure this user in your `.env` file inside of the web root, as below: - :::php - // Configure a default username and password to access the CMS on all sites in this environment. - define('SS_DEFAULT_ADMIN_USERNAME', 'admin'); - define('SS_DEFAULT_ADMIN_PASSWORD', 'password'); + # Configure a default username and password to access the CMS on all sites in this environment. + SS_DEFAULT_ADMIN_USERNAME="admin" + SS_DEFAULT_ADMIN_PASSWORD="password" When a user logs in with these credentials, then a [api:Member] with the Email 'admin' will be generated in the database, but without any password information. This means that the password can be reset or changed by simply -updating the `_ss_environment.php` file. +updating the `.env` file. diff --git a/docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md b/docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md index cd416a127..9dc949973 100644 --- a/docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md +++ b/docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md @@ -537,11 +537,10 @@ as well as the login form. To prevent a forged hostname appearing being used by the application, SilverStripe allows the configure of a whitelist of hosts that are allowed to access the system. By defining -this whitelist in your _ss_environment.php file, any request presenting a `Host` header that is +this whitelist in your `.env` file, any request presenting a `Host` header that is _not_ in this list will be blocked with a HTTP 400 error: - :::php - define('SS_ALLOWED_HOSTS', 'www.mysite.com,mysite.com,subdomain.mysite.com'); + SS_ALLOWED_HOSTS="www.mysite.com,mysite.com,subdomain.mysite.com" Please note that if this configuration is defined, you _must_ include _all_ subdomains (eg www.) that will be accessing the site. @@ -556,14 +555,12 @@ mechanisms, as rewritten urls could persist between requests in order to misdire into visiting external sites. In order to prevent this kind of attack, it's necessary to whitelist trusted proxy -server IPs using the SS_TRUSTED_PROXY_IPS define in your _ss_environment.php. +server IPs using the SS_TRUSTED_PROXY_IPS define in your `.env`. - - :::php - define('SS_TRUSTED_PROXY_IPS', '127.0.0.1,192.168.0.1'); - define('SS_TRUSTED_PROXY_HOST_HEADER', 'HTTP_X_FORWARDED_HOST'); - define('SS_TRUSTED_PROXY_IP_HEADER', 'HTTP_X_FORWARDED_FOR'); - define('SS_TRUSTED_PROXY_PROTOCOL_HEADER', 'HTTP_X_FORWARDED_PROTOCOL'); + SS_TRUSTED_PROXY_IPS="127.0.0.1,192.168.0.1" + SS_TRUSTED_PROXY_HOST_HEADER="HTTP_X_FORWARDED_HOST" + SS_TRUSTED_PROXY_IP_HEADER="HTTP_X_FORWARDED_FOR" + SS_TRUSTED_PROXY_PROTOCOL_HEADER="HTTP_X_FORWARDED_PROTOCOL" At the same time, you'll also need to define which headers you trust from these proxy IPs. Since there are multiple ways through which proxies can pass through HTTP information on the original hostname, IP and protocol, these values need to be adjusted for your specific proxy. The header names match their equivalent `$_SERVER` values. @@ -571,14 +568,14 @@ If there is no proxy server, 'none' can be used to distrust all clients. If only trusted servers will make requests then you can use '*' to trust all clients. Otherwise a comma separated list of individual IP addresses should be declared. -This behaviour is enabled whenever SS_TRUSTED_PROXY_IPS is defined, or if the +This behaviour is enabled whenever `SS_TRUSTED_PROXY_IPS` is defined, or if the `BlockUntrustedIPs` environment variable is declared. It is advisable to include the following in your .htaccess to ensure this behaviour is activated. # Ensure that X-Forwarded-Host is only allowed to determine the request - # hostname for servers ips defined by SS_TRUSTED_PROXY_IPS in your _ss_environment.php + # hostname for servers ips defined by SS_TRUSTED_PROXY_IPS in your .env # Note that in a future release this setting will be always on. SetEnv BlockUntrustedIPs true @@ -586,7 +583,7 @@ following in your .htaccess to ensure this behaviour is activated. In a future release this behaviour will be changed to be on by default, and this environment variable will be no longer necessary, thus it will be necessary to always set -SS_TRUSTED_PROXY_IPS if using a proxy. +`SS_TRUSTED_PROXY_IPS` if using a proxy. ## Related diff --git a/docs/en/02_Developer_Guides/14_Files/03_File_Security.md b/docs/en/02_Developer_Guides/14_Files/03_File_Security.md index 8f92cf7f9..19d6d4579 100644 --- a/docs/en/02_Developer_Guides/14_Files/03_File_Security.md +++ b/docs/en/02_Developer_Guides/14_Files/03_File_Security.md @@ -232,11 +232,10 @@ In order to better ensure these files are protected, it's recommended to move th root altogether. For instance, given your web root is in the folder `/sites/mysite/www`, you can tell the asset store -to put protected files into `/sites/mysite/protected` with the below `_ss_environment.php` setting: +to put protected files into `/sites/mysite/protected` with the below `.env` setting: - :::php - define('SS_PROTECTED_ASSETS_PATH', '/sites/mysite/protected'); + SS_PROTECTED_ASSETS_PATH="/sites/mysite/protected" ### Configuring: File types diff --git a/docs/en/02_Developer_Guides/16_Execution_Pipeline/02_Manifests.md b/docs/en/02_Developer_Guides/16_Execution_Pipeline/02_Manifests.md index eb9812b33..c1c430da3 100644 --- a/docs/en/02_Developer_Guides/16_Execution_Pipeline/02_Manifests.md +++ b/docs/en/02_Developer_Guides/16_Execution_Pipeline/02_Manifests.md @@ -15,7 +15,7 @@ By default, manifests are stored on the local filesystem through PHP's `serializ Combined with PHP opcode caching this provides fast access. In order to share manifests between servers, or centralise cache management, other storage adapters are available. These can be configured by a `SS_MANIFESTCACHE` constant, -placed in your `_ss_environment.php`. +placed in your `.env`. * `ManifestCache_File`: The default adapter using PHP's `serialize()` * `ManifestCache_File_PHP`: Using `var_export()`, which is faster when a PHP opcode cache is installed diff --git a/docs/en/02_Developer_Guides/16_Execution_Pipeline/index.md b/docs/en/02_Developer_Guides/16_Execution_Pipeline/index.md index 91fc2c77c..7e91aa99b 100644 --- a/docs/en/02_Developer_Guides/16_Execution_Pipeline/index.md +++ b/docs/en/02_Developer_Guides/16_Execution_Pipeline/index.md @@ -80,13 +80,12 @@ can leave sensitive files exposed to public access (the `RewriteRule` conditions All requests go through `framework/main.php`, which sets up the execution environment: - * Tries to locate an `_ss_environment.php` - [configuration file](/getting_started/environment_management) in the webroot, - or the two levels above it (to allow sharing configuration between multiple webroots). + * Tries to locate an `.env` + [configuration file](/getting_started/environment_management) in the webroot. * Sets constants based on the filesystem structure (e.g. `BASE_URL`, `BASE_PATH` and `TEMP_FOLDER`) * Normalizes the `url` parameter in preparation for handing it off to `Director` * Connects to a database, based on information stored in the global `$databaseConfig` variable. - The configuration is either defined in your `_config.php`, or through `_ss_environment.php` + The configuration is either defined in your `_config.php`, or through `.env` * Sets up [error handlers](../debugging/error_handling) * Optionally continues a [session](../cookies_and_sessions/sessions) if the request already contains a session identifier * Loads manifests for PHP classes, templates, as well as any [YAML configuration](../configuration). diff --git a/docs/en/04_Changelogs/4.0.0.md b/docs/en/04_Changelogs/4.0.0.md index 2e78b427c..8db4ea5fe 100644 --- a/docs/en/04_Changelogs/4.0.0.md +++ b/docs/en/04_Changelogs/4.0.0.md @@ -49,6 +49,7 @@ guide developers in preparing existing 3.x code for compatibility with 4.0 * Themes are now configured to cascade, where you can specify a list of themes, and have the template engine search programatically through a prioritised list when resolving template and CSS file paths. * i18n Updated to use symfony/translation over zend Framework 1. Zend_Translate has been removed. +* _ss_environment.php files have been removed in favour of `.env` and "real" environment variables. ## Upgrading @@ -1327,7 +1328,7 @@ handle field-level and form-level messages. This has the following properties: ### Email and Mailer -#### Email Additions / Changes +#### Email Additions / Changes * `Mailer` converted to an interface * `SwfitMailer` added as new default mailer @@ -1335,3 +1336,19 @@ handle field-level and form-level messages. This has the following properties: * Default template body variable renamed from `$Body` to `$EmailContent` * `$email->setTemplate()` renamed to `$email->setHTMLTemplate()` * Added `$email->setPlainTemplate` for rendering plain versions of email + + +### Environment management + +See [Environment Management docs](https://docs.silverstripe.org/en/4/getting_started/environment_management/) for full +details. + +The removal of the `_ss_environment.php` file means that conditional logic is no longer available in the environment +varialbe set-up process. This generally encouraged bad practice and should be avoided. If you still require conditional +logic early in the bootstrap, this is best placed in the `_config.php` files. + +#### Environment file changes + +* Removed support for _ss_environment.php in favour of .env and first class environment variables +* Environment variables now can be set in `.env` file placed in webroot or one level above +* Environment variables will be read from the environment as well diff --git a/docs/en/05_Contributing/04_Release_Process.md b/docs/en/05_Contributing/04_Release_Process.md index 5f0d73860..3d3b7ef60 100644 --- a/docs/en/05_Contributing/04_Release_Process.md +++ b/docs/en/05_Contributing/04_Release_Process.md @@ -75,7 +75,7 @@ This change could be committed to a minor release like *3.2.0*, and remains depr (e.g. *3.3.0*, *3.4.0*), until a new major release (e.g. *4.0.0*), at which point it gets removed from the codebase. Deprecation notices are enabled by default on dev environment, but can be -turned off via either _ss_environment.php or in your _config.php. Deprecation +turned off via either `.env` or in your _config.php. Deprecation notices are always disabled on both live and test. @@ -86,11 +86,10 @@ notices are always disabled on both live and test. Deprecation::set_enabled(false); -`_ss_environment.php` +`.env` - :::php - define('SS_DEPRECATION_ENABLED', false); + SS_DEPRECATION_ENABLED="0" ## Security Releases diff --git a/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md b/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md index edca6e272..98d87a546 100644 --- a/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md +++ b/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md @@ -36,30 +36,28 @@ As a core contributor it is necessary to have installed the following set of too * [AWS CLI tools](https://aws.amazon.com/cli/): `pip install awscli` * The `tar` and `zip` commands -* A good _ss_environment.php setup in your localhost webroot. +* A good `.env` setup in your localhost webroot. -Example `_ss_environment.php`: +Example `.env`: - :::php - Date: Mon, 30 Jan 2017 15:35:43 +0000 Subject: [PATCH 3/3] NEW Director::host() to determine host name of site --- cli-script.php | 15 +++ .../03_Environment_Management.md | 1 + docs/en/02_Developer_Guides/17_CLI/index.md | 26 ++-- docs/en/04_Changelogs/4.0.0.md | 1 + .../05_Making_A_SilverStripe_Core_Release.md | 3 +- main.php | 3 +- src/Control/Director.php | 114 ++++++++++++------ src/Core/Constants.php | 74 ------------ .../Startup/ParameterConfirmationToken.php | 3 +- src/Dev/DevelopmentAdmin.php | 25 ---- tests/bootstrap/cli.php | 16 +++ tests/php/Dev/DevAdminControllerTest.php | 2 +- 12 files changed, 127 insertions(+), 156 deletions(-) diff --git a/cli-script.php b/cli-script.php index e3b2ac16a..7880e9084 100755 --- a/cli-script.php +++ b/cli-script.php @@ -20,6 +20,21 @@ if(PHP_SAPI != "cli" && PHP_SAPI != "cgi" && PHP_SAPI != "cgi-fcgi") { die(); } +// We update the $_SERVER variable to contain data consistent with the rest of the application. +$_SERVER = array_merge(array( + 'SERVER_PROTOCOL' => 'HTTP/1.1', + 'HTTP_ACCEPT' => 'text/plain;q=0.5', + 'HTTP_ACCEPT_LANGUAGE' => '*;q=0.5', + 'HTTP_ACCEPT_ENCODING' => '', + 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1;q=0.5', + 'SERVER_SIGNATURE' => 'Command-line PHP/' . phpversion(), + 'SERVER_SOFTWARE' => 'PHP/' . phpversion(), + 'SERVER_ADDR' => '127.0.0.1', + 'REMOTE_ADDR' => '127.0.0.1', + 'REQUEST_METHOD' => 'GET', + 'HTTP_USER_AGENT' => 'CLI', +), $_SERVER); + /** * Identify the cli-script.php file and change to its container directory, so that require_once() works */ diff --git a/docs/en/00_Getting_Started/03_Environment_Management.md b/docs/en/00_Getting_Started/03_Environment_Management.md index 9a817a293..289e3e20b 100644 --- a/docs/en/00_Getting_Started/03_Environment_Management.md +++ b/docs/en/00_Getting_Started/03_Environment_Management.md @@ -87,3 +87,4 @@ SilverStripe core environment variables are listed here, though you're free to d | `SS_ALLOWED_HOSTS` | A comma deliminated list of hostnames the site is allowed to respond to | | `SS_MANIFESTCACHE` | The manifest cache to use (defaults to file based caching) | | `SS_IGNORE_DOT_ENV` | If set the .env file will be ignored. This is good for live to mitigate any performance implications of loading the .env file | +| `SS_HOST` | The hostname to use when it isn't determinable by other means (eg: for CLI commands) | diff --git a/docs/en/02_Developer_Guides/17_CLI/index.md b/docs/en/02_Developer_Guides/17_CLI/index.md index f1b02fc31..aeb63d505 100644 --- a/docs/en/02_Developer_Guides/17_CLI/index.md +++ b/docs/en/02_Developer_Guides/17_CLI/index.md @@ -44,25 +44,21 @@ This currently only works on UNIX like systems, not on Windows. Sometimes SilverStripe needs to know the URL of your site. For example, when sending an email or generating static files. When you're visiting the site in a web browser this is easy to work out, but when executing scripts on the -command line, it has no way of knowing. To work this out, add lines to your -[_ss_environment.php](/getting_started/environment_management) file. +command line, it has no way of knowing. To work this out, there are several ways to resolve this. You can set alternate +base URLs, hosts, and protocol. - :::php - global $_FILE_TO_URL_MAPPING; +eg: - $_FILE_TO_URL_MAPPING['/Users/sminnee/Sites'] = 'http://localhost'; +```yml +SilverStripe\Control\Director: + alternate_base_url: 'https://example.com/' +``` -The above statement tells SilverStripe that anything executed under the `/Users/sminnee/Sites` directory will have the -base URL `http://localhost`. The site `/Users/sminnee/Sites/my_silverstripe_project` will translate to the URL -`http://localhost/my_silverstripe_project`. +Alternatively you can use the `SS_HOST` environment variable to set a fallback hostname: -You can add multiple file to url mapping definitions. The most specific mapping will be used. - - :::php - global $_FILE_TO_URL_MAPPING; - - $_FILE_TO_URL_MAPPING['/Users/sminnee/Sites'] = 'http://localhost'; - $_FILE_TO_URL_MAPPING['/Users/sminnee/Sites/my_silverstripe_project'] = 'http://project.localhost'; +``` +SS_HOST="localhost" +``` ### Usage diff --git a/docs/en/04_Changelogs/4.0.0.md b/docs/en/04_Changelogs/4.0.0.md index 8db4ea5fe..005510064 100644 --- a/docs/en/04_Changelogs/4.0.0.md +++ b/docs/en/04_Changelogs/4.0.0.md @@ -1352,3 +1352,4 @@ logic early in the bootstrap, this is best placed in the `_config.php` files. * Removed support for _ss_environment.php in favour of .env and first class environment variables * Environment variables now can be set in `.env` file placed in webroot or one level above * Environment variables will be read from the environment as well +* `$_FILE_TO_URL_MAPPING` has been removed and replaced with using `Director.alternate_host` or `SS_HOST` env var diff --git a/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md b/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md index 98d87a546..81ed1aaac 100644 --- a/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md +++ b/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md @@ -58,8 +58,7 @@ Example `.env`: SS_DEFAULT_ADMIN_PASSWORD="password" # Basic CLI hostname - global $_FILE_TO_URL_MAPPING; - $_FILE_TO_URL_MAPPING[__DIR__] = "http://localhost"; + SS_HOST="localhost"; You will also need to be assigned the following permissions. Contact one of the SS staff from diff --git a/main.php b/main.php index c1b121b11..daa214c59 100644 --- a/main.php +++ b/main.php @@ -188,8 +188,9 @@ if(!isset($databaseConfig) || !isset($databaseConfig['database']) || !$databaseC header($_SERVER['SERVER_PROTOCOL'] . " 500 Server Error"); die('SilverStripe Framework requires a $databaseConfig defined.'); } + $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; $s = (isset($_SERVER['SSL']) || (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')) ? 's' : ''; - $installURL = "http$s://" . $_SERVER['HTTP_HOST'] . BASE_URL . '/install.php'; + $installURL = "http$s://" . $host . BASE_URL . '/install.php'; // The above dirname() will equate to "\" on Windows when installing directly from http://localhost (not using // a sub-directory), this really messes things up in some browsers. Let's get rid of the backslashes diff --git a/src/Control/Director.php b/src/Control/Director.php index b9c6e0366..ba8fc2ac5 100644 --- a/src/Control/Director.php +++ b/src/Control/Director.php @@ -101,6 +101,13 @@ class Director implements TemplateGlobalProvider */ private static $alternate_protocol; + /** + * @config + * + * @var string + */ + private static $alternate_host; + /** * @config * @@ -139,6 +146,15 @@ class Director implements TemplateGlobalProvider */ public static function direct($url, DataModel $model) { + // check allowed hosts + if (getenv('SS_ALLOWED_HOSTS') && !Director::is_cli()) { + $all_allowed_hosts = explode(',', getenv('SS_ALLOWED_HOSTS')); + if (!in_array(static::host(), $all_allowed_hosts)) { + throw new HTTPResponse_Exception('Invalid Host', 400); + } + } + + // Validate $_FILES array before merging it with $_POST foreach ($_FILES as $k => $v) { if (is_array($v['tmp_name'])) { @@ -551,6 +567,62 @@ class Director implements TemplateGlobalProvider return Controller::join_links($parent, $url); } + /** + * A helper to determine the current hostname used to access the site. + * The following are used to determine the host (in order) + * - Director.alternate_host + * - Director.alternate_base_url (if it contains a domain name) + * - Trusted proxy headers + * - HTTP Host header + * - SS_HOST env var + * - SERVER_NAME + * - gethostname() + * + * @return string + */ + public static function host() + { + $headerOverride = false; + if (TRUSTED_PROXY) { + $headers = (getenv('SS_TRUSTED_PROXY_HOST_HEADER')) ? array(getenv('SS_TRUSTED_PROXY_HOST_HEADER')) : null; + if (!$headers) { + // Backwards compatible defaults + $headers = array('HTTP_X_FORWARDED_HOST'); + } + foreach ($headers as $header) { + if (!empty($_SERVER[$header])) { + // Get the first host, in case there's multiple separated through commas + $headerOverride = strtok($_SERVER[$header], ','); + break; + } + } + } + + if ($host = static::config()->get('alternate_host')) { + return $host; + } + + if ($baseURL = static::config()->get('alternate_base_url')) { + if (preg_match('/^(http[^:]*:\/\/[^\/]+)(\/|$)/', $baseURL, $matches)) { + return parse_url($baseURL, PHP_URL_HOST); + } + } + + if ($headerOverride) { + return $headerOverride; + } + + if (isset($_SERVER['HTTP_HOST'])) { + return $_SERVER['HTTP_HOST']; + } + + if ($host = getenv('SS_HOST')) { + return $host; + } + + return isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : gethostname(); + } + /** * Returns the domain part of the URL 'http://www.mysite.com'. Returns FALSE is this environment * variable isn't set. @@ -559,31 +631,7 @@ class Director implements TemplateGlobalProvider */ public static function protocolAndHost() { - $alternate = Config::inst()->get('SilverStripe\\Control\\Director', 'alternate_base_url'); - if ($alternate) { - if (preg_match('/^(http[^:]*:\/\/[^\/]+)(\/|$)/', $alternate, $matches)) { - return $matches[1]; - } - } - - if (isset($_SERVER['HTTP_HOST'])) { - return Director::protocol() . $_SERVER['HTTP_HOST']; - } else { - global $_FILE_TO_URL_MAPPING; - if (Director::is_cli() && isset($_FILE_TO_URL_MAPPING)) { - $errorSuggestion = ' You probably want to define ' . - 'an entry in $_FILE_TO_URL_MAPPING that covers "' . Director::baseFolder() . '"'; - } elseif (Director::is_cli()) { - $errorSuggestion = ' You probably want to define $_FILE_TO_URL_MAPPING in ' . - 'your _ss_environment.php as instructed on the "sake" page of the doc.silverstripe.com wiki'; - } else { - $errorSuggestion = ""; - } - - user_error("Director::protocolAndHost() lacks sufficient information - HTTP_HOST not set." - . $errorSuggestion, E_USER_WARNING); - return false; - } + return static::protocol() . static::host(); } /** @@ -950,7 +998,7 @@ class Director implements TemplateGlobalProvider $login = "$_SERVER[PHP_AUTH_USER]:$_SERVER[PHP_AUTH_PW]@"; } - return Director::protocol() . $login . $_SERVER['HTTP_HOST'] . Director::baseURL(); + return Director::protocol() . $login . static::host() . Director::baseURL(); } /** @@ -1052,7 +1100,7 @@ class Director implements TemplateGlobalProvider */ public static function forceWWW() { - if (!Director::isDev() && !Director::isTest() && strpos($_SERVER['HTTP_HOST'], 'www') !== 0) { + if (!Director::isDev() && !Director::isTest() && strpos(static::host(), 'www') !== 0) { $destURL = str_replace( Director::protocol(), Director::protocol() . 'www.', @@ -1191,11 +1239,7 @@ class Director implements TemplateGlobalProvider // Check if we are running on one of the test servers $devServers = (array)Config::inst()->get('SilverStripe\\Control\\Director', 'dev_servers'); - if (isset($_SERVER['HTTP_HOST']) && in_array($_SERVER['HTTP_HOST'], $devServers)) { - return true; - } - - return false; + return in_array(static::host(), $devServers); } /** @@ -1223,11 +1267,7 @@ class Director implements TemplateGlobalProvider // Check if we are running on one of the test servers $testServers = (array)Config::inst()->get('SilverStripe\\Control\\Director', 'test_servers'); - if (isset($_SERVER['HTTP_HOST']) && in_array($_SERVER['HTTP_HOST'], $testServers)) { - return true; - } - - return false; + return in_array(static::host(), $testServers); } /** diff --git a/src/Core/Constants.php b/src/Core/Constants.php index fb1188815..46a9153b0 100644 --- a/src/Core/Constants.php +++ b/src/Core/Constants.php @@ -61,80 +61,6 @@ if (!defined('TRUSTED_PROXY')) { define('TRUSTED_PROXY', $trusted); } -/** - * 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. - */ -if (!isset($_SERVER['HTTP_HOST'])) { - // HTTP_HOST, REQUEST_PORT, SCRIPT_NAME, and PHP_SELF - global $_FILE_TO_URL_MAPPING; - if (isset($_FILE_TO_URL_MAPPING)) { - $fullPath = $testPath = realpath($_SERVER['SCRIPT_FILENAME']); - while ($testPath && $testPath != '/' && !preg_match('/^[A-Z]:\\\\$/', $testPath)) { - if (isset($_FILE_TO_URL_MAPPING[$testPath])) { - $url = $_FILE_TO_URL_MAPPING[$testPath] - . str_replace(DIRECTORY_SEPARATOR, '/', substr($fullPath, strlen($testPath))); - - $components = parse_url($url); - $_SERVER['HTTP_HOST'] = $components['host']; - if (!empty($components['port'])) { - $_SERVER['HTTP_HOST'] .= ':' . $components['port']; - } - $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'] = $components['path']; - if (!empty($components['port'])) { - $_SERVER['REQUEST_PORT'] = $components['port']; - } - break; - } - $testPath = dirname($testPath); - } - } - - // Everything else - $serverDefaults = array( - 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'HTTP_ACCEPT' => 'text/plain;q=0.5', - 'HTTP_ACCEPT_LANGUAGE' => '*;q=0.5', - 'HTTP_ACCEPT_ENCODING' => '', - 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1;q=0.5', - 'SERVER_SIGNATURE' => 'Command-line PHP/' . phpversion(), - 'SERVER_SOFTWARE' => 'PHP/' . phpversion(), - 'SERVER_ADDR' => '127.0.0.1', - 'REMOTE_ADDR' => '127.0.0.1', - 'REQUEST_METHOD' => 'GET', - 'HTTP_USER_AGENT' => 'CLI', - ); - - $_SERVER = array_merge($serverDefaults, $_SERVER); - - /** - * If we have an HTTP_HOST value, then we're being called from the webserver and there are some things that - * need checking - */ -} else { - - /** - * Fix HTTP_HOST from reverse proxies - */ - $trustedProxyHeader = (defined('SS_TRUSTED_PROXY_HOST_HEADER')) - ? SS_TRUSTED_PROXY_HOST_HEADER - : 'HTTP_X_FORWARDED_HOST'; - - if (TRUSTED_PROXY && !empty($_SERVER[$trustedProxyHeader])) { - // Get the first host, in case there's multiple separated through commas - $_SERVER['HTTP_HOST'] = strtok($_SERVER[$trustedProxyHeader], ','); - } -} - -// Filter by configured allowed hosts -if (defined('SS_ALLOWED_HOSTS') && php_sapi_name() !== "cli") { - $all_allowed_hosts = explode(',', SS_ALLOWED_HOSTS); - if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $all_allowed_hosts)) { - header('HTTP/1.1 400 Invalid Host', true, 400); - die(); - } -} - /** * Define system paths */ diff --git a/src/Core/Startup/ParameterConfirmationToken.php b/src/Core/Startup/ParameterConfirmationToken.php index b9075614a..862ed4739 100644 --- a/src/Core/Startup/ParameterConfirmationToken.php +++ b/src/Core/Startup/ParameterConfirmationToken.php @@ -2,6 +2,7 @@ namespace SilverStripe\Core\Startup; +use SilverStripe\Control\Director; use SilverStripe\Security\RandomGenerator; /** @@ -203,7 +204,7 @@ class ParameterConfirmationToken $parts = array_filter(array( // What's our host - $_SERVER['HTTP_HOST'], + Director::host(), // SilverStripe base self::$alternateBaseURL !== null ? self::$alternateBaseURL : BASE_URL, // And URL including base script (eg: if it's index.php/page/url/) diff --git a/src/Dev/DevelopmentAdmin.php b/src/Dev/DevelopmentAdmin.php index e8bc4124e..9b8bd28e6 100644 --- a/src/Dev/DevelopmentAdmin.php +++ b/src/Dev/DevelopmentAdmin.php @@ -64,31 +64,6 @@ class DevelopmentAdmin extends Controller return; } - // check for valid url mapping - // lacking this information can cause really nasty bugs, - // e.g. when running Director::test() from a FunctionalTest instance - global $_FILE_TO_URL_MAPPING; - if (Director::is_cli()) { - if (isset($_FILE_TO_URL_MAPPING)) { - $testPath = BASE_PATH; - $matched = false; - while ($testPath && $testPath != "/" && !preg_match('/^[A-Z]:\\\\$/', $testPath)) { - if (isset($_FILE_TO_URL_MAPPING[$testPath])) { - $matched = true; - break; - } - $testPath = dirname($testPath); - } - if (!$matched) { - echo 'Warning: You probably want to define '. - 'an entry in $_FILE_TO_URL_MAPPING that covers "' . Director::baseFolder() . '"' . "\n"; - } - } else { - echo 'Warning: You probably want to define $_FILE_TO_URL_MAPPING in '. - 'your _ss_environment.php as instructed on the "sake" page of the doc.silverstripe.org wiki'."\n"; - } - } - // Backwards compat: Default to "draft" stage, which is important // for tasks like dev/build which call DataObject->requireDefaultRecords(), // but also for other administrative tasks which have assumptions about the default stage. diff --git a/tests/bootstrap/cli.php b/tests/bootstrap/cli.php index b3fb74fed..dbc3d52d1 100644 --- a/tests/bootstrap/cli.php +++ b/tests/bootstrap/cli.php @@ -6,6 +6,22 @@ if (!$_SERVER) { $_SERVER = array(); } +// We update the $_SERVER variable to contain data consistent with the rest of the application. +$_SERVER = array_merge(array( + 'SERVER_PROTOCOL' => 'HTTP/1.1', + 'HTTP_ACCEPT' => 'text/plain;q=0.5', + 'HTTP_ACCEPT_LANGUAGE' => '*;q=0.5', + 'HTTP_ACCEPT_ENCODING' => '', + 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1;q=0.5', + 'SERVER_SIGNATURE' => 'Command-line PHP/' . phpversion(), + 'SERVER_SOFTWARE' => 'PHP/' . phpversion(), + 'SERVER_NAME' => 'localhost', + 'SERVER_ADDR' => '127.0.0.1', + 'REMOTE_ADDR' => '127.0.0.1', + 'REQUEST_METHOD' => 'GET', + 'HTTP_USER_AGENT' => 'CLI', +), $_SERVER); + $frameworkPath = dirname(dirname(__FILE__)); $frameworkDir = basename($frameworkPath); diff --git a/tests/php/Dev/DevAdminControllerTest.php b/tests/php/Dev/DevAdminControllerTest.php index e8de7540f..ab8210ff9 100644 --- a/tests/php/Dev/DevAdminControllerTest.php +++ b/tests/php/Dev/DevAdminControllerTest.php @@ -42,7 +42,7 @@ class DevAdminControllerTest extends FunctionalTest public function testGoodRegisteredControllerOutput() { // Check for the controller running from the registered url above - // (we use contains rather than equals because sometimes you get Warning: You probably want to define an entry in $_FILE_TO_URL_MAPPING) + // (we use contains rather than equals because sometimes you get a warning) $this->assertContains(Controller1::OK_MSG, $this->getCapture('/dev/x1')); $this->assertContains(Controller1::OK_MSG, $this->getCapture('/dev/x1/y1')); }