"MySQLDatabase", "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 : "", "database" => isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : "SS_mysite", ); } if(isset($_REQUEST['admin'])) { $adminConfig = $_REQUEST['admin']; } else { $_REQUEST['admin'] = $adminConfig = array( 'username' => 'admin', 'password' => 'password', 'firstname' => '', 'surname' => '' ); } $alreadyInstalled = false; if(file_exists('mysite/_config.php')) { // Find the $database variable in the relevant config file without having to execute the config file if(preg_match("/\\\$database\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("mysite/_config.php"), $parts)) { eval($parts[0]); if($database) $alreadyInstalled = true; // Assume that if $databaseConfig is defined in mysite/_config.php, then a non-environment-based installation has // already gone ahead } else if(preg_match("/\\\$databaseConfig\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("mysite/_config.php"), $parts)) { $alreadyInstalled = true; } } if(file_exists('sapphire/silverstripe_version')) { $sapphireVersionFile = file_get_contents('sapphire/silverstripe_version'); if(strstr($sapphireVersionFile, "/sapphire/trunk")) { $silverstripe_version = "trunk"; } else { preg_match("/sapphire\/(?:(?:branches)|(?:tags))(?:\/rc)?\/([A-Za-z0-9._-]+)\/silverstripe_version/", $sapphireVersionFile, $matches); $silverstripe_version = $matches[1]; } } else { $silverstripe_version = "unknown"; } // Check requirements $req = new InstallRequirements(); $req->check(); if($req->hasErrors()) { $hasErrorOtherThanDatabase = true; } if($databaseConfig) { $dbReq = new InstallRequirements(); $dbReq->checkdatabase($databaseConfig); } // Actual processor $installFromCli = (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == 'install'); // CLI-install error message. exit(1) will halt any makefile. if($installFromCli && ($req->hasErrors() || $dbReq->hasErrors())) { echo "Cannot install due to errors:\n"; $req->listErrors(); $dbReq->listErrors(); exit(1); } if(isset($_REQUEST['go']) || $installFromCli && !$req->hasErrors() && !$dbReq->hasErrors()) { // Confirm before reinstalling if(!isset($_REQUEST['force_reinstall']) && !$installFromCli && $alreadyInstalled) { include('sapphire/dev/install/config-form.html'); } else { $inst = new Installer(); if($_REQUEST) $inst->install($_REQUEST); else $inst->install(array( 'database' => $databaseConfig['type'], 'mysql' => $databaseConfig, 'admin' => $adminConfig, )); } // Show the config form } else { include('sapphire/dev/install/config-form.html'); } /** * This class checks requirements * Each of the requireXXX functions takes an argument which gives a user description of the test. It's an array * of 3 parts: * $description[0] - The test catetgory * $description[1] - The test title * $description[2] - The test error to show, if it goes wrong */ class InstallRequirements { var $errors, $warnings, $tests; /** * Just check that the database configuration is okay */ function checkdatabase($databaseConfig) { if($this->requireFunction('mysql_connect', array("PHP Configuration", "MySQL support", "MySQL support not included in PHP."))) { $this->requireMySQLServer($databaseConfig['server'], array("MySQL Configuration", "Does the server exist", "Can't find the a MySQL server on '$databaseConfig[server]'", $databaseConfig['server'])); if($this->requireMysqlConnection($databaseConfig['server'], $databaseConfig['username'], $databaseConfig['password'], array("MySQL Configuration", "Are the access credentials correct", "That username/password doesn't work"))) { @$this->requireMySQLVersion("4.1", array("MySQL Configuration", "MySQL version at least 4.1", "MySQL version 4.1 is required, you only have ", "MySQL " . mysql_get_server_info())); } $this->requireDatabaseOrCreatePermissions($databaseConfig['server'], $databaseConfig['username'], $databaseConfig['password'], $databaseConfig['database'], array("MySQL Configuration", "Can I access/create the database", "I can't create new databases and the database '$databaseConfig[database]' doesn't exist")); } } /** * Check everything except the database */ function check() { $this->errors = null; $this->requirePHPVersion('5.2.0', '5.0.4', array("PHP Configuration", "PHP5 installed", null, "PHP version " . phpversion())); // Check that we can identify the root folder successfully $this->requireFile('sapphire/dev/install/config-form.html', array("File permissions", "Does the webserver know where files are stored?", "The webserver isn't letting me identify where files are stored.", $this->getBaseDir() )); $this->requireFile('mysite', array("File permissions", "mysite/ folder exists", "There's no mysite folder.")); $this->requireFile('sapphire', array("File permissions", "sapphire/ folder exists", "There's no sapphire folder.")); $this->requireFile('cms', array("File permissions", "cms/ folder exists", "There's no cms folder.")); $this->requireFile('jsparty', array("File permissions", "jsparty/ folder exists", "There's no jsparty folder.")); $this->requireWriteable('.htaccess', array("File permissions", "Is the .htaccess file writeable?", null)); $this->requireWriteable('mysite/_config.php', array("File permissions", "Is the mysite/_config.php file writeable?", null)); $this->requireWriteable('assets', array("File permissions", "Is the assets/ folder writeable?", null)); $this->requireTempFolder(array('File permissions', 'Is the temporary folder writeable?', null)); // Check for web server, unless we're calling the installer from the command-line if(!isset($_SERVER['argv']) || !$_SERVER['argv']) { $webserver = strip_tags(trim($_SERVER['SERVER_SIGNATURE'])); if($webserver == '') { $webserver = "I can't tell what webserver you are running"; } $this->isRunningApache(array("Webserver Configuration", "Server software", "$webserver. Without Apache I can't tell if mod_rewrite is enabled.", $webserver)); if(function_exists('apache_get_modules')) { $this->requireApacheModule('mod_rewrite', array("Webserver Configuration", "mod_rewrite enabled", "You need mod_rewrite to run SilverStripe CMS, but it is not enabled.")); } else { $this->warning(array("Webserver Configuration", "mod_rewrite enabled", "I can't tell whether mod_rewrite is running. You may need to configure a rewriting rule yourself.")); } $this->requireServerVariables(array('SCRIPT_NAME','HTTP_HOST','SCRIPT_FILENAME'), array("Webserver config", "Recognised webserver", "You seem to be using an unsupported webserver. The server variables SCRIPT_NAME, HTTP_HOST, SCRIPT_FILENAME need to be set.")); } // Check for GD support if(!$this->requireFunction("imagecreatetruecolor", array("PHP Configuration", "GD2 support", "PHP must have GD version 2."))) { $this->requireFunction("imagecreate", array("PHP Configuration", "GD2 support", "GD support for PHP not included.")); } // Check for XML support $this->requireFunction('xml_set_object', array("PHP Configuration", "XML support", "XML support not included in PHP.")); // Check for MySQL support $this->requireFunction('mysql_connect', array("PHP Configuration", "MySQL support", "MySQL support not included in PHP.")); // Check memory allocation $this->requireMemory(32*1024*1024, 64*1024*1024, array("PHP Configuration", "Memory allocated (PHP config option 'memory_limit')", "SilverStripe needs a minimum of 32M allocated to PHP, but recommends 64M.", ini_get("memory_limit"))); // Check that troublesome classes don't exist $badClasses = array('Query', 'HTTPResponse'); $this->requireNoClasses($badClasses, array("PHP Configuration", "Check that certain classes haven't been defined by PHP plugins", "Your version of PHP has defined some classes that conflict with SilverStripe's")); // Check allow_call_time_pass_reference $this->suggestPHPSetting('allow_call_time_pass_reference', array(1,'1','on','On'), array("PHP Configuration", "Check that the php.ini setting allow_call_time_pass_reference is on", "You can install with allow_call_time_pass_reference not set, but some warnings may get displayed. For best results, turn it on.")); return $this->errors; } function suggestPHPSetting($settingName, $settingValues, $testDetails) { $this->testing($testDetails); $val = ini_get($settingName); if(!in_array($val, $settingValues) && $val != $settingValues) { $testDetails[2] = "$settingName is set to '$val' in php.ini. $testDetails[2]"; $this->warning($testDetails); } } function requireMemory($min, $recommended, $testDetails) { $_SESSION['forcemem'] = false; $mem = $this->getPHPMemory(); if($mem < (64 * 1024 * 1024)) { ini_set('memory_limit', '64M'); $mem = $this->getPHPMemory(); $testDetails[3] = ini_get("memory_limit"); } $this->testing($testDetails); if($mem < $min && $mem > 0) { $testDetails[2] .= " You only have " . ini_get("memory_limit") . " allocated"; $this->error($testDetails); } else if($mem < $recommended && $mem > 0) { $testDetails[2] .= " You only have " . ini_get("memory_limit") . " allocated"; $this->warning($testDetails); } elseif($mem == 0) { $testDetails[2] .= " We can't determine how much memory you have allocated. Install only if you're sure you've allocated at least 20 MB."; $this->warning($testDetails); } } function getPHPMemory() { $memString = ini_get("memory_limit"); 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); } } function listErrors() { if($this->errors) { echo "

The following problems are preventing me from installing SilverStripe CMS:

\n\n"; foreach($this->errors as $error) { echo "
  • " . htmlentities(implode(", ", $error)) . "
  • \n"; } } } function showTable($section = null) { if($section) { $tests = $this->tests[$section]; echo ""; foreach($tests as $test => $result) { echo ""; } echo "
    $test" . nl2br(htmlentities($result[1])) . "
    "; } else { foreach($this->tests as $section => $tests) { echo "
    $section
    "; echo ""; foreach($tests as $test => $result) { echo ""; } echo "
    $test" . nl2br(htmlentities($result[1])) . "
    "; } } } function showInstallStatus() { if($this->warnings) { echo "I have installed SilverStripe CMS, however, you should note the following:"; foreach($this->warnings as $warning) { echo "
  • " . htmlentities($warning) . "
  • "; } } else { if(isset($_SERVER['HTTP_HOST'])) { ?>

    I have installed SilverStripe CMS successfully!

    Open the CMS tool
    Open the site

    testing($testDetails); if(!function_exists($funcName)) $this->error($testDetails); else return true; } /** * Require that the given class doesn't exist */ function requireNoClasses($classNames, $testDetails) { $this->testing($testDetails); $badClasses = array(); foreach($classNames as $className) { if(class_exists($className)) $badClasses[] = $className; } if($badClasses) { $testDetails[2] .= ". The following classes are at fault: " . implode(', ', $badClasses); $this->error($testDetails); } else return true; } function requirePHPVersion($recommendedVersion, $requiredVersion, $testDetails) { $this->testing($testDetails); list($recA, $recB, $recC) = explode('.', $recommendedVersion); list($reqA, $reqB, $reqC) = explode('.', $requiredVersion); list($a, $b, $c) = explode('.', phpversion()); $c = ereg_replace('-.*$','',$c); if($a > $recA || ($a == $recA && $b > $recB) || ($a == $reqA && $b == $reqB && $c >= $reqC)) { $testDetails[2] = "SilverStripe recommends PHP version $recommendedVersion or later, only $a.$b.$c is installed. While SilverStripe should run, you may run into issues, and future versions of SilverStripe may require a later version. Upgrading PHP is recommended."; $this->warning($testDetails); return; } if($a > $reqA) return true; if($a == $reqA && $b > $reqB) return true; if($a == $reqA && $b == $reqB && $c >= $reqC) return true; if(!$testDetails[2]) { if($a < $reqA) { $testDetails[2] = "You need PHP version $version or later, only $a.$b.$c is installed. Unfortunately PHP$a and PHP$reqA have some incompatabilities, so if you are on a your web-host may need to move you to a different server. Some software doesn't work with PHP5 and so upgrading a shared server could be problematic."; } else { $testDetails[2] = "You need PHP version $requiredVersion or later, only $a.$b.$c is installed. Please upgrade your server, or ask your web-host to do so."; } } $this->error($testDetails); } function requireFile($filename, $testDetails) { $this->testing($testDetails); $filename = $this->getBaseDir() . $filename; if(!file_exists($filename)) { $testDetails[2] .= " (file '$filename' not found)"; $this->error($testDetails); } } function requireNoFile($filename, $testDetails) { $this->testing($testDetails); $filename = $this->getBaseDir() . $filename; if(file_exists($filename)) { $testDetails[2] .= " (file '$filename' found)"; $this->error($testDetails); } } function moveFileOutOfTheWay($filename, $testDetails) { $this->testing($testDetails); $filename = $this->getBaseDir() . $filename; if(file_exists($filename)) { if(file_exists("$filename.bak")) rm("$filename.bak"); rename($filename, "$filename.bak"); } } function requireWriteable($filename, $testDetails) { $this->testing($testDetails); $filename = $this->getBaseDir() . str_replace("/", DIRECTORY_SEPARATOR,$filename); if(!is_writeable($filename)) { if(function_exists('posix_getgroups')) { $userID = posix_geteuid(); $user = posix_getpwuid($userID); $currentOwnerID = fileowner($filename); $currentOwner = posix_getpwuid($currentOwnerID); $testDetails[2] .= "User '$user[name]' needs to be able to write to this file:\n$filename\n\nThe file is currently owned by '$currentOwner[name]'. "; if($user['name'] == $currentOwner['name']) { $testDetails[2] .= "We recommend that you make the file writeable."; } else { $groups = posix_getgroups(); foreach($groups as $group) { $groupInfo = posix_getgrgid($group); if(in_array($currentOwner['name'], $groupInfo['members'])) $groupList[] = $groupInfo['name']; } if($groupList) { $testDetails[2] .= " We recommend that you make the file group-writeable and change the group to one of these groups:\n - ". implode("\n - ", $groupList) . "\n\nFor example:\nchmod g+w $filename\nchgrp " . $groupList[0] . " $filename"; } else { $testDetails[2] .= " There is no user-group that contains both the web-server user and the owner of this file. Change the ownership of the file, create a new group, or temporarily make the file writeable by everyone during the install process."; } } } else { $testDetails[2] .= "The webserver user needs to be able to write to this file:\n$filename"; } $this->error($testDetails); } } function requireTempFolder($testDetails) { $this->testing($testDetails); if(function_exists('sys_get_temp_dir')) { $sysTmp = sys_get_temp_dir(); } elseif(isset($_ENV['TMP'])) { $sysTmp = $_ENV['TMP']; } else { @$tmpFile = tempnam('adfadsfdas',''); @unlink($tmpFile); $sysTmp = dirname($tmpFile); } $worked = true; $ssTmp = "$sysTmp/silverstripe-cache"; if(!@file_exists($ssTmp)) { @$worked = mkdir($ssTmp); if(!$worked) { $ssTmp = dirname($_SERVER['SCRIPT_FILENAME']) . "/silverstripe-cache"; $worked = true; if(!@file_exists($ssTmp)) { @$worked = mkdir($ssTmp); } if(!$worked) { $testDetails[2] = "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 adequate permissions"; $this->error($testDetails); } } } } function requireApacheModule($moduleName, $testDetails) { $this->testing($testDetails); if(!in_array($moduleName, apache_get_modules())) $this->error($testDetails); } function requireMysqlConnection($server, $username, $password, $testDetails) { $this->testing($testDetails); $conn = @mysql_connect($server, $username, $password); if($conn) { return true; /* if(mysql_query("CREATE DATABASE testing123")) { mysql_query("DROP DATABASE testing123"); return true; } else { $testDetails[2] .= " (user '$username' doesn't have CREATE DATABASE permissions.)"; $this->error($testDetails); } */ } else { $testDetails[2] .= ": " . mysql_error(); $this->error($testDetails); } } function requireMySQLServer($server, $testDetails) { $this->testing($testDetails); $conn = @mysql_connect($server, null, null); if($conn || mysql_errno() < 2000) { return true; } else { $testDetails[2] .= ": " . mysql_error(); $this->error($testDetails); } } function requireMySQLVersion($version, $testDetails) { $this->testing($testDetails); if(!mysql_get_server_info()) { $testDetails[2] = 'Cannot determine the version of MySQL installed. Please ensure at least version 4.1 is installed.'; $this->warning($testDetails); } else { list($majorRequested, $minorRequested) = explode('.', $version); $result = mysql_query('SELECT VERSION()'); $row=mysql_fetch_row($result); $version = ereg_replace("([A-Za-z-])", "", $row[0]); list($majorHas, $minorHas) = explode('.', substr(trim($version), 0, 3)); if(($majorHas > $majorRequested) || ($majorHas == $majorRequested && $minorHas >= $minorRequested)) { return true; } else { $testDetails[2] .= "{$majorHas}.{$minorHas}."; $this->error($testDetails); } } } function requireDatabaseOrCreatePermissions($server, $username, $password, $database, $testDetails) { $this->testing($testDetails); $conn = @mysql_connect($server, $username, $password); if(@mysql_select_db($database)) { $okay = "Database '$database' exists"; } else { if(@mysql_query("CREATE DATABASE testing123")) { mysql_query("DROP DATABASE testing123"); $okay = "Able to create a new database"; } else { $testDetails[2] .= " (user '$username' doesn't have CREATE DATABASE permissions.)"; $this->error($testDetails); return; } } if($okay) { $testDetails[3] = $okay; $this->testing($testDetails); } } function requireServerVariables($varNames, $errorMessage) { //$this->testing($testDetails); foreach($varNames as $varName) { if(!$_SERVER[$varName]) $missing[] = '$_SERVER[' . $varName . ']'; } if(!isset($missing)) { return true; } else { $testDetails[2] .= " (the following PHP variables are missing: " . implode(", ", $missing) . ")"; $this->error($testDetails); } } function isRunningApache($testDetails) { $this->testing($testDetails); if(function_exists('apache_get_modules') || stristr($_SERVER['SERVER_SIGNATURE'], 'Apache')) return true; $this->warning($testDetails); return false; } // Must be PHP4 compatible var $baseDir; function getBaseDir() { // Cache the value so that when the installer mucks with SCRIPT_FILENAME half way through, this method // still returns the correct value. if(!$this->baseDir) $this->baseDir = realpath(dirname($_SERVER['SCRIPT_FILENAME'])) . DIRECTORY_SEPARATOR; return $this->baseDir; } function testing($testDetails) { if(!$testDetails) return; $section = $testDetails[0]; $test = $testDetails[1]; $message = "OK"; if(isset($testDetails[3])) $message .= " ($testDetails[3])"; $this->tests[$section][$test] = array("good", $message); } function error($testDetails) { $section = $testDetails[0]; $test = $testDetails[1]; $this->tests[$section][$test] = array("error", $testDetails[2]); $this->errors[] = $testDetails; } function warning($testDetails) { $section = $testDetails[0]; $test = $testDetails[1]; $this->tests[$section][$test] = array("warning", $testDetails[2]); $this->warnings[] = $testDetails; } function hasErrors() { return sizeof($this->errors); } function hasWarnings() { return sizeof($this->warnings); } } class Installer extends InstallRequirements { function __construct() { // Cache the baseDir value $this->getBaseDir(); } function install($config) { if(isset($_SERVER['HTTP_HOST'])) { ?> PHP 5 is required

    Installing SilverStripe...

    I am now running through the installation steps (this should take about 30 seconds)

    If you receive a fatal error, refresh this page to continue the installation