* When an upgrade key is entered, or a supplied upgrade key is edited into LocalSettings.php by the upgrader, fetch database settings from LocalSettings.php and AdminSettings.php for use during the upgrade. This allows the DBConnect page to be skipped, making web upgrade almost as easy to use as CLI upgrade.
* Made LocalSettingsGenerator add $wgUpgradeKey in non-commented form, for easier subsequent upgrades.
* Converted the $wgUpgradeKey check to a normal in-sequence page, called ExistingWiki. This allows the removal of related special cases from WebInstaller. The code for WebInstaller_ExistingWiki is loosely based on WebInstaller_Locked.
* Added Status::replaceMessage(), to support informative DB connection error messages from the ExistingWiki page.
* In WebInstaller::getInfoBox(), call parse() with $lineStart=true, so that line-start syntax like bullet points can work.
* Reduced the length of the generated $wgUpgradeKey from 64 to 16. This is ample for what it does, and makes it fit on the screen and not overlap with the right sidebar when when displayed by WebInstaller_ExistingWiki.
* Added $wgUpgradeKey to DefaultSettings.php.
$wgSeleniumTestConfigs = array();
$wgSeleniumConfigFile = null;
+/**
+ * Set this to a random string to allow web-based upgrades
+ */
+$wgUpgradeKey = false;
/**
return false;
}
+ /**
+ * If the specified source message exists, replace it with the specified
+ * destination message, but keep the same parameters as in the original error.
+ *
+ * Return true if the replacement was done, false otherwise.
+ */
+ function replaceMessage( $source, $dest ) {
+ $replaced = false;
+ foreach ( $this->errors as $index => $error ) {
+ if ( $error['message'] === $source ) {
+ $this->errors[$index]['message'] = $dest;
+ $replaced = true;
+ }
+ }
+ return $replaced;
+ }
+
/**
* Backward compatibility function for WikiError -> Status migration
*
'_CCDone' => false,
'_Extensions' => array(),
'_MemCachedServers' => '',
- '_LocalSettingsLocked' => true,
- '_UpgradeKey' => '',
+ '_UpgradeKeySupplied' => false,
+ '_ExistingDBSettings' => false,
);
/**
*
* @return Status
*/
- protected function generateSecret( $secretName ) {
+ protected function generateSecret( $secretName, $length = 64 ) {
if ( wfIsWindows() ) {
$file = null;
} else {
$status = Status::newGood();
if ( $file ) {
- $secretKey = bin2hex( fread( $file, 32 ) );
+ $secretKey = bin2hex( fread( $file, $length / 2 ) );
fclose( $file );
} else {
$secretKey = '';
- for ( $i=0; $i<8; $i++ ) {
+ for ( $i = 0; $i < $length / 8; $i++ ) {
$secretKey .= dechex( mt_rand( 0, 0x7fffffff ) );
}
}
/**
- * Generate a default $wgUpradeKey, Will warn if we had to use
+ * Generate a default $wgUpgradeKey. Will warn if we had to use
* mt_rand() instead of /dev/urandom
*
* @return Status
*/
- protected function generateUpgradeKey() {
- return $this->generateSecret( 'wgUpgradeKey' );
+ public function generateUpgradeKey() {
+ if ( strval( $this->getVar( 'wgUpgradeKey' ) ) === '' ) {
+ return $this->generateSecret( 'wgUpgradeKey', 16 );
+ }
}
/**
'config-desc' => 'The installer for MediaWiki',
'config-title' => 'MediaWiki $1 installation',
'config-information' => 'Information',
- 'config-localsettings-upgrade' => "'''Warning''': A <code>LocalSettings.php</code> file has been detected.
-Your software is able to upgrade.
-Please fill in the value of <code>\$wgUpgradeKey</code> in the box.",
+ 'config-localsettings-upgrade' => "A <code>LocalSettings.php</code> file has been detected.
+To upgrade this installation, please enter the value of <code>\$wgUpgradeKey</code> in the box below.
+You will find it in LocalSettings.php.",
'config-localsettings-key' => 'Upgrade key:',
- 'config-localsettings-badkey' => 'The key you provided is incorrect',
- 'config-localsettings-noupgrade' => "'''Error''': A <code>LocalSettings.php</code> file has been detected.
-Your software is not able to upgrade at this time.
-The installer has been disabled for security reasons.",
+ 'config-localsettings-badkey' => 'The key you provided is incorrect.',
+ 'config-upgrade-key-missing' => 'An existing installation of MediaWiki has been detected.
+To upgrade this installation, please put the following line at the bottom of your LocalSettings.php:
+
+$1
+',
+ 'config-localsettings-incomplete' => 'The existing LocalSettings.php appears to be incomplete.
+The $1 variable is not set.
+Please change LocalSettings.php so that this variable is set, and click "Continue".',
+ 'config-localsettings-connection-error' => 'An error was encountered when connecting to the database using the settings specified in LocalSettings.php or AdminSettings.php. Please fix these settings and try again.
+
+$1',
'config-session-error' => 'Error starting session: $1',
'config-session-expired' => 'Your session data seems to have expired.
Sessions are configured for a lifetime of $1.
'config-page-releasenotes' => 'Release notes',
'config-page-copying' => 'Copying',
'config-page-upgradedoc' => 'Upgrading',
- 'config-page-locked' => 'Permission denied',
+ 'config-page-existingwiki' => 'Existing wiki',
'config-help-restart' => 'Do you want to clear all saved data that you have entered and restart the installation process?',
'config-restart' => 'Yes, restart it',
'config-welcome' => "=== Environmental checks ===
}
/**
- * Determine if LocalSettings exists. If it does, return an appropriate
- * status for whether upgrading is enabled or not.
+ * Determine if LocalSettings.php exists. If it does, return its variables,
+ * merged with those from AdminSettings.php, as an array.
*
- * @return Status
+ * @return Array
*/
- public function getLocalSettingsStatus() {
+ public function getExistingLocalSettings() {
global $IP;
- $status = Status::newGood();
-
wfSuppressWarnings();
- $ls = file_exists( "$IP/LocalSettings.php" );
+ $_lsExists = file_exists( "$IP/LocalSettings.php" );
wfRestoreWarnings();
- if( $ls ) {
+ if( $_lsExists ) {
require( "$IP/includes/DefaultSettings.php" );
- require_once( "$IP/LocalSettings.php" );
- $vars = get_defined_vars();
- if( isset( $vars['wgUpgradeKey'] ) && $vars['wgUpgradeKey'] ) {
- $status->warning( 'config-localsettings-upgrade' );
- $this->setVar( '_UpgradeKey', $vars['wgUpgradeKey' ] );
- } else {
- $status->fatal( 'config-localsettings-noupgrade' );
+ require( "$IP/LocalSettings.php" );
+ if ( file_exists( "$IP/AdminSettings.php" ) ) {
+ require( "$IP/AdminSettings.php" );
}
+ $vars = get_defined_vars();
+ unset( $vars['_lsExists'] );
+ return $vars;
+ } else {
+ return false;
}
-
- return $status;
}
/**
# Site upgrade key. Must be set to a string (default provided) to turn on the
# web installer while LocalSettings.php is in place
-#\$wgUpgradeKey = \"{$this->values['wgUpgradeKey']}\";
+\$wgUpgradeKey = \"{$this->values['wgUpgradeKey']}\";
## Default skin: you can change the default skin. Use the internal symbolic
## names, ie 'standard', 'nostalgia', 'cologneblue', 'monobook', 'vector':
*/
public $pageSequence = array(
'Language',
+ 'ExistingWiki',
'Welcome',
'DBConnect',
'Upgrade',
# Get the page name.
$pageName = $this->request->getVal( 'page' );
- # Check LocalSettings status
- $localSettings = $this->getLocalSettingsStatus();
-
- if( !$localSettings->isGood() && $this->getVar( '_LocalSettingsLocked' ) ) {
- $pageName = 'Locked';
- $pageId = false;
- $page = $this->getPageByName( $pageName );
- $page->setLocalSettingsStatus( $localSettings );
- } elseif ( in_array( $pageName, $this->otherPages ) ) {
+ if ( in_array( $pageName, $this->otherPages ) ) {
# Out of sequence
$pageId = false;
$page = $this->getPageByName( $pageName );
) . "\n" .
"</div>\n" .
"<div class=\"config-info-right\">\n" .
- $this->parse( $text ) . "\n" .
+ $this->parse( $text, true ) . "\n" .
"</div>\n" .
"<div style=\"clear: left;\"></div>\n" .
"</div>\n";
}
}
-class WebInstaller_Locked extends WebInstallerPage {
- // The status of Installer::getLocalSettingsStatus()
- private $status;
-
- public function setLocalSettingsStatus( Status $s ) {
- $this->status = $s;
- }
-
- protected function getId() {
- return 0;
- }
-
- public function execute() {
- $r = $this->parent->request;
- if( !$r->wasPosted() || !$this->status->isOK() ) {
- $this->display();
- return 'output';
- } else {
- $key = $r->getText( 'config_wpUpgradeKey' );
- if( !$key || $key !== $this->getVar( '_UpgradeKey' ) ) {
- $this->parent->showError( 'config-localsettings-badkey' );
- $this->display();
- return 'output';
- } else {
- $this->setVar( '_LocalSettingsLocked', false );
- return 'continue';
- }
- }
- }
-
- /**
- * Display stuff to the end user
- */
- private function display() {
- $this->startForm();
- $this->parent->showStatusBox( $this->status );
- $continue = false;
- if( $this->status->isOK() && !$this->status->isGood() ) {
- $this->addHTML( "<br />" .
- $this->parent->getTextBox( array(
- 'var' => 'wpUpgradeKey',
- 'label' => 'config-localsettings-key',
- ) )
- );
- $continue = 'continue';
- }
- $this->endForm( $continue );
- }
-}
-
class WebInstaller_Language extends WebInstallerPage {
public function execute() {
}
+class WebInstaller_ExistingWiki extends WebInstallerPage {
+ public function execute() {
+ // If there is no LocalSettings.php, continue to the installer welcome page
+ $vars = $this->parent->getExistingLocalSettings();
+ if ( !$vars ) {
+ return 'skip';
+ }
+
+ // Check if the upgrade key supplied to the user has appeared in LocalSettings.php
+ if ( $vars['wgUpgradeKey'] !== false
+ && $this->getVar( '_UpgradeKeySupplied' )
+ && $this->getVar( 'wgUpgradeKey' ) === $vars['wgUpgradeKey'] )
+ {
+ // It's there, so the user is authorized
+ $status = $this->handleExistingUpgrade( $vars );
+ if ( $status->isOK() ) {
+ return 'skip';
+ } else {
+ $this->startForm();
+ $this->parent->showStatusBox( $status );
+ $this->endForm( 'continue' );
+ return 'output';
+ }
+ return $this->handleExistingUpgrade( $vars );
+ }
+
+ // If there is no $wgUpgradeKey, tell the user to add one to LocalSettings.php
+ if ( $vars['wgUpgradeKey'] === false ) {
+ if ( $this->getVar( 'wgUpgradeKey', false ) === false ) {
+ $this->parent->generateUpgradeKey();
+ $this->setVar( '_UpgradeKeySupplied', true );
+ }
+ $this->startForm();
+ $this->addHTML( $this->parent->getInfoBox(
+ wfMsgNoTrans( 'config-upgrade-key-missing',
+ "<pre>\$wgUpgradeKey = '" . $this->getVar( 'wgUpgradeKey' ) . "';</pre>" )
+ ) );
+ $this->endForm( 'continue' );
+ return 'output';
+ }
+
+ // If there is an upgrade key, but it wasn't supplied, prompt the user to enter it
+
+ $r = $this->parent->request;
+ if ( $r->wasPosted() ) {
+ $key = $r->getText( 'config_wgUpgradeKey' );
+ if( !$key || $key !== $vars['wgUpgradeKey'] ) {
+ $this->parent->showError( 'config-localsettings-badkey' );
+ $this->showKeyForm();
+ return 'output';
+ }
+ // Key was OK
+ $status = $this->handleExistingUpgrade( $vars );
+ if ( $status->isOK() ) {
+ return 'continue';
+ } else {
+ $this->parent->showStatusBox( $status );
+ $this->showKeyForm();
+ return 'output';
+ }
+ } else {
+ $this->showKeyForm();
+ return 'output';
+ }
+ }
+
+ /**
+ * Show the "enter key" form
+ */
+ protected function showKeyForm() {
+ $this->startForm();
+ $this->addHTML(
+ $this->parent->getInfoBox( wfMsgNoTrans( 'config-localsettings-upgrade' ) ).
+ '<br />' .
+ $this->parent->getTextBox( array(
+ 'var' => 'wgUpgradeKey',
+ 'label' => 'config-localsettings-key',
+ 'attribs' => array( 'autocomplete' => 'off' ),
+ ) )
+ );
+ $this->endForm( 'continue' );
+ }
+
+ protected function importVariables( $names, $vars ) {
+ $status = Status::newGood();
+ foreach ( $names as $name ) {
+ if ( !isset( $vars[$name] ) ) {
+ $status->fatal( 'config-localsettings-incomplete', $name );
+ }
+ $this->setVar( $name, $vars[$name] );
+ }
+ return $status;
+ }
+
+ /**
+ * Initiate an upgrade of the existing database
+ * @param $vars Variables from LocalSettings.php and AdminSettings.php
+ * @return Status
+ */
+ protected function handleExistingUpgrade( $vars ) {
+ // Check $wgDBtype
+ if ( !isset( $vars['wgDBtype'] ) || !in_array( $vars['wgDBtype'], Installer::getDBTypes() ) ) {
+ return Status::newFatal( 'config-localsettings-connection-error', '' );
+ }
+
+ // Set the relevant variables from LocalSettings.php
+ $requiredVars = array( 'wgDBtype', 'wgDBuser', 'wgDBpassword' );
+ $status = $this->importVariables( $requiredVars , $vars );
+ $installer = $this->parent->getDBInstaller();
+ $status->merge( $this->importVariables( $installer->getGlobalNames(), $vars ) );
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+
+ if ( isset( $vars['wgDBadminuser'] ) ) {
+ $this->setVar( '_InstallUser', $vars['wgDBadminuser'] );
+ } else {
+ $this->setVar( '_InstallUser', $vars['wgDBuser'] );
+ }
+ if ( isset( $vars['wgDBadminpassword'] ) ) {
+ $this->setVar( '_InstallPassword', $vars['wgDBadminpassword'] );
+ } else {
+ $this->setVar( '_InstallPassword', $vars['wgDBpassword'] );
+ }
+
+ // Test the database connection
+ $status = $installer->getConnection();
+ if ( !$status->isOK() ) {
+ // Adjust the error message to explain things correctly
+ $status->replaceMessage( 'config-connection-error',
+ 'config-localsettings-connection-error' );
+ return $status;
+ }
+
+ // All good
+ $this->setVar( '_ExistingDBSettings', true );
+ return $status;
+ }
+}
+
class WebInstaller_Welcome extends WebInstallerPage {
public function execute() {
class WebInstaller_DBConnect extends WebInstallerPage {
public function execute() {
+ if ( $this->getVar( '_ExistingDBSettings' ) ) {
+ return 'skip';
+ }
+
$r = $this->parent->request;
if ( $r->wasPosted() ) {
$status = $this->submit();