aboutsummaryrefslogtreecommitdiff
path: root/install
diff options
context:
space:
mode:
Diffstat (limited to 'install')
-rw-r--r--install/ElggInstaller.php903
-rw-r--r--install/ElggRewriteTester.php199
-rw-r--r--install/cli/sample_installer.php67
-rw-r--r--install/css/install.css (renamed from install/install.css)135
-rw-r--r--install/js/install.js42
-rw-r--r--install/languages/en.php161
6 files changed, 1153 insertions, 354 deletions
diff --git a/install/ElggInstaller.php b/install/ElggInstaller.php
index 6d1553572..78cdde90f 100644
--- a/install/ElggInstaller.php
+++ b/install/ElggInstaller.php
@@ -1,14 +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.
+ *
+ * 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
+ * @package Elgg.Core
* @subpackage Installer
- * @author Curverider Ltd
- * @link http://elgg.org/
*/
-
class ElggInstaller {
protected $steps = array(
@@ -21,41 +39,52 @@ class ElggInstaller {
);
protected $status = array(
+ 'config' => FALSE,
'database' => FALSE,
'settings' => FALSE,
'admin' => FALSE,
);
- protected $isAction;
+ protected $isAction = 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();
-
+
$this->bootstrapEngine();
- elgg_set_viewtype('failsafe');
+ 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);
}
/**
* 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) {
- // check if this a mod rewrite test coming in
- $this->runModRewriteTest();
+ // check if this is a URL rewrite test coming in
+ $this->processRewriteTest();
if (!in_array($step, $this->getSteps())) {
- throw new InstallationException("$step is an unknown installation step.");
+ $msg = elgg_echo('InstallationException:UnknownStep', array($step));
+ throw new InstallationException($msg);
}
$this->setInstallStatus();
@@ -72,10 +101,115 @@ class ElggInstaller {
}
/**
+ * Set the auto login 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()) {
@@ -83,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/install',
+ 'default',
array(
'step' => $step,
'steps' => $this->getSteps(),
@@ -103,6 +237,8 @@ class ElggInstaller {
* Welcome controller
*
* @param array $vars Not used
+ *
+ * @return void
*/
protected function welcome($vars) {
$this->render('welcome');
@@ -113,26 +249,22 @@ class ElggInstaller {
*
* Checks version of php, libraries, permissions, and rewrite rules
*
- * @param array $vars
+ * @param array $vars Vars
+ *
+ * @return void
*/
protected function requirements($vars) {
$report = array();
-
+
// check PHP parameters and libraries
$this->checkPHP($report);
- // @todo - rewrite this to handle different web servers
- // attempt to create .htaccess file
- $htaccessExists = $this->createHtaccess($report);
+ // check URL rewriting
+ $this->checkRewriteRules($report);
- // check rewrite module
- if ($htaccessExists) {
- $this->checkRewriteModule($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);
}
@@ -161,10 +293,12 @@ class ElggInstaller {
/**
* Database set up controller
- *
+ *
* Creates the settings.php file and creates the database tables
*
* @param array $submissionVars Submitted form variables
+ *
+ * @return void
*/
protected function database($submissionVars) {
@@ -177,7 +311,7 @@ class ElggInstaller {
'dbpassword' => array(
'type' => 'password',
'value' => '',
- 'required' => TRUE,
+ 'required' => FALSE,
),
'dbname' => array(
'type' => 'text',
@@ -215,7 +349,7 @@ class ElggInstaller {
}
}
- // check db version and connect
+ // check db version and connect
if (!$this->connectToDatabase()) {
break;
}
@@ -224,7 +358,7 @@ class ElggInstaller {
break;
}
- system_message('Database has been installed.');
+ system_message(elgg_echo('install:success:database'));
$this->continueToNextStep('database');
} while (FALSE); // PHP doesn't support breaking out of if statements
@@ -247,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(
@@ -266,7 +401,7 @@ class ElggInstaller {
),
'wwwroot' => array(
'type' => 'text',
- 'value' => $CONFIG->wwwroot,
+ 'value' => elgg_get_site_url(),
'required' => TRUE,
),
'path' => array(
@@ -279,21 +414,26 @@ class ElggInstaller {
'value' => '',
'required' => TRUE,
),
- 'language' => array(
- 'type' => 'pulldown',
- 'value' => 'en',
- 'options_values' => $languages,
- 'required' => TRUE,
- ),
'siteaccess' => array(
'type' => 'access',
'value' => ACCESS_PUBLIC,
'required' => TRUE,
),
);
-
+
+ // 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;
}
@@ -301,14 +441,14 @@ class ElggInstaller {
if (!$this->saveSiteSettings($submissionVars)) {
break;
}
-
- system_message('Site settings have been saved.');
+
+ system_message(elgg_echo('install:success:settings'));
$this->continueToNextStep('settings');
} while (FALSE); // PHP doesn't support breaking out of if statements
}
-
+
$formVars = $this->makeFormSticky($formVars, $submissionVars);
$this->render('settings', array('variables' => $formVars));
@@ -319,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(
@@ -349,24 +491,31 @@ class ElggInstaller {
'required' => TRUE,
),
);
-
+
if ($this->isAction) {
do {
if (!$this->validateAdminVars($submissionVars, $formVars)) {
break;
}
- if (!$this->createAdminAccount($submissionVars)) {
+ if (!$this->createAdminAccount($submissionVars, $this->autoLogin)) {
break;
}
-
- system_message('Admin account has been created.');
+
+ system_message(elgg_echo('install:success:admin'));
$this->continueToNextStep('admin');
} while (FALSE); // PHP doesn't support breaking out of if statements
}
-
+
+ // bit of a hack to get the password help to show right number of characters
+ 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);
+
$formVars = $this->makeFormSticky($formVars, $submissionVars);
$this->render('admin', array('variables' => $formVars));
@@ -375,11 +524,18 @@ class ElggInstaller {
/**
* Controller for last step
*
- * @param array $vars
+ * @return void
*/
- protected function complete($vars) {
+ protected function complete() {
- $this->render('complete');
+ $params = array();
+ if ($this->autoLogin) {
+ $params['destination'] = 'admin';
+ } else {
+ $params['destination'] = 'index.php';
+ }
+
+ $this->render('complete', $params);
}
/**
@@ -397,8 +553,10 @@ 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;
@@ -408,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,
@@ -452,7 +620,8 @@ class ElggInstaller {
}
if (!include_once("{$CONFIG->path}engine/lib/database.php")) {
- throw new InstallationException("Could not load database.php");
+ $msg = elgg_echo('InstallationException:MissingLibrary', array('database.php'));
+ throw new InstallationException($msg);
}
// check that the config table has been created
@@ -468,6 +637,9 @@ class ElggInstaller {
if ($this->status['database'] == FALSE) {
return;
}
+ } else {
+ // no tables
+ return;
}
// check that the config table has entries
@@ -493,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') {
@@ -508,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) {
@@ -524,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");
}
/**
@@ -541,6 +716,8 @@ class ElggInstaller {
/**
* Load the essential libraries of the engine
+ *
+ * @return void
*/
protected function bootstrapEngine() {
global $CONFIG;
@@ -549,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) {
@@ -565,58 +743,83 @@ 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) {
- // install has its own session handling
- session_name('Elgg');
- session_start();
- unregister_elgg_event_handler('boot', 'system', 'session_init');
-
- // once the database has been created, load rest of engine
$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());
+ // 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();
+ elgg_unregister_event_handler('boot', 'system', 'session_init');
+ }
+
if ($stepIndex > $dbIndex) {
+ // once the database has been created, load rest of engine
global $CONFIG;
$lib_dir = $CONFIG->path . 'engine/lib/';
$this->loadSettingsFile();
-
+
$lib_files = array(
// 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)) {
- throw new InstallationException("Could not load {$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;
@@ -627,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() {
@@ -651,11 +861,18 @@ class ElggInstaller {
return $url;
}
- function loadSettingsFile() {
+ /**
+ * Load settings.php
+ *
+ * @return void
+ * @throws InstallationException
+ */
+ protected function loadSettingsFile() {
global $CONFIG;
-
+
if (!include_once("{$CONFIG->path}engine/settings.php")) {
- throw new InstallationException("Elgg could not load the settings file. It does not exist or there is a permissions issue.");
+ $msg = elgg_echo('InstallationException:CannotLoadSettings');
+ throw new InstallationException($msg);
}
}
@@ -666,7 +883,10 @@ class ElggInstaller {
/**
* Return an associative array of post variables
* (could be selective based on expected variables)
- *
+ *
+ * Does not filter as person installing the site should not be attempting
+ * XSS attacks. If filtering is added, it should not be done for passwords.
+ *
* @return array
*/
protected function getPostVariables() {
@@ -680,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) {
@@ -696,70 +917,18 @@ class ElggInstaller {
*/
/**
- * Create Elgg's .htaccess file or confirm that it exists
- *
- * @param array $report Reference to the report array
- * @return bool
- */
- protected function createHtaccess(&$report) {
- global $CONFIG;
-
- $filename = "{$CONFIG->path}.htaccess";
- if (file_exists($filename)) {
- // check that this is the Elgg .htaccess
- $data = file_get_contents($filename);
- if ($data === FALSE) {
- // don't have permission to read the file
- }
- if (strpos($data, 'Elgg') === FALSE) {
- $report['htaccess'] = array(
- array(
- 'severity' => 'failure',
- 'message' => elgg_echo('install:check:htaccess_exists'),
- )
- );
- return FALSE;
- } else {
- // Elgg .htaccess is already there
- return TRUE;
- }
- }
-
- if (!is_writable($CONFIG->path)) {
- $report['htaccess'] = array(
- array(
- 'severity' => 'failure',
- 'message' => elgg_echo('install:check:root'),
- )
- );
- return FALSE;
- }
-
- // create the .htaccess file
- $result = copy("{$CONFIG->path}htaccess_dist", $filename);
- if (!$result) {
- $report['htaccess'] = array(
- array(
- 'severity' => 'failure',
- 'message' => elgg_echo('install:check:htaccess_fail'),
- )
- );
- }
-
- return $result;
- }
-
- /**
* Check that the engine dir is writable
- * @param array $report
+ *
+ * @param array &$report The requirements report object
+ *
* @return bool
*/
protected function checkEngineDir(&$report) {
global $CONFIG;
-
+
$writable = is_writable("{$CONFIG->path}engine");
if (!$writable) {
- $report['engine'] = array(
+ $report['settings'] = array(
array(
'severity' => 'failure',
'message' => elgg_echo('install:check:enginedir'),
@@ -773,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();
@@ -796,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))
);
}
@@ -817,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();
@@ -831,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))
);
}
}
@@ -843,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))
);
}
}
@@ -851,8 +1037,10 @@ 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')) {
@@ -868,65 +1056,54 @@ class ElggInstaller {
'message' => elgg_echo("install:check:php:safe_mode")
);
}
- }
- /**
- * Confirm that Apache's rewrite module and AllowOverride are set up
- * @param array $report
- * @return bool
- */
- protected function checkRewriteModule(&$report) {
- global $CONFIG;
-
- $url = "{$CONFIG->wwwroot}modrewrite.php";
-
- if (function_exists('curl_init')) {
- // try curl if installed
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- $response = curl_exec($ch);
- curl_close($ch);
- $result = $response === 'success';
- } else if (ini_get('allow_url_fopen')) {
- // use file_get_contents as fallback
- $data = file_get_contents($url);
- $result = $data === 'success';
- } else {
- $report['htaccess'] = array(
- array(
- 'severity' => 'warning',
- 'message' => elgg_echo('install:check:rewrite:unknown'),
- )
+ 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,
);
- return FALSE;
}
- if ($result) {
- $report['htaccess'] = array(
- array(
- 'severity' => 'pass',
- 'message' => elgg_echo('install:check:rewrite:success'),
- )
+ if (ini_get('register_globals')) {
+ $phpReport[] = array(
+ 'severity' => 'failure',
+ 'message' => elgg_echo("install:check:php:register_globals")
);
- } else {
- $report['htaccess'] = array(
- array(
- 'severity' => 'failure',
- 'message' => elgg_echo('install:check:rewrite:fail'),
- )
+ }
+
+ if (ini_get('session.auto_start')) {
+ $phpReport[] = array(
+ 'severity' => 'failure',
+ 'message' => elgg_echo("install:check:php:session.auto_start")
);
}
+ }
- return $result;
+ /**
+ * Confirm that the rewrite rules are firing
+ *
+ * @param array &$report The requirements report array
+ *
+ * @return void
+ */
+ protected function checkRewriteRules(&$report) {
+ global $CONFIG;
+
+ $tester = new ElggRewriteTester();
+ $url = elgg_get_site_url() . "rewrite.php";
+ $report['rewrite'] = array($tester->run($url, $CONFIG->path));
}
/**
- * Check if the request is coming from the mod rewrite test on the
+ * Check if the request is coming from the URL rewrite test on the
* requirements page.
+ *
+ * @return void
*/
- protected function runModRewriteTest() {
- if (strpos($_SERVER['REQUEST_URI'], 'modrewrite.php') !== FALSE) {
+ protected function processRewriteTest() {
+ if (strpos($_SERVER['REQUEST_URI'], 'rewrite.php') !== FALSE) {
echo 'success';
exit;
}
@@ -935,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) {
@@ -952,7 +1130,7 @@ class ElggInstaller {
return $count;
}
-
+
/**
* Database support methods
*/
@@ -960,20 +1138,31 @@ 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) {
foreach ($formVars as $field => $info) {
if ($info['required'] == TRUE && !$submissionVars[$field]) {
- $name = elgg_echo("installation:database:label:$field");
- register_error("$name is required");
+ $name = elgg_echo("install:database:label:$field");
+ 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'],
@@ -985,33 +1174,35 @@ 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
*/
- function checkDatabaseSettings($user, $password, $dbname, $host) {
+ protected function checkDatabaseSettings($user, $password, $dbname, $host) {
$mysql_dblink = mysql_connect($host, $user, $password, true);
if ($mysql_dblink == FALSE) {
- register_error('Unable to connect to the database with these settings.');
+ register_error(elgg_echo('install:error:databasesettings'));
return $FALSE;
}
$result = mysql_select_db($dbname, $mysql_dblink);
// check MySQL version - must be 5.0 or >
+ $required_version = 5.0;
$version = mysql_get_server_info();
$points = explode('.', $version);
- if ($points[0] < 5) {
- register_error("MySQL must be 5.0 or above. Your server is using $version.");
+ if ($points[0] < $required_version) {
+ register_error(elgg_echo('install:error:oldmysql', array($version)));
return FALSE;
}
mysql_close($mysql_dblink);
if (!$result) {
- register_error("Unable to use database $dbname");
+ register_error(elgg_echo('install:error:nodatabase', array($dbname)));
}
return $result;
@@ -1020,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) {
@@ -1029,18 +1221,18 @@ class ElggInstaller {
$templateFile = "{$CONFIG->path}engine/settings.example.php";
$template = file_get_contents($templateFile);
if (!$template) {
- register_error('Unable to read engine/settings.example.php');
+ register_error(elgg_echo('install:error:readsettingsphp'));
return FALSE;
}
foreach ($params as $k => $v) {
- $template = str_replace("{{".$k."}}", $v, $template);
+ $template = str_replace("{{" . $k . "}}", $v, $template);
}
$settingsFilename = "{$CONFIG->path}engine/settings.php";
$result = file_put_contents($settingsFilename, $template);
if (!$result) {
- register_error('Unable to write engine/settings.php');
+ register_error(elgg_echo('install:error:writesettingphp'));
return FALSE;
}
@@ -1056,12 +1248,13 @@ class ElggInstaller {
global $CONFIG;
if (!include_once("{$CONFIG->path}engine/settings.php")) {
- register_error("Elgg could not load the settings file.");
+ register_error(elgg_echo('InstallationException:CannotLoadSettings'));
return FALSE;
}
if (!include_once("{$CONFIG->path}engine/lib/database.php")) {
- register_error("Elgg could not load the database library.");
+ $msg = elgg_echo('InstallationException:MissingLibrary', array('database.php'));
+ register_error($msg);
return FALSE;
}
@@ -1077,7 +1270,7 @@ class ElggInstaller {
/**
* Create the database tables
- *
+ *
* @return bool
*/
protected function installDatabase() {
@@ -1086,10 +1279,14 @@ class ElggInstaller {
try {
run_sql_script("{$CONFIG->path}engine/schema/mysql.sql");
} catch (Exception $e) {
- register_error($e->getMessage());
+ $msg = $e->getMessage();
+ if (strpos($msg, 'already exists')) {
+ $msg = elgg_echo('install:error:tables_exist');
+ }
+ register_error($msg);
return FALSE;
}
-
+
return TRUE;
}
@@ -1098,43 +1295,105 @@ 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]) {
- $name = elgg_echo("installation:settings:label:$field");
- register_error("$name is required");
+ $submissionVars[$field] = trim($submissionVars[$field]);
+ if ($info['required'] == TRUE && $submissionVars[$field] === '') {
+ $name = elgg_echo("install:settings:label:$field");
+ register_error(elgg_echo('install:error:requiredfield', array($name)));
+ return FALSE;
+ }
+ }
+
+ // 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 writable
if (!is_writable($submissionVars['dataroot'])) {
- register_error("Your data directory {$submissionVars['dataroot']} is not writable by the web server.");
+ $msg = elgg_echo('install:error:writedatadirectory', 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) {
- register_error("Your data directory {$submissionVars['dataroot']} must be outside of your install path for security.");
- 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;
+ }
}
- // @todo move is_email_address to a better library than users.php
// check that email address is email address
- //if ($submissionVars['siteemail'] && !is_email_address($submissionVars['siteemail'])) {
- // register_error("{$submissionVars['']} is not a valid email address.");
- // return FALSE;
- //}
+ if ($submissionVars['siteemail'] && !is_email_address($submissionVars['siteemail'])) {
+ $msg = elgg_echo('install:error:emailaddress', array($submissionVars['siteemail']));
+ register_error($msg);
+ return FALSE;
+ }
// @todo check that url is a url
-
+ // @note filter_var cannot be used because it doesn't work on international urls
return TRUE;
}
@@ -1142,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) {
@@ -1154,14 +1414,14 @@ 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("Unable to create the site.");
+ register_error(elgg_echo('install:error:createsite'));
return FALSE;
}
@@ -1174,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();
}
}
}
@@ -1213,27 +1477,41 @@ 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) {
-
+
foreach ($formVars as $field => $info) {
if ($info['required'] == TRUE && !$submissionVars[$field]) {
- $name = elgg_echo("installation:admin:label:$field");
- register_error("$name is required");
+ $name = elgg_echo("install:admin:label:$field");
+ register_error(elgg_echo('install:error:requiredfield', array($name)));
return FALSE;
}
}
if ($submissionVars['password1'] !== $submissionVars['password2']) {
- register_error("Your passwords must match.");
+ register_error(elgg_echo('install:admin:password:mismatch'));
return FALSE;
}
if (trim($submissionVars['password1']) == "") {
- register_error("Password cannot be empty.");
+ register_error(elgg_echo('install:admin:password:empty'));
+ return FALSE;
+ }
+
+ $minLength = get_config('min_password_length');
+ if (strlen($submissionVars['password1']) < $minLength) {
+ register_error(elgg_echo('install:admin:password:tooshort'));
+ return FALSE;
+ }
+
+ // check that email address is email address
+ if ($submissionVars['email'] && !is_email_address($submissionVars['email'])) {
+ $msg = elgg_echo('install:error:emailaddress', array($submissionVars['email']));
+ register_error($msg);
return FALSE;
}
@@ -1243,30 +1521,53 @@ class ElggInstaller {
/**
* Create a user account for the admin
*
- * @param array $submissionVars
+ * @param array $submissionVars Submitted vars
+ * @param bool $login Login in the admin user?
+ *
* @return bool
*/
- protected function createAdminAccount($submissionVars) {
+ 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("Unable to create an admin account.");
- return FALSE;
+ register_error(elgg_echo('install:admin:cannot_create'));
+ return false;
}
- // @todo - register plugin hook instead for can edit
- // need a logged in user to set admin flag so we go directly to database
- $result = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='yes' where guid=$guid");
- if (!$result) {
- register_error("Unable to give new user account admin privileges.");
- return FALSE;
+ $user = get_entity($guid);
+ if (!$user) {
+ register_error(elgg_echo('install:error:loadadmin'));
+ 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);
+
+ // add validation data to satisfy user validation plugins
+ create_metadata($guid, 'validated', TRUE, '', 0, ACCESS_PUBLIC);
+ create_metadata($guid, 'validated_method', 'admin_user', '', 0, ACCESS_PUBLIC);
+
+ if ($login) {
+ if (login($user) == FALSE) {
+ register_error(elgg_echo('install:error:adminlogin'));
+ }
}
return TRUE;
diff --git a/install/ElggRewriteTester.php b/install/ElggRewriteTester.php
new file mode 100644
index 000000000..ab68da2b7
--- /dev/null
+++ b/install/ElggRewriteTester.php
@@ -0,0 +1,199 @@
+<?php
+
+/**
+ * Elgg RewriteTester.
+ * Test if URL rewriting is working.
+ *
+ * @package Elgg.Core
+ * @subpackage Installer
+ */
+class ElggRewriteTester {
+ protected $webserver;
+ protected $serverSupportsRemoteRead;
+ protected $rewriteTestPassed;
+ protected $htaccessIssue;
+
+ /**
+ * Set the webserver as unknown.
+ */
+ public function __construct() {
+ $this->webserver = 'unknown';
+ }
+
+ /**
+ * Run the rewrite test and return a status array
+ *
+ * @param string $url URL of rewrite test
+ * @param string $path Root directory of Elgg with trailing slash
+ *
+ * @return array
+ */
+ public function run($url, $path) {
+
+ $this->webserver = ElggRewriteTester::guessWebServer();
+
+ $this->rewriteTestPassed = $this->runRewriteTest($url);
+
+ if ($this->rewriteTestPassed == FALSE) {
+ if ($this->webserver == 'apache' || $this->webserver == 'unknown') {
+ if ($this->createHtaccess($path)) {
+ $this->rewriteTestPassed = $this->runRewriteTest($url);
+ }
+ }
+ }
+
+ return $this->returnStatus($url);
+ }
+
+ /**
+ * Guess the web server from $_SERVER['SERVER_SOFTWARE']
+ *
+ * @return string
+ */
+ public static function guessWebServer() {
+ $serverString = strtolower($_SERVER['SERVER_SOFTWARE']);
+ $possibleServers = array('apache', 'nginx', 'lighttpd', 'iis');
+ foreach ($possibleServers as $server) {
+ if (strpos($serverString, $server) !== FALSE) {
+ return $server;
+ }
+ }
+ return 'unknown';
+ }
+
+ /**
+ * Hit the rewrite test URL to determine if the rewrite rules are working
+ *
+ * @param string $url Rewrite test URL
+ *
+ * @return bool
+ */
+ protected function runRewriteTest($url) {
+
+ $this->serverSupportsRemoteRead = TRUE;
+
+ if (function_exists('curl_init')) {
+ // try curl if installed
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec($ch);
+ curl_close($ch);
+ return $response === 'success';
+ } else if (ini_get('allow_url_fopen')) {
+ // use file_get_contents as fallback
+ $response = file_get_contents($url);
+ return $response === 'success';
+ } else {
+ $this->serverSupportsRemoteRead = FALSE;
+ return FALSE;
+ }
+ }
+
+ /**
+ * Create Elgg's .htaccess file or confirm that it exists
+ *
+ * @param string $path Elgg's root directory with trailing slash
+ *
+ * @return bool
+ */
+ public function createHtaccess($path) {
+ $filename = "{$path}.htaccess";
+ if (file_exists($filename)) {
+ // check that this is the Elgg .htaccess
+ $data = file_get_contents($filename);
+ if ($data === FALSE) {
+ // don't have permission to read the file
+ $this->htaccessIssue = 'read_permission';
+ return FALSE;
+ }
+ if (strpos($data, 'Elgg') === FALSE) {
+ $this->htaccessIssue = 'non_elgg_htaccess';
+ return FALSE;
+ } else {
+ // check if this is an old Elgg htaccess
+ if (strpos($data, 'RewriteRule ^rewrite.php$ install.php') == FALSE) {
+ $this->htaccessIssue = 'old_elgg_htaccess';
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+
+ if (!is_writable($path)) {
+ $this->htaccessIssue = 'write_permission';
+ return FALSE;
+ }
+
+ // create the .htaccess file
+ $result = copy("{$path}htaccess_dist", $filename);
+ if (!$result) {
+ $this->htaccessIssue = 'cannot_copy';
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Create the status array required by the ElggInstaller
+ *
+ * @param string $url Rewrite test URL
+ *
+ * @return array
+ */
+ protected function returnStatus($url) {
+ if ($this->rewriteTestPassed) {
+ return array(
+ 'severity' => 'pass',
+ 'message' => elgg_echo('install:check:rewrite:success'),
+ );
+ }
+
+ if ($this->serverSupportsRemoteRead == FALSE) {
+ $msg = elgg_echo('install:warning:rewrite:unknown', array($url));
+ $msg .= elgg_view('install/js_rewrite_check', array('url' => $url));
+
+ return array(
+ 'severity' => 'warning',
+ 'message' => $msg,
+ );
+ }
+
+ if ($this->webserver == 'apache') {
+ $serverString = elgg_echo('install:error:rewrite:apache');
+ $msg = "$serverString\n\n";
+ if (!isset($this->htaccessIssue)) {
+ $msg .= elgg_echo('install:error:rewrite:allowoverride');
+ $msg .= elgg_view('install/js_rewrite_check', array('url' => $url));
+
+ return array(
+ 'severity' => 'failure',
+ 'message' => $msg,
+ );
+ }
+ $msg .= elgg_echo("install:error:rewrite:htaccess:{$this->htaccessIssue}");
+ return array(
+ 'severity' => 'failure',
+ 'message' => $msg,
+ );
+ }
+
+ if ($this->webserver != 'unknown') {
+ $serverString = elgg_echo("install:error:rewrite:{$this->webserver}");
+ $msg = "$serverString\n\n";
+ $msg .= elgg_echo("install:error:rewrite:altserver");
+ return array(
+ 'severity' => 'failure',
+ 'message' => $msg,
+ );
+ }
+
+ return array(
+ 'severity' => 'failure',
+ 'message' => elgg_echo('install:error:rewrite:unknown'),
+ );
+ }
+} \ No newline at end of file
diff --git a/install/cli/sample_installer.php b/install/cli/sample_installer.php
new file mode 100644
index 000000000..a51f9aae4
--- /dev/null
+++ b/install/cli/sample_installer.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * Sample cli installer script
+ */
+
+// change to true to run this script. Change back to false when done.
+$enabled = false;
+
+// none of the following may be empty
+$params = array(
+ // database parameters
+ 'dbuser' => '',
+ 'dbpassword' => '',
+ 'dbname' => '',
+
+ // site settings
+ 'sitename' => '',
+ 'siteemail' => '',
+ 'wwwroot' => '',
+ 'dataroot' => '',
+
+ // admin account
+ 'displayname' => '',
+ 'email' => '',
+ 'username' => '',
+ 'password' => '',
+);
+
+
+// Do not edit below this line. //////////////////////////////
+
+
+if (!$enabled) {
+ echo "To enable this script, change \$enabled to true.\n";
+ echo "You *must* disable this script after a successful installation.\n";
+ exit;
+}
+
+if (PHP_SAPI !== 'cli') {
+ echo "You must use the command line to run this script.";
+ exit;
+}
+
+require_once(dirname(dirname(__FILE__)) . "/ElggInstaller.php");
+
+$installer = new ElggInstaller();
+
+// install and create the .htaccess file
+$installer->batchInstall($params, TRUE);
+
+// at this point installation has completed (otherwise an exception halted execution).
+// try to rewrite the script to disable it.
+if (is_writable(__FILE__)) {
+ $code = file_get_contents(__FILE__);
+ if (preg_match('~\\$enabled\\s*=\\s*(true|1)\\s*;~i', $code)) {
+ // looks safe to rewrite
+ $code = preg_replace('~\\$enabled\\s*=\\s*(true|1)\\s*;~i', '$enabled = false;', $code);
+ file_put_contents(__FILE__, $code);
+
+ echo "\nNote: This script has been disabled for your safety.\n";
+ exit;
+ }
+}
+
+echo "\nWarning: You *must* disable this script by setting \$enabled = false;.\n";
+echo "Leaving this script enabled could endanger your installation.\n";
diff --git a/install/install.css b/install/css/install.css
index de10f10a5..e7290c130 100644
--- a/install/install.css
+++ b/install/css/install.css
@@ -62,37 +62,44 @@ ul {
list-style: none;
}
-.clearfloat {
- clear:both;
- height:0;
- font-size: 1px;
- line-height: 0px;
-}
-
-#elgg_wrapper {
- background: white;
- width: 800px;
+.elgg-page {
+ width: 880px;
margin: auto;
- padding: 10px 40px;
margin-top: 20px;
+}
+.elgg-page-header {
border-right: 1px solid #666666;
+ padding: 15px 50px 10px;
+ background: white;
+}
+.elgg-page-body {
border-bottom: 1px solid #666666;
+ border-right: 1px solid #666666;
+ padding: 0 40px 5px;
+ background: white;
}
-#elgg_header {
- margin: 20px 10px;
+
+.elgg-page-body:after,
+.elgg-page-header:after {
+ display: block;
+ content: '.';
+ line-height: 0;
+ height: 0;
+ visibility: hidden;
+ clear: both;
}
-#elgg_sidebar {
+
+.elgg-sidebar {
float: left;
width: 250px;
}
-#elgg_content {
- float: left;
- width: 550px;
+.elgg-body {
+ overflow: hidden;
min-height: 320px;
- padding-bottom: 60px;
+ padding-bottom: 10px;
position: relative;
}
-#elgg_footer {
+.elgg-page-footer {
width: 800px;
height: 20px;
clear: both;
@@ -101,28 +108,28 @@ ul {
margin-bottom: 40px;
}
-.install_nav {
+.elgg-install-nav {
width: 100%;
text-align: right;
position: absolute;
bottom: 0px;
}
-#elgg_footer a {
+.elgg-page-footer a {
color: white;
}
-#elgg_footer li {
+.elgg-page-footer li {
float: left;
list-style: none;
margin-right: 20px;
}
-#elgg_sidebar ol {
+.elgg-sidebar ol {
padding-left: 30px;
}
-#elgg_sidebar li {
+.elgg-sidebar li {
font-size: 1.2em;
margin-bottom: 5px;
}
@@ -142,105 +149,121 @@ h3 {
margin: 15px 0 5px;
}
+form > div {
+ margin-bottom: 15px;
+}
label {
font-weight: bold;
- color:#333333;
+ color: #333333;
font-size: 140%;
}
+.elgg-combo-label {
+ font-size: 120%;
+}
input[type="text"],
input[type="password"] {
font: 120% Arial, Helvetica, sans-serif;
padding: 5px;
border: 1px solid #cccccc;
- color:#666666;
- width:566px;
+ color: #666666;
+ width: 96%;
}
-.database_settings input[type="text"],
-.database_settings input[type="password"] {
- width:220px;
+.database-settings input[type="text"],
+.database-settings input[type="password"] {
+ width: 220px;
}
-textarea {
- width: 100%;
- height: 100%;
- font: 120% Arial, Helvetica, sans-serif;
- border: solid 1px #cccccc;
- padding: 5px;
- color:#666666;
-}
-textarea:focus, input[type="password"]:focus, input[type="text"]:focus {
+input[type="password"]:focus, input[type="text"]:focus {
border: solid 1px #4690d6;
background: #e4ecf5;
- color:#333333;
+ color: #333333;
}
input[type="submit"] {
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
font-weight: bold;
- color: #ffffff;
+ color: #fff;
background: #4690d6;
border: 4px solid #4690d6;
+
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
+ border-radius: 4px;
+
width: auto;
height: 35px;
- padding: 2px 6px 2px 6px;
- margin: 10px 0 10px 0;
+ padding: 2px 6px;
+ margin: 10px 0;
cursor: pointer;
float: right;
}
-
input[type="submit"]:hover {
background: #0054a7;
border: 4px solid #0054a7;
}
-
select {
display: block;
padding: 5px;
}
-.install_nav a {
+.install-help {
+ font-size: 90%;
+}
+
+.elgg-require-database {
+ padding-bottom: 50px;
+}
+
+.elgg-install-nav a {
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
font-weight: bold;
color: #ffffff;
background: #4690d6;
border: 4px solid #4690d6;
+
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
- padding: 2px 9px 2px 9px;
+ border-radius: 4px;
+
+ padding: 2px 9px;
margin: 10px;
cursor: pointer;
float: right;
}
-.install_nav a:hover {
+.elgg-install-nav a:hover {
text-decoration: none;
background: #0054a7;
border: 4px solid #0054a7;
}
-.install_nav .disabled, .install_nav .disabled:hover {
+.elgg-install-nav .elgg-state-disabled,
+.elgg-install-nav .elgg-state-disabled:hover {
background: #555555;
border-color: #555555;
cursor: default;
}
-#elgg_system_message {
+.elgg-system-messages li {
padding: 3px 10px 3px 10px;
margin-bottom: 20px;
}
-.success {
+.elgg-state-success {
border: 1px solid #00cc00;
background: #ccffcc;
}
-.error {
+.elgg-state-error {
border: 1px solid #D3322A;
background: #F7DAD8;
}
-#elgg_content li {
+.elgg-state-warning {
+ border: 1px solid #ded0a9;
+ background: #FEF5AA;
+}
+
+.elgg-body li {
margin-top: 5px;
padding: 5px;
}
@@ -264,3 +287,9 @@ select {
border: 1px solid #aaaaaa;
background: #ffffff;
}
+
+.messages {
+ padding: 3px 10px 3px 10px;
+ margin: 20px 0px 10px 0px;
+ width: 95%;
+} \ No newline at end of file
diff --git a/install/js/install.js b/install/js/install.js
new file mode 100644
index 000000000..37e5b0dc3
--- /dev/null
+++ b/install/js/install.js
@@ -0,0 +1,42 @@
+
+$(function() {
+ // prevent double-submission of forms
+ $('form').submit(function() {
+ if ($(this).data('submitted')) {
+ return false;
+ }
+ $(this).data('submitted', true);
+ return true;
+ });
+
+ // toggle the disable attribute of text box based on checkbox
+ $('.elgg-combo-checkbox').click(function() {
+ if ($(this).is(':checked')) {
+ $(this).prev().attr('disabled', true);
+ $(this).prev().val('');
+ } else {
+ $(this).prev().attr('disabled', false);
+ }
+ });
+});
+
+elgg = {
+ installer: {}
+};
+
+/**
+ * Check the rewrite address for "success" and then allows the installation to proceed.
+ */
+elgg.installer.rewriteTest = function(url, success_msg, nextURL) {
+ $.ajax(url, {
+ success: function(data, status, xhr) {
+ if (data == 'success') {
+ $('.elgg-require-rewrite li').attr('class', 'pass');
+ $('.elgg-require-rewrite li').html('<p>' + success_msg + '</p>');
+ $('.elgg-install-nav a.elgg-state-disabled')
+ .removeClass('elgg-state-disabled')
+ .attr('href', nextURL);
+ }
+ }
+ });
+}
diff --git a/install/languages/en.php b/install/languages/en.php
new file mode 100644
index 000000000..531379b1e
--- /dev/null
+++ b/install/languages/en.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * Installer English Language
+ *
+ * @package ElggLanguage
+ * @subpackage Installer
+ */
+
+$english = array(
+ 'install:title' => 'Elgg Install',
+ 'install:welcome' => 'Welcome',
+ 'install:requirements' => 'Requirements check',
+ 'install:database' => 'Database installation',
+ 'install:settings' => 'Configure site',
+ 'install:admin' => 'Create admin account',
+ 'install:complete' => 'Finished',
+
+ 'install:next' => 'Next',
+ 'install:refresh' => 'Refresh',
+
+ 'install:welcome:instructions' => "Installing Elgg has 6 simple steps and reading this welcome is the first one!
+
+If you haven't already, read through the installation instructions included with Elgg (or click the instructions link at the bottom of the page).
+
+If you are ready to proceed, click the Next button.",
+ 'install:requirements:instructions:success' => "Your server passed the requirement checks.",
+ 'install:requirements:instructions:failure' => "Your server failed the requirements check. After you have fixed the below issues, refresh this page. Check the troubleshooting links at the bottom of this page if you need further assistance.",
+ 'install:requirements:instructions:warning' => "Your server passed the requirements check, but there is at least one warning. We recommend that you check the install troubleshooting page for more details.",
+
+ 'install:require:php' => 'PHP',
+ 'install:require:rewrite' => 'Web server',
+ 'install:require:settings' => 'Settings file',
+ 'install:require:database' => 'Database',
+
+ 'install:check:root' => 'Your web server does not have permission to create an .htaccess file in the root directory of Elgg. You have two choices:
+
+ 1. Change the permissions on the root directory
+
+ 2. Copy the file htaccess_dist to .htaccess',
+
+ 'install:check:php:version' => 'Elgg requires PHP %s or above. This server is using version %s.',
+ 'install:check:php:extension' => 'Elgg requires the PHP extension %s.',
+ 'install:check:php:extension:recommend' => 'It is recommended that the PHP extension %s is installed.',
+ 'install:check:php:open_basedir' => 'The open_basedir PHP directive may prevent Elgg from saving files to its data directory.',
+ 'install:check:php:safe_mode' => 'Running PHP in safe mode is not recommened and may cause problems with Elgg.',
+ 'install:check:php:arg_separator' => 'arg_separator.output must be & for Elgg to work and your server\'s value is %s',
+ 'install:check:php:register_globals' => 'Register globals must be turned off.',
+ 'install:check:php:session.auto_start' => "session.auto_start must be off for Elgg to work. Either change the configuration of your server or add this directive to Elgg's .htaccess file.",
+
+ 'install:check:enginedir' => 'Your web server does not have permission to create the settings.php file in the engine directory. You have two choices:
+
+ 1. Change the permissions on the engine directory
+
+ 2. Copy the file settings.example.php to settings.php and follow the instructions in it for setting your database parameters.',
+ 'install:check:readsettings' => 'A settings file exists in the engine directory, but the web server cannot read it. You can delete the file or change the read permissions on it.',
+
+ 'install:check:php:success' => "Your server's PHP satisfies all of Elgg's requirements.",
+ 'install:check:rewrite:success' => 'The test of the rewrite rules was successful.',
+ 'install:check:database' => 'The database requirements are checked when Elgg loads its database.',
+
+ 'install:database:instructions' => "If you haven't already created a database for Elgg, do that now. Then fill in the values below to initialize the Elgg database.",
+ 'install:database:error' => 'There was an error creating the Elgg database and installation cannot continue. Review the message above and correct any problems. If you need more help, visit the Install troubleshooting link below or post to the Elgg community forums.',
+
+ 'install:database:label:dbuser' => 'Database Username',
+ 'install:database:label:dbpassword' => 'Database Password',
+ 'install:database:label:dbname' => 'Database Name',
+ 'install:database:label:dbhost' => 'Database Host',
+ 'install:database:label:dbprefix' => 'Database Table Prefix',
+
+ 'install:database:help:dbuser' => 'User that has full privileges to the MySQL database that you created for Elgg',
+ 'install:database:help:dbpassword' => 'Password for the above database user account',
+ 'install:database:help:dbname' => 'Name of the Elgg database',
+ 'install:database:help:dbhost' => 'Hostname of the MySQL server (usually localhost)',
+ 'install:database:help:dbprefix' => "The prefix given to all of Elgg's tables (usually elgg_)",
+
+ 'install:settings:instructions' => 'We need some information about the site as we configure Elgg. If you haven\'t <a href="http://docs.elgg.org/wiki/Data_directory" target="_blank">created a data directory</a> for Elgg, you need to do so now.',
+
+ 'install:settings:label:sitename' => 'Site Name',
+ 'install:settings:label:siteemail' => 'Site Email Address',
+ 'install:settings:label:wwwroot' => 'Site URL',
+ 'install:settings:label:path' => 'Elgg Install Directory',
+ 'install:settings:label:dataroot' => 'Data Directory',
+ 'install:settings:label:language' => 'Site Language',
+ 'install:settings:label:siteaccess' => 'Default Site Access',
+ 'install:label:combo:dataroot' => 'Elgg creates data directory',
+
+ 'install:settings:help:sitename' => 'The name of your new Elgg site',
+ 'install:settings:help:siteemail' => 'Email address used by Elgg for communication with users',
+ 'install:settings:help:wwwroot' => 'The address of the site (Elgg usually guesses this correctly)',
+ 'install:settings:help:path' => 'The directory where you put the Elgg code (Elgg usually guesses this correctly)',
+ 'install:settings:help:dataroot' => 'The directory that you created for Elgg to save files (the permissions on this directory are checked when you click Next). It must be an absolute path.',
+ 'install:settings:help:dataroot:apache' => 'You have the option of Elgg creating the data directory or entering the directory that you already created for storing user files (the permissions on this directory are checked when you click Next)',
+ 'install:settings:help:language' => 'The default language for the site',
+ 'install:settings:help:siteaccess' => 'The default access level for new user created content',
+
+ 'install:admin:instructions' => "It is now time to create an administrator's account.",
+
+ 'install:admin:label:displayname' => 'Display Name',
+ 'install:admin:label:email' => 'Email Address',
+ 'install:admin:label:username' => 'Username',
+ 'install:admin:label:password1' => 'Password',
+ 'install:admin:label:password2' => 'Password Again',
+
+ 'install:admin:help:displayname' => 'The name that is displayed on the site for this account',
+ 'install:admin:help:email' => '',
+ 'install:admin:help:username' => 'Account username used for logging in',
+ 'install:admin:help:password1' => "Account password must be at least %u characters long",
+ 'install:admin:help:password2' => 'Retype password to confirm',
+
+ 'install:admin:password:mismatch' => 'Password must match.',
+ 'install:admin:password:empty' => 'Password cannot be empty.',
+ 'install:admin:password:tooshort' => 'Your password was too short',
+ 'install:admin:cannot_create' => 'Unable to create an admin account.',
+
+ 'install:complete:instructions' => 'Your Elgg site is now ready to be used. Click the button below to be taken to your site.',
+ 'install:complete:gotosite' => 'Go to site',
+
+ 'InstallationException:UnknownStep' => '%s is an unknown installation step.',
+
+ 'install:success:database' => 'Database has been installed.',
+ 'install:success:settings' => 'Site settings have been saved.',
+ 'install:success:admin' => 'Admin account has been created.',
+
+ 'install:error:htaccess' => 'Unable to create an .htaccess',
+ 'install:error:settings' => 'Unable to create the settings file',
+ 'install:error:databasesettings' => 'Unable to connect to the database with these settings.',
+ 'install:error:database_prefix' => 'Invalid characters in database prefix',
+ 'install:error:oldmysql' => 'MySQL must be version 5.0 or above. Your server is using %s.',
+ 'install:error:nodatabase' => 'Unable to use database %s. It may not exist.',
+ 'install:error:cannotloadtables' => 'Cannot load the database tables',
+ 'install:error:tables_exist' => 'There are already Elgg tables in the database. You need to either drop those tables or restart the installer and we will attempt to use them. To restart the installer, remove \'?step=database\' from the URL in your browser\'s address bar and press Enter.',
+ 'install:error:readsettingsphp' => 'Unable to read engine/settings.example.php',
+ 'install:error:writesettingphp' => 'Unable to write engine/settings.php',
+ 'install:error:requiredfield' => '%s is required',
+ 'install:error:relative_path' => 'We don\'t think "%s" is an absolute path for your data directory',
+ 'install:error:datadirectoryexists' => 'Your data directory %s does not exist.',
+ 'install:error:writedatadirectory' => 'Your data directory %s is not writable by the web server.',
+ 'install:error:locationdatadirectory' => 'Your data directory %s must be outside of your install path for security.',
+ 'install:error:emailaddress' => '%s is not a valid email address',
+ 'install:error:createsite' => 'Unable to create the site.',
+ 'install:error:savesitesettings' => 'Unable to save site settings',
+ 'install:error:loadadmin' => 'Unable to load admin user.',
+ 'install:error:adminaccess' => 'Unable to give new user account admin privileges.',
+ 'install:error:adminlogin' => 'Unable to login the new admin user automatically.',
+ 'install:error:rewrite:apache' => 'We think your server is running the Apache web server.',
+ 'install:error:rewrite:nginx' => 'We think your server is running the Nginx web server.',
+ 'install:error:rewrite:lighttpd' => 'We think your server is running the Lighttpd web server.',
+ 'install:error:rewrite:iis' => 'We think your server is running the IIS web server.',
+ 'install:error:rewrite:allowoverride' => "The rewrite test failed and the most likely cause is that AllowOverride is not set to All for Elgg's directory. This prevents Apache from processing the .htaccess file which contains the rewrite rules.
+ \n\nA less likely cause is Apache is configured with an alias for your Elgg directory and you need to set the RewriteBase in your .htaccess. There are further instructions in the .htaccess file in your Elgg directory.",
+ 'install:error:rewrite:htaccess:write_permission' => 'Your web server does not have permission to create the .htaccess file in Elgg\'s directory. You need to manually copy htaccess_dist to .htaccess or change the permissions on the directory.',
+ 'install:error:rewrite:htaccess:read_permission' => 'There is an .htaccess file in Elgg\'s directory, but your web server does not have permission to read it.',
+ 'install:error:rewrite:htaccess:non_elgg_htaccess' => 'There is an .htaccess file in Elgg\'s directory that was not not created by Elgg. Please remove it.',
+ 'install:error:rewrite:htaccess:old_elgg_htaccess' => 'There appears to be an old Elgg .htaccess file in Elgg\'s directory. It does not contain the rewrite rule for testing the web server.',
+ 'install:error:rewrite:htaccess:cannot_copy' => 'A unknown error occurred while creating the .htaccess file. You need to manually copy htaccess_dist to .htaccess in Elgg\'s directory.',
+ 'install:error:rewrite:altserver' => 'The rewrite rules test failed. You need to configure your web server with Elgg\'s rewrite rules and try again.',
+ 'install:error:rewrite:unknown' => 'Oof. We couldn\'t figure out what kind of web server is running on your server and it failed the rewrite rules. We cannot offer any specific advice. Please check the troubleshooting link.',
+ 'install:warning:rewrite:unknown' => 'Your server does not support automatic testing of the rewrite rules and your browser does not support checking via JavaScript. You can continue the installation, but you may experience problems with your site. You can manually test the rewrite rules by clicking this link: <a href="%s" target="_blank">test</a>. You will see the word success if the rules are working.',
+);
+
+add_translation("en", $english);