diff options
Diffstat (limited to 'install/ElggInstaller.php')
| -rw-r--r-- | install/ElggInstaller.php | 609 |
1 files changed, 462 insertions, 147 deletions
diff --git a/install/ElggInstaller.php b/install/ElggInstaller.php index 57940dda3..78cdde90f 100644 --- a/install/ElggInstaller.php +++ b/install/ElggInstaller.php @@ -1,15 +1,32 @@ <?php + /** * Elgg Installer. - * Controller for installing Elgg. + * Controller for installing Elgg. Supports both web-based on CLI installation. + * + * This controller steps the user through the install process. The method for + * each step handles both the GET and POST requests. There is no XSS/CSRF protection + * on the POST processing since the installer is only run once by the administrator. + * + * The installation process can be resumed by hitting the first page. The installer + * will try to figure out where to pick up again. * - * @package Elgg + * All the logic for the installation process is in this class, but it depends on + * the core libraries. To do this, we selectively load a subset of the core libraries + * for the first few steps and then load the entire engine once the database and + * site settings are configured. In addition, this controller does its own session + * handling until the database is setup. + * + * There is an aborted attempt in the code at creating the data directory for + * users as a subdirectory of Elgg's root. The idea was to protect this directory + * through a .htaccess file. The problem is that a malicious user can upload a + * .htaccess of his own that overrides the protection for his user directory. The + * best solution is server level configuration that turns off AllowOverride for the + * data directory. See ticket #3453 for discussion on this. + * + * @package Elgg.Core * @subpackage Installer - * @author Curverider Ltd - * @link http://elgg.org/ */ - - class ElggInstaller { protected $steps = array( @@ -22,6 +39,7 @@ class ElggInstaller { ); protected $status = array( + 'config' => FALSE, 'database' => FALSE, 'settings' => FALSE, 'admin' => FALSE, @@ -29,12 +47,15 @@ class ElggInstaller { protected $isAction = FALSE; - protected $autoLogin = FALSE; + protected $autoLogin = TRUE; /** * Constructor bootstraps the Elgg engine */ public function __construct() { + // load ElggRewriteTester as we depend on it + require_once(dirname(__FILE__) . "/ElggRewriteTester.php"); + $this->isAction = $_SERVER['REQUEST_METHOD'] === 'POST'; $this->bootstrapConfig(); @@ -43,8 +64,8 @@ class ElggInstaller { elgg_set_viewtype('installation'); - set_error_handler('__elgg_php_error_handler'); - set_exception_handler('__elgg_php_exception_handler'); + set_error_handler('_elgg_php_error_handler'); + set_exception_handler('_elgg_php_exception_handler'); register_translations(dirname(__FILE__) . '/languages/', TRUE); } @@ -52,7 +73,9 @@ class ElggInstaller { /** * Dispatches a request to one of the step controllers * - * @param string $step + * @param string $step The installation step to run + * + * @return void */ public function run($step) { @@ -60,7 +83,7 @@ class ElggInstaller { $this->processRewriteTest(); if (!in_array($step, $this->getSteps())) { - $msg = sprintf(elgg_echo('InstallationException:UnknownStep'), $step); + $msg = elgg_echo('InstallationException:UnknownStep', array($step)); throw new InstallationException($msg); } @@ -79,18 +102,114 @@ class ElggInstaller { /** * Set the auto login flag - * - * @param bool $flag + * + * @param bool $flag Auto login + * + * @return void */ public function setAutoLogin(bool $flag) { $this->autoLogin = $value; } /** + * A batch install of Elgg + * + * All required parameters must be passed in as an associative array. See + * $requiredParams for a list of them. This creates the necessary files, + * loads the database, configures the site settings, and creates the admin + * account. If it fails, an exception is thrown. It does not check any of + * the requirements as the multiple step web installer does. + * + * If the settings.php file exists, it will use that rather than the parameters + * passed to this function. + * + * @param array $params Array of key value pairs + * @param bool $createHtaccess Should .htaccess be created + * + * @return void + * @throws InstallationException + */ + public function batchInstall(array $params, $createHtaccess = FALSE) { + global $CONFIG; + + restore_error_handler(); + restore_exception_handler(); + + $defaults = array( + 'dbhost' => 'localhost', + 'dbprefix' => 'elgg_', + 'path' => $CONFIG->path, + 'language' => 'en', + 'siteaccess' => ACCESS_PUBLIC, + ); + $params = array_merge($defaults, $params); + + $requiredParams = array( + 'dbuser', + 'dbpassword', + 'dbname', + 'sitename', + 'wwwroot', + 'dataroot', + 'displayname', + 'email', + 'username', + 'password', + ); + foreach ($requiredParams as $key) { + if (empty($params[$key])) { + $msg = elgg_echo('install:error:requiredfield', array($key)); + throw new InstallationException($msg); + } + } + + // password is passed in once + $params['password1'] = $params['password2'] = $params['password']; + + if ($createHtaccess) { + $rewriteTester = new ElggRewriteTester(); + if (!$rewriteTester->createHtaccess($CONFIG->path)) { + throw new InstallationException(elgg_echo('install:error:htaccess')); + } + } + + $this->setInstallStatus(); + + if (!$this->status['config']) { + if (!$this->createSettingsFile($params)) { + throw new InstallationException(elgg_echo('install:error:settings')); + } + } + + if (!$this->connectToDatabase()) { + throw new InstallationException(elgg_echo('install:error:databasesettings')); + } + + if (!$this->status['database']) { + if (!$this->installDatabase()) { + throw new InstallationException(elgg_echo('install:error:cannotloadtables')); + } + } + + // load remaining core libraries + $this->finishBootstraping('settings'); + + if (!$this->saveSiteSettings($params)) { + throw new InstallationException(elgg_echo('install:error:savesitesettings')); + } + + if (!$this->createAdminAccount($params)) { + throw new InstallationException(elgg_echo('install:admin:cannot_create')); + } + } + + /** * Renders the data passed by a controller * - * @param string $step - * @param array $vars + * @param string $step The current step + * @param array $vars Array of vars to pass to the view + * + * @return void */ protected function render($step, $vars = array()) { @@ -98,10 +217,10 @@ class ElggInstaller { $title = elgg_echo("install:$step"); $body = elgg_view("install/pages/$step", $vars); - page_draw( + echo elgg_view_page( $title, $body, - 'page_shells/default', + 'default', array( 'step' => $step, 'steps' => $this->getSteps(), @@ -118,6 +237,8 @@ class ElggInstaller { * Welcome controller * * @param array $vars Not used + * + * @return void */ protected function welcome($vars) { $this->render('welcome'); @@ -128,7 +249,9 @@ class ElggInstaller { * * Checks version of php, libraries, permissions, and rewrite rules * - * @param array $vars + * @param array $vars Vars + * + * @return void */ protected function requirements($vars) { @@ -141,7 +264,7 @@ class ElggInstaller { $this->checkRewriteRules($report); // check for existence of settings file - if ($this->checkSettingsFile() != TRUE) { + if ($this->checkSettingsFile($report) != TRUE) { // no file, so check permissions on engine directory $this->checkEngineDir($report); } @@ -174,6 +297,8 @@ class ElggInstaller { * Creates the settings.php file and creates the database tables * * @param array $submissionVars Submitted form variables + * + * @return void */ protected function database($submissionVars) { @@ -186,7 +311,7 @@ class ElggInstaller { 'dbpassword' => array( 'type' => 'password', 'value' => '', - 'required' => TRUE, + 'required' => FALSE, ), 'dbname' => array( 'type' => 'text', @@ -256,16 +381,17 @@ class ElggInstaller { * * Sets the site name, URL, data directory, etc. * - * @param array $submissionVars + * @param array $submissionVars Submitted vars + * + * @return void */ protected function settings($submissionVars) { global $CONFIG; - $languages = get_installed_translations(); $formVars = array( 'sitename' => array( 'type' => 'text', - 'value' => 'New Elgg site', + 'value' => 'My New Community', 'required' => TRUE, ), 'siteemail' => array( @@ -275,7 +401,7 @@ class ElggInstaller { ), 'wwwroot' => array( 'type' => 'text', - 'value' => $CONFIG->wwwroot, + 'value' => elgg_get_site_url(), 'required' => TRUE, ), 'path' => array( @@ -288,12 +414,6 @@ class ElggInstaller { 'value' => '', 'required' => TRUE, ), - 'language' => array( - 'type' => 'pulldown', - 'value' => 'en', - 'options_values' => $languages, - 'required' => TRUE, - ), 'siteaccess' => array( 'type' => 'access', 'value' => ACCESS_PUBLIC, @@ -301,8 +421,19 @@ class ElggInstaller { ), ); + // if Apache, we give user option of having Elgg create data directory + //if (ElggRewriteTester::guessWebServer() == 'apache') { + // $formVars['dataroot']['type'] = 'combo'; + // $CONFIG->translations['en']['install:settings:help:dataroot'] = + // $CONFIG->translations['en']['install:settings:help:dataroot:apache']; + //} + if ($this->isAction) { do { + //if (!$this->createDataDirectory($submissionVars, $formVars)) { + // break; + //} + if (!$this->validateSettingsVars($submissionVars, $formVars)) { break; } @@ -328,7 +459,9 @@ class ElggInstaller { * * Creates an admin user account * - * @param array $submissionVars + * @param array $submissionVars Submitted vars + * + * @return void */ protected function admin($submissionVars) { $formVars = array( @@ -358,7 +491,7 @@ class ElggInstaller { 'required' => TRUE, ), ); - + if ($this->isAction) { do { if (!$this->validateAdminVars($submissionVars, $formVars)) { @@ -368,7 +501,7 @@ class ElggInstaller { if (!$this->createAdminAccount($submissionVars, $this->autoLogin)) { break; } - + system_message(elgg_echo('install:success:admin')); $this->continueToNextStep('admin'); @@ -380,7 +513,8 @@ class ElggInstaller { global $CONFIG; $lang = get_current_language(); $CONFIG->translations[$lang]['install:admin:help:password1'] = - sprintf($CONFIG->translations[$lang]['install:admin:help:password1'], $CONFIG->min_password_length); + sprintf($CONFIG->translations[$lang]['install:admin:help:password1'], + $CONFIG->min_password_length); $formVars = $this->makeFormSticky($formVars, $submissionVars); @@ -390,17 +524,13 @@ class ElggInstaller { /** * Controller for last step * - * @param array $vars + * @return void */ - protected function complete($vars) { + protected function complete() { $params = array(); if ($this->autoLogin) { - // remind users to enable / disable desired tools - $msg = elgg_echo('firstadminlogininstructions'); - elgg_add_admin_notice('first_installation_plugin_reminder', $msg); - - $params['destination'] = 'pg/admin/plugins/simple'; + $params['destination'] = 'admin'; } else { $params['destination'] = 'index.php'; } @@ -424,7 +554,9 @@ class ElggInstaller { /** * Forwards the browser to the next step * - * @param string $currentStep + * @param string $currentStep Current installation step + * + * @return void */ protected function continueToNextStep($currentStep) { $this->isAction = FALSE; @@ -434,38 +566,48 @@ class ElggInstaller { /** * Get the next step as a string * - * @param string $currentStep + * @param string $currentStep Current installation step + * * @return string */ protected function getNextStep($currentStep) { - return $this->steps[1 + array_search($currentStep, $this->steps)]; + $index = 1 + array_search($currentStep, $this->steps); + if (isset($this->steps[$index])) { + return $this->steps[$index]; + } else { + return null; + } } /** * Get the URL of the next step * - * @param string $currentStep + * @param string $currentStep Current installation step + * * @return string */ protected function getNextStepUrl($currentStep) { global $CONFIG; $nextStep = $this->getNextStep($currentStep); - return "{$CONFIG->wwwroot}install.php?step=$nextStep"; + return elgg_get_site_url() . "install.php?step=$nextStep"; } /** - * Check the different nstall steps for completion + * Check the different install steps for completion + * + * @return void */ protected function setInstallStatus() { global $CONFIG; - $settingsCreated = $this->checkSettingsFile(); - if ($settingsCreated == FALSE) { + if (!is_readable("{$CONFIG->path}engine/settings.php")) { return; } $this->loadSettingsFile(); + $this->status['config'] = TRUE; + // must be able to connect to database to jump install steps $dbSettingsPass = $this->checkDatabaseSettings( $CONFIG->dbuser, @@ -478,7 +620,7 @@ class ElggInstaller { } if (!include_once("{$CONFIG->path}engine/lib/database.php")) { - $msg = sprintf(elgg_echo('InstallationException:MissingLibrary'), 'database.php'); + $msg = elgg_echo('InstallationException:MissingLibrary', array('database.php')); throw new InstallationException($msg); } @@ -523,7 +665,9 @@ class ElggInstaller { * Security check to ensure the installer cannot be run after installation * has finished. If this is detected, the viewer is sent to the front page. * - * @param string $step + * @param string $step Installation step to check against + * + * @return void */ protected function checkInstallCompletion($step) { if ($step != 'complete') { @@ -538,7 +682,8 @@ class ElggInstaller { * Check if this is a case of a install being resumed and figure * out where to continue from. Returns the best guess on the step. * - * @param string $step + * @param string $step Installation step to resume from + * * @return string */ protected function resumeInstall($step) { @@ -554,15 +699,15 @@ class ElggInstaller { } if ($this->status['settings'] == FALSE) { - forward("{$CONFIG->wwwroot}install.php?step=settings"); + forward("install.php?step=settings"); } if ($this->status['admin'] == FALSE) { - forward("{$CONFIG->wwwroot}install.php?step=admin"); + forward("install.php?step=admin"); } // everything appears to be set up - forward("{$CONFIG->wwwroot}install.php?step=complete"); + forward("install.php?step=complete"); } /** @@ -571,6 +716,8 @@ class ElggInstaller { /** * Load the essential libraries of the engine + * + * @return void */ protected function bootstrapEngine() { global $CONFIG; @@ -579,8 +726,9 @@ class ElggInstaller { // bootstrapping with required files in a required order $required_files = array( - 'exceptions.php', 'elgglib.php', 'views.php', 'access.php', 'system_log.php', 'export.php', - 'sessions.php', 'languages.php', 'input.php', 'install.php', 'cache.php', 'output.php' + 'elgglib.php', 'views.php', 'access.php', 'system_log.php', 'export.php', + 'configuration.php', 'sessions.php', 'languages.php', 'pageowner.php', + 'input.php', 'cache.php', 'output.php', ); foreach ($required_files as $file) { @@ -596,19 +744,27 @@ class ElggInstaller { /** * Load remaining engine libraries and complete bootstraping (see start.php) * - * @param string $step + * @param string $step Which step to boot strap for. Required because + * boot strapping is different until the DB is populated. + * + * @return void */ protected function finishBootstraping($step) { $dbIndex = array_search('database', $this->getSteps()); $settingsIndex = array_search('settings', $this->getSteps()); + $adminIndex = array_search('admin', $this->getSteps()); + $completeIndex = array_search('complete', $this->getSteps()); $stepIndex = array_search($step, $this->getSteps()); - if ($stepIndex <= $settingsIndex) { - // install has its own session handling before the db created and set up - session_name('Elgg'); + // To log in the user, we need to use the Elgg core session handling. + // Otherwise, use default php session handling + $useElggSession = ($stepIndex == $adminIndex && $this->isAction) || + $stepIndex == $completeIndex; + if (!$useElggSession) { + session_name('Elgg_install'); session_start(); - unregister_elgg_event_handler('boot', 'system', 'session_init'); + elgg_unregister_event_handler('boot', 'system', 'session_init'); } if ($stepIndex > $dbIndex) { @@ -622,35 +778,48 @@ class ElggInstaller { // these want to be loaded first apparently? 'database.php', 'actions.php', - 'admin.php', 'annotations.php', 'api.php', - 'calendar.php', 'configuration.php', 'cron.php', 'entities.php', + 'admin.php', 'annotations.php', + 'calendar.php', 'cron.php', 'entities.php', 'extender.php', 'filestore.php', 'group.php', 'location.php', 'mb_wrapper.php', - 'memcache.php', 'metadata.php', 'metastrings.php', 'notification.php', + 'memcache.php', 'metadata.php', 'metastrings.php', + 'navigation.php', 'notification.php', 'objects.php', 'opendd.php', 'pagehandler.php', - 'pageowner.php', 'pam.php', 'plugins.php', 'query.php', - 'relationships.php', 'river.php', 'sites.php', 'social.php', - 'statistics.php', 'tags.php', 'usersettings.php', - 'users.php', 'version.php', 'widgets.php', 'xml.php', 'xml-rpc.php' + 'pam.php', 'plugins.php', + 'private_settings.php', 'relationships.php', 'river.php', + 'sites.php', 'statistics.php', 'tags.php', 'user_settings.php', + 'users.php', 'upgrade.php', 'web_services.php', + 'widgets.php', 'xml.php', 'xml-rpc.php', + 'deprecated-1.7.php', 'deprecated-1.8.php', ); foreach ($lib_files as $file) { $path = $lib_dir . $file; if (!include_once($path)) { - $msg = sprintf(elgg_echo('InstallationException:MissingLibrary'), $file); + $msg = elgg_echo('InstallationException:MissingLibrary', array($file)); throw new InstallationException($msg); } } - set_default_config(); + setup_db_connections(); + register_translations(dirname(dirname(__FILE__)) . "/languages/"); + + if ($stepIndex > $settingsIndex) { + $CONFIG->site_guid = (int) datalist_get('default_site'); + $CONFIG->site_id = $CONFIG->site_guid; + $CONFIG->site = get_entity($CONFIG->site_guid); + $CONFIG->dataroot = datalist_get('dataroot'); + _elgg_session_boot(NULL, NULL, NULL); + } - trigger_elgg_event('boot', 'system'); - trigger_elgg_event('init', 'system'); + elgg_trigger_event('init', 'system'); } } /** * Set up configuration variables + * + * @return void */ protected function bootstrapConfig() { global $CONFIG; @@ -661,11 +830,18 @@ class ElggInstaller { $CONFIG->wwwroot = $this->getBaseUrl(); $CONFIG->url = $CONFIG->wwwroot; $CONFIG->path = dirname(dirname(__FILE__)) . '/'; + $CONFIG->viewpath = $CONFIG->path . 'views/'; + $CONFIG->pluginspath = $CONFIG->path . 'mod/'; + $CONFIG->context = array(); + $CONFIG->entity_types = array('group', 'object', 'site', 'user'); } /** * Get the best guess at the base URL + * + * @note Cannot use current_page_url() because it depends on $CONFIG->wwwroot * @todo Should this be a core function? + * * @return string */ protected function getBaseUrl() { @@ -687,6 +863,9 @@ class ElggInstaller { /** * Load settings.php + * + * @return void + * @throws InstallationException */ protected function loadSettingsFile() { global $CONFIG; @@ -721,8 +900,9 @@ class ElggInstaller { /** * If form is reshown, remember previously submitted variables * - * @param array $formVars - * @param array $submissionVars + * @param array $formVars Vars int he form + * @param array $submissionVars Submitted vars + * * @return array */ protected function makeFormSticky($formVars, $submissionVars) { @@ -738,7 +918,9 @@ class ElggInstaller { /** * Check that the engine dir is writable - * @param array $report + * + * @param array &$report The requirements report object + * * @return bool */ protected function checkEngineDir(&$report) { @@ -746,7 +928,7 @@ class ElggInstaller { $writable = is_writable("{$CONFIG->path}engine"); if (!$writable) { - $report['engine'] = array( + $report['settings'] = array( array( 'severity' => 'failure', 'message' => elgg_echo('install:check:enginedir'), @@ -760,21 +942,36 @@ class ElggInstaller { /** * Check that the settings file exists + * + * @param array &$report The requirements report array + * * @return bool */ - protected function checkSettingsFile() { + protected function checkSettingsFile(&$report = array()) { global $CONFIG; - if (is_readable("{$CONFIG->path}engine/settings.php")) { - return TRUE; + if (!file_exists("{$CONFIG->path}engine/settings.php")) { + return FALSE; } - return FALSE; + if (!is_readable("{$CONFIG->path}engine/settings.php")) { + $report['settings'] = array( + array( + 'severity' => 'failure', + 'message' => elgg_echo('install:check:readsettings'), + ) + ); + } + + return TRUE; } /** * Check version of PHP, extensions, and variables - * @param array $report + * + * @param array &$report The requirements report array + * + * @return void */ protected function checkPHP(&$report) { $phpReport = array(); @@ -783,7 +980,7 @@ class ElggInstaller { if (version_compare(PHP_VERSION, $elgg_php_version, '<')) { $phpReport[] = array( 'severity' => 'failure', - 'message' => sprintf(elgg_echo('install:check:php:version'), $elgg_php_version, PHP_VERSION) + 'message' => elgg_echo('install:check:php:version', array($elgg_php_version, PHP_VERSION)) ); } @@ -804,7 +1001,9 @@ class ElggInstaller { /** * Check the server's PHP extensions * - * @param array $phpReport + * @param array &$phpReport The PHP requirements report array + * + * @return void */ protected function checkPhpExtensions(&$phpReport) { $extensions = get_loaded_extensions(); @@ -818,7 +1017,7 @@ class ElggInstaller { if (!in_array($extension, $extensions)) { $phpReport[] = array( 'severity' => 'failure', - 'message' => sprintf(elgg_echo('install:check:php:extension'), $extension) + 'message' => elgg_echo('install:check:php:extension', array($extension)) ); } } @@ -830,7 +1029,7 @@ class ElggInstaller { if (!in_array($extension, $extensions)) { $phpReport[] = array( 'severity' => 'warning', - 'message' => sprintf(elgg_echo('install:check:php:extension:recommend'), $extension) + 'message' => elgg_echo('install:check:php:extension:recommend', array($extension)) ); } } @@ -839,7 +1038,9 @@ class ElggInstaller { /** * Check PHP parameters * - * @param array $phpReport + * @param array &$phpReport The PHP requirements report array + * + * @return void */ protected function checkPhpDirectives(&$phpReport) { if (ini_get('open_basedir')) { @@ -855,25 +1056,51 @@ class ElggInstaller { 'message' => elgg_echo("install:check:php:safe_mode") ); } + + if (ini_get('arg_separator.output') !== '&') { + $separator = htmlspecialchars(ini_get('arg_separator.output')); + $msg = elgg_echo("install:check:php:arg_separator", array($separator)); + $phpReport[] = array( + 'severity' => 'failure', + 'message' => $msg, + ); + } + + if (ini_get('register_globals')) { + $phpReport[] = array( + 'severity' => 'failure', + 'message' => elgg_echo("install:check:php:register_globals") + ); + } + + if (ini_get('session.auto_start')) { + $phpReport[] = array( + 'severity' => 'failure', + 'message' => elgg_echo("install:check:php:session.auto_start") + ); + } } /** * Confirm that the rewrite rules are firing - * @param array $report + * + * @param array &$report The requirements report array + * + * @return void */ protected function checkRewriteRules(&$report) { global $CONFIG; - require_once(dirname(__FILE__) . "/ElggRewriteTester.php"); - $tester = new ElggRewriteTester(); - $url = "{$CONFIG->wwwroot}rewrite.php"; + $url = elgg_get_site_url() . "rewrite.php"; $report['rewrite'] = array($tester->run($url, $CONFIG->path)); } /** * Check if the request is coming from the URL rewrite test on the * requirements page. + * + * @return void */ protected function processRewriteTest() { if (strpos($_SERVER['REQUEST_URI'], 'rewrite.php') !== FALSE) { @@ -885,8 +1112,9 @@ class ElggInstaller { /** * Count the number of failures in the requirements report * - * @param array $report + * @param array $report The requirements report array * @param string $condition 'failure' or 'warning' + * * @return int */ protected function countNumConditions($report, $condition) { @@ -910,8 +1138,9 @@ class ElggInstaller { /** * Validate the variables for the database step * - * @param array $submissionVars - * @param array $formVars + * @param array $submissionVars Submitted vars + * @param array $formVars Vars in the form + * * @return bool */ protected function validateDatabaseVars($submissionVars, $formVars) { @@ -919,11 +1148,21 @@ class ElggInstaller { foreach ($formVars as $field => $info) { if ($info['required'] == TRUE && !$submissionVars[$field]) { $name = elgg_echo("install:database:label:$field"); - register_error("$name is required"); + register_error(elgg_echo('install:error:requiredfield', array($name))); return FALSE; } } + // according to postgres documentation: SQL identifiers and key words must + // begin with a letter (a-z, but also letters with diacritical marks and + // non-Latin letters) or an underscore (_). Subsequent characters in an + // identifier or key word can be letters, underscores, digits (0-9), or dollar signs ($). + // Refs #4994 + if (!preg_match("/^[a-zA-Z_][\w]*$/", $submissionVars['dbprefix'])) { + register_error(elgg_echo('install:error:database_prefix')); + return FALSE; + } + return $this->checkDatabaseSettings( $submissionVars['dbuser'], $submissionVars['dbpassword'], @@ -935,10 +1174,11 @@ class ElggInstaller { /** * Confirm the settings for the database * - * @param string $user - * @param string $password - * @param string $dbname - * @param string $host + * @param string $user Username + * @param string $password Password + * @param string $dbname Database name + * @param string $host Host + * * @return bool */ protected function checkDatabaseSettings($user, $password, $dbname, $host) { @@ -955,14 +1195,14 @@ class ElggInstaller { $version = mysql_get_server_info(); $points = explode('.', $version); if ($points[0] < $required_version) { - register_error(sprintf(elgg_echo('install:error:oldmysql'), $version)); + register_error(elgg_echo('install:error:oldmysql', array($version))); return FALSE; } mysql_close($mysql_dblink); if (!$result) { - register_error(sprintf(elgg_echo('install:error:nodatabase'), $dbname)); + register_error(elgg_echo('install:error:nodatabase', array($dbname))); } return $result; @@ -971,7 +1211,8 @@ class ElggInstaller { /** * Writes the settings file to the engine directory * - * @param array $params + * @param array $params Array of inputted params from the user + * * @return bool */ protected function createSettingsFile($params) { @@ -985,7 +1226,7 @@ class ElggInstaller { } foreach ($params as $k => $v) { - $template = str_replace("{{".$k."}}", $v, $template); + $template = str_replace("{{" . $k . "}}", $v, $template); } $settingsFilename = "{$CONFIG->path}engine/settings.php"; @@ -1012,7 +1253,7 @@ class ElggInstaller { } if (!include_once("{$CONFIG->path}engine/lib/database.php")) { - $msg = sprintf(elgg_echo('InstallationException:MissingLibrary'), 'database.php'); + $msg = elgg_echo('InstallationException:MissingLibrary', array('database.php')); register_error($msg); return FALSE; } @@ -1054,39 +1295,99 @@ class ElggInstaller { */ /** + * Create the data directory if requested + * + * @param array $submissionVars Submitted vars + * @param array $formVars Variables in the form + * @return bool + */ + protected function createDataDirectory(&$submissionVars, $formVars) { + // did the user have option of Elgg creating the data directory + if ($formVars['dataroot']['type'] != 'combo') { + return TRUE; + } + + // did the user select the option + if ($submissionVars['dataroot'] != 'dataroot-checkbox') { + return TRUE; + } + + $dir = sanitise_filepath($submissionVars['path']) . 'data'; + if (file_exists($dir) || mkdir($dir, 0700)) { + $submissionVars['dataroot'] = $dir; + if (!file_exists("$dir/.htaccess")) { + $htaccess = "Order Deny,Allow\nDeny from All\n"; + if (!file_put_contents("$dir/.htaccess", $htaccess)) { + return FALSE; + } + } + return TRUE; + } + + return FALSE; + } + + /** * Validate the site settings form variables * - * @param array $submissionVars - * @param array $formVars + * @param array $submissionVars Submitted vars + * @param array $formVars Vars in the form + * * @return bool */ protected function validateSettingsVars($submissionVars, $formVars) { + global $CONFIG; foreach ($formVars as $field => $info) { - if ($info['required'] == TRUE && !$submissionVars[$field]) { + $submissionVars[$field] = trim($submissionVars[$field]); + if ($info['required'] == TRUE && $submissionVars[$field] === '') { $name = elgg_echo("install:settings:label:$field"); - register_error(sprintf(elgg_echo('install:error:requiredfield'), $name)); + register_error(elgg_echo('install:error:requiredfield', array($name))); return FALSE; } } - // check that data root is writable - if (!is_writable($submissionVars['dataroot'])) { - $msg = sprintf(elgg_echo('install:error:writedatadirectory'), $submissionVars['dataroot']); + // check that data root is absolute path + if (stripos(PHP_OS, 'win') === 0) { + if (strpos($submissionVars['dataroot'], ':') !== 1) { + $msg = elgg_echo('install:error:relative_path', array($submissionVars['dataroot'])); + register_error($msg); + return FALSE; + } + } else { + if (strpos($submissionVars['dataroot'], '/') !== 0) { + $msg = elgg_echo('install:error:relative_path', array($submissionVars['dataroot'])); + register_error($msg); + return FALSE; + } + } + + // check that data root exists + if (!file_exists($submissionVars['dataroot'])) { + $msg = elgg_echo('install:error:datadirectoryexists', array($submissionVars['dataroot'])); register_error($msg); return FALSE; } - // check that data root is not subdirectory of Elgg root - if (stripos($submissionVars['dataroot'], $submissionVars['path']) !== FALSE) { - $msg = sprintf(elgg_echo('install:error:locationdatadirectory'), $submissionVars['dataroot']); + // check that data root is writable + if (!is_writable($submissionVars['dataroot'])) { + $msg = elgg_echo('install:error:writedatadirectory', array($submissionVars['dataroot'])); register_error($msg); return FALSE; } + if (!isset($CONFIG->data_dir_override) || !$CONFIG->data_dir_override) { + // check that data root is not subdirectory of Elgg root + if (stripos($submissionVars['dataroot'], $submissionVars['path']) === 0) { + $msg = elgg_echo('install:error:locationdatadirectory', array($submissionVars['dataroot'])); + register_error($msg); + return FALSE; + } + } + // check that email address is email address if ($submissionVars['siteemail'] && !is_email_address($submissionVars['siteemail'])) { - $msg = sprintf(elgg_echo('install:error:emailaddress'), $submissionVars['siteemail']); + $msg = elgg_echo('install:error:emailaddress', array($submissionVars['siteemail'])); register_error($msg); return FALSE; } @@ -1100,7 +1401,8 @@ class ElggInstaller { /** * Initialize the site including site entity, plugins, and configuration * - * @param array $submissionVars + * @param array $submissionVars Submitted vars + * * @return bool */ protected function saveSiteSettings($submissionVars) { @@ -1112,11 +1414,11 @@ class ElggInstaller { $submissionVars['wwwroot'] = sanitise_filepath($submissionVars['wwwroot']); $site = new ElggSite(); - $site->name = $submissionVars['sitename']; - $site->url = $submissionVars['wwwroot']; + $site->name = strip_tags($submissionVars['sitename']); + $site->url = $submissionVars['wwwroot']; $site->access_id = ACCESS_PUBLIC; - $site->email = $submissionVars['siteemail']; - $guid = $site->save(); + $site->email = $submissionVars['siteemail']; + $guid = $site->save(); if (!$guid) { register_error(elgg_echo('install:error:createsite')); @@ -1132,33 +1434,37 @@ class ElggInstaller { datalist_set('dataroot', $submissionVars['dataroot']); datalist_set('default_site', $site->getGUID()); datalist_set('version', get_version()); + datalist_set('simplecache_enabled', 1); + datalist_set('system_cache_enabled', 1); + + // new installations have run all the upgrades + $upgrades = elgg_get_upgrade_files($submissionVars['path'] . 'engine/lib/upgrades/'); + datalist_set('processed_upgrades', serialize($upgrades)); set_config('view', 'default', $site->getGUID()); - set_config('language', $submissionVars['language'], $site->getGUID()); + set_config('language', 'en', $site->getGUID()); set_config('default_access', $submissionVars['siteaccess'], $site->getGUID()); set_config('allow_registration', TRUE, $site->getGUID()); set_config('walled_garden', FALSE, $site->getGUID()); + set_config('allow_user_default_access', '', $site->getGUID()); $this->enablePlugins(); - // reset the views path in case of installing over an old data dir. - $dataroot = datalist_get('dataroot'); - $cache = new ElggFileCache($dataroot); - $cache->delete('view_paths'); - return TRUE; } /** * Enable a set of default plugins + * + * @return void */ protected function enablePlugins() { - // activate plugins with manifest.xml: elgg_install_state = enabled - $plugins = get_plugin_list(); + elgg_generate_plugin_entities(); + $plugins = elgg_get_plugins('any'); foreach ($plugins as $plugin) { - if ($manifest = load_plugin_manifest($plugin)) { - if (isset($manifest['elgg_install_state']) && $manifest['elgg_install_state'] == 'enabled') { - enable_plugin($plugin); + if ($plugin->getManifest()) { + if ($plugin->getManifest()->getActivateOnInstall()) { + $plugin->activate(); } } } @@ -1171,8 +1477,9 @@ class ElggInstaller { /** * Validate account form variables * - * @param array $submissionVars - * @param array $formVars + * @param array $submissionVars Submitted vars + * @param array $formVars Form vars + * * @return bool */ protected function validateAdminVars($submissionVars, $formVars) { @@ -1180,7 +1487,7 @@ class ElggInstaller { foreach ($formVars as $field => $info) { if ($info['required'] == TRUE && !$submissionVars[$field]) { $name = elgg_echo("install:admin:label:$field"); - register_error(sprintf(elgg_echo('install:error:requiredfield'), $name)); + register_error(elgg_echo('install:error:requiredfield', array($name))); return FALSE; } } @@ -1203,7 +1510,7 @@ class ElggInstaller { // check that email address is email address if ($submissionVars['email'] && !is_email_address($submissionVars['email'])) { - $msg = sprintf(elgg_echo('install:error:emailaddress'), $submissionVars['email']); + $msg = elgg_echo('install:error:emailaddress', array($submissionVars['email'])); register_error($msg); return FALSE; } @@ -1214,36 +1521,44 @@ class ElggInstaller { /** * Create a user account for the admin * - * @param array $submissionVars - * @param bool $login Login in the admin user? + * @param array $submissionVars Submitted vars + * @param bool $login Login in the admin user? + * * @return bool */ protected function createAdminAccount($submissionVars, $login = FALSE) { global $CONFIG; - $guid = register_user( - $submissionVars['username'], - $submissionVars['password1'], - $submissionVars['displayname'], - $submissionVars['email'] - ); + try { + $guid = register_user( + $submissionVars['username'], + $submissionVars['password1'], + $submissionVars['displayname'], + $submissionVars['email'] + ); + } catch (Exception $e) { + register_error($e->getMessage()); + return false; + } if (!$guid) { register_error(elgg_echo('install:admin:cannot_create')); - return FALSE; + return false; } $user = get_entity($guid); if (!$user) { register_error(elgg_echo('install:error:loadadmin')); - return FALSE; + return false; } elgg_set_ignore_access(TRUE); if ($user->makeAdmin() == FALSE) { register_error(elgg_echo('install:error:adminaccess')); + } else { + datalist_set('admin_registered', 1); } - elgg_set_ignore_access(FALSE); + elgg_set_ignore_access(false); // add validation data to satisfy user validation plugins create_metadata($guid, 'validated', TRUE, '', 0, ACCESS_PUBLIC); @@ -1251,7 +1566,7 @@ class ElggInstaller { if ($login) { if (login($user) == FALSE) { - register_error(elgg_echo('install:error:adminlogin')); + register_error(elgg_echo('install:error:adminlogin')); } } |
