MINOR: Converted dos 2 unix

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/phpinstaller/branches/2.3@66887 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
sminnee 2008-11-28 01:09:45 +00:00 committed by Sam Minnee
parent 0934c8a724
commit 38daa8be70

View File

@ -1,1116 +1,1116 @@
<?php <?php
/** /**
* SilverStripe CMS Installer * SilverStripe CMS Installer
* This installer doesn't use any of the fancy Sapphire stuff in case it's unsupported. * This installer doesn't use any of the fancy Sapphire stuff in case it's unsupported.
*/ */
ini_set('max_execution_time', 0); ini_set('max_execution_time', 0);
error_reporting(E_ALL ^ E_NOTICE); error_reporting(E_ALL ^ E_NOTICE);
session_start(); session_start();
// Include environment files // Include environment files
$usingEnv = false; $usingEnv = false;
$envFiles = array('_ss_environment.php', '../_ss_environment.php', '../../_ss_environment.php'); $envFiles = array('_ss_environment.php', '../_ss_environment.php', '../../_ss_environment.php');
foreach($envFiles as $envFile) { foreach($envFiles as $envFile) {
if(@file_exists($envFile)) { if(@file_exists($envFile)) {
include_once($envFile); include_once($envFile);
$usingEnv = true; $usingEnv = true;
break; break;
} }
} }
// Load database config // Load database config
if(isset($_REQUEST['mysql'])) { if(isset($_REQUEST['mysql'])) {
$databaseConfig = $_REQUEST['mysql']; $databaseConfig = $_REQUEST['mysql'];
} else { } else {
$_REQUEST['mysql'] = $databaseConfig = array( $_REQUEST['mysql'] = $databaseConfig = array(
"type" => "MySQLDatabase", "type" => "MySQLDatabase",
"server" => defined('SS_DATABASE_SERVER') ? SS_DATABASE_SERVER : "localhost", "server" => defined('SS_DATABASE_SERVER') ? SS_DATABASE_SERVER : "localhost",
"username" => defined('SS_DATABASE_USERNAME') ? SS_DATABASE_USERNAME : "root", "username" => defined('SS_DATABASE_USERNAME') ? SS_DATABASE_USERNAME : "root",
"password" => defined('SS_DATABASE_PASSWORD') ? SS_DATABASE_PASSWORD : "", "password" => defined('SS_DATABASE_PASSWORD') ? SS_DATABASE_PASSWORD : "",
"database" => isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : "SS_mysite", "database" => isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : "SS_mysite",
); );
} }
if(isset($_REQUEST['admin'])) { if(isset($_REQUEST['admin'])) {
$adminConfig = $_REQUEST['admin']; $adminConfig = $_REQUEST['admin'];
} else { } else {
$_REQUEST['admin'] = $adminConfig = array( $_REQUEST['admin'] = $adminConfig = array(
'username' => 'admin', 'username' => 'admin',
'password' => 'password', 'password' => 'password',
'firstname' => '', 'firstname' => '',
'surname' => '' 'surname' => ''
); );
} }
$alreadyInstalled = false; $alreadyInstalled = false;
if(file_exists('mysite/_config.php')) { if(file_exists('mysite/_config.php')) {
// Find the $database variable in the relevant config file without having to execute the config file // 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)) { if(preg_match("/\\\$database\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("mysite/_config.php"), $parts)) {
eval($parts[0]); eval($parts[0]);
if($database) $alreadyInstalled = true; if($database) $alreadyInstalled = true;
// Assume that if $databaseConfig is defined in mysite/_config.php, then a non-environment-based installation has // Assume that if $databaseConfig is defined in mysite/_config.php, then a non-environment-based installation has
// already gone ahead // already gone ahead
} else if(preg_match("/\\\$databaseConfig\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("mysite/_config.php"), $parts)) { } else if(preg_match("/\\\$databaseConfig\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("mysite/_config.php"), $parts)) {
$alreadyInstalled = true; $alreadyInstalled = true;
} }
} }
if(file_exists('sapphire/silverstripe_version')) { if(file_exists('sapphire/silverstripe_version')) {
$sapphireVersionFile = file_get_contents('sapphire/silverstripe_version'); $sapphireVersionFile = file_get_contents('sapphire/silverstripe_version');
if(strstr($sapphireVersionFile, "/sapphire/trunk")) { if(strstr($sapphireVersionFile, "/sapphire/trunk")) {
$silverstripe_version = "trunk"; $silverstripe_version = "trunk";
} else { } else {
preg_match("/sapphire\/(?:(?:branches)|(?:tags))(?:\/rc)?\/([A-Za-z0-9._-]+)\/silverstripe_version/", $sapphireVersionFile, $matches); preg_match("/sapphire\/(?:(?:branches)|(?:tags))(?:\/rc)?\/([A-Za-z0-9._-]+)\/silverstripe_version/", $sapphireVersionFile, $matches);
$silverstripe_version = $matches[1]; $silverstripe_version = $matches[1];
} }
} else { } else {
$silverstripe_version = "unknown"; $silverstripe_version = "unknown";
} }
// Check requirements // Check requirements
$req = new InstallRequirements(); $req = new InstallRequirements();
$req->check(); $req->check();
if($req->hasErrors()) { if($req->hasErrors()) {
$hasErrorOtherThanDatabase = true; $hasErrorOtherThanDatabase = true;
} }
if($databaseConfig) { if($databaseConfig) {
$dbReq = new InstallRequirements(); $dbReq = new InstallRequirements();
$dbReq->checkdatabase($databaseConfig); $dbReq->checkdatabase($databaseConfig);
} }
// Actual processor // Actual processor
$installFromCli = (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == 'install'); $installFromCli = (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == 'install');
// CLI-install error message. exit(1) will halt any makefile. // CLI-install error message. exit(1) will halt any makefile.
if($installFromCli && ($req->hasErrors() || $dbReq->hasErrors())) { if($installFromCli && ($req->hasErrors() || $dbReq->hasErrors())) {
echo "Cannot install due to errors:\n"; echo "Cannot install due to errors:\n";
$req->listErrors(); $req->listErrors();
$dbReq->listErrors(); $dbReq->listErrors();
exit(1); exit(1);
} }
if(isset($_REQUEST['go']) || $installFromCli && !$req->hasErrors() && !$dbReq->hasErrors()) { if(isset($_REQUEST['go']) || $installFromCli && !$req->hasErrors() && !$dbReq->hasErrors()) {
// Confirm before reinstalling // Confirm before reinstalling
if(!isset($_REQUEST['force_reinstall']) && !$installFromCli && $alreadyInstalled) { if(!isset($_REQUEST['force_reinstall']) && !$installFromCli && $alreadyInstalled) {
include('config-form.html'); include('config-form.html');
} else { } else {
$inst = new Installer(); $inst = new Installer();
if($_REQUEST) $inst->install($_REQUEST); if($_REQUEST) $inst->install($_REQUEST);
else $inst->install(array( else $inst->install(array(
'database' => $databaseConfig['type'], 'database' => $databaseConfig['type'],
'mysql' => $databaseConfig, 'mysql' => $databaseConfig,
'admin' => $adminConfig, 'admin' => $adminConfig,
)); ));
} }
// Show the config form // Show the config form
} else { } else {
include('config-form.html'); include('config-form.html');
} }
/** /**
* This class checks requirements * This class checks requirements
* Each of the requireXXX functions takes an argument which gives a user description of the test. It's an array * Each of the requireXXX functions takes an argument which gives a user description of the test. It's an array
* of 3 parts: * of 3 parts:
* $description[0] - The test catetgory * $description[0] - The test catetgory
* $description[1] - The test title * $description[1] - The test title
* $description[2] - The test error to show, if it goes wrong * $description[2] - The test error to show, if it goes wrong
*/ */
class InstallRequirements { class InstallRequirements {
var $errors, $warnings, $tests; var $errors, $warnings, $tests;
/** /**
* Just check that the database configuration is okay * Just check that the database configuration is okay
*/ */
function checkdatabase($databaseConfig) { function checkdatabase($databaseConfig) {
if($this->requireFunction('mysql_connect', array("PHP Configuration", "MySQL support", "MySQL support not included in PHP."))) { 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", $this->requireMySQLServer($databaseConfig['server'], array("MySQL Configuration", "Does the server exist",
"Can't find the a MySQL server on '$databaseConfig[server]'", $databaseConfig['server'])); "Can't find the a MySQL server on '$databaseConfig[server]'", $databaseConfig['server']));
if($this->requireMysqlConnection($databaseConfig['server'], $databaseConfig['username'], $databaseConfig['password'], if($this->requireMysqlConnection($databaseConfig['server'], $databaseConfig['username'], $databaseConfig['password'],
array("MySQL Configuration", "Are the access credentials correct", "That username/password doesn't work"))) { 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->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'], $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")); 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 * Check everything except the database
*/ */
function check() { function check() {
$this->errors = null; $this->errors = null;
$this->requirePHPVersion('5.2.0', '5.0.4', array("PHP Configuration", "PHP5 installed", null, "PHP version " . phpversion())); $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 // Check that we can identify the root folder successfully
$this->requireFile('config-form.html', array("File permissions", $this->requireFile('config-form.html', array("File permissions",
"Does the webserver know where files are stored?", "Does the webserver know where files are stored?",
"The webserver isn't letting me identify where files are stored.", "The webserver isn't letting me identify where files are stored.",
$this->getBaseDir() $this->getBaseDir()
)); ));
$this->requireFile('mysite', array("File permissions", "mysite/ folder exists", "There's no mysite folder.")); $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('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('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->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('.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('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->requireWriteable('assets', array("File permissions", "Is the assets/ folder writeable?", null));
$this->requireTempFolder(array('File permissions', 'Is the temporary 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 // Check for web server, unless we're calling the installer from the command-line
if(!isset($_SERVER['argv']) || !$_SERVER['argv']) { if(!isset($_SERVER['argv']) || !$_SERVER['argv']) {
$webserver = strip_tags(trim($_SERVER['SERVER_SIGNATURE'])); $webserver = strip_tags(trim($_SERVER['SERVER_SIGNATURE']));
if($webserver == '') { if($webserver == '') {
$webserver = "I can't tell what webserver you are running"; $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)); $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')) { 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.")); $this->requireApacheModule('mod_rewrite', array("Webserver Configuration", "mod_rewrite enabled", "You need mod_rewrite to run SilverStripe CMS, but it is not enabled."));
} else { } 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->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.")); $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 // Check for GD support
if(!$this->requireFunction("imagecreatetruecolor", array("PHP Configuration", "GD2 support", "PHP must have GD version 2."))) { 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.")); $this->requireFunction("imagecreate", array("PHP Configuration", "GD2 support", "GD support for PHP not included."));
} }
// Check for XML support // Check for XML support
$this->requireFunction('xml_set_object', array("PHP Configuration", "XML support", "XML support not included in PHP.")); $this->requireFunction('xml_set_object', array("PHP Configuration", "XML support", "XML support not included in PHP."));
// Check for MySQL support // Check for MySQL support
$this->requireFunction('mysql_connect', array("PHP Configuration", "MySQL support", "MySQL support not included in PHP.")); $this->requireFunction('mysql_connect', array("PHP Configuration", "MySQL support", "MySQL support not included in PHP."));
// Check memory allocation // 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"))); $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 // Check that troublesome classes don't exist
$badClasses = array('Query', 'HTTPResponse'); $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")); $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 // 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", $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.")); "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; return $this->errors;
} }
function suggestPHPSetting($settingName, $settingValues, $testDetails) { function suggestPHPSetting($settingName, $settingValues, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$val = ini_get($settingName); $val = ini_get($settingName);
if(!in_array($val, $settingValues) && $val != $settingValues) { if(!in_array($val, $settingValues) && $val != $settingValues) {
$testDetails[2] = "$settingName is set to '$val' in php.ini. $testDetails[2]"; $testDetails[2] = "$settingName is set to '$val' in php.ini. $testDetails[2]";
$this->warning($testDetails); $this->warning($testDetails);
} }
} }
function requireMemory($min, $recommended, $testDetails) { function requireMemory($min, $recommended, $testDetails) {
$_SESSION['forcemem'] = false; $_SESSION['forcemem'] = false;
$mem = $this->getPHPMemory(); $mem = $this->getPHPMemory();
if($mem < (64 * 1024 * 1024)) { if($mem < (64 * 1024 * 1024)) {
ini_set('memory_limit', '64M'); ini_set('memory_limit', '64M');
$mem = $this->getPHPMemory(); $mem = $this->getPHPMemory();
$testDetails[3] = ini_get("memory_limit"); $testDetails[3] = ini_get("memory_limit");
} }
$this->testing($testDetails); $this->testing($testDetails);
if($mem < $min && $mem > 0) { if($mem < $min && $mem > 0) {
$testDetails[2] .= " You only have " . ini_get("memory_limit") . " allocated"; $testDetails[2] .= " You only have " . ini_get("memory_limit") . " allocated";
$this->error($testDetails); $this->error($testDetails);
} else if($mem < $recommended && $mem > 0) { } else if($mem < $recommended && $mem > 0) {
$testDetails[2] .= " You only have " . ini_get("memory_limit") . " allocated"; $testDetails[2] .= " You only have " . ini_get("memory_limit") . " allocated";
$this->warning($testDetails); $this->warning($testDetails);
} elseif($mem == 0) { } 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."; $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); $this->warning($testDetails);
} }
} }
function getPHPMemory() { function getPHPMemory() {
$memString = ini_get("memory_limit"); $memString = ini_get("memory_limit");
switch(strtolower(substr($memString,-1))) { switch(strtolower(substr($memString,-1))) {
case "k": case "k":
return round(substr($memString,0,-1)*1024); return round(substr($memString,0,-1)*1024);
case "m": case "m":
return round(substr($memString,0,-1)*1024*1024); return round(substr($memString,0,-1)*1024*1024);
case "g": case "g":
return round(substr($memString,0,-1)*1024*1024*1024); return round(substr($memString,0,-1)*1024*1024*1024);
default: default:
return round($memString); return round($memString);
} }
} }
function listErrors() { function listErrors() {
if($this->errors) { if($this->errors) {
echo "<p>The following problems are preventing me from installing SilverStripe CMS:</p>\n\n"; echo "<p>The following problems are preventing me from installing SilverStripe CMS:</p>\n\n";
foreach($this->errors as $error) { foreach($this->errors as $error) {
echo "<li>" . htmlentities(implode(", ", $error)) . "</li>\n"; echo "<li>" . htmlentities(implode(", ", $error)) . "</li>\n";
} }
} }
} }
function showTable($section = null) { function showTable($section = null) {
if($section) { if($section) {
$tests = $this->tests[$section]; $tests = $this->tests[$section];
echo "<table class=\"testResults\" width=\"100%\">"; echo "<table class=\"testResults\" width=\"100%\">";
foreach($tests as $test => $result) { foreach($tests as $test => $result) {
echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>"; echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
} }
echo "</table>"; echo "</table>";
} else { } else {
foreach($this->tests as $section => $tests) { foreach($this->tests as $section => $tests) {
echo "<h5>$section</h5>"; echo "<h5>$section</h5>";
echo "<table class=\"testResults\">"; echo "<table class=\"testResults\">";
foreach($tests as $test => $result) { foreach($tests as $test => $result) {
echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>"; echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
} }
echo "</table>"; echo "</table>";
} }
} }
} }
function showInstallStatus() { function showInstallStatus() {
if($this->warnings) { if($this->warnings) {
echo "I have installed SilverStripe CMS, however, you should note the following:"; echo "I have installed SilverStripe CMS, however, you should note the following:";
foreach($this->warnings as $warning) { foreach($this->warnings as $warning) {
echo "<li>" . htmlentities($warning) . "</li>"; echo "<li>" . htmlentities($warning) . "</li>";
} }
} else { } else {
if(isset($_SERVER['HTTP_HOST'])) { if(isset($_SERVER['HTTP_HOST'])) {
?> ?>
<p>I have installed SilverStripe CMS successfully!</p> <p>I have installed SilverStripe CMS successfully!</p>
<p><a href="./admin/" target="_blank">Open the CMS tool</a><br /> <p><a href="./admin/" target="_blank">Open the CMS tool</a><br />
<a href="./" target="_blank">Open the site</a></p> <a href="./" target="_blank">Open the site</a></p>
<?php <?php
} else { } else {
echo "\nSilverStripe successfully installed\n"; echo "\nSilverStripe successfully installed\n";
} }
} }
} }
function requireFunction($funcName, $testDetails) { function requireFunction($funcName, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
if(!function_exists($funcName)) $this->error($testDetails); if(!function_exists($funcName)) $this->error($testDetails);
else return true; else return true;
} }
/** /**
* Require that the given class doesn't exist * Require that the given class doesn't exist
*/ */
function requireNoClasses($classNames, $testDetails) { function requireNoClasses($classNames, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$badClasses = array(); $badClasses = array();
foreach($classNames as $className) { foreach($classNames as $className) {
if(class_exists($className)) $badClasses[] = $className; if(class_exists($className)) $badClasses[] = $className;
} }
if($badClasses) { if($badClasses) {
$testDetails[2] .= ". The following classes are at fault: " . implode(', ', $badClasses); $testDetails[2] .= ". The following classes are at fault: " . implode(', ', $badClasses);
$this->error($testDetails); $this->error($testDetails);
} }
else return true; else return true;
} }
function requirePHPVersion($recommendedVersion, $requiredVersion, $testDetails) { function requirePHPVersion($recommendedVersion, $requiredVersion, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
list($recA, $recB, $recC) = explode('.', $recommendedVersion); list($recA, $recB, $recC) = explode('.', $recommendedVersion);
list($reqA, $reqB, $reqC) = explode('.', $requiredVersion); list($reqA, $reqB, $reqC) = explode('.', $requiredVersion);
list($a, $b, $c) = explode('.', phpversion()); list($a, $b, $c) = explode('.', phpversion());
$c = ereg_replace('-.*$','',$c); $c = ereg_replace('-.*$','',$c);
if($a > $recA || ($a == $recA && $b > $recB) || ($a == $reqA && $b == $reqB && $c >= $reqC)) { 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."; $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); $this->warning($testDetails);
return; return;
} }
if($a > $reqA) return true; if($a > $reqA) return true;
if($a == $reqA && $b > $reqB) return true; if($a == $reqA && $b > $reqB) return true;
if($a == $reqA && $b == $reqB && $c >= $reqC) return true; if($a == $reqA && $b == $reqB && $c >= $reqC) return true;
if(!$testDetails[2]) { if(!$testDetails[2]) {
if($a < $reqA) { 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."; $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 { } 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."; $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); $this->error($testDetails);
} }
function requireFile($filename, $testDetails) { function requireFile($filename, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$filename = $this->getBaseDir() . $filename; $filename = $this->getBaseDir() . $filename;
if(!file_exists($filename)) { if(!file_exists($filename)) {
$testDetails[2] .= " (file '$filename' not found)"; $testDetails[2] .= " (file '$filename' not found)";
$this->error($testDetails); $this->error($testDetails);
} }
} }
function requireNoFile($filename, $testDetails) { function requireNoFile($filename, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$filename = $this->getBaseDir() . $filename; $filename = $this->getBaseDir() . $filename;
if(file_exists($filename)) { if(file_exists($filename)) {
$testDetails[2] .= " (file '$filename' found)"; $testDetails[2] .= " (file '$filename' found)";
$this->error($testDetails); $this->error($testDetails);
} }
} }
function moveFileOutOfTheWay($filename, $testDetails) { function moveFileOutOfTheWay($filename, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$filename = $this->getBaseDir() . $filename; $filename = $this->getBaseDir() . $filename;
if(file_exists($filename)) { if(file_exists($filename)) {
if(file_exists("$filename.bak")) rm("$filename.bak"); if(file_exists("$filename.bak")) rm("$filename.bak");
rename($filename, "$filename.bak"); rename($filename, "$filename.bak");
} }
} }
function requireWriteable($filename, $testDetails) { function requireWriteable($filename, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$filename = $this->getBaseDir() . str_replace("/", DIRECTORY_SEPARATOR,$filename); $filename = $this->getBaseDir() . str_replace("/", DIRECTORY_SEPARATOR,$filename);
if(!is_writeable($filename)) { if(!is_writeable($filename)) {
if(function_exists('posix_getgroups')) { if(function_exists('posix_getgroups')) {
$userID = posix_geteuid(); $userID = posix_geteuid();
$user = posix_getpwuid($userID); $user = posix_getpwuid($userID);
$currentOwnerID = fileowner($filename); $currentOwnerID = fileowner($filename);
$currentOwner = posix_getpwuid($currentOwnerID); $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]'. "; $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']) { if($user['name'] == $currentOwner['name']) {
$testDetails[2] .= "We recommend that you make the file writeable."; $testDetails[2] .= "We recommend that you make the file writeable.";
} else { } else {
$groups = posix_getgroups(); $groups = posix_getgroups();
foreach($groups as $group) { foreach($groups as $group) {
$groupInfo = posix_getgrgid($group); $groupInfo = posix_getgrgid($group);
if(in_array($currentOwner['name'], $groupInfo['members'])) $groupList[] = $groupInfo['name']; if(in_array($currentOwner['name'], $groupInfo['members'])) $groupList[] = $groupInfo['name'];
} }
if($groupList) { 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) $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"; . "\n\nFor example:\nchmod g+w $filename\nchgrp " . $groupList[0] . " $filename";
} else { } 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."; $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 { } else {
$testDetails[2] .= "The webserver user needs to be able to write to this file:\n$filename"; $testDetails[2] .= "The webserver user needs to be able to write to this file:\n$filename";
} }
$this->error($testDetails); $this->error($testDetails);
} }
} }
function requireTempFolder($testDetails) { function requireTempFolder($testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
if(function_exists('sys_get_temp_dir')) { if(function_exists('sys_get_temp_dir')) {
$sysTmp = sys_get_temp_dir(); $sysTmp = sys_get_temp_dir();
} elseif(isset($_ENV['TMP'])) { } elseif(isset($_ENV['TMP'])) {
$sysTmp = $_ENV['TMP']; $sysTmp = $_ENV['TMP'];
} else { } else {
@$tmpFile = tempnam('adfadsfdas',''); @$tmpFile = tempnam('adfadsfdas','');
@unlink($tmpFile); @unlink($tmpFile);
$sysTmp = dirname($tmpFile); $sysTmp = dirname($tmpFile);
} }
$worked = true; $worked = true;
$ssTmp = "$sysTmp/silverstripe-cache"; $ssTmp = "$sysTmp/silverstripe-cache";
if(!@file_exists($ssTmp)) { if(!@file_exists($ssTmp)) {
@$worked = mkdir($ssTmp); @$worked = mkdir($ssTmp);
if(!$worked) { if(!$worked) {
$ssTmp = dirname($_SERVER['SCRIPT_FILENAME']) . "/silverstripe-cache"; $ssTmp = dirname($_SERVER['SCRIPT_FILENAME']) . "/silverstripe-cache";
$worked = true; $worked = true;
if(!@file_exists($ssTmp)) { if(!@file_exists($ssTmp)) {
@$worked = mkdir($ssTmp); @$worked = mkdir($ssTmp);
} }
if(!$worked) { if(!$worked) {
$testDetails[2] = "Permission problem gaining access to a temp folder. " . $testDetails[2] = "Permission problem gaining access to a temp folder. " .
"Please create a folder named silverstripe-cache in the base folder " . "Please create a folder named silverstripe-cache in the base folder " .
"of the installation and ensure it has the adequate permissions"; "of the installation and ensure it has the adequate permissions";
$this->error($testDetails); $this->error($testDetails);
} }
} }
} }
} }
function requireApacheModule($moduleName, $testDetails) { function requireApacheModule($moduleName, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
if(!in_array($moduleName, apache_get_modules())) $this->error($testDetails); if(!in_array($moduleName, apache_get_modules())) $this->error($testDetails);
} }
function requireMysqlConnection($server, $username, $password, $testDetails) { function requireMysqlConnection($server, $username, $password, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$conn = @mysql_connect($server, $username, $password); $conn = @mysql_connect($server, $username, $password);
if($conn) { if($conn) {
return true; return true;
/* /*
if(mysql_query("CREATE DATABASE testing123")) { if(mysql_query("CREATE DATABASE testing123")) {
mysql_query("DROP DATABASE testing123"); mysql_query("DROP DATABASE testing123");
return true; return true;
} else { } else {
$testDetails[2] .= " (user '$username' doesn't have CREATE DATABASE permissions.)"; $testDetails[2] .= " (user '$username' doesn't have CREATE DATABASE permissions.)";
$this->error($testDetails); $this->error($testDetails);
} }
*/ */
} else { } else {
$testDetails[2] .= ": " . mysql_error(); $testDetails[2] .= ": " . mysql_error();
$this->error($testDetails); $this->error($testDetails);
} }
} }
function requireMySQLServer($server, $testDetails) { function requireMySQLServer($server, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$conn = @mysql_connect($server, null, null); $conn = @mysql_connect($server, null, null);
if($conn || mysql_errno() < 2000) { if($conn || mysql_errno() < 2000) {
return true; return true;
} else { } else {
$testDetails[2] .= ": " . mysql_error(); $testDetails[2] .= ": " . mysql_error();
$this->error($testDetails); $this->error($testDetails);
} }
} }
function requireMySQLVersion($version, $testDetails) { function requireMySQLVersion($version, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
if(!mysql_get_server_info()) { if(!mysql_get_server_info()) {
$testDetails[2] = 'Cannot determine the version of MySQL installed. Please ensure at least version 4.1 is installed.'; $testDetails[2] = 'Cannot determine the version of MySQL installed. Please ensure at least version 4.1 is installed.';
$this->warning($testDetails); $this->warning($testDetails);
} else { } else {
list($majorRequested, $minorRequested) = explode('.', $version); list($majorRequested, $minorRequested) = explode('.', $version);
$result = mysql_query('SELECT VERSION()'); $result = mysql_query('SELECT VERSION()');
$row=mysql_fetch_row($result); $row=mysql_fetch_row($result);
$version = ereg_replace("([A-Za-z-])", "", $row[0]); $version = ereg_replace("([A-Za-z-])", "", $row[0]);
list($majorHas, $minorHas) = explode('.', substr(trim($version), 0, 3)); list($majorHas, $minorHas) = explode('.', substr(trim($version), 0, 3));
if(($majorHas > $majorRequested) || ($majorHas == $majorRequested && $minorHas >= $minorRequested)) { if(($majorHas > $majorRequested) || ($majorHas == $majorRequested && $minorHas >= $minorRequested)) {
return true; return true;
} else { } else {
$testDetails[2] .= "{$majorHas}.{$minorHas}."; $testDetails[2] .= "{$majorHas}.{$minorHas}.";
$this->error($testDetails); $this->error($testDetails);
} }
} }
} }
function requireDatabaseOrCreatePermissions($server, $username, $password, $database, $testDetails) { function requireDatabaseOrCreatePermissions($server, $username, $password, $database, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$conn = @mysql_connect($server, $username, $password); $conn = @mysql_connect($server, $username, $password);
if(@mysql_select_db($database)) { if(@mysql_select_db($database)) {
$okay = "Database '$database' exists"; $okay = "Database '$database' exists";
} else { } else {
if(@mysql_query("CREATE DATABASE testing123")) { if(@mysql_query("CREATE DATABASE testing123")) {
mysql_query("DROP DATABASE testing123"); mysql_query("DROP DATABASE testing123");
$okay = "Able to create a new database"; $okay = "Able to create a new database";
} else { } else {
$testDetails[2] .= " (user '$username' doesn't have CREATE DATABASE permissions.)"; $testDetails[2] .= " (user '$username' doesn't have CREATE DATABASE permissions.)";
$this->error($testDetails); $this->error($testDetails);
return; return;
} }
} }
if($okay) { if($okay) {
$testDetails[3] = $okay; $testDetails[3] = $okay;
$this->testing($testDetails); $this->testing($testDetails);
} }
} }
function requireServerVariables($varNames, $errorMessage) { function requireServerVariables($varNames, $errorMessage) {
//$this->testing($testDetails); //$this->testing($testDetails);
foreach($varNames as $varName) { foreach($varNames as $varName) {
if(!$_SERVER[$varName]) $missing[] = '$_SERVER[' . $varName . ']'; if(!$_SERVER[$varName]) $missing[] = '$_SERVER[' . $varName . ']';
} }
if(!isset($missing)) { if(!isset($missing)) {
return true; return true;
} else { } else {
$testDetails[2] .= " (the following PHP variables are missing: " . implode(", ", $missing) . ")"; $testDetails[2] .= " (the following PHP variables are missing: " . implode(", ", $missing) . ")";
$this->error($testDetails); $this->error($testDetails);
} }
} }
function isRunningApache($testDetails) { function isRunningApache($testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
if(function_exists('apache_get_modules') || stristr($_SERVER['SERVER_SIGNATURE'], 'Apache')) if(function_exists('apache_get_modules') || stristr($_SERVER['SERVER_SIGNATURE'], 'Apache'))
return true; return true;
$this->warning($testDetails); $this->warning($testDetails);
return false; return false;
} }
protected $baseDir; protected $baseDir;
function getBaseDir() { function getBaseDir() {
// Cache the value so that when the installer mucks with SCRIPT_FILENAME half way through, this method // Cache the value so that when the installer mucks with SCRIPT_FILENAME half way through, this method
// still returns the correct value. // still returns the correct value.
if(!$this->baseDir) $this->baseDir = realpath(dirname($_SERVER['SCRIPT_FILENAME'])) . DIRECTORY_SEPARATOR; if(!$this->baseDir) $this->baseDir = realpath(dirname($_SERVER['SCRIPT_FILENAME'])) . DIRECTORY_SEPARATOR;
return $this->baseDir; return $this->baseDir;
} }
function testing($testDetails) { function testing($testDetails) {
if(!$testDetails) return; if(!$testDetails) return;
$section = $testDetails[0]; $section = $testDetails[0];
$test = $testDetails[1]; $test = $testDetails[1];
$message = "OK"; $message = "OK";
if(isset($testDetails[3])) $message .= " ($testDetails[3])"; if(isset($testDetails[3])) $message .= " ($testDetails[3])";
$this->tests[$section][$test] = array("good", $message); $this->tests[$section][$test] = array("good", $message);
} }
function error($testDetails) { function error($testDetails) {
$section = $testDetails[0]; $section = $testDetails[0];
$test = $testDetails[1]; $test = $testDetails[1];
$this->tests[$section][$test] = array("error", $testDetails[2]); $this->tests[$section][$test] = array("error", $testDetails[2]);
$this->errors[] = $testDetails; $this->errors[] = $testDetails;
} }
function warning($testDetails) { function warning($testDetails) {
$section = $testDetails[0]; $section = $testDetails[0];
$test = $testDetails[1]; $test = $testDetails[1];
$this->tests[$section][$test] = array("warning", $testDetails[2]); $this->tests[$section][$test] = array("warning", $testDetails[2]);
$this->warnings[] = $testDetails; $this->warnings[] = $testDetails;
} }
function hasErrors() { function hasErrors() {
return sizeof($this->errors); return sizeof($this->errors);
} }
function hasWarnings() { function hasWarnings() {
return sizeof($this->warnings); return sizeof($this->warnings);
} }
} }
class Installer extends InstallRequirements { class Installer extends InstallRequirements {
function __construct() { function __construct() {
// Cache the baseDir value // Cache the baseDir value
$this->getBaseDir(); $this->getBaseDir();
} }
function install($config) { function install($config) {
if(isset($_SERVER['HTTP_HOST'])) { if(isset($_SERVER['HTTP_HOST'])) {
?> ?>
<h1>Installing SilverStripe...</h1> <h1>Installing SilverStripe...</h1>
<p>I am now running through the installation steps (this should take about 30 seconds)</p> <p>I am now running through the installation steps (this should take about 30 seconds)</p>
<p>If you receive a fatal error, refresh this page to continue the installation <p>If you receive a fatal error, refresh this page to continue the installation
<?php <?php
} else { } else {
echo "SILVERSTRIPE COMMAND-LINE INSTALLATION\n\n"; echo "SILVERSTRIPE COMMAND-LINE INSTALLATION\n\n";
} }
flush(); flush();
if(isset($_POST['stats'])) { if(isset($_POST['stats'])) {
if(file_exists('sapphire/silverstripe_version')) { if(file_exists('sapphire/silverstripe_version')) {
$sapphireVersionFile = file_get_contents('sapphire/silverstripe_version'); $sapphireVersionFile = file_get_contents('sapphire/silverstripe_version');
if(strstr($sapphireVersionFile, "/sapphire/trunk")) { if(strstr($sapphireVersionFile, "/sapphire/trunk")) {
$silverstripe_version = "trunk"; $silverstripe_version = "trunk";
} else { } else {
preg_match("/sapphire\/(?:(?:branches)|(?:tags))(?:\/rc)?\/([A-Za-z0-9._-]+)\/silverstripe_version/", $sapphireVersionFile, $matches); preg_match("/sapphire\/(?:(?:branches)|(?:tags))(?:\/rc)?\/([A-Za-z0-9._-]+)\/silverstripe_version/", $sapphireVersionFile, $matches);
$silverstripe_version = $matches[1]; $silverstripe_version = $matches[1];
} }
} else { } else {
$silverstripe_version = "unknown"; $silverstripe_version = "unknown";
} }
$phpVersion = urlencode(phpversion()); $phpVersion = urlencode(phpversion());
$conn = @mysql_connect($config['mysql']['server'], null, null); $conn = @mysql_connect($config['mysql']['server'], null, null);
$databaseVersion = urlencode('MySQL ' . mysql_get_server_info()); $databaseVersion = urlencode('MySQL ' . mysql_get_server_info());
$webserver = urlencode($_SERVER['SERVER_SOFTWARE']); $webserver = urlencode($_SERVER['SERVER_SOFTWARE']);
$url = "http://ss2stat.silverstripe.com/Installation/add?SilverStripe=$silverstripe_version&PHP=$phpVersion&Database=$databaseVersion&WebServer=$webserver"; $url = "http://ss2stat.silverstripe.com/Installation/add?SilverStripe=$silverstripe_version&PHP=$phpVersion&Database=$databaseVersion&WebServer=$webserver";
if(isset($_SESSION['StatsID']) && $_SESSION['StatsID']) { if(isset($_SESSION['StatsID']) && $_SESSION['StatsID']) {
$url .= '&ID=' . $_SESSION['StatsID']; $url .= '&ID=' . $_SESSION['StatsID'];
} }
@$_SESSION['StatsID'] = file_get_contents($url); @$_SESSION['StatsID'] = file_get_contents($url);
} }
if(file_exists('mysite/_config.php')) { if(file_exists('mysite/_config.php')) {
unlink('mysite/_config.php'); unlink('mysite/_config.php');
} }
$theme = isset($_POST['template']) ? $_POST['template'] : 'blackcandy'; $theme = isset($_POST['template']) ? $_POST['template'] : 'blackcandy';
// Write the config file // Write the config file
global $usingEnv; global $usingEnv;
if($usingEnv) { if($usingEnv) {
$this->statusMessage("Creating 'mysite/_config.php' for use with _ss_environment.php..."); $this->statusMessage("Creating 'mysite/_config.php' for use with _ss_environment.php...");
$this->createFile("mysite/_config.php", <<<PHP $this->createFile("mysite/_config.php", <<<PHP
<?php <?php
global \$project; global \$project;
\$project = 'mysite'; \$project = 'mysite';
global \$database; global \$database;
\$database = "{$config['mysql']['database']}"; \$database = "{$config['mysql']['database']}";
require_once("conf/ConfigureFromEnv.php"); require_once("conf/ConfigureFromEnv.php");
// This line set's the current theme. More themes can be // This line set's the current theme. More themes can be
// downloaded from http://www.silverstripe.com/themes/ // downloaded from http://www.silverstripe.com/themes/
SSViewer::set_theme('$theme'); SSViewer::set_theme('$theme');
?> ?>
PHP PHP
); );
} else { } else {
$this->statusMessage("Creating 'mysite/_config.php'..."); $this->statusMessage("Creating 'mysite/_config.php'...");
$devServers = $this->var_export_array_nokeys(explode("\n", $_POST['devsites'])); $devServers = $this->var_export_array_nokeys(explode("\n", $_POST['devsites']));
$escapedPassword = addslashes($config['mysql']['password']); $escapedPassword = addslashes($config['mysql']['password']);
$this->createFile("mysite/_config.php", <<<PHP $this->createFile("mysite/_config.php", <<<PHP
<?php <?php
global \$project; global \$project;
\$project = 'mysite'; \$project = 'mysite';
global \$databaseConfig; global \$databaseConfig;
\$databaseConfig = array( \$databaseConfig = array(
"type" => "$config[database]", "type" => "$config[database]",
"server" => "{$config['mysql']['server']}", "server" => "{$config['mysql']['server']}",
"username" => "{$config['mysql']['username']}", "username" => "{$config['mysql']['username']}",
"password" => "{$escapedPassword}", "password" => "{$escapedPassword}",
"database" => "{$config['mysql']['database']}", "database" => "{$config['mysql']['database']}",
); );
// Sites running on the following servers will be // Sites running on the following servers will be
// run in development mode. See // run in development mode. See
// http://doc.silverstripe.com/doku.php?id=devmode // http://doc.silverstripe.com/doku.php?id=devmode
// for a description of what dev mode does. // for a description of what dev mode does.
Director::set_dev_servers($devServers); Director::set_dev_servers($devServers);
// This line set's the current theme. More themes can be // This line set's the current theme. More themes can be
// downloaded from http://www.silverstripe.com/themes/ // downloaded from http://www.silverstripe.com/themes/
SSViewer::set_theme('$theme'); SSViewer::set_theme('$theme');
?> ?>
PHP PHP
); );
} }
$this->statusMessage("Creating '.htaccess' file..."); $this->statusMessage("Creating '.htaccess' file...");
$this->createHtaccess(); $this->createHtaccess();
// Load the sapphire runtime // Load the sapphire runtime
$_SERVER['SCRIPT_FILENAME'] = dirname(realpath($_SERVER['SCRIPT_FILENAME'])) . '/sapphire/main.php'; $_SERVER['SCRIPT_FILENAME'] = dirname(realpath($_SERVER['SCRIPT_FILENAME'])) . '/sapphire/main.php';
chdir('sapphire'); chdir('sapphire');
$_GET['flush'] = true; $_GET['flush'] = true;
require_once('core/Core.php'); require_once('core/Core.php');
$this->statusMessage("Building database schema..."); $this->statusMessage("Building database schema...");
// Build database // Build database
$con = new Controller(); $con = new Controller();
$con->pushCurrent(); $con->pushCurrent();
global $databaseConfig; global $databaseConfig;
DB::connect($databaseConfig); DB::connect($databaseConfig);
$dbAdmin = new DatabaseAdmin(); $dbAdmin = new DatabaseAdmin();
$dbAdmin->init(); $dbAdmin->init();
$_REQUEST['username'] = $config['admin']['username']; $_REQUEST['username'] = $config['admin']['username'];
$_REQUEST['password'] = $config['admin']['password']; $_REQUEST['password'] = $config['admin']['password'];
$dbAdmin->doBuild(true); $dbAdmin->doBuild(true);
$adminmember = DataObject::get_one('Member',"`Email`= '".$_REQUEST['admin']['username']."'"); $adminmember = DataObject::get_one('Member',"`Email`= '".$_REQUEST['admin']['username']."'");
if($adminmember) { if($adminmember) {
$adminmember->FirstName = $_REQUEST['admin']['firstname']; $adminmember->FirstName = $_REQUEST['admin']['firstname'];
$adminmember->Surname = $_REQUEST['admin']['surname']; $adminmember->Surname = $_REQUEST['admin']['surname'];
$adminmember->write(); $adminmember->write();
} }
// Syncing filesystem (so /assets/Uploads is available instantly, see ticket #2266) // Syncing filesystem (so /assets/Uploads is available instantly, see ticket #2266)
FileSystem::sync(); FileSystem::sync();
if(isset($_SERVER['HTTP_HOST'])) { if(isset($_SERVER['HTTP_HOST'])) {
$this->statusMessage("Checking mod_rewrite works..."); $this->statusMessage("Checking mod_rewrite works...");
$modRewriteWorks = $this->checkModRewrite(); $modRewriteWorks = $this->checkModRewrite();
} else { } else {
$modRewriteWorks = true; $modRewriteWorks = true;
} }
$_SESSION['username'] = $config['admin']['username']; $_SESSION['username'] = $config['admin']['username'];
$_SESSION['password'] = $config['admin']['password']; $_SESSION['password'] = $config['admin']['password'];
if($modRewriteWorks && !$this->errors) { if($modRewriteWorks && !$this->errors) {
if(isset($_SERVER['HTTP_HOST'])) { if(isset($_SERVER['HTTP_HOST'])) {
echo "<p>Installed SilverStripe successfully. I will now try and direct you to echo "<p>Installed SilverStripe successfully. I will now try and direct you to
<a href=\"home/successfullyinstalled?flush=1\">home/successfullyinstalled</a> to confirm that the installation was successful.</p> <a href=\"home/successfullyinstalled?flush=1\">home/successfullyinstalled</a> to confirm that the installation was successful.</p>
<script>setTimeout(function() { window.location.href = 'home/successfullyinstalled?flush=1'; }, 1000);</script> <script>setTimeout(function() { window.location.href = 'home/successfullyinstalled?flush=1'; }, 1000);</script>
"; ";
} else { } else {
echo "\nSilverStripe successfully installed\n"; echo "\nSilverStripe successfully installed\n";
} }
} }
return $this->errors; return $this->errors;
} }
function makeFolder($folder) { function makeFolder($folder) {
$base = $this->getBaseDir(); $base = $this->getBaseDir();
if(!file_exists($base . $folder)) { if(!file_exists($base . $folder)) {
if(!mkdir($base . $folder, 02775)) { if(!mkdir($base . $folder, 02775)) {
$this->error("Couldn't create a folder called $base$folder"); $this->error("Couldn't create a folder called $base$folder");
} else { } else {
chmod($base . $folder, 02775); chmod($base . $folder, 02775);
} }
} }
} }
function renameFolder($oldName, $newName) { function renameFolder($oldName, $newName) {
if($oldName == $newName) return true; if($oldName == $newName) return true;
$base = $this->getBaseDir(); $base = $this->getBaseDir();
if(!rename($base . $oldName, $base . $newName)) { if(!rename($base . $oldName, $base . $newName)) {
$this->error("Couldn't rename $base$oldName to $base$newName"); $this->error("Couldn't rename $base$oldName to $base$newName");
return false; return false;
} else { } else {
return true; return true;
} }
} }
function copyFolder($oldName, $newName) { function copyFolder($oldName, $newName) {
if($oldName == $newName) return true; if($oldName == $newName) return true;
$base = $this->getBaseDir(); $base = $this->getBaseDir();
if(!copyr($base . $oldName, $base . $newName)) { if(!copyr($base . $oldName, $base . $newName)) {
$this->error("Couldn't rename $base$oldName to $base$newName"); $this->error("Couldn't rename $base$oldName to $base$newName");
return false; return false;
} else { } else {
return true; return true;
} }
} }
function createFile($filename, $content) { function createFile($filename, $content) {
$base = $this->getBaseDir(); $base = $this->getBaseDir();
$this->statusMessage("Creating $base$filename"); $this->statusMessage("Creating $base$filename");
if((@$fh = fopen($base . $filename, 'w')) && fwrite($fh, $content) && fclose($fh)) { if((@$fh = fopen($base . $filename, 'w')) && fwrite($fh, $content) && fclose($fh)) {
return true; return true;
} else { } else {
$this->error("Couldn't write to file $base$filename"); $this->error("Couldn't write to file $base$filename");
} }
} }
function createHtaccess() { function createHtaccess() {
$start = "### SILVERSTRIPE START ###\n"; $start = "### SILVERSTRIPE START ###\n";
$end = "\n### SILVERSTRIPE END ###"; $end = "\n### SILVERSTRIPE END ###";
$base = dirname($_SERVER['SCRIPT_NAME']); $base = dirname($_SERVER['SCRIPT_NAME']);
if(defined('DIRECTORY_SEPARATOR')) $base = str_replace(DIRECTORY_SEPARATOR, '/', $base); if(defined('DIRECTORY_SEPARATOR')) $base = str_replace(DIRECTORY_SEPARATOR, '/', $base);
else $base = str_replace("\\", '/', $base); else $base = str_replace("\\", '/', $base);
if($base != '.') $baseClause = "RewriteBase $base\n"; if($base != '.') $baseClause = "RewriteBase $base\n";
else $baseClause = ""; else $baseClause = "";
$rewrite = <<<TEXT $rewrite = <<<TEXT
<IfModule mod_dir.c> <IfModule mod_dir.c>
DirectorySlash Off DirectorySlash Off
</IfModule> </IfModule>
<Files *.ss> <Files *.ss>
Order deny,allow Order deny,allow
Deny from all Deny from all
Allow from 127.0.0.1 Allow from 127.0.0.1
</Files> </Files>
<IfModule mod_rewrite.c> <IfModule mod_rewrite.c>
RewriteEngine On RewriteEngine On
$baseClause $baseClause
RewriteCond %{REQUEST_URI} !(\.gif)|(\.jpg)|(\.png)|(\.css)|(\.js)|(\.php)$ RewriteCond %{REQUEST_URI} !(\.gif)|(\.jpg)|(\.png)|(\.css)|(\.js)|(\.php)$
RewriteCond %{REQUEST_URI} ^(.*)$ RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* sapphire/main.php?url=%1&%{QUERY_STRING} [L] RewriteRule .* sapphire/main.php?url=%1&%{QUERY_STRING} [L]
</IfModule> </IfModule>
TEXT TEXT
; ;
if(file_exists('.htaccess')) { if(file_exists('.htaccess')) {
$htaccess = file_get_contents('.htaccess'); $htaccess = file_get_contents('.htaccess');
if(strpos($htaccess, '### SILVERSTRIPE START ###') === false && strpos($htaccess, '### SILVERSTRIPE END ###') === false) { if(strpos($htaccess, '### SILVERSTRIPE START ###') === false && strpos($htaccess, '### SILVERSTRIPE END ###') === false) {
$htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n"; $htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n";
} }
if(strpos($htaccess, '### SILVERSTRIPE START ###') !== false && strpos($htaccess, '### SILVERSTRIPE END ###') !== false) { if(strpos($htaccess, '### SILVERSTRIPE START ###') !== false && strpos($htaccess, '### SILVERSTRIPE END ###') !== false) {
$start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###')) . "### SILVERSTRIPE START ###\n"; $start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###')) . "### SILVERSTRIPE START ###\n";
$end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###')); $end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###'));
} }
} }
$this->createFile('.htaccess', $start . $rewrite . $end); $this->createFile('.htaccess', $start . $rewrite . $end);
} }
function createHtaccessAlternative() { function createHtaccessAlternative() {
$start = "### SILVERSTRIPE START ###\n"; $start = "### SILVERSTRIPE START ###\n";
$end= "\n### SILVERSTRIPE END ###"; $end= "\n### SILVERSTRIPE END ###";
$base = dirname($_SERVER['SCRIPT_NAME']); $base = dirname($_SERVER['SCRIPT_NAME']);
if($base != '.') $baseClause = "RewriteBase $base\n"; if($base != '.') $baseClause = "RewriteBase $base\n";
$rewrite = <<<TEXT $rewrite = <<<TEXT
<IfModule mod_dir.c> <IfModule mod_dir.c>
DirectorySlash Off DirectorySlash Off
</IfModule> </IfModule>
<Files *.ss> <Files *.ss>
Order deny,allow Order deny,allow
Deny from all Deny from all
Allow from 127.0.0.1 Allow from 127.0.0.1
</Files> </Files>
<IfModule mod_rewrite.c> <IfModule mod_rewrite.c>
RewriteEngine On RewriteEngine On
$baseClause $baseClause
RewriteCond %{REQUEST_URI} !(\.gif)|(\.jpg)|(\.png)|(\.css)|(\.js)|(\.php)$ RewriteCond %{REQUEST_URI} !(\.gif)|(\.jpg)|(\.png)|(\.css)|(\.js)|(\.php)$
RewriteCond %{REQUEST_URI} ^(.*)$ RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* $_SERVER[DOCUMENT_ROOT]/sapphire/main.php?url=%1&%{QUERY_STRING} [L] RewriteRule .* $_SERVER[DOCUMENT_ROOT]/sapphire/main.php?url=%1&%{QUERY_STRING} [L]
</IfModule> </IfModule>
TEXT; TEXT;
if(file_exists($this->getBaseDir() . '.htaccess')) { if(file_exists($this->getBaseDir() . '.htaccess')) {
$htaccess = file_get_contents($this->getBaseDir() . '.htaccess'); $htaccess = file_get_contents($this->getBaseDir() . '.htaccess');
if(strpos($htaccess, '### SILVERSTRIPE START ###') === false && strpos($htaccess, '### SILVERSTRIPE END ###') === false) { if(strpos($htaccess, '### SILVERSTRIPE START ###') === false && strpos($htaccess, '### SILVERSTRIPE END ###') === false) {
$htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n"; $htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n";
} }
if(strpos($htaccess, '### SILVERSTRIPE START ###') !== false && strpos($htaccess, '### SILVERSTRIPE END ###') !== false) { if(strpos($htaccess, '### SILVERSTRIPE START ###') !== false && strpos($htaccess, '### SILVERSTRIPE END ###') !== false) {
$start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###')) . "### SILVERSTRIPE START ###\n"; $start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###')) . "### SILVERSTRIPE START ###\n";
$end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###')); $end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###'));
} }
} }
echo "\n\nRewrite is $rewrite\n"; echo "\n\nRewrite is $rewrite\n";
$this->createFile('.htaccess', $start . $rewrite . $end); $this->createFile('.htaccess', $start . $rewrite . $end);
} }
function restoreHtaccess() { function restoreHtaccess() {
$start = "### SILVERSTRIPE START ###\n"; $start = "### SILVERSTRIPE START ###\n";
$end= "\n### SILVERSTRIPE END ###"; $end= "\n### SILVERSTRIPE END ###";
if(file_exists('.htaccess')) { if(file_exists('.htaccess')) {
$htaccess = file_get_contents('.htaccess'); $htaccess = file_get_contents('.htaccess');
if(strpos($htaccess, '### SILVERSTRIPE START ###') === false && strpos($htaccess, '### SILVERSTRIPE END ###') === false) { if(strpos($htaccess, '### SILVERSTRIPE START ###') === false && strpos($htaccess, '### SILVERSTRIPE END ###') === false) {
$htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n"; $htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n";
} }
if(strpos($htaccess, '### SILVERSTRIPE START ###') !== false && strpos($htaccess, '### SILVERSTRIPE END ###') !== false) { if(strpos($htaccess, '### SILVERSTRIPE START ###') !== false && strpos($htaccess, '### SILVERSTRIPE END ###') !== false) {
$start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###')) . "### SILVERSTRIPE START ###\n"; $start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###')) . "### SILVERSTRIPE START ###\n";
$end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###')); $end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###'));
} }
} }
$this->createFile('.htaccess', $start . $end); $this->createFile('.htaccess', $start . $end);
} }
function checkModRewrite() { function checkModRewrite() {
if($this->performModRewriteTest() == true) { if($this->performModRewriteTest() == true) {
return true; return true;
} }
$this->createHtaccessAlternative(); $this->createHtaccessAlternative();
if($this->performModRewriteTest() == false) { if($this->performModRewriteTest() == false) {
echo "<li>ERROR: mod_rewrite not working, redirecting to mod_rewrite test page</li>"; echo "<li>ERROR: mod_rewrite not working, redirecting to mod_rewrite test page</li>";
$this->restoreHtaccess(); $this->restoreHtaccess();
echo "I will now try and direct you to <a href=\"rewritetest.php\">rewritetest</a> to troubleshoot mod_rewrite</p> echo "I will now try and direct you to <a href=\"rewritetest.php\">rewritetest</a> to troubleshoot mod_rewrite</p>
<script>setTimeout(function() { window.location.href = 'rewritetest.php'; }, 1000);</script> <script>setTimeout(function() { window.location.href = 'rewritetest.php'; }, 1000);</script>
"; ";
return false; return false;
} }
return true; return true;
} }
function performModRewriteTest() { function performModRewriteTest() {
if(!isset($_SERVER['HTTP_HOST']) || !$_SERVER['HTTP_HOST']) { if(!isset($_SERVER['HTTP_HOST']) || !$_SERVER['HTTP_HOST']) {
$this->statusMessage("Installer seems to be called from command-line, we're going to assume that rewriting is working."); $this->statusMessage("Installer seems to be called from command-line, we're going to assume that rewriting is working.");
return true; return true;
} }
$baseURL = dirname($_SERVER['SCRIPT_NAME']); $baseURL = dirname($_SERVER['SCRIPT_NAME']);
if($baseURL == "/") { if($baseURL == "/") {
$baseURL = ""; $baseURL = "";
} }
// Check if mod_rewrite works properly // Check if mod_rewrite works properly
$location = 'http://' . (isset($_SERVER['PHP_AUTH_USER']) ? "$_SERVER[PHP_AUTH_USER]:$_SERVER[PHP_AUTH_PW]@" : '') . $_SERVER['HTTP_HOST'] . $baseURL . '/InstallerTest/testrewrite'; $location = 'http://' . (isset($_SERVER['PHP_AUTH_USER']) ? "$_SERVER[PHP_AUTH_USER]:$_SERVER[PHP_AUTH_PW]@" : '') . $_SERVER['HTTP_HOST'] . $baseURL . '/InstallerTest/testrewrite';
echo $location; echo $location;
@$testrewriting = file_get_contents($location); @$testrewriting = file_get_contents($location);
if($testrewriting == 'OK') { if($testrewriting == 'OK') {
return true; return true;
} }
// Workaround for 'URL file-access is disabled in the server configuration' using curl // Workaround for 'URL file-access is disabled in the server configuration' using curl
if(function_exists('curl_init')) { if(function_exists('curl_init')) {
$ch = curl_init($location); $ch = curl_init($location);
$fp = @fopen(dirname(tempnam('adfadsfdas','')) . '/rewritetest', "w"); $fp = @fopen(dirname(tempnam('adfadsfdas','')) . '/rewritetest', "w");
if($fp) { if($fp) {
curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch); curl_exec($ch);
curl_close($ch); curl_close($ch);
fclose($fp); fclose($fp);
$testrewriting = file_get_contents(dirname(tempnam('adfadsfdas','')) . '/rewritetest'); $testrewriting = file_get_contents(dirname(tempnam('adfadsfdas','')) . '/rewritetest');
unlink(dirname(tempnam('adfadsfdas','')) . '/rewritetest'); unlink(dirname(tempnam('adfadsfdas','')) . '/rewritetest');
if($testrewriting == 'OK') { if($testrewriting == 'OK') {
return true; return true;
} }
} }
} }
return false; return false;
} }
function var_export_array_nokeys($array) { function var_export_array_nokeys($array) {
$retval = "array(\n"; $retval = "array(\n";
foreach($array as $item) { foreach($array as $item) {
$retval .= "\t'"; $retval .= "\t'";
$retval .= trim($item); $retval .= trim($item);
$retval .= "',\n"; $retval .= "',\n";
} }
$retval .= ")"; $retval .= ")";
return $retval; return $retval;
} }
/** /**
* Show an installation status message. * Show an installation status message.
* The output differs depending on whether this is CLI or web based * The output differs depending on whether this is CLI or web based
*/ */
function statusMessage($msg) { function statusMessage($msg) {
if(isset($_SERVER['HTTP_HOST'])) echo "<li>$msg</li>\n"; if(isset($_SERVER['HTTP_HOST'])) echo "<li>$msg</li>\n";
else echo "$msg\n"; else echo "$msg\n";
flush(); flush();
} }
} }
/** /**
* Copy a file, or recursively copy a folder and its contents * Copy a file, or recursively copy a folder and its contents
* *
* @author Aidan Lister <aidan@php.net> * @author Aidan Lister <aidan@php.net>
* @version 1.0.1 * @version 1.0.1
* @link http://aidanlister.com/repos/v/function.copyr.php * @link http://aidanlister.com/repos/v/function.copyr.php
* @param string $source Source path * @param string $source Source path
* @param string $dest Destination path * @param string $dest Destination path
* @return bool Returns TRUE on success, FALSE on failure * @return bool Returns TRUE on success, FALSE on failure
*/ */
function copyr($source, $dest) function copyr($source, $dest)
{ {
// Simple copy for a file // Simple copy for a file
if (is_file($source)) { if (is_file($source)) {
return copy($source, $dest); return copy($source, $dest);
} }
// Make destination directory // Make destination directory
if (!is_dir($dest)) { if (!is_dir($dest)) {
mkdir($dest); mkdir($dest);
} }
// Loop through the folder // Loop through the folder
$dir = dir($source); $dir = dir($source);
while (false !== $entry = $dir->read()) { while (false !== $entry = $dir->read()) {
// Skip pointers // Skip pointers
if ($entry == '.' || $entry == '..') { if ($entry == '.' || $entry == '..') {
continue; continue;
} }
// Deep copy directories // Deep copy directories
if ($dest !== "$source/$entry") { if ($dest !== "$source/$entry") {
copyr("$source/$entry", "$dest/$entry"); copyr("$source/$entry", "$dest/$entry");
} }
} }
// Clean up // Clean up
$dir->close(); $dir->close();
return true; return true;
} }
function rm($fileglob) function rm($fileglob)
{ {
if (is_string($fileglob)) { if (is_string($fileglob)) {
if (is_file($fileglob)) { if (is_file($fileglob)) {
return unlink($fileglob); return unlink($fileglob);
} else if (is_dir($fileglob)) { } else if (is_dir($fileglob)) {
$ok = rm("$fileglob/*"); $ok = rm("$fileglob/*");
if (! $ok) { if (! $ok) {
return false; return false;
} }
return rmdir($fileglob); return rmdir($fileglob);
} else { } else {
$matching = glob($fileglob); $matching = glob($fileglob);
if ($matching === false) { if ($matching === false) {
trigger_error(sprintf('No files match supplied glob %s', $fileglob), E_USER_WARNING); trigger_error(sprintf('No files match supplied glob %s', $fileglob), E_USER_WARNING);
return false; return false;
} }
$rcs = array_map('rm', $matching); $rcs = array_map('rm', $matching);
if (in_array(false, $rcs)) { if (in_array(false, $rcs)) {
return false; return false;
} }
} }
} else if (is_array($fileglob)) { } else if (is_array($fileglob)) {
$rcs = array_map('rm', $fileglob); $rcs = array_map('rm', $fileglob);
if (in_array(false, $rcs)) { if (in_array(false, $rcs)) {
return false; return false;
} }
} else { } else {
trigger_error('Param #1 must be filename or glob pattern, or array of filenames or glob patterns', E_USER_ERROR); trigger_error('Param #1 must be filename or glob pattern, or array of filenames or glob patterns', E_USER_ERROR);
return false; return false;
} }
return true; return true;
} }
?> ?>