";
}
}
}
function showInstallStatus() {
if($this->warnings) {
echo "I have installed SilverStripe CMS, however, you should note the following:";
foreach($this->warnings as $warning) {
echo "
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);
$installedVersion = phpversion();
if(version_compare($installedVersion, $requiredVersion, '<')) {
$testDetails[2] = "SilverStripe requires PHP version $requiredVersion or later.\n
PHP version $installedVersion is currently installed.\n
While SilverStripe requires at least PHP version $requiredVersion, upgrading to $recommendedVersion or later is recommended.\n
If you are installing SilverStripe on a shared web server, please ask your web hosting provider to upgrade PHP for you.";
$this->error($testDetails);
return;
}
if(version_compare($installedVersion, $recommendedVersion, '<')) {
$testDetails[2] = "PHP version $installedVersion is currently installed.\n
Upgrading to at least PHP version $recommendedVersion is recommended.\n
SilverStripe should run, but you may run into issues. Future releases may require a later version of PHP.\n";
$this->warning($testDetails);
return;
}
return true;
}
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 requireIISRewriteModule($moduleName, $testDetails) {
$this->testing($testDetails);
if(isset($_SERVER[$moduleName]) && $_SERVER[$moduleName]) {
return true;
} else {
$this->error($testDetails);
return false;
}
}
/**
* Get an instance of a helper class for the specific database.
* @param string $databaseClass e.g. MySQLDatabase or MSSQLDatabase
*/
function getDatabaseConfigurationHelper($databaseClass) {
$class = $databaseClass . 'ConfigurationHelper';
return new $class();
}
function requireDatabaseFunctions($databaseConfig, $testDetails) {
$this->testing($testDetails);
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
$result = $helper->requireDatabaseFunctions($databaseConfig);
if($result) {
return true;
} else {
$this->error($testDetails);
return false;
}
}
function requireDatabaseConnection($databaseConfig, $testDetails) {
$this->testing($testDetails);
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
$result = $helper->requireDatabaseConnection($databaseConfig);
if($result['success']) {
return true;
} else {
$testDetails[2] .= ": " . $result['error'];
$this->error($testDetails);
return false;
}
}
function requireDatabaseServer($databaseConfig, $testDetails) {
$this->testing($testDetails);
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
$result = $helper->requireDatabaseServer($databaseConfig);
if($result['success']) {
return true;
} else {
$testDetails[2] .= ": " . $result['error'];
$this->error($testDetails);
return false;
}
}
function requireDatabaseOrCreatePermissions($databaseConfig, $testDetails) {
$this->testing($testDetails);
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
$result = $helper->requireDatabaseOrCreatePermissions($databaseConfig);
if($result['success']) {
if($result['alreadyExists']) $testDetails[3] = "Database $databaseConfig[database] exists";
else $testDetails[3] = "Able to create a new database";
$this->testing($testDetails);
return true;
} else {
$testDetails[2] .= " (user '$databaseConfig[username]' doesn't have CREATE DATABASE permissions.)";
$this->error($testDetails);
return false;
}
}
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 isRunningWebServer($testDetails) {
$this->testing($testDetails);
if(function_exists('apache_get_modules') || stristr($_SERVER['SERVER_SIGNATURE'], 'Apache')) {
return true;
} elseif(strpos($_SERVER['SERVER_SOFTWARE'], 'IIS') !== false) {
return true;
} else {
$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
SilverStripe CMS Installation
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
statusMessage("Setting up 'mysite/_config.php' for use with _ss_environment.php...");
$this->writeToFile("mysite/_config.php", <<statusMessage("Setting up 'mysite/_config.php'...");
$devServers = $this->var_export_array_nokeys(explode("\n", $_POST['devsites']));
$escapedPassword = addslashes($config['db']['password']);
$this->writeToFile("mysite/_config.php", << "{$config['db']['type']}",
"server" => "{$config['db']['server']}",
"username" => "{$config['db']['username']}",
"password" => '{$escapedPassword}',
"database" => "{$config['db']['database']}",
);
// Sites running on the following servers will be
// run in development mode. See
// http://doc.silverstripe.org/doku.php?id=configuration
// for a description of what dev mode does.
Director::set_dev_servers($devServers);
// This line set's the current theme. More themes can be
// downloaded from http://www.silverstripe.org/themes/
SSViewer::set_theme('$theme');
// enable nested URLs for this site (e.g. page/sub-page/)
SiteTree::enable_nested_urls();
?>
PHP
);
}
$this->statusMessage("Setting up '.htaccess' file...");
$this->createHtaccess();
// Load the sapphire runtime
$_SERVER['SCRIPT_FILENAME'] = dirname(realpath($_SERVER['SCRIPT_FILENAME'])) . '/sapphire/main.php';
chdir('sapphire');
// Rebuild the manifest
$_GET['flush'] = true;
// Show errors as if you're in development mode
$_SESSION['isDev'] = 1;
require_once('core/Core.php');
$this->statusMessage("Building database schema...");
// Build database
$con = new Controller();
$con->pushCurrent();
global $databaseConfig;
DB::connect($databaseConfig);
$dbAdmin = new DatabaseAdmin();
$dbAdmin->init();
$dbAdmin->doBuild(true);
// Create default administrator user and group in database
// (not using Security::setDefaultAdmin())
$adminMember = Security::findAnAdministrator();
$adminMember->Email = $config['admin']['username'];
$adminMember->Password = $config['admin']['password'];
$adminMember->PasswordEncryption = Security::get_password_encryption_algorithm();
$adminMember->FirstName = $config['admin']['firstname'];
$adminMember->Surname = $config['admin']['surname'];
$adminMember->write();
// Syncing filesystem (so /assets/Uploads is available instantly, see ticket #2266)
FileSystem::sync();
$_SESSION['username'] = $config['admin']['username'];
$_SESSION['password'] = $config['admin']['password'];
if(!$this->errors) {
if(isset($_SERVER['HTTP_HOST'])) {
$this->statusMessage("Checking that friendly URLs work...");
$this->checkModRewrite();
} else {
echo "\n\nSilverStripe successfully installed\n";
}
}
return $this->errors;
}
function makeFolder($folder) {
$base = $this->getBaseDir();
if(!file_exists($base . $folder)) {
if(!mkdir($base . $folder, 02775)) {
$this->error("Couldn't create a folder called $base$folder");
} else {
chmod($base . $folder, 02775);
}
}
}
function renameFolder($oldName, $newName) {
if($oldName == $newName) return true;
$base = $this->getBaseDir();
if(!rename($base . $oldName, $base . $newName)) {
$this->error("Couldn't rename $base$oldName to $base$newName");
return false;
} else {
return true;
}
}
function copyFolder($oldName, $newName) {
if($oldName == $newName) return true;
$base = $this->getBaseDir();
if(!copyr($base . $oldName, $base . $newName)) {
$this->error("Couldn't rename $base$oldName to $base$newName");
return false;
} else {
return true;
}
}
function writeToFile($filename, $content) {
$base = $this->getBaseDir();
$this->statusMessage("Setting up $base$filename");
if((@$fh = fopen($base . $filename, 'wb')) && fwrite($fh, $content) && fclose($fh)) {
return true;
} else {
$this->error("Couldn't write to file $base$filename");
}
}
function createHtaccess() {
$start = "### SILVERSTRIPE START ###\n";
$end = "\n### SILVERSTRIPE END ###";
$base = dirname($_SERVER['SCRIPT_NAME']);
if(defined('DIRECTORY_SEPARATOR')) $base = str_replace(DIRECTORY_SEPARATOR, '/', $base);
else $base = str_replace("\\", '/', $base);
if($base != '.') $baseClause = "RewriteBase $base\n";
else $baseClause = "";
$rewrite = <<
Order deny,allow
Deny from all
Allow from 127.0.0.1
Order deny,allow
Deny from all
RewriteEngine On
$baseClause
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* sapphire/main.php?url=%1&%{QUERY_STRING} [L]
TEXT
;
if(file_exists('.htaccess')) {
$htaccess = file_get_contents('.htaccess');
if(strpos($htaccess, '### SILVERSTRIPE START ###') === false && strpos($htaccess, '### SILVERSTRIPE END ###') === false) {
$htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n";
}
if(strpos($htaccess, '### SILVERSTRIPE START ###') !== false && strpos($htaccess, '### SILVERSTRIPE END ###') !== false) {
$start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###')) . "### SILVERSTRIPE START ###\n";
$end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###'));
}
}
$this->writeToFile('.htaccess', $start . $rewrite . $end);
}
function restoreHtaccess() {
$start = "### SILVERSTRIPE START ###\n";
$end= "\n### SILVERSTRIPE END ###";
if(file_exists('.htaccess')) {
$htaccess = file_get_contents('.htaccess');
if(strpos($htaccess, '### SILVERSTRIPE START ###') === false && strpos($htaccess, '### SILVERSTRIPE END ###') === false) {
$htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n";
}
if(strpos($htaccess, '### SILVERSTRIPE START ###') !== false && strpos($htaccess, '### SILVERSTRIPE END ###') !== false) {
$start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###')) . "### SILVERSTRIPE START ###\n";
$end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###'));
}
}
$this->writeToFile('.htaccess', $start . $end);
}
function checkModRewrite() {
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.");
return true;
}
echo <<Testing...
HTML;
}
function var_export_array_nokeys($array) {
$retval = "array(\n";
foreach($array as $item) {
$retval .= "\t'";
$retval .= trim($item);
$retval .= "',\n";
}
$retval .= ")";
return $retval;
}
/**
* Show an installation status message.
* The output differs depending on whether this is CLI or web based
*/
function statusMessage($msg) {
if(isset($_SERVER['HTTP_HOST'])) echo "
$msg
\n";
else echo "$msg\n";
flush();
}
}
/**
* Copy a file, or recursively copy a folder and its contents
*
* @author Aidan Lister
* @version 1.0.1
* @link http://aidanlister.com/repos/v/function.copyr.php
* @param string $source Source path
* @param string $dest Destination path
* @return bool Returns TRUE on success, FALSE on failure
*/
function copyr($source, $dest)
{
// Simple copy for a file
if (is_file($source)) {
return copy($source, $dest);
}
// Make destination directory
if (!is_dir($dest)) {
mkdir($dest);
}
// Loop through the folder
$dir = dir($source);
while (false !== $entry = $dir->read()) {
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}
// Deep copy directories
if ($dest !== "$source/$entry") {
copyr("$source/$entry", "$dest/$entry");
}
}
// Clean up
$dir->close();
return true;
}
function rm($fileglob)
{
if (is_string($fileglob)) {
if (is_file($fileglob)) {
return unlink($fileglob);
} else if (is_dir($fileglob)) {
$ok = rm("$fileglob/*");
if (! $ok) {
return false;
}
return rmdir($fileglob);
} else {
$matching = glob($fileglob);
if ($matching === false) {
trigger_error(sprintf('No files match supplied glob %s', $fileglob), E_USER_WARNING);
return false;
}
$rcs = array_map('rm', $matching);
if (in_array(false, $rcs)) {
return false;
}
}
} else if (is_array($fileglob)) {
$rcs = array_map('rm', $fileglob);
if (in_array(false, $rcs)) {
return false;
}
} else {
trigger_error('Param #1 must be filename or glob pattern, or array of filenames or glob patterns', E_USER_ERROR);
return false;
}
return true;
}