2010-05-07 12:25:01 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Base installer class
|
|
|
|
|
* Handles everything that is independent of user interface
|
|
|
|
|
*/
|
|
|
|
|
abstract class Installer {
|
|
|
|
|
var $settings, $output;
|
|
|
|
|
|
|
|
|
|
/**
|
2010-07-18 18:52:05 +00:00
|
|
|
* MediaWiki configuration globals that will eventually be passed through
|
|
|
|
|
* to LocalSettings.php. The names only are given here, the defaults
|
2010-05-07 12:25:01 +00:00
|
|
|
* typically come from DefaultSettings.php.
|
|
|
|
|
*/
|
2010-07-05 00:29:38 +00:00
|
|
|
protected $defaultVarNames = array(
|
2010-05-07 12:25:01 +00:00
|
|
|
'wgSitename',
|
|
|
|
|
'wgPasswordSender',
|
2010-07-18 18:52:05 +00:00
|
|
|
'wgLanguageCode',
|
2010-05-07 12:25:01 +00:00
|
|
|
'wgRightsIcon',
|
|
|
|
|
'wgRightsText',
|
|
|
|
|
'wgRightsUrl',
|
|
|
|
|
'wgMainCacheType',
|
|
|
|
|
'wgEnableEmail',
|
|
|
|
|
'wgEnableUserEmail',
|
|
|
|
|
'wgEnotifUserTalk',
|
|
|
|
|
'wgEnotifWatchlist',
|
|
|
|
|
'wgEmailAuthentication',
|
|
|
|
|
'wgDBtype',
|
|
|
|
|
'wgDiff3',
|
|
|
|
|
'wgImageMagickConvertCommand',
|
|
|
|
|
'IP',
|
|
|
|
|
'wgScriptPath',
|
|
|
|
|
'wgScriptExtension',
|
|
|
|
|
'wgMetaNamespace',
|
2010-07-06 19:06:44 +00:00
|
|
|
'wgDeletedDirectory',
|
2010-05-07 12:25:01 +00:00
|
|
|
'wgEnableUploads',
|
|
|
|
|
'wgLogo',
|
|
|
|
|
'wgShellLocale',
|
|
|
|
|
'wgSecretKey',
|
2010-07-10 12:29:15 +00:00
|
|
|
'wgUseInstantCommons',
|
2010-05-07 12:25:01 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
2010-07-18 18:52:05 +00:00
|
|
|
* Variables that are stored alongside globals, and are used for any
|
|
|
|
|
* configuration of the installation process aside from the MediaWiki
|
2010-05-07 12:25:01 +00:00
|
|
|
* configuration. Map of names to defaults.
|
|
|
|
|
*/
|
2010-07-05 00:29:38 +00:00
|
|
|
protected $internalDefaults = array(
|
2010-05-07 12:25:01 +00:00
|
|
|
'_UserLang' => 'en',
|
|
|
|
|
'_Environment' => false,
|
|
|
|
|
'_CompiledDBs' => array(),
|
|
|
|
|
'_SafeMode' => false,
|
|
|
|
|
'_RaiseMemory' => false,
|
|
|
|
|
'_UpgradeDone' => false,
|
2010-07-09 19:05:48 +00:00
|
|
|
'_InstallDone' => false,
|
2010-05-07 12:25:01 +00:00
|
|
|
'_Caches' => array(),
|
|
|
|
|
'_InstallUser' => 'root',
|
|
|
|
|
'_InstallPassword' => '',
|
|
|
|
|
'_SameAccount' => true,
|
|
|
|
|
'_CreateDBAccount' => false,
|
|
|
|
|
'_NamespaceType' => 'site-name',
|
2010-07-14 17:28:08 +00:00
|
|
|
'_AdminName' => '', // will be set later, when the user selects language
|
2010-05-07 12:25:01 +00:00
|
|
|
'_AdminPassword' => '',
|
|
|
|
|
'_AdminPassword2' => '',
|
|
|
|
|
'_AdminEmail' => '',
|
|
|
|
|
'_Subscribe' => false,
|
|
|
|
|
'_SkipOptional' => 'continue',
|
|
|
|
|
'_RightsProfile' => 'wiki',
|
|
|
|
|
'_LicenseCode' => 'none',
|
|
|
|
|
'_CCDone' => false,
|
|
|
|
|
'_Extensions' => array(),
|
|
|
|
|
'_MemCachedServers' => '',
|
2010-07-10 12:29:15 +00:00
|
|
|
'_ExternalHTTP' => false,
|
2010-05-07 12:25:01 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Known database types. These correspond to the class names <type>Installer,
|
|
|
|
|
* and are also MediaWiki database types valid for $wgDBtype.
|
|
|
|
|
*
|
2010-07-18 18:52:05 +00:00
|
|
|
* To add a new type, create a <type>Installer class and a Database<type>
|
2010-05-07 12:25:01 +00:00
|
|
|
* class, and add a config-type-<type> message to MessagesEn.php.
|
|
|
|
|
*/
|
2010-07-05 00:29:38 +00:00
|
|
|
private $dbTypes = array(
|
2010-05-07 12:25:01 +00:00
|
|
|
'mysql',
|
|
|
|
|
'postgres',
|
|
|
|
|
'sqlite',
|
|
|
|
|
'oracle'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Minimum memory size in MB
|
|
|
|
|
*/
|
|
|
|
|
private $minMemorySize = 50;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Cached DB installer instances, access using getDBInstaller()
|
|
|
|
|
*/
|
2010-07-05 00:29:38 +00:00
|
|
|
private $dbInstallers = array();
|
2010-05-07 12:25:01 +00:00
|
|
|
|
|
|
|
|
/**
|
2010-07-18 18:52:05 +00:00
|
|
|
* A list of environment check methods called by doEnvironmentChecks().
|
|
|
|
|
* These may output warnings using showMessage(), and/or abort the
|
2010-05-07 12:25:01 +00:00
|
|
|
* installation process by returning false.
|
|
|
|
|
*/
|
2010-07-05 00:29:38 +00:00
|
|
|
protected $envChecks = array(
|
2010-05-07 12:25:01 +00:00
|
|
|
'envLatestVersion',
|
|
|
|
|
'envCheckDB',
|
|
|
|
|
'envCheckRegisterGlobals',
|
|
|
|
|
'envCheckMagicQuotes',
|
|
|
|
|
'envCheckMagicSybase',
|
|
|
|
|
'envCheckMbstring',
|
|
|
|
|
'envCheckZE1',
|
|
|
|
|
'envCheckSafeMode',
|
|
|
|
|
'envCheckXML',
|
|
|
|
|
'envCheckPCRE',
|
|
|
|
|
'envCheckMemory',
|
|
|
|
|
'envCheckCache',
|
|
|
|
|
'envCheckDiff3',
|
|
|
|
|
'envCheckGraphics',
|
|
|
|
|
'envCheckPath',
|
|
|
|
|
'envCheckWriteableDir',
|
|
|
|
|
'envCheckExtension',
|
|
|
|
|
'envCheckShellLocale',
|
|
|
|
|
'envCheckUploadsDirectory',
|
|
|
|
|
);
|
|
|
|
|
|
2010-07-05 00:29:38 +00:00
|
|
|
/**
|
|
|
|
|
* Steps for installation.
|
|
|
|
|
*/
|
2010-07-09 21:19:58 +00:00
|
|
|
protected $installSteps = array(
|
2010-05-07 12:25:01 +00:00
|
|
|
'database',
|
|
|
|
|
'tables',
|
2010-05-07 13:51:19 +00:00
|
|
|
'interwiki',
|
2010-05-07 12:25:01 +00:00
|
|
|
'secretkey',
|
|
|
|
|
'sysop',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Known object cache types and the functions used to test for their existence
|
|
|
|
|
*/
|
2010-07-05 00:29:38 +00:00
|
|
|
protected $objectCaches = array(
|
2010-05-07 12:25:01 +00:00
|
|
|
'xcache' => 'xcache_get',
|
|
|
|
|
'apc' => 'apc_fetch',
|
2010-05-13 18:07:48 +00:00
|
|
|
'eaccel' => 'eaccelerator_get',
|
|
|
|
|
'wincache' => 'wincache_ucache_get'
|
2010-05-07 12:25:01 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* User rights profiles
|
|
|
|
|
*/
|
|
|
|
|
var $rightsProfiles = array(
|
|
|
|
|
'wiki' => array(),
|
|
|
|
|
'no-anon' => array(
|
|
|
|
|
'*' => array( 'edit' => false )
|
|
|
|
|
),
|
|
|
|
|
'fishbowl' => array(
|
2010-07-18 18:52:05 +00:00
|
|
|
'*' => array(
|
2010-05-07 12:25:01 +00:00
|
|
|
'createaccount' => false,
|
|
|
|
|
'edit' => false,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
'private' => array(
|
|
|
|
|
'*' => array(
|
|
|
|
|
'createaccount' => false,
|
|
|
|
|
'edit' => false,
|
|
|
|
|
'read' => false,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* License types
|
|
|
|
|
*/
|
|
|
|
|
var $licenses = array(
|
|
|
|
|
'none' => array(
|
|
|
|
|
'url' => '',
|
|
|
|
|
'icon' => '',
|
|
|
|
|
'text' => ''
|
|
|
|
|
),
|
2010-05-17 12:17:27 +00:00
|
|
|
'cc-by-sa' => array(
|
|
|
|
|
'url' => 'http://creativecommons.org/licenses/by-sa/3.0/',
|
|
|
|
|
'icon' => '{$wgStylePath}/common/images/cc-by-sa.png',
|
|
|
|
|
),
|
|
|
|
|
'cc-by-nc-sa' => array(
|
|
|
|
|
'url' => 'http://creativecommons.org/licenses/by-nc-sa/3.0/',
|
|
|
|
|
'icon' => '{$wgStylePath}/common/images/cc-by-nc-sa.png',
|
|
|
|
|
),
|
2010-05-07 12:25:01 +00:00
|
|
|
'pd' => array(
|
|
|
|
|
'url' => 'http://creativecommons.org/licenses/publicdomain/',
|
|
|
|
|
'icon' => '{$wgStylePath}/common/images/public-domain.png',
|
|
|
|
|
),
|
|
|
|
|
'gfdl-old' => array(
|
|
|
|
|
'url' => 'http://www.gnu.org/licenses/old-licenses/fdl-1.2.html',
|
|
|
|
|
'icon' => '{$wgStylePath}/common/images/gnu-fdl.png',
|
|
|
|
|
),
|
|
|
|
|
'gfdl-current' => array(
|
|
|
|
|
'url' => 'http://www.gnu.org/copyleft/fdl.html',
|
|
|
|
|
'icon' => '{$wgStylePath}/common/images/gnu-fdl.png',
|
|
|
|
|
),
|
|
|
|
|
'cc-choose' => array(
|
|
|
|
|
// details will be filled in by the selector
|
2010-07-18 18:52:05 +00:00
|
|
|
'url' => '',
|
2010-05-07 12:25:01 +00:00
|
|
|
'icon' => '',
|
|
|
|
|
'text' => '',
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
/**
|
|
|
|
|
* Cached Title and ParserOptions used by parse()
|
|
|
|
|
*/
|
2010-07-05 00:29:38 +00:00
|
|
|
private $parserTitle, $parserOptions;
|
2010-05-07 12:25:01 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor, always call this from child classes
|
|
|
|
|
*/
|
|
|
|
|
function __construct() {
|
2010-06-27 21:48:51 +00:00
|
|
|
// Disable the i18n cache and LoadBalancer
|
|
|
|
|
Language::getLocalisationCache()->disableBackend();
|
|
|
|
|
LBFactory::disableBackend();
|
|
|
|
|
|
|
|
|
|
// Load the installer's i18n file
|
|
|
|
|
global $wgExtensionMessagesFiles;
|
|
|
|
|
$wgExtensionMessagesFiles['MediawikiInstaller'] =
|
|
|
|
|
'./includes/installer/Installer.i18n.php';
|
|
|
|
|
|
2010-07-03 06:06:02 +00:00
|
|
|
global $wgUser;
|
|
|
|
|
$wgUser = User::newFromId( 0 );
|
|
|
|
|
// Having a user with id = 0 safeguards us from DB access via User::loadOptions()
|
|
|
|
|
|
2010-06-30 00:52:11 +00:00
|
|
|
// Set our custom <doclink> hook
|
|
|
|
|
global $wgHooks;
|
|
|
|
|
$wgHooks['ParserFirstCallInit'][] = array( $this, 'registerDocLink' );
|
2010-06-27 21:48:51 +00:00
|
|
|
|
2010-05-07 12:25:01 +00:00
|
|
|
$this->settings = $this->internalDefaults;
|
|
|
|
|
foreach ( $this->defaultVarNames as $var ) {
|
|
|
|
|
$this->settings[$var] = $GLOBALS[$var];
|
|
|
|
|
}
|
|
|
|
|
foreach ( $this->dbTypes as $type ) {
|
|
|
|
|
$installer = $this->getDBInstaller( $type );
|
2010-07-07 13:52:05 +00:00
|
|
|
if ( !$installer->isCompiled() ) {
|
2010-05-07 12:25:01 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
$defaults = $installer->getGlobalDefaults();
|
|
|
|
|
foreach ( $installer->getGlobalNames() as $var ) {
|
|
|
|
|
if ( isset( $defaults[$var] ) ) {
|
|
|
|
|
$this->settings[$var] = $defaults[$var];
|
|
|
|
|
} else {
|
|
|
|
|
$this->settings[$var] = $GLOBALS[$var];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-07-07 02:53:19 +00:00
|
|
|
|
|
|
|
|
$this->parserTitle = Title::newFromText( 'Installer' );
|
|
|
|
|
$this->parserOptions = new ParserOptions;
|
|
|
|
|
$this->parserOptions->setEditSection( false );
|
2010-05-07 12:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* UI interface for displaying a short message
|
|
|
|
|
* The parameters are like parameters to wfMsg().
|
2010-07-18 18:52:05 +00:00
|
|
|
* The messages will be in wikitext format, which will be converted to an
|
2010-05-07 12:25:01 +00:00
|
|
|
* output format such as HTML or text before being sent to the user.
|
|
|
|
|
*/
|
|
|
|
|
abstract function showMessage( $msg /*, ... */ );
|
|
|
|
|
|
2010-07-02 21:15:13 +00:00
|
|
|
abstract function showStatusMessage( $status );
|
2010-05-07 12:25:01 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get a list of known DB types
|
|
|
|
|
*/
|
|
|
|
|
function getDBTypes() {
|
|
|
|
|
return $this->dbTypes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get an instance of InstallerDBType for the specified DB type
|
|
|
|
|
* @param $type Mixed: DB installer for which is needed, false to use default
|
|
|
|
|
*/
|
|
|
|
|
function getDBInstaller( $type = false ) {
|
|
|
|
|
if ( !$type ) {
|
|
|
|
|
$type = $this->getVar( 'wgDBtype' );
|
|
|
|
|
}
|
2010-07-07 02:53:19 +00:00
|
|
|
$type = strtolower($type);
|
|
|
|
|
|
2010-05-07 12:25:01 +00:00
|
|
|
if ( !isset( $this->dbInstallers[$type] ) ) {
|
|
|
|
|
$class = ucfirst( $type ). 'Installer';
|
2010-07-07 13:52:05 +00:00
|
|
|
$this->dbInstallers[$type] = new $class( $this );
|
2010-05-07 12:25:01 +00:00
|
|
|
}
|
|
|
|
|
return $this->dbInstallers[$type];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-07-18 18:52:05 +00:00
|
|
|
* Do initial checks of the PHP environment. Set variables according to
|
2010-05-07 12:25:01 +00:00
|
|
|
* the observed environment.
|
|
|
|
|
*
|
|
|
|
|
* It's possible that this may be called under the CLI SAPI, not the SAPI
|
|
|
|
|
* that the wiki will primarily run under. In that case, the subclass should
|
|
|
|
|
* initialise variables such as wgScriptPath, before calling this function.
|
|
|
|
|
*
|
2010-07-18 18:52:05 +00:00
|
|
|
* Under the web subclass, it can already be assumed that PHP 5+ is in use
|
2010-05-07 12:25:01 +00:00
|
|
|
* and that sessions are working.
|
|
|
|
|
*/
|
2010-07-10 10:39:30 +00:00
|
|
|
function doEnvironmentChecks() {
|
2010-05-07 12:25:01 +00:00
|
|
|
$this->showMessage( 'config-env-php', phpversion() );
|
|
|
|
|
|
|
|
|
|
$good = true;
|
|
|
|
|
foreach ( $this->envChecks as $check ) {
|
|
|
|
|
$status = $this->$check();
|
|
|
|
|
if ( $status === false ) {
|
|
|
|
|
$good = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$this->setVar( '_Environment', $good );
|
|
|
|
|
if ( $good ) {
|
|
|
|
|
$this->showMessage( 'config-env-good' );
|
|
|
|
|
} else {
|
|
|
|
|
$this->showMessage( 'config-env-bad' );
|
|
|
|
|
}
|
|
|
|
|
return $good;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get an MW configuration variable, or internal installer configuration variable.
|
|
|
|
|
* The defaults come from $GLOBALS (ultimately DefaultSettings.php).
|
|
|
|
|
* Installer variables are typically prefixed by an underscore.
|
|
|
|
|
*/
|
|
|
|
|
function getVar( $name, $default = null ) {
|
|
|
|
|
if ( !isset( $this->settings[$name] ) ) {
|
|
|
|
|
return $default;
|
|
|
|
|
} else {
|
|
|
|
|
return $this->settings[$name];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set a MW configuration variable, or internal installer configuration variable.
|
|
|
|
|
*/
|
|
|
|
|
function setVar( $name, $value ) {
|
|
|
|
|
$this->settings[$name] = $value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Exports all wg* variables stored by the installer into global scope
|
|
|
|
|
*/
|
|
|
|
|
function exportVars() {
|
|
|
|
|
foreach ( $this->settings as $name => $value ) {
|
|
|
|
|
if ( substr( $name, 0, 2 ) == 'wg' ) {
|
|
|
|
|
$GLOBALS[$name] = $value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get a fake password for sending back to the user in HTML.
|
|
|
|
|
* This is a security mechanism to avoid compromise of the password in the
|
|
|
|
|
* event of session ID compromise.
|
|
|
|
|
*/
|
|
|
|
|
function getFakePassword( $realPassword ) {
|
|
|
|
|
return str_repeat( '*', strlen( $realPassword ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-07-18 18:52:05 +00:00
|
|
|
* Set a variable which stores a password, except if the new value is a
|
2010-05-07 12:25:01 +00:00
|
|
|
* fake password in which case leave it as it is.
|
|
|
|
|
*/
|
|
|
|
|
function setPassword( $name, $value ) {
|
|
|
|
|
if ( !preg_match( '/^\*+$/', $value ) ) {
|
|
|
|
|
$this->setVar( $name, $value );
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-07-18 18:52:05 +00:00
|
|
|
|
2010-05-07 12:25:01 +00:00
|
|
|
/** Check if we're installing the latest version */
|
|
|
|
|
function envLatestVersion() {
|
|
|
|
|
global $wgVersion;
|
|
|
|
|
$latestInfoUrl = 'http://www.mediawiki.org/w/api.php?action=mwreleases&format=json';
|
|
|
|
|
$latestInfo = Http::get( $latestInfoUrl );
|
|
|
|
|
if( !$latestInfo ) {
|
|
|
|
|
$this->showMessage( 'config-env-latest-can-not-check', $latestInfoUrl );
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-07-10 12:29:15 +00:00
|
|
|
$this->setVar( '_ExternalHTTP', true );
|
2010-05-07 12:25:01 +00:00
|
|
|
$latestInfo = FormatJson::decode($latestInfo);
|
|
|
|
|
if ($latestInfo === false || !isset( $latestInfo->mwreleases ) ) {
|
|
|
|
|
# For when the request is successful but there's e.g. some silly man in
|
|
|
|
|
# the middle firewall blocking us, e.g. one of those annoying airport ones
|
|
|
|
|
$this->showMessage( 'config-env-latest-data-invalid', $latestInfoUrl );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
foreach( $latestInfo->mwreleases as $rel ) {
|
|
|
|
|
if( isset( $rel->current ) )
|
|
|
|
|
$currentVersion = $rel->version;
|
|
|
|
|
}
|
|
|
|
|
if( version_compare( $wgVersion, $currentVersion, '<' ) ) {
|
|
|
|
|
$this->showMessage( 'config-env-latest-old' );
|
2010-07-18 18:52:05 +00:00
|
|
|
$this->showHelpBox( 'config-env-latest-help', $wgVersion, $currentVersion );
|
2010-05-07 12:25:01 +00:00
|
|
|
} elseif( version_compare( $wgVersion, $currentVersion, '>' ) ) {
|
|
|
|
|
$this->showMessage( 'config-env-latest-new' );
|
|
|
|
|
}
|
|
|
|
|
$this->showMessage( 'config-env-latest-ok' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for DB types */
|
|
|
|
|
function envCheckDB() {
|
|
|
|
|
$compiledDBs = array();
|
|
|
|
|
$goodNames = array();
|
|
|
|
|
$allNames = array();
|
|
|
|
|
foreach ( $this->dbTypes as $name ) {
|
|
|
|
|
$db = $this->getDBInstaller( $name );
|
|
|
|
|
$readableName = wfMsg( 'config-type-' . $name );
|
2010-07-07 15:05:05 +00:00
|
|
|
if ( $db->isCompiled() ) {
|
2010-05-07 12:25:01 +00:00
|
|
|
$compiledDBs[] = $name;
|
|
|
|
|
$goodNames[] = $readableName;
|
|
|
|
|
}
|
|
|
|
|
$allNames[] = $readableName;
|
|
|
|
|
}
|
|
|
|
|
$this->setVar( '_CompiledDBs', $compiledDBs );
|
|
|
|
|
|
|
|
|
|
global $wgLang;
|
|
|
|
|
if ( !$compiledDBs ) {
|
|
|
|
|
$this->showMessage( 'config-no-db' );
|
|
|
|
|
$this->showHelpBox( 'config-no-db-help', $wgLang->commaList( $allNames ) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$this->showMessage( 'config-have-db', $wgLang->commaList( $goodNames ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for register_globals */
|
|
|
|
|
function envCheckRegisterGlobals() {
|
|
|
|
|
if( wfIniGetBool( "magic_quotes_runtime" ) ) {
|
|
|
|
|
$this->showMessage( 'config-register-globals' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for magic_quotes_runtime */
|
|
|
|
|
function envCheckMagicQuotes() {
|
|
|
|
|
if( wfIniGetBool( "magic_quotes_runtime" ) ) {
|
|
|
|
|
$this->showMessage( 'config-magic-quotes-runtime' );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for magic_quotes_sybase */
|
|
|
|
|
function envCheckMagicSybase() {
|
|
|
|
|
if ( wfIniGetBool( 'magic_quotes_sybase' ) ) {
|
|
|
|
|
$this->showMessage( 'config-magic-quotes-sybase' );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Environment check for mbstring.func_overload */
|
|
|
|
|
function envCheckMbstring() {
|
|
|
|
|
if ( wfIniGetBool( 'mbstring.func_overload' ) ) {
|
|
|
|
|
$this->showMessage( 'config-mbstring' );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for zend.ze1_compatibility_mode */
|
|
|
|
|
function envCheckZE1() {
|
|
|
|
|
if ( wfIniGetBool( 'zend.ze1_compatibility_mode' ) ) {
|
|
|
|
|
$this->showMessage( 'config-ze1' );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for safe_mode */
|
|
|
|
|
function envCheckSafeMode() {
|
|
|
|
|
if ( wfIniGetBool( 'safe_mode' ) ) {
|
|
|
|
|
$this->setVar( '_SafeMode', true );
|
|
|
|
|
$this->showMessage( 'config-safe-mode' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for the XML module */
|
|
|
|
|
function envCheckXML() {
|
|
|
|
|
if ( !function_exists( "utf8_encode" ) ) {
|
|
|
|
|
$this->showMessage( 'config-xml-bad' );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$this->showMessage( 'config-xml-good' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for the PCRE module */
|
|
|
|
|
function envCheckPCRE() {
|
|
|
|
|
if ( !function_exists( 'preg_match' ) ) {
|
|
|
|
|
$this->showMessage( 'config-pcre' );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for available memory */
|
|
|
|
|
function envCheckMemory() {
|
|
|
|
|
$limit = ini_get( 'memory_limit' );
|
|
|
|
|
if ( !$limit || $limit == -1 ) {
|
|
|
|
|
$this->showMessage( 'config-memory-none' );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
$n = intval( $limit );
|
|
|
|
|
if( preg_match( '/^([0-9]+)[Mm]$/', trim( $limit ), $m ) ) {
|
|
|
|
|
$n = intval( $m[1] * (1024*1024) );
|
|
|
|
|
}
|
|
|
|
|
if( $n < $this->minMemorySize*1024*1024 ) {
|
|
|
|
|
$newLimit = "{$this->minMemorySize}M";
|
|
|
|
|
if( false === ini_set( "memory_limit", $newLimit ) ) {
|
|
|
|
|
$this->showMessage( 'config-memory-bad', $limit );
|
|
|
|
|
} else {
|
|
|
|
|
$this->showMessage( 'config-memory-raised', $limit, $newLimit );
|
|
|
|
|
$this->setVar( '_RaiseMemory', true );
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$this->showMessage( 'config-memory-ok', $limit );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for compiled object cache types */
|
|
|
|
|
function envCheckCache() {
|
|
|
|
|
$caches = array();
|
|
|
|
|
foreach ( $this->objectCaches as $name => $function ) {
|
|
|
|
|
if ( function_exists( $function ) ) {
|
|
|
|
|
$caches[$name] = true;
|
|
|
|
|
$this->showMessage( 'config-' . $name );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( !$caches ) {
|
|
|
|
|
$this->showMessage( 'config-no-cache' );
|
|
|
|
|
}
|
|
|
|
|
$this->setVar( '_Caches', $caches );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Search for GNU diff3 */
|
|
|
|
|
function envCheckDiff3() {
|
|
|
|
|
$paths = array_merge(
|
|
|
|
|
array(
|
|
|
|
|
"/usr/bin",
|
|
|
|
|
"/usr/local/bin",
|
|
|
|
|
"/opt/csw/bin",
|
|
|
|
|
"/usr/gnu/bin",
|
|
|
|
|
"/usr/sfw/bin" ),
|
|
|
|
|
explode( PATH_SEPARATOR, getenv( "PATH" ) ) );
|
|
|
|
|
$names = array( "gdiff3", "diff3", "diff3.exe" );
|
|
|
|
|
|
|
|
|
|
$versionInfo = array( '$1 --version 2>&1', 'diff3 (GNU diffutils)' );
|
|
|
|
|
$haveDiff3 = false;
|
|
|
|
|
foreach ( $paths as $path ) {
|
|
|
|
|
$exe = $this->locateExecutable( $path, $names, $versionInfo );
|
|
|
|
|
if ($exe !== false) {
|
|
|
|
|
$this->setVar( 'wgDiff3', $exe );
|
|
|
|
|
$haveDiff3 = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( $haveDiff3 ) {
|
|
|
|
|
$this->showMessage( 'config-diff3-good', $exe );
|
|
|
|
|
} else {
|
|
|
|
|
$this->setVar( 'wgDiff3', false );
|
|
|
|
|
$this->showMessage( 'config-diff3-bad' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-07-18 18:52:05 +00:00
|
|
|
* Search a path for any of the given executable names. Returns the
|
|
|
|
|
* executable name if found. Also checks the version string returned
|
2010-05-07 12:25:01 +00:00
|
|
|
* by each executable
|
|
|
|
|
*
|
2010-05-09 14:06:36 +00:00
|
|
|
* @param $path String: path to search
|
|
|
|
|
* @param $names Array of executable names
|
|
|
|
|
* @param $versionInfo Boolean false or array with two members:
|
2010-07-18 18:52:05 +00:00
|
|
|
* 0 => Command to run for version check, with $1 for the path
|
|
|
|
|
* 1 => String to compare the output with
|
2010-05-07 12:25:01 +00:00
|
|
|
*
|
2010-07-18 18:52:05 +00:00
|
|
|
* If $versionInfo is not false, only executables with a version
|
2010-05-07 12:25:01 +00:00
|
|
|
* matching $versionInfo[1] will be returned.
|
|
|
|
|
*/
|
|
|
|
|
function locateExecutable( $path, $names, $versionInfo = false ) {
|
|
|
|
|
if (!is_array($names))
|
|
|
|
|
$names = array($names);
|
|
|
|
|
|
|
|
|
|
foreach ($names as $name) {
|
|
|
|
|
$command = "$path/$name";
|
|
|
|
|
if ( @file_exists( $command ) ) {
|
|
|
|
|
if ( !$versionInfo )
|
|
|
|
|
return $command;
|
|
|
|
|
|
|
|
|
|
$file = str_replace( '$1', $command, $versionInfo[0] );
|
2010-07-04 19:44:21 +00:00
|
|
|
# Should maybe be wfShellExec( $file), but runs into a ulimit, see
|
2010-07-18 18:52:05 +00:00
|
|
|
# http://www.mediawiki.org/w/index.php?title=New-installer_issues&diff=prev&oldid=335456
|
2010-07-04 19:44:21 +00:00
|
|
|
if ( strstr( `$file`, $versionInfo[1]) !== false )
|
2010-05-07 12:25:01 +00:00
|
|
|
return $command;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for ImageMagick and GD */
|
|
|
|
|
function envCheckGraphics() {
|
|
|
|
|
$imcheck = array( "/usr/bin", "/opt/csw/bin", "/usr/local/bin", "/sw/bin", "/opt/local/bin" );
|
|
|
|
|
foreach( $imcheck as $dir ) {
|
|
|
|
|
$im = "$dir/convert";
|
|
|
|
|
if( @file_exists( $im ) ) {
|
|
|
|
|
$this->showMessage( 'config-imagemagick', $im );
|
|
|
|
|
$this->setVar( 'wgImageMagickConvertCommand', $im );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( function_exists( 'imagejpeg' ) ) {
|
|
|
|
|
$this->showMessage( 'config-gd' );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
$this->showMessage( 'no-scaling' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for setting $IP and $wgScriptPath */
|
|
|
|
|
function envCheckPath() {
|
|
|
|
|
$IP = dirname( dirname( dirname( __FILE__ ) ) );
|
|
|
|
|
$this->setVar( 'IP', $IP );
|
|
|
|
|
$this->showMessage( 'config-dir', $IP );
|
|
|
|
|
|
|
|
|
|
// PHP_SELF isn't available sometimes, such as when PHP is CGI but
|
|
|
|
|
// cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME
|
|
|
|
|
// to get the path to the current script... hopefully it's reliable. SIGH
|
|
|
|
|
if ( !empty( $_SERVER['PHP_SELF'] ) ) {
|
|
|
|
|
$path = $_SERVER['PHP_SELF'];
|
|
|
|
|
} elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) {
|
|
|
|
|
$path = $_SERVER['SCRIPT_NAME'];
|
|
|
|
|
} elseif ( $this->getVar( 'wgScriptPath' ) ) {
|
|
|
|
|
// Some kind soul has set it for us already (e.g. debconf)
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
$this->showMessage( 'config-no-uri' );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$uri = preg_replace( '{^(.*)/config.*$}', '$1', $path );
|
|
|
|
|
$this->setVar( 'wgScriptPath', $uri );
|
|
|
|
|
$this->showMessage( 'config-uri', $uri );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for writable config/ directory */
|
|
|
|
|
function envCheckWriteableDir() {
|
|
|
|
|
$ipDir = $this->getVar( 'IP' );
|
|
|
|
|
$configDir = $ipDir . '/config';
|
|
|
|
|
if( !is_writeable( $configDir ) ) {
|
|
|
|
|
$webserverGroup = self::maybeGetWebserverPrimaryGroup();
|
|
|
|
|
if ( $webserverGroup !== null ) {
|
|
|
|
|
$this->showMessage( 'config-dir-not-writable-group', $ipDir, $webserverGroup );
|
|
|
|
|
} else {
|
|
|
|
|
$this->showMessage( 'config-dir-not-writable-nogroup', $ipDir, $webserverGroup );
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Environment check for setting the preferred PHP file extension */
|
|
|
|
|
function envCheckExtension() {
|
|
|
|
|
// FIXME: detect this properly
|
|
|
|
|
if ( defined( 'MW_INSTALL_PHP5_EXT' ) ) {
|
|
|
|
|
$ext = 'php5';
|
|
|
|
|
} else {
|
|
|
|
|
$ext = 'php';
|
|
|
|
|
}
|
|
|
|
|
$this->setVar( 'wgScriptExtension', ".$ext" );
|
|
|
|
|
$this->showMessage( 'config-file-extension', $ext );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function envCheckShellLocale() {
|
|
|
|
|
# Give up now if we're in safe mode or open_basedir
|
|
|
|
|
# It's theoretically possible but tricky to work with
|
|
|
|
|
if ( wfIniGetBool( "safe_mode" ) || ini_get( 'open_basedir' ) || !function_exists( 'exec' ) ) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$os = php_uname( 's' );
|
|
|
|
|
$supported = array( 'Linux', 'SunOS', 'HP-UX' ); # Tested these
|
|
|
|
|
if ( !in_array( $os, $supported ) ) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Get a list of available locales
|
|
|
|
|
$lines = $ret = false;
|
|
|
|
|
exec( '/usr/bin/locale -a', $lines, $ret );
|
|
|
|
|
if ( $ret ) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$lines = wfArrayMap( 'trim', $lines );
|
|
|
|
|
$candidatesByLocale = array();
|
|
|
|
|
$candidatesByLang = array();
|
|
|
|
|
foreach ( $lines as $line ) {
|
|
|
|
|
if ( $line === '' ) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ( !preg_match( '/^([a-zA-Z]+)(_[a-zA-Z]+|)\.(utf8|UTF-8)(@[a-zA-Z_]*|)$/i', $line, $m ) ) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
list( $all, $lang, $territory, $charset, $modifier ) = $m;
|
|
|
|
|
$candidatesByLocale[$m[0]] = $m;
|
|
|
|
|
$candidatesByLang[$lang][] = $m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Try the current value of LANG
|
|
|
|
|
if ( isset( $candidatesByLocale[ getenv( 'LANG' ) ] ) ) {
|
|
|
|
|
$this->setVar( 'wgShellLocale', getenv( 'LANG' ) );
|
|
|
|
|
$this->showMessage( 'config-shell-locale', getenv( 'LANG' ) );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Try the most common ones
|
|
|
|
|
$commonLocales = array( 'en_US.UTF-8', 'en_US.utf8', 'de_DE.UTF-8', 'de_DE.utf8' );
|
|
|
|
|
foreach ( $commonLocales as $commonLocale ) {
|
|
|
|
|
if ( isset( $candidatesByLocale[$commonLocale] ) ) {
|
|
|
|
|
$this->setVar( 'wgShellLocale', $commonLocale );
|
|
|
|
|
$this->showMessage( 'config-shell-locale', $commonLocale );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Is there an available locale in the Wiki's language?
|
|
|
|
|
$wikiLang = $this->getVar( 'wgLanguageCode' );
|
|
|
|
|
if ( isset( $candidatesByLang[$wikiLang] ) ) {
|
|
|
|
|
$m = reset( $candidatesByLang[$wikiLang] );
|
|
|
|
|
$this->setVar( 'wgShellLocale', $m[0] );
|
|
|
|
|
$this->showMessage( 'config-shell-locale', $m[0] );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Are there any at all?
|
|
|
|
|
if ( count( $candidatesByLocale ) ) {
|
|
|
|
|
$m = reset( $candidatesByLocale );
|
|
|
|
|
$this->setVar( 'wgShellLocale', $m[0] );
|
|
|
|
|
$this->showMessage( 'config-shell-locale', $m[0] );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Give up
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2010-07-18 18:52:05 +00:00
|
|
|
|
2010-05-07 12:25:01 +00:00
|
|
|
function envCheckUploadsDirectory() {
|
|
|
|
|
global $IP, $wgServer;
|
|
|
|
|
$dir = $IP . '/images/';
|
|
|
|
|
$url = $wgServer . $this->getVar( 'wgScriptPath' ) . '/images/';
|
|
|
|
|
$safe = !$this->dirIsExecutable( $dir, $url );
|
|
|
|
|
if ( $safe ) {
|
|
|
|
|
$this->showMessage( 'config-uploads-safe' );
|
|
|
|
|
} else {
|
|
|
|
|
$this->showMessage( 'config-uploads-not-safe', $dir );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks if scripts located in the given directory can be executed via the given URL
|
|
|
|
|
*/
|
|
|
|
|
function dirIsExecutable( $dir, $url ) {
|
|
|
|
|
$scriptTypes = array(
|
|
|
|
|
'php' => array(
|
|
|
|
|
"<?php echo 'ex' . 'ec';",
|
|
|
|
|
"#!/var/env php5\n<?php echo 'ex' . 'ec';",
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
// it would be good to check other popular languages here, but it'll be slow
|
|
|
|
|
|
|
|
|
|
wfSuppressWarnings();
|
|
|
|
|
foreach ( $scriptTypes as $ext => $contents ) {
|
|
|
|
|
foreach ( $contents as $source ) {
|
|
|
|
|
$file = 'exectest.' . $ext;
|
|
|
|
|
if ( !file_put_contents( $dir . $file, $source ) ) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
$text = Http::get( $url . $file );
|
|
|
|
|
unlink( $dir . $file );
|
|
|
|
|
if ( $text == 'exec' ) {
|
|
|
|
|
wfRestoreWarnings();
|
|
|
|
|
return $ext;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
wfRestoreWarnings();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert wikitext $text to HTML.
|
|
|
|
|
*
|
|
|
|
|
* This is potentially error prone since many parser features require a complete
|
2010-07-18 18:52:05 +00:00
|
|
|
* installed MW database. The solution is to just not use those features when you
|
2010-05-07 12:25:01 +00:00
|
|
|
* write your messages. This appears to work well enough. Basic formatting and
|
|
|
|
|
* external links work just fine.
|
|
|
|
|
*
|
2010-07-18 18:52:05 +00:00
|
|
|
* But in case a translator decides to throw in a #ifexist or internal link or
|
|
|
|
|
* whatever, this function is guarded to catch attempted DB access and to present
|
2010-05-07 12:25:01 +00:00
|
|
|
* some fallback text.
|
|
|
|
|
*
|
2010-05-09 14:06:36 +00:00
|
|
|
* @param $text String
|
|
|
|
|
* @param $lineStart Boolean
|
|
|
|
|
* @return String
|
2010-05-07 12:25:01 +00:00
|
|
|
*/
|
|
|
|
|
function parse( $text, $lineStart = false ) {
|
|
|
|
|
global $wgParser;
|
|
|
|
|
try {
|
|
|
|
|
$out = $wgParser->parse( $text, $this->parserTitle, $this->parserOptions, $lineStart );
|
|
|
|
|
$html = $out->getText();
|
2010-06-09 19:07:11 +00:00
|
|
|
} catch ( DBAccessError $e ) {
|
2010-05-07 12:25:01 +00:00
|
|
|
$html = '<!--DB access attempted during parse--> ' . htmlspecialchars( $text );
|
|
|
|
|
if ( !empty( $this->debug ) ) {
|
|
|
|
|
$html .= "<!--\n" . $e->getTraceAsString() . "\n-->";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $html;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-30 00:52:11 +00:00
|
|
|
/**
|
|
|
|
|
* Register tag hook below
|
|
|
|
|
*/
|
|
|
|
|
function registerDocLink( &$parser ) {
|
|
|
|
|
$parser->setHook( 'doclink', array( $this, 'docLink' ) );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-07 12:25:01 +00:00
|
|
|
/**
|
|
|
|
|
* Extension tag hook for a documentation link
|
|
|
|
|
*/
|
|
|
|
|
function docLink( $linkText, $attribs, $parser ) {
|
|
|
|
|
$url = $this->getDocUrl( $attribs['href'] );
|
2010-07-18 18:52:05 +00:00
|
|
|
return '<a href="' . htmlspecialchars( $url ) . '">' .
|
|
|
|
|
htmlspecialchars( $linkText ) .
|
2010-05-07 12:25:01 +00:00
|
|
|
'</a>';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Overridden by WebInstaller to provide lastPage parameters
|
|
|
|
|
*/
|
|
|
|
|
protected function getDocUrl( $page ) {
|
|
|
|
|
return "{$_SERVER['PHP_SELF']}?page=" . urlencode( $attribs['href'] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function findExtensions() {
|
|
|
|
|
if( $this->getVar( 'IP' ) === null ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$exts = array();
|
|
|
|
|
$dir = $this->getVar( 'IP' ) . '/extensions';
|
|
|
|
|
$dh = opendir( $dir );
|
|
|
|
|
while ( ( $file = readdir( $dh ) ) !== false ) {
|
|
|
|
|
if( file_exists( "$dir/$file/$file.php" ) ) {
|
2010-07-06 21:34:20 +00:00
|
|
|
$exts[$file] = null;
|
2010-05-07 12:25:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$this->setVar( '_Extensions', $exts );
|
|
|
|
|
return $exts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getInstallSteps() {
|
|
|
|
|
if( $this->getVar( '_UpgradeDone' ) ) {
|
|
|
|
|
$this->installSteps = array( 'localsettings' );
|
|
|
|
|
}
|
|
|
|
|
if( count( $this->getVar( '_Extensions' ) ) ) {
|
2010-05-12 20:01:11 +00:00
|
|
|
array_unshift( $this->installSteps, 'extensions' );
|
2010-05-07 12:25:01 +00:00
|
|
|
}
|
|
|
|
|
return $this->installSteps;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-06 18:31:55 +00:00
|
|
|
/**
|
|
|
|
|
* Actually perform the installation
|
|
|
|
|
* @param Array $startCB A callback array for the beginning of each step
|
|
|
|
|
* @param Array $endCB A callback array for the end of each step
|
|
|
|
|
* @return Array of Status objects
|
|
|
|
|
*/
|
|
|
|
|
public function performInstallation( $startCB, $endCB ) {
|
|
|
|
|
$installResults = array();
|
2010-07-07 13:52:05 +00:00
|
|
|
$installer = $this->getDBInstaller();
|
2010-07-06 18:31:55 +00:00
|
|
|
foreach( $this->getInstallSteps() as $stepObj ) {
|
|
|
|
|
$step = is_array( $stepObj ) ? $stepObj['name'] : $stepObj;
|
|
|
|
|
call_user_func_array( $startCB, array( $step ) );
|
|
|
|
|
$status = null;
|
|
|
|
|
|
|
|
|
|
# Call our working function
|
2010-07-07 13:39:57 +00:00
|
|
|
if ( is_array( $stepObj ) ) {
|
2010-07-06 18:31:55 +00:00
|
|
|
# A custom callaback
|
|
|
|
|
$callback = $stepObj['callback'];
|
2010-07-07 13:53:27 +00:00
|
|
|
$status = call_user_func_array( $callback, array( $installer ) );
|
2010-07-06 18:31:55 +00:00
|
|
|
} else {
|
|
|
|
|
# Boring implicitly named callback
|
|
|
|
|
$func = 'install' . ucfirst( $step );
|
2010-07-07 13:52:05 +00:00
|
|
|
$status = $this->{$func}( $installer );
|
2010-07-06 18:31:55 +00:00
|
|
|
}
|
|
|
|
|
call_user_func_array( $endCB, array( $step, $status ) );
|
|
|
|
|
$installResults[$step] = $status;
|
2010-07-07 12:48:20 +00:00
|
|
|
|
|
|
|
|
// If we've hit some sort of fatal, we need to bail. Callback
|
|
|
|
|
// already had a chance to do output above.
|
|
|
|
|
if( !$status->isOk() )
|
|
|
|
|
break;
|
2010-07-06 18:31:55 +00:00
|
|
|
}
|
2010-07-14 01:18:14 +00:00
|
|
|
if( $status->isOk() ) {
|
|
|
|
|
$this->setVar( '_InstallDone', true );
|
|
|
|
|
}
|
2010-07-06 18:31:55 +00:00
|
|
|
return $installResults;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-07 12:25:01 +00:00
|
|
|
public function installExtensions() {
|
|
|
|
|
global $wgHooks, $wgAutoloadClasses;
|
|
|
|
|
$exts = $this->getVar( '_Extensions' );
|
|
|
|
|
$path = $this->getVar( 'IP' ) . '/extensions';
|
|
|
|
|
foreach( $exts as $e ) {
|
|
|
|
|
require( "$path/$e/$e.php" );
|
|
|
|
|
}
|
|
|
|
|
return Status::newGood();
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-07 13:52:05 +00:00
|
|
|
public function installDatabase( &$installer ) {
|
2010-07-07 02:53:19 +00:00
|
|
|
if(!$installer) {
|
2010-07-07 13:52:05 +00:00
|
|
|
$type = $this->getVar( 'wgDBtype' );
|
2010-07-07 02:53:19 +00:00
|
|
|
$status = Status::newFatal( "config-no-db", $type );
|
|
|
|
|
} else {
|
|
|
|
|
$status = $installer->setupDatabase();
|
|
|
|
|
}
|
2010-05-07 12:25:01 +00:00
|
|
|
return $status;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-07 13:52:05 +00:00
|
|
|
public function installTables( &$installer ) {
|
2010-05-07 12:25:01 +00:00
|
|
|
$status = $installer->createTables();
|
2010-07-02 21:15:13 +00:00
|
|
|
if( $status->isOK() ) {
|
2010-05-07 12:25:01 +00:00
|
|
|
LBFactory::enableBackend();
|
|
|
|
|
}
|
|
|
|
|
return $status;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-07 13:52:05 +00:00
|
|
|
public function installInterwiki( &$installer ) {
|
2010-05-07 13:51:19 +00:00
|
|
|
return $installer->populateInterwikiTable();
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-07 12:25:01 +00:00
|
|
|
public function installSecretKey() {
|
2010-06-30 05:30:29 +00:00
|
|
|
if ( wfIsWindows() ) {
|
|
|
|
|
$file = null;
|
|
|
|
|
} else {
|
|
|
|
|
wfSuppressWarnings();
|
|
|
|
|
$file = fopen( "/dev/urandom", "r" );
|
|
|
|
|
wfRestoreWarnings();
|
|
|
|
|
}
|
2010-07-02 21:15:13 +00:00
|
|
|
|
|
|
|
|
$status = Status::newGood();
|
|
|
|
|
|
2010-05-07 12:25:01 +00:00
|
|
|
if ( $file ) {
|
|
|
|
|
$secretKey = bin2hex( fread( $file, 32 ) );
|
|
|
|
|
fclose( $file );
|
|
|
|
|
} else {
|
|
|
|
|
$secretKey = "";
|
|
|
|
|
for ( $i=0; $i<8; $i++ ) {
|
|
|
|
|
$secretKey .= dechex(mt_rand(0, 0x7fffffff));
|
|
|
|
|
}
|
2010-07-02 21:15:13 +00:00
|
|
|
$status->warning( 'config-insecure-secretkey' );
|
2010-05-07 12:25:01 +00:00
|
|
|
}
|
|
|
|
|
$this->setVar( 'wgSecretKey', $secretKey );
|
2010-07-02 21:15:13 +00:00
|
|
|
|
|
|
|
|
return $status;
|
2010-05-07 12:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function installSysop() {
|
|
|
|
|
$name = $this->getVar( '_AdminName' );
|
|
|
|
|
$user = User::newFromName( $name );
|
|
|
|
|
if ( !$user ) {
|
|
|
|
|
// we should've validated this earlier anyway!
|
|
|
|
|
return Status::newFatal( 'config-admin-error-user', $name );
|
|
|
|
|
}
|
|
|
|
|
if ( $user->idForName() == 0 ) {
|
|
|
|
|
$user->addToDatabase();
|
|
|
|
|
try {
|
|
|
|
|
$user->setPassword( $this->getVar( '_AdminPassword' ) );
|
|
|
|
|
} catch( PasswordError $pwe ) {
|
|
|
|
|
return Status::newFatal( 'config-admin-error-password', $name, $pwe->getMessage() );
|
|
|
|
|
}
|
|
|
|
|
$user->addGroup( 'sysop' );
|
|
|
|
|
$user->addGroup( 'bureaucrat' );
|
2010-06-07 16:33:12 +00:00
|
|
|
$user->saveSettings();
|
2010-05-07 12:25:01 +00:00
|
|
|
}
|
|
|
|
|
return Status::newGood();
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-04 19:41:26 +00:00
|
|
|
/**
|
|
|
|
|
* Determine if LocalSettings exists. If it does, return an appropriate
|
|
|
|
|
* status for whether we should can upgrade or not
|
|
|
|
|
* @return Status
|
|
|
|
|
*/
|
|
|
|
|
function getLocalSettingsStatus() {
|
|
|
|
|
global $IP;
|
|
|
|
|
|
|
|
|
|
$status = Status::newGood();
|
|
|
|
|
|
|
|
|
|
wfSuppressWarnings();
|
|
|
|
|
$ls = file_exists( "$IP/LocalSettings.php" );
|
|
|
|
|
wfRestoreWarnings();
|
2010-07-18 18:52:05 +00:00
|
|
|
|
2010-07-04 19:41:26 +00:00
|
|
|
if( $ls ) {
|
2010-07-05 00:06:06 +00:00
|
|
|
if( $this->getDBInstaller()->needsUpgrade() ) {
|
2010-07-04 19:41:26 +00:00
|
|
|
$status->warning( 'config-localsettings-upgrade' );
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$status->fatal( 'config-localsettings-noupgrade' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $status;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-27 21:48:51 +00:00
|
|
|
/**
|
2010-05-07 12:25:01 +00:00
|
|
|
* On POSIX systems return the primary group of the webserver we're running under.
|
|
|
|
|
* On other systems just returns null.
|
|
|
|
|
*
|
|
|
|
|
* This is used to advice the user that he should chgrp his config/data/images directory as the
|
|
|
|
|
* webserver user before he can install.
|
|
|
|
|
*
|
|
|
|
|
* Public because SqliteInstaller needs it, and doesn't subclass Installer.
|
|
|
|
|
*
|
2010-05-09 14:06:36 +00:00
|
|
|
* @return String
|
2010-05-07 12:25:01 +00:00
|
|
|
*/
|
|
|
|
|
public static function maybeGetWebserverPrimaryGroup() {
|
|
|
|
|
if ( ! function_exists('posix_getegid') || ! function_exists('posix_getpwuid') ) {
|
|
|
|
|
# I don't know this, this isn't UNIX
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# posix_getegid() *not* getmygid() because we want the group of the webserver,
|
|
|
|
|
# not whoever owns the current script
|
|
|
|
|
$gid = posix_getegid();
|
|
|
|
|
$getpwuid = posix_getpwuid( $gid );
|
|
|
|
|
$group = $getpwuid["name"];
|
|
|
|
|
|
|
|
|
|
return $group;
|
|
|
|
|
}
|
2010-06-27 21:48:51 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Override the necessary bits of the config to run an installation
|
|
|
|
|
*/
|
|
|
|
|
public static function overrideConfig() {
|
|
|
|
|
define( 'MW_NO_SESSION', 1 );
|
|
|
|
|
|
|
|
|
|
// Don't access the database
|
|
|
|
|
$GLOBALS['wgUseDatabaseMessages'] = false;
|
|
|
|
|
// Debug-friendly
|
|
|
|
|
$GLOBALS['wgShowExceptionDetails'] = true;
|
|
|
|
|
// Don't break forms
|
|
|
|
|
$GLOBALS['wgExternalLinkTarget'] = '_blank';
|
|
|
|
|
|
|
|
|
|
// Extended debugging. Maybe disable before release?
|
|
|
|
|
$GLOBALS['wgShowSQLErrors'] = true;
|
|
|
|
|
$GLOBALS['wgShowDBErrorBacktrace'] = true;
|
|
|
|
|
}
|
2010-07-07 02:53:19 +00:00
|
|
|
|
|
|
|
|
/**
|
2010-07-18 18:52:05 +00:00
|
|
|
* Add an installation step following the given step.
|
2010-07-07 02:53:19 +00:00
|
|
|
* @param $findStep String the step to find. Use NULL to put the step at the beginning.
|
|
|
|
|
* @param $callback array
|
|
|
|
|
*/
|
|
|
|
|
function addInstallStepFollowing( $findStep, $callback ) {
|
|
|
|
|
$where = 0;
|
|
|
|
|
if( $findStep !== null ) $where = array_search( $findStep, $this->installSteps );
|
|
|
|
|
|
|
|
|
|
array_splice( $this->installSteps, $where, 0, $callback );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-05-07 12:25:01 +00:00
|
|
|
}
|