'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 magic quotes setting */ if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) { if($_REQUEST) stripslashes_recursively($_REQUEST); if($_GET) stripslashes_recursively($_GET); if($_POST) stripslashes_recursively($_POST); } /** * Fix HTTP_HOST from reverse proxies */ if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { // Get the first host, in case there's multiple separated through commas $_SERVER['HTTP_HOST'] = strtok($_SERVER['HTTP_X_FORWARDED_HOST'], ','); } } /** * Define system paths */ if(!defined('BASE_PATH')) { // Assuming that this file is framework/core/Core.php we can then determine the base path $candidateBasePath = rtrim(dirname(dirname(dirname(__FILE__))), DIRECTORY_SEPARATOR); // We can't have an empty BASE_PATH. Making it / means that double-slashes occur in places but that's benign. // This likely only happens on chrooted environemnts if($candidateBasePath == '') $candidateBasePath = DIRECTORY_SEPARATOR; define('BASE_PATH', $candidateBasePath); } if(!defined('BASE_URL')) { // Determine the base URL by comparing SCRIPT_NAME to SCRIPT_FILENAME and getting common elements $path = realpath($_SERVER['SCRIPT_FILENAME']); if(substr($path, 0, strlen(BASE_PATH)) == BASE_PATH) { $urlSegmentToRemove = substr($path, strlen(BASE_PATH)); if(substr($_SERVER['SCRIPT_NAME'], -strlen($urlSegmentToRemove)) == $urlSegmentToRemove) { $baseURL = substr($_SERVER['SCRIPT_NAME'], 0, -strlen($urlSegmentToRemove)); define('BASE_URL', rtrim($baseURL, DIRECTORY_SEPARATOR)); } } // If that didn't work, failover to the old syntax. Hopefully this isn't necessary, and maybe // if can be phased out? if(!defined('BASE_URL')) { $dir = (strpos($_SERVER['SCRIPT_NAME'], 'index.php') !== false) ? dirname($_SERVER['SCRIPT_NAME']) : dirname(dirname($_SERVER['SCRIPT_NAME'])); define('BASE_URL', rtrim($dir, DIRECTORY_SEPARATOR)); } } define('MODULES_DIR', 'modules'); define('MODULES_PATH', BASE_PATH . '/' . MODULES_DIR); define('THEMES_DIR', 'themes'); define('THEMES_PATH', BASE_PATH . '/' . THEMES_DIR); // Relies on this being in a subdir of the framework. // If it isn't, or is symlinked to a folder with a different name, you must define FRAMEWORK_DIR if(!defined('FRAMEWORK_DIR')) { define('FRAMEWORK_DIR', basename(dirname(dirname(__FILE__)))); } define('FRAMEWORK_PATH', BASE_PATH . '/' . FRAMEWORK_DIR); define('FRAMEWORK_ADMIN_DIR', FRAMEWORK_DIR . '/admin'); define('FRAMEWORK_ADMIN_PATH', BASE_PATH . '/' . FRAMEWORK_ADMIN_DIR); // These are all deprecated. Use the FRAMEWORK_ versions instead. define('SAPPHIRE_DIR', FRAMEWORK_DIR); define('SAPPHIRE_PATH', FRAMEWORK_PATH); define('SAPPHIRE_ADMIN_DIR', FRAMEWORK_ADMIN_DIR); define('SAPPHIRE_ADMIN_PATH', FRAMEWORK_ADMIN_PATH); define('THIRDPARTY_DIR', FRAMEWORK_DIR . '/thirdparty'); define('THIRDPARTY_PATH', BASE_PATH . '/' . THIRDPARTY_DIR); define('ASSETS_DIR', 'assets'); define('ASSETS_PATH', BASE_PATH . '/' . ASSETS_DIR); /** * Define the temporary folder if it wasn't defined yet */ if(!defined('TEMP_FOLDER')) { define('TEMP_FOLDER', getTempFolder()); } /** * Priorities definition. These constants are used in calls to _t() as an optional argument */ define('PR_HIGH',100); define('PR_MEDIUM',50); define('PR_LOW',10); /** * Ensure we have enough memory */ increase_memory_limit_to('64M'); /** * Ensure we don't run into xdebug's fairly conservative infinite recursion protection limit */ increase_xdebug_nesting_level_to(200); /** * Set default encoding */ mb_http_output('UTF-8'); mb_internal_encoding('UTF-8'); mb_regex_encoding('UTF-8'); /////////////////////////////////////////////////////////////////////////////// // INCLUDES if(defined('CUSTOM_INCLUDE_PATH')) { $includePath = CUSTOM_INCLUDE_PATH . PATH_SEPARATOR . FRAMEWORK_PATH . PATH_SEPARATOR . FRAMEWORK_PATH . '/parsers' . PATH_SEPARATOR . THIRDPARTY_PATH . PATH_SEPARATOR . get_include_path(); } else { $includePath = FRAMEWORK_PATH . PATH_SEPARATOR . FRAMEWORK_PATH . '/parsers' . PATH_SEPARATOR . THIRDPARTY_PATH . PATH_SEPARATOR . get_include_path(); } set_include_path($includePath); // Include the files needed the initial manifest building, as well as any files // that are needed for the boostrap process on every request. require_once 'cache/Cache.php'; require_once 'core/Object.php'; require_once 'core/ClassInfo.php'; require_once 'view/TemplateGlobalProvider.php'; require_once 'control/Director.php'; require_once 'dev/Debug.php'; require_once 'dev/DebugView.php'; require_once 'dev/Backtrace.php'; require_once 'dev/ZendLog.php'; require_once 'dev/Log.php'; require_once 'filesystem/FileFinder.php'; require_once 'core/manifest/ClassLoader.php'; require_once 'core/manifest/ClassManifest.php'; require_once 'core/manifest/ManifestFileFinder.php'; require_once 'core/manifest/TemplateLoader.php'; require_once 'core/manifest/TemplateManifest.php'; require_once 'core/manifest/TokenisedRegularExpression.php'; /////////////////////////////////////////////////////////////////////////////// // MANIFEST // Regenerate the manifest if ?flush is set, or if the database is being built. // The coupling is a hack, but it removes an annoying bug where new classes // referenced in _config.php files can be referenced during the build process. $flush = (isset($_GET['flush']) || isset($_REQUEST['url']) && ( $_REQUEST['url'] == 'dev/build' || $_REQUEST['url'] == BASE_URL . '/dev/build' )); $manifest = new SS_ClassManifest(BASE_PATH, false, $flush); $loader = SS_ClassLoader::instance(); $loader->registerAutoloader(); $loader->pushManifest($manifest); // Now that the class manifest is up, load the configuration $configManifest = new SS_ConfigManifest(BASE_PATH, false, $flush); Config::inst()->pushConfigManifest($configManifest); SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest( BASE_PATH, false, isset($_GET['flush']) )); // If in live mode, ensure deprecation, strict and notices are not reported if(Director::isLive()) { error_reporting(E_ALL & ~(E_DEPRECATED | E_STRICT | E_NOTICE)); } /////////////////////////////////////////////////////////////////////////////// // POST-MANIFEST COMMANDS /** * Load error handlers */ Debug::loadErrorHandlers(); // initialise the dependency injector $default_options = array('locator' => 'SilverStripeServiceConfigurationLocator'); Injector::inst($default_options)->addAutoProperty('injector', Injector::inst()); /////////////////////////////////////////////////////////////////////////////// // HELPER FUNCTIONS function getSysTempDir() { Deprecation::notice(3.0, 'Please use PHP function get_sys_temp_dir() instead.'); return sys_get_temp_dir(); } /** * Returns the temporary folder that silverstripe should use for its cache files * This is loaded into the TEMP_FOLDER define on start up * * @param $base The base path to use as the basis for the temp folder name. Defaults to BASE_PATH, * which is usually fine; however, the $base argument can be used to help test. */ function getTempFolder($base = null) { if(!$base) $base = BASE_PATH; if($base) { $cachefolder = "silverstripe-cache" . str_replace(array(' ', "/", ":", "\\"), "-", $base); } else { $cachefolder = "silverstripe-cache"; } $ssTmp = BASE_PATH . "/silverstripe-cache"; if(@file_exists($ssTmp)) { return $ssTmp; } $sysTmp = sys_get_temp_dir(); $worked = true; $ssTmp = "$sysTmp/$cachefolder"; if(!@file_exists($ssTmp)) { @$worked = mkdir($ssTmp); } if(!$worked) { $ssTmp = BASE_PATH . "/silverstripe-cache"; $worked = true; if(!@file_exists($ssTmp)) { @$worked = mkdir($ssTmp); } } if(!$worked) { throw new Exception( 'Permission problem gaining access to a temp folder. ' . 'Please create a folder named silverstripe-cache in the base folder ' . 'of the installation and ensure it has the correct permissions' ); } return $ssTmp; } /** * @deprecated 3.0 Please use {@link SS_ClassManifest::getItemPath()}. */ function getClassFile($className) { Deprecation::notice('3.0', 'Use SS_ClassManifest::getItemPath() instead.'); return SS_ClassLoader::instance()->getManifest()->getItemPath($className); } /** * Creates a class instance by the "singleton" design pattern. * It will always return the same instance for this class, * which can be used for performance reasons and as a simple * way to access instance methods which don't rely on instance * data (e.g. the custom SilverStripe static handling). * * @uses Object::strong_create() * * @param string $className * @return Object */ function singleton($className) { global $_SINGLETONS; if(!isset($className)) user_error("singleton() Called without a class", E_USER_ERROR); if(!is_string($className)) user_error("singleton() passed bad class_name: " . var_export($className,true), E_USER_ERROR); if(!isset($_SINGLETONS[$className])) { if(!class_exists($className)) user_error("Bad class to singleton() - $className", E_USER_ERROR); $_SINGLETONS[$className] = Object::strong_create($className,null, true); if(!$_SINGLETONS[$className]) user_error("singleton() Unknown class '$className'", E_USER_ERROR); } return $_SINGLETONS[$className]; } function project() { global $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() */ function _t($entity, $string = "", $context = "", $injection = "") { return i18n::_t($entity, $string, $context, $injection); } /** * Increase the memory limit to the given level if it's currently too low. * Only increases up to the maximum defined in {@link set_increase_memory_limit_max()}, * and defaults to the 'memory_limit' setting in the PHP configuration. * * @param A memory limit string, such as "64M". If omitted, unlimited memory will be set. * @return Boolean TRUE indicates a successful change, FALSE a denied change. */ function increase_memory_limit_to($memoryLimit = -1) { $curLimit = ini_get('memory_limit'); // Can't go higher than infinite if($curLimit == -1 ) return true; // Check hard maximums $max = get_increase_memory_limit_max(); if($max != -1 && translate_memstring($memoryLimit) > translate_memstring($max)) return false; // Increase the memory limit if it's too low if($memoryLimit == -1 || translate_memstring($memoryLimit) > translate_memstring($curLimit)) { ini_set('memory_limit', $memoryLimit); } return true; } $_increase_memory_limit_max = ini_get('memory_limit'); /** * Set the maximum allowed value for {@link increase_memory_limit_to()}. * The same result can also be achieved through 'suhosin.memory_limit' * if PHP is running with the Suhosin system. * * @param Memory limit string */ function set_increase_memory_limit_max($memoryLimit) { global $_increase_memory_limit_max; $_increase_memory_limit_max = $memoryLimit; } /** * @return Memory limit string */ function get_increase_memory_limit_max() { global $_increase_memory_limit_max; return $_increase_memory_limit_max; } /** * Increases the XDebug parameter max_nesting_level, which limits how deep recursion can go. * Only does anything if (a) xdebug is installed and (b) the new limit is higher than the existing limit * * @param int $limit - The new limit to increase to */ function increase_xdebug_nesting_level_to($limit) { if (function_exists('xdebug_enable')) { $current = ini_get('xdebug.max_nesting_level'); if ((int)$current < $limit) ini_set('xdebug.max_nesting_level', $limit); } } /** * Turn a memory string, such as 512M into an actual number of bytes. * * @param A memory limit string, such as "64M" */ function translate_memstring($memString) { switch(strtolower(substr($memString, -1))) { case "k": return round(substr($memString, 0, -1)*1024); case "m": return round(substr($memString, 0, -1)*1024*1024); case "g": return round(substr($memString, 0, -1)*1024*1024*1024); default: return round($memString); } } /** * Increase the time limit of this script. By default, the time will be unlimited. * Only works if 'safe_mode' is off in the PHP configuration. * Only values up to {@link get_increase_time_limit_max()} are allowed. * * @param $timeLimit The time limit in seconds. If omitted, no time limit will be set. * @return Boolean TRUE indicates a successful change, FALSE a denied change. */ function increase_time_limit_to($timeLimit = null) { $max = get_increase_time_limit_max(); if($max != -1 && $timeLimit > $max) return false; if(!ini_get('safe_mode')) { if(!$timeLimit) { set_time_limit(0); return true; } else { $currTimeLimit = ini_get('max_execution_time'); // Only increase if its smaller if($currTimeLimit && $currTimeLimit < $timeLimit) { set_time_limit($timeLimit); } return true; } } else { return false; } } $_increase_time_limit_max = -1; /** * Set the maximum allowed value for {@link increase_timeLimit_to()}; * * @param Int Limit in seconds */ function set_increase_time_limit_max($timeLimit) { global $_increase_time_limit_max; $_increase_time_limit_max = $timeLimit; } /** * @return Int Limit in seconds */ function get_increase_time_limit_max() { global $_increase_time_limit_max; return $_increase_time_limit_max; }