MediaWiki
REL1_19
|
00001 <?php 00015 abstract class WebInstallerPage { 00016 00022 public $parent; 00023 00024 public abstract function execute(); 00025 00031 public function __construct( WebInstaller $parent ) { 00032 $this->parent = $parent; 00033 } 00034 00040 public function isSlow() { 00041 return false; 00042 } 00043 00044 public function addHTML( $html ) { 00045 $this->parent->output->addHTML( $html ); 00046 } 00047 00048 public function startForm() { 00049 $this->addHTML( 00050 "<div class=\"config-section\">\n" . 00051 Html::openElement( 00052 'form', 00053 array( 00054 'method' => 'post', 00055 'action' => $this->parent->getUrl( array( 'page' => $this->getName() ) ) 00056 ) 00057 ) . "\n" 00058 ); 00059 } 00060 00061 public function endForm( $continue = 'continue', $back = 'back' ) { 00062 $s = "<div class=\"config-submit\">\n"; 00063 $id = $this->getId(); 00064 00065 if ( $id === false ) { 00066 $s .= Html::hidden( 'lastPage', $this->parent->request->getVal( 'lastPage' ) ); 00067 } 00068 00069 if ( $continue ) { 00070 // Fake submit button for enter keypress (bug 26267) 00071 $s .= Xml::submitButton( wfMsg( "config-$continue" ), 00072 array( 'name' => "enter-$continue", 'style' => 00073 'visibility:hidden;overflow:hidden;width:1px;margin:0' ) ) . "\n"; 00074 } 00075 00076 if ( $back ) { 00077 $s .= Xml::submitButton( wfMsg( "config-$back" ), 00078 array( 00079 'name' => "submit-$back", 00080 'tabindex' => $this->parent->nextTabIndex() 00081 ) ) . "\n"; 00082 } 00083 00084 if ( $continue ) { 00085 $s .= Xml::submitButton( wfMsg( "config-$continue" ), 00086 array( 00087 'name' => "submit-$continue", 00088 'tabindex' => $this->parent->nextTabIndex(), 00089 ) ) . "\n"; 00090 } 00091 00092 $s .= "</div></form></div>\n"; 00093 $this->addHTML( $s ); 00094 } 00095 00096 public function getName() { 00097 return str_replace( 'WebInstaller_', '', get_class( $this ) ); 00098 } 00099 00100 protected function getId() { 00101 return array_search( $this->getName(), $this->parent->pageSequence ); 00102 } 00103 00104 public function getVar( $var ) { 00105 return $this->parent->getVar( $var ); 00106 } 00107 00108 public function setVar( $name, $value ) { 00109 $this->parent->setVar( $name, $value ); 00110 } 00111 00119 protected function getFieldsetStart( $legend ) { 00120 return "\n<fieldset><legend>" . wfMsgHtml( $legend ) . "</legend>\n"; 00121 } 00122 00128 protected function getFieldsetEnd() { 00129 return "</fieldset>\n"; 00130 } 00131 00135 protected function startLiveBox() { 00136 $this->addHTML( 00137 '<div id="config-spinner" style="display:none;">' . 00138 '<img src="../skins/common/images/ajax-loader.gif" /></div>' . 00139 '<script>jQuery( "#config-spinner" ).show();</script>' . 00140 '<div id="config-live-log">' . 00141 '<textarea name="LiveLog" rows="10" cols="30" readonly="readonly">' 00142 ); 00143 $this->parent->output->flush(); 00144 } 00145 00149 protected function endLiveBox() { 00150 $this->addHTML( '</textarea></div> 00151 <script>jQuery( "#config-spinner" ).hide()</script>' ); 00152 $this->parent->output->flush(); 00153 } 00154 } 00155 00156 class WebInstaller_Language extends WebInstallerPage { 00157 00158 public function execute() { 00159 global $wgLang; 00160 $r = $this->parent->request; 00161 $userLang = $r->getVal( 'uselang' ); 00162 $contLang = $r->getVal( 'ContLang' ); 00163 00164 $languages = Language::getLanguageNames(); 00165 $lifetime = intval( ini_get( 'session.gc_maxlifetime' ) ); 00166 if ( !$lifetime ) { 00167 $lifetime = 1440; // PHP default 00168 } 00169 00170 if ( $r->wasPosted() ) { 00171 # Do session test 00172 if ( $this->parent->getSession( 'test' ) === null ) { 00173 $requestTime = $r->getVal( 'LanguageRequestTime' ); 00174 if ( !$requestTime ) { 00175 // The most likely explanation is that the user was knocked back 00176 // from another page on POST due to session expiry 00177 $msg = 'config-session-expired'; 00178 } elseif ( time() - $requestTime > $lifetime ) { 00179 $msg = 'config-session-expired'; 00180 } else { 00181 $msg = 'config-no-session'; 00182 } 00183 $this->parent->showError( $msg, $wgLang->formatTimePeriod( $lifetime ) ); 00184 } else { 00185 if ( isset( $languages[$userLang] ) ) { 00186 $this->setVar( '_UserLang', $userLang ); 00187 } 00188 if ( isset( $languages[$contLang] ) ) { 00189 $this->setVar( 'wgLanguageCode', $contLang ); 00190 } 00191 return 'continue'; 00192 } 00193 } elseif ( $this->parent->showSessionWarning ) { 00194 # The user was knocked back from another page to the start 00195 # This probably indicates a session expiry 00196 $this->parent->showError( 'config-session-expired', 00197 $wgLang->formatTimePeriod( $lifetime ) ); 00198 } 00199 00200 $this->parent->setSession( 'test', true ); 00201 00202 if ( !isset( $languages[$userLang] ) ) { 00203 $userLang = $this->getVar( '_UserLang', 'en' ); 00204 } 00205 if ( !isset( $languages[$contLang] ) ) { 00206 $contLang = $this->getVar( 'wgLanguageCode', 'en' ); 00207 } 00208 $this->startForm(); 00209 $s = Html::hidden( 'LanguageRequestTime', time() ) . 00210 $this->getLanguageSelector( 'uselang', 'config-your-language', $userLang, 00211 $this->parent->getHelpBox( 'config-your-language-help' ) ) . 00212 $this->getLanguageSelector( 'ContLang', 'config-wiki-language', $contLang, 00213 $this->parent->getHelpBox( 'config-wiki-language-help' ) ); 00214 $this->addHTML( $s ); 00215 $this->endForm( 'continue', false ); 00216 } 00217 00227 public function getLanguageSelector( $name, $label, $selectedCode, $helpHtml = '' ) { 00228 global $wgDummyLanguageCodes; 00229 00230 $s = $helpHtml; 00231 00232 $s .= Html::openElement( 'select', array( 'id' => $name, 'name' => $name, 00233 'tabindex' => $this->parent->nextTabIndex() ) ) . "\n"; 00234 00235 $languages = Language::getLanguageNames(); 00236 ksort( $languages ); 00237 foreach ( $languages as $code => $lang ) { 00238 if ( isset( $wgDummyLanguageCodes[$code] ) ) continue; 00239 $s .= "\n" . Xml::option( "$code - $lang", $code, $code == $selectedCode ); 00240 } 00241 $s .= "\n</select>\n"; 00242 return $this->parent->label( $label, $name, $s ); 00243 } 00244 00245 } 00246 00247 class WebInstaller_ExistingWiki extends WebInstallerPage { 00248 public function execute() { 00249 // If there is no LocalSettings.php, continue to the installer welcome page 00250 $vars = Installer::getExistingLocalSettings(); 00251 if ( !$vars ) { 00252 return 'skip'; 00253 } 00254 00255 // Check if the upgrade key supplied to the user has appeared in LocalSettings.php 00256 if ( $vars['wgUpgradeKey'] !== false 00257 && $this->getVar( '_UpgradeKeySupplied' ) 00258 && $this->getVar( 'wgUpgradeKey' ) === $vars['wgUpgradeKey'] ) 00259 { 00260 // It's there, so the user is authorized 00261 $status = $this->handleExistingUpgrade( $vars ); 00262 if ( $status->isOK() ) { 00263 return 'skip'; 00264 } else { 00265 $this->startForm(); 00266 $this->parent->showStatusBox( $status ); 00267 $this->endForm( 'continue' ); 00268 return 'output'; 00269 } 00270 } 00271 00272 // If there is no $wgUpgradeKey, tell the user to add one to LocalSettings.php 00273 if ( $vars['wgUpgradeKey'] === false ) { 00274 if ( $this->getVar( 'wgUpgradeKey', false ) === false ) { 00275 $secretKey = $this->getVar( 'wgSecretKey' ); // preserve $wgSecretKey 00276 $this->parent->generateKeys(); 00277 $this->setVar( 'wgSecretKey', $secretKey ); 00278 $this->setVar( '_UpgradeKeySupplied', true ); 00279 } 00280 $this->startForm(); 00281 $this->addHTML( $this->parent->getInfoBox( 00282 wfMsgNoTrans( 'config-upgrade-key-missing', 00283 "<pre dir=\"ltr\">\$wgUpgradeKey = '" . $this->getVar( 'wgUpgradeKey' ) . "';</pre>" ) 00284 ) ); 00285 $this->endForm( 'continue' ); 00286 return 'output'; 00287 } 00288 00289 // If there is an upgrade key, but it wasn't supplied, prompt the user to enter it 00290 00291 $r = $this->parent->request; 00292 if ( $r->wasPosted() ) { 00293 $key = $r->getText( 'config_wgUpgradeKey' ); 00294 if( !$key || $key !== $vars['wgUpgradeKey'] ) { 00295 $this->parent->showError( 'config-localsettings-badkey' ); 00296 $this->showKeyForm(); 00297 return 'output'; 00298 } 00299 // Key was OK 00300 $status = $this->handleExistingUpgrade( $vars ); 00301 if ( $status->isOK() ) { 00302 return 'continue'; 00303 } else { 00304 $this->parent->showStatusBox( $status ); 00305 $this->showKeyForm(); 00306 return 'output'; 00307 } 00308 } else { 00309 $this->showKeyForm(); 00310 return 'output'; 00311 } 00312 } 00313 00317 protected function showKeyForm() { 00318 $this->startForm(); 00319 $this->addHTML( 00320 $this->parent->getInfoBox( wfMsgNoTrans( 'config-localsettings-upgrade' ) ). 00321 '<br />' . 00322 $this->parent->getTextBox( array( 00323 'var' => 'wgUpgradeKey', 00324 'label' => 'config-localsettings-key', 00325 'attribs' => array( 'autocomplete' => 'off' ), 00326 ) ) 00327 ); 00328 $this->endForm( 'continue' ); 00329 } 00330 00331 protected function importVariables( $names, $vars ) { 00332 $status = Status::newGood(); 00333 foreach ( $names as $name ) { 00334 if ( !isset( $vars[$name] ) ) { 00335 $status->fatal( 'config-localsettings-incomplete', $name ); 00336 } 00337 $this->setVar( $name, $vars[$name] ); 00338 } 00339 return $status; 00340 } 00341 00347 protected function handleExistingUpgrade( $vars ) { 00348 // Check $wgDBtype 00349 if ( !isset( $vars['wgDBtype'] ) || 00350 !in_array( $vars['wgDBtype'], Installer::getDBTypes() ) ) { 00351 return Status::newFatal( 'config-localsettings-connection-error', '' ); 00352 } 00353 00354 // Set the relevant variables from LocalSettings.php 00355 $requiredVars = array( 'wgDBtype' ); 00356 $status = $this->importVariables( $requiredVars , $vars ); 00357 $installer = $this->parent->getDBInstaller(); 00358 $status->merge( $this->importVariables( $installer->getGlobalNames(), $vars ) ); 00359 if ( !$status->isOK() ) { 00360 return $status; 00361 } 00362 00363 if ( isset( $vars['wgDBadminuser'] ) ) { 00364 $this->setVar( '_InstallUser', $vars['wgDBadminuser'] ); 00365 } else { 00366 $this->setVar( '_InstallUser', $vars['wgDBuser'] ); 00367 } 00368 if ( isset( $vars['wgDBadminpassword'] ) ) { 00369 $this->setVar( '_InstallPassword', $vars['wgDBadminpassword'] ); 00370 } else { 00371 $this->setVar( '_InstallPassword', $vars['wgDBpassword'] ); 00372 } 00373 00374 // Test the database connection 00375 $status = $installer->getConnection(); 00376 if ( !$status->isOK() ) { 00377 // Adjust the error message to explain things correctly 00378 $status->replaceMessage( 'config-connection-error', 00379 'config-localsettings-connection-error' ); 00380 return $status; 00381 } 00382 00383 // All good 00384 $this->setVar( '_ExistingDBSettings', true ); 00385 return $status; 00386 } 00387 } 00388 00389 class WebInstaller_Welcome extends WebInstallerPage { 00390 00391 public function execute() { 00392 if ( $this->parent->request->wasPosted() ) { 00393 if ( $this->getVar( '_Environment' ) ) { 00394 return 'continue'; 00395 } 00396 } 00397 $this->parent->output->addWikiText( wfMsgNoTrans( 'config-welcome' ) ); 00398 $status = $this->parent->doEnvironmentChecks(); 00399 if ( $status->isGood() ) { 00400 $this->parent->output->addHTML( '<span class="success-message">' . 00401 wfMsgHtml( 'config-env-good' ) . '</span>' ); 00402 $this->parent->output->addWikiText( wfMsgNoTrans( 'config-copyright', 00403 SpecialVersion::getCopyrightAndAuthorList() ) ); 00404 $this->startForm(); 00405 $this->endForm(); 00406 } else { 00407 $this->parent->showStatusMessage( $status ); 00408 } 00409 } 00410 00411 } 00412 00413 class WebInstaller_DBConnect extends WebInstallerPage { 00414 00415 public function execute() { 00416 if ( $this->getVar( '_ExistingDBSettings' ) ) { 00417 return 'skip'; 00418 } 00419 00420 $r = $this->parent->request; 00421 if ( $r->wasPosted() ) { 00422 $status = $this->submit(); 00423 00424 if ( $status->isGood() ) { 00425 $this->setVar( '_UpgradeDone', false ); 00426 return 'continue'; 00427 } else { 00428 $this->parent->showStatusBox( $status ); 00429 } 00430 } 00431 00432 $this->startForm(); 00433 00434 $types = "<ul class=\"config-settings-block\">\n"; 00435 $settings = ''; 00436 $defaultType = $this->getVar( 'wgDBtype' ); 00437 00438 $dbSupport = ''; 00439 foreach( $this->parent->getDBTypes() as $type ) { 00440 $link = DatabaseBase::factory( $type )->getSoftwareLink(); 00441 $dbSupport .= wfMsgNoTrans( "config-support-$type", $link ) . "\n"; 00442 } 00443 $this->addHTML( $this->parent->getInfoBox( 00444 wfMsg( 'config-support-info', $dbSupport ) ) ); 00445 00446 foreach ( $this->parent->getVar( '_CompiledDBs' ) as $type ) { 00447 $installer = $this->parent->getDBInstaller( $type ); 00448 $types .= 00449 '<li>' . 00450 Xml::radioLabel( 00451 $installer->getReadableName(), 00452 'DBType', 00453 $type, 00454 "DBType_$type", 00455 $type == $defaultType, 00456 array( 'class' => 'dbRadio', 'rel' => "DB_wrapper_$type" ) 00457 ) . 00458 "</li>\n"; 00459 00460 $settings .= 00461 Html::openElement( 'div', array( 'id' => 'DB_wrapper_' . $type, 00462 'class' => 'dbWrapper' ) ) . 00463 Html::element( 'h3', array(), wfMsg( 'config-header-' . $type ) ) . 00464 $installer->getConnectForm() . 00465 "</div>\n"; 00466 } 00467 $types .= "</ul><br style=\"clear: left\"/>\n"; 00468 00469 $this->addHTML( 00470 $this->parent->label( 'config-db-type', false, $types ) . 00471 $settings 00472 ); 00473 00474 $this->endForm(); 00475 } 00476 00477 public function submit() { 00478 $r = $this->parent->request; 00479 $type = $r->getVal( 'DBType' ); 00480 $this->setVar( 'wgDBtype', $type ); 00481 $installer = $this->parent->getDBInstaller( $type ); 00482 if ( !$installer ) { 00483 return Status::newFatal( 'config-invalid-db-type' ); 00484 } 00485 return $installer->submitConnectForm(); 00486 } 00487 00488 } 00489 00490 class WebInstaller_Upgrade extends WebInstallerPage { 00491 public function isSlow() { 00492 return true; 00493 } 00494 00495 public function execute() { 00496 if ( $this->getVar( '_UpgradeDone' ) ) { 00497 // Allow regeneration of LocalSettings.php, unless we are working 00498 // from a pre-existing LocalSettings.php file and we want to avoid 00499 // leaking its contents 00500 if ( $this->parent->request->wasPosted() && !$this->getVar( '_ExistingDBSettings' ) ) { 00501 // Done message acknowledged 00502 return 'continue'; 00503 } else { 00504 // Back button click 00505 // Show the done message again 00506 // Make them click back again if they want to do the upgrade again 00507 $this->showDoneMessage(); 00508 return 'output'; 00509 } 00510 } 00511 00512 // wgDBtype is generally valid here because otherwise the previous page 00513 // (connect) wouldn't have declared its happiness 00514 $type = $this->getVar( 'wgDBtype' ); 00515 $installer = $this->parent->getDBInstaller( $type ); 00516 00517 if ( !$installer->needsUpgrade() ) { 00518 return 'skip'; 00519 } 00520 00521 if ( $this->parent->request->wasPosted() ) { 00522 $installer->preUpgrade(); 00523 00524 $this->startLiveBox(); 00525 $result = $installer->doUpgrade(); 00526 $this->endLiveBox(); 00527 00528 if ( $result ) { 00529 // If they're going to possibly regenerate LocalSettings, we 00530 // need to create the upgrade/secret keys. Bug 26481 00531 if( !$this->getVar( '_ExistingDBSettings' ) ) { 00532 $this->parent->generateKeys(); 00533 } 00534 $this->setVar( '_UpgradeDone', true ); 00535 $this->showDoneMessage(); 00536 return 'output'; 00537 } 00538 } 00539 00540 $this->startForm(); 00541 $this->addHTML( $this->parent->getInfoBox( 00542 wfMsgNoTrans( 'config-can-upgrade', $GLOBALS['wgVersion'] ) ) ); 00543 $this->endForm(); 00544 } 00545 00546 public function showDoneMessage() { 00547 $this->startForm(); 00548 $regenerate = !$this->getVar( '_ExistingDBSettings' ); 00549 if ( $regenerate ) { 00550 $msg = 'config-upgrade-done'; 00551 } else { 00552 $msg = 'config-upgrade-done-no-regenerate'; 00553 } 00554 $this->parent->disableLinkPopups(); 00555 $this->addHTML( 00556 $this->parent->getInfoBox( 00557 wfMsgNoTrans( $msg, 00558 $this->getVar( 'wgServer' ) . 00559 $this->getVar( 'wgScriptPath' ) . '/index' . 00560 $this->getVar( 'wgScriptExtension' ) 00561 ), 'tick-32.png' 00562 ) 00563 ); 00564 $this->parent->restoreLinkPopups(); 00565 $this->endForm( $regenerate ? 'regenerate' : false, false ); 00566 } 00567 00568 } 00569 00570 class WebInstaller_DBSettings extends WebInstallerPage { 00571 00572 public function execute() { 00573 $installer = $this->parent->getDBInstaller( $this->getVar( 'wgDBtype' ) ); 00574 00575 $r = $this->parent->request; 00576 if ( $r->wasPosted() ) { 00577 $status = $installer->submitSettingsForm(); 00578 if ( $status === false ) { 00579 return 'skip'; 00580 } elseif ( $status->isGood() ) { 00581 return 'continue'; 00582 } else { 00583 $this->parent->showStatusBox( $status ); 00584 } 00585 } 00586 00587 $form = $installer->getSettingsForm(); 00588 if ( $form === false ) { 00589 return 'skip'; 00590 } 00591 00592 $this->startForm(); 00593 $this->addHTML( $form ); 00594 $this->endForm(); 00595 } 00596 00597 } 00598 00599 class WebInstaller_Name extends WebInstallerPage { 00600 00601 public function execute() { 00602 $r = $this->parent->request; 00603 if ( $r->wasPosted() ) { 00604 if ( $this->submit() ) { 00605 return 'continue'; 00606 } 00607 } 00608 00609 $this->startForm(); 00610 00611 // Encourage people to not name their site 'MediaWiki' by blanking the 00612 // field. I think that was the intent with the original $GLOBALS['wgSitename'] 00613 // but these two always were the same so had the effect of making the 00614 // installer forget $wgSitename when navigating back to this page. 00615 if ( $this->getVar( 'wgSitename' ) == 'MediaWiki' ) { 00616 $this->setVar( 'wgSitename', '' ); 00617 } 00618 00619 // Set wgMetaNamespace to something valid before we show the form. 00620 // $wgMetaNamespace defaults to $wgSiteName which is 'MediaWiki' 00621 $metaNS = $this->getVar( 'wgMetaNamespace' ); 00622 $this->setVar( 'wgMetaNamespace', wfMsgForContent( 'config-ns-other-default' ) ); 00623 00624 $this->addHTML( 00625 $this->parent->getTextBox( array( 00626 'var' => 'wgSitename', 00627 'label' => 'config-site-name', 00628 'help' => $this->parent->getHelpBox( 'config-site-name-help' ) 00629 ) ) . 00630 $this->parent->getRadioSet( array( 00631 'var' => '_NamespaceType', 00632 'label' => 'config-project-namespace', 00633 'itemLabelPrefix' => 'config-ns-', 00634 'values' => array( 'site-name', 'generic', 'other' ), 00635 'commonAttribs' => array( 'class' => 'enableForOther', 00636 'rel' => 'config_wgMetaNamespace' ), 00637 'help' => $this->parent->getHelpBox( 'config-project-namespace-help' ) 00638 ) ) . 00639 $this->parent->getTextBox( array( 00640 'var' => 'wgMetaNamespace', 00641 'label' => '', //TODO: Needs a label? 00642 'attribs' => array( 'readonly' => 'readonly', 'class' => 'enabledByOther' ), 00643 00644 ) ) . 00645 $this->getFieldSetStart( 'config-admin-box' ) . 00646 $this->parent->getTextBox( array( 00647 'var' => '_AdminName', 00648 'label' => 'config-admin-name', 00649 'help' => $this->parent->getHelpBox( 'config-admin-help' ) 00650 ) ) . 00651 $this->parent->getPasswordBox( array( 00652 'var' => '_AdminPassword', 00653 'label' => 'config-admin-password', 00654 ) ) . 00655 $this->parent->getPasswordBox( array( 00656 'var' => '_AdminPassword2', 00657 'label' => 'config-admin-password-confirm' 00658 ) ) . 00659 $this->parent->getTextBox( array( 00660 'var' => '_AdminEmail', 00661 'label' => 'config-admin-email', 00662 'help' => $this->parent->getHelpBox( 'config-admin-email-help' ) 00663 ) ) . 00664 $this->parent->getCheckBox( array( 00665 'var' => '_Subscribe', 00666 'label' => 'config-subscribe', 00667 'help' => $this->parent->getHelpBox( 'config-subscribe-help' ) 00668 ) ) . 00669 $this->getFieldSetEnd() . 00670 $this->parent->getInfoBox( wfMsg( 'config-almost-done' ) ) . 00671 $this->parent->getRadioSet( array( 00672 'var' => '_SkipOptional', 00673 'itemLabelPrefix' => 'config-optional-', 00674 'values' => array( 'continue', 'skip' ) 00675 ) ) 00676 ); 00677 00678 // Restore the default value 00679 $this->setVar( 'wgMetaNamespace', $metaNS ); 00680 00681 $this->endForm(); 00682 return 'output'; 00683 } 00684 00685 public function submit() { 00686 $retVal = true; 00687 $this->parent->setVarsFromRequest( array( 'wgSitename', '_NamespaceType', 00688 '_AdminName', '_AdminPassword', '_AdminPassword2', '_AdminEmail', 00689 '_Subscribe', '_SkipOptional', 'wgMetaNamespace' ) ); 00690 00691 // Validate site name 00692 if ( strval( $this->getVar( 'wgSitename' ) ) === '' ) { 00693 $this->parent->showError( 'config-site-name-blank' ); 00694 $retVal = false; 00695 } 00696 00697 // Fetch namespace 00698 $nsType = $this->getVar( '_NamespaceType' ); 00699 if ( $nsType == 'site-name' ) { 00700 $name = $this->getVar( 'wgSitename' ); 00701 // Sanitize for namespace 00702 // This algorithm should match the JS one in WebInstallerOutput.php 00703 $name = preg_replace( '/[\[\]\{\}|#<>%+? ]/', '_', $name ); 00704 $name = str_replace( '&', '&', $name ); 00705 $name = preg_replace( '/__+/', '_', $name ); 00706 $name = ucfirst( trim( $name, '_' ) ); 00707 } elseif ( $nsType == 'generic' ) { 00708 $name = wfMsg( 'config-ns-generic' ); 00709 } else { // other 00710 $name = $this->getVar( 'wgMetaNamespace' ); 00711 } 00712 00713 // Validate namespace 00714 if ( strpos( $name, ':' ) !== false ) { 00715 $good = false; 00716 } else { 00717 // Title-style validation 00718 $title = Title::newFromText( $name ); 00719 if ( !$title ) { 00720 $good = $nsType == 'site-name'; 00721 } else { 00722 $name = $title->getDBkey(); 00723 $good = true; 00724 } 00725 } 00726 if ( !$good ) { 00727 $this->parent->showError( 'config-ns-invalid', $name ); 00728 $retVal = false; 00729 } 00730 00731 // Make sure it won't conflict with any existing namespaces 00732 global $wgContLang; 00733 $nsIndex = $wgContLang->getNsIndex( $name ); 00734 if( $nsIndex !== false && $nsIndex !== NS_PROJECT ) { 00735 $this->parent->showError( 'config-ns-conflict', $name ); 00736 $retVal = false; 00737 } 00738 00739 $this->setVar( 'wgMetaNamespace', $name ); 00740 00741 // Validate username for creation 00742 $name = $this->getVar( '_AdminName' ); 00743 if ( strval( $name ) === '' ) { 00744 $this->parent->showError( 'config-admin-name-blank' ); 00745 $cname = $name; 00746 $retVal = false; 00747 } else { 00748 $cname = User::getCanonicalName( $name, 'creatable' ); 00749 if ( $cname === false ) { 00750 $this->parent->showError( 'config-admin-name-invalid', $name ); 00751 $retVal = false; 00752 } else { 00753 $this->setVar( '_AdminName', $cname ); 00754 } 00755 } 00756 00757 // Validate password 00758 $msg = false; 00759 $pwd = $this->getVar( '_AdminPassword' ); 00760 $user = User::newFromName( $cname ); 00761 $valid = $user && $user->getPasswordValidity( $pwd ); 00762 if ( strval( $pwd ) === '' ) { 00763 # $user->getPasswordValidity just checks for $wgMinimalPasswordLength. 00764 # This message is more specific and helpful. 00765 $msg = 'config-admin-password-blank'; 00766 } elseif ( $pwd !== $this->getVar( '_AdminPassword2' ) ) { 00767 $msg = 'config-admin-password-mismatch'; 00768 } elseif ( $valid !== true ) { 00769 # As of writing this will only catch the username being e.g. 'FOO' and 00770 # the password 'foo' 00771 $msg = $valid; 00772 } 00773 if ( $msg !== false ) { 00774 call_user_func_array( array( $this->parent, 'showError' ), (array)$msg ); 00775 $this->setVar( '_AdminPassword', '' ); 00776 $this->setVar( '_AdminPassword2', '' ); 00777 $retVal = false; 00778 } 00779 00780 // Validate e-mail if provided 00781 $email = $this->getVar( '_AdminEmail' ); 00782 if( $email && !Sanitizer::validateEmail( $email ) ) { 00783 $this->parent->showError( 'config-admin-error-bademail' ); 00784 $retVal = false; 00785 } 00786 // If they asked to subscribe to mediawiki-announce but didn't give 00787 // an e-mail, show an error. Bug 29332 00788 if( !$email && $this->getVar( '_Subscribe' ) ) { 00789 $this->parent->showError( 'config-subscribe-noemail' ); 00790 $retVal = false; 00791 } 00792 00793 return $retVal; 00794 } 00795 00796 } 00797 00798 class WebInstaller_Options extends WebInstallerPage { 00799 00800 public function execute() { 00801 if ( $this->getVar( '_SkipOptional' ) == 'skip' ) { 00802 return 'skip'; 00803 } 00804 if ( $this->parent->request->wasPosted() ) { 00805 if ( $this->submit() ) { 00806 return 'continue'; 00807 } 00808 } 00809 00810 $emailwrapperStyle = $this->getVar( 'wgEnableEmail' ) ? '' : 'display: none'; 00811 $this->startForm(); 00812 $this->addHTML( 00813 # User Rights 00814 $this->parent->getRadioSet( array( 00815 'var' => '_RightsProfile', 00816 'label' => 'config-profile', 00817 'itemLabelPrefix' => 'config-profile-', 00818 'values' => array_keys( $this->parent->rightsProfiles ), 00819 ) ) . 00820 $this->parent->getInfoBox( wfMsgNoTrans( 'config-profile-help' ) ) . 00821 00822 # Licensing 00823 $this->parent->getRadioSet( array( 00824 'var' => '_LicenseCode', 00825 'label' => 'config-license', 00826 'itemLabelPrefix' => 'config-license-', 00827 'values' => array_keys( $this->parent->licenses ), 00828 'commonAttribs' => array( 'class' => 'licenseRadio' ), 00829 ) ) . 00830 $this->getCCChooser() . 00831 $this->parent->getHelpBox( 'config-license-help' ) . 00832 00833 # E-mail 00834 $this->getFieldSetStart( 'config-email-settings' ) . 00835 $this->parent->getCheckBox( array( 00836 'var' => 'wgEnableEmail', 00837 'label' => 'config-enable-email', 00838 'attribs' => array( 'class' => 'showHideRadio', 'rel' => 'emailwrapper' ), 00839 ) ) . 00840 $this->parent->getHelpBox( 'config-enable-email-help' ) . 00841 "<div id=\"emailwrapper\" style=\"$emailwrapperStyle\">" . 00842 $this->parent->getTextBox( array( 00843 'var' => 'wgPasswordSender', 00844 'label' => 'config-email-sender' 00845 ) ) . 00846 $this->parent->getHelpBox( 'config-email-sender-help' ) . 00847 $this->parent->getCheckBox( array( 00848 'var' => 'wgEnableUserEmail', 00849 'label' => 'config-email-user', 00850 ) ) . 00851 $this->parent->getHelpBox( 'config-email-user-help' ) . 00852 $this->parent->getCheckBox( array( 00853 'var' => 'wgEnotifUserTalk', 00854 'label' => 'config-email-usertalk', 00855 ) ) . 00856 $this->parent->getHelpBox( 'config-email-usertalk-help' ) . 00857 $this->parent->getCheckBox( array( 00858 'var' => 'wgEnotifWatchlist', 00859 'label' => 'config-email-watchlist', 00860 ) ) . 00861 $this->parent->getHelpBox( 'config-email-watchlist-help' ) . 00862 $this->parent->getCheckBox( array( 00863 'var' => 'wgEmailAuthentication', 00864 'label' => 'config-email-auth', 00865 ) ) . 00866 $this->parent->getHelpBox( 'config-email-auth-help' ) . 00867 "</div>" . 00868 $this->getFieldSetEnd() 00869 ); 00870 00871 $extensions = $this->parent->findExtensions(); 00872 00873 if( $extensions ) { 00874 $extHtml = $this->getFieldSetStart( 'config-extensions' ); 00875 00876 foreach( $extensions as $ext ) { 00877 $extHtml .= $this->parent->getCheckBox( array( 00878 'var' => "ext-$ext", 00879 'rawtext' => $ext, 00880 ) ); 00881 } 00882 00883 $extHtml .= $this->parent->getHelpBox( 'config-extensions-help' ) . 00884 $this->getFieldSetEnd(); 00885 $this->addHTML( $extHtml ); 00886 } 00887 00888 // Having / in paths in Windows looks funny :) 00889 $this->setVar( 'wgDeletedDirectory', 00890 str_replace( 00891 '/', DIRECTORY_SEPARATOR, 00892 $this->getVar( 'wgDeletedDirectory' ) 00893 ) 00894 ); 00895 00896 $uploadwrapperStyle = $this->getVar( 'wgEnableUploads' ) ? '' : 'display: none'; 00897 $this->addHTML( 00898 # Uploading 00899 $this->getFieldSetStart( 'config-upload-settings' ) . 00900 $this->parent->getCheckBox( array( 00901 'var' => 'wgEnableUploads', 00902 'label' => 'config-upload-enable', 00903 'attribs' => array( 'class' => 'showHideRadio', 'rel' => 'uploadwrapper' ), 00904 'help' => $this->parent->getHelpBox( 'config-upload-help' ) 00905 ) ) . 00906 '<div id="uploadwrapper" style="' . $uploadwrapperStyle . '">' . 00907 $this->parent->getTextBox( array( 00908 'var' => 'wgDeletedDirectory', 00909 'label' => 'config-upload-deleted', 00910 'attribs' => array( 'dir' => 'ltr' ), 00911 'help' => $this->parent->getHelpBox( 'config-upload-deleted-help' ) 00912 ) ) . 00913 '</div>' . 00914 $this->parent->getTextBox( array( 00915 'var' => 'wgLogo', 00916 'label' => 'config-logo', 00917 'attribs' => array( 'dir' => 'ltr' ), 00918 'help' => $this->parent->getHelpBox( 'config-logo-help' ) 00919 ) ) 00920 ); 00921 $this->addHTML( 00922 $this->parent->getCheckBox( array( 00923 'var' => 'wgUseInstantCommons', 00924 'label' => 'config-instantcommons', 00925 'help' => $this->parent->getHelpBox( 'config-instantcommons-help' ) 00926 ) ) . 00927 $this->getFieldSetEnd() 00928 ); 00929 00930 $caches = array( 'none' ); 00931 if( count( $this->getVar( '_Caches' ) ) ) { 00932 $caches[] = 'accel'; 00933 } 00934 $caches[] = 'memcached'; 00935 00936 // We'll hide/show this on demand when the value changes, see config.js. 00937 $cacheval = $this->getVar( 'wgMainCacheType' ); 00938 if (!$cacheval) { 00939 // We need to set a default here; but don't hardcode it 00940 // or we lose it every time we reload the page for validation 00941 // or going back! 00942 $cacheval = 'none'; 00943 } 00944 $hidden = ($cacheval == 'memcached') ? '' : 'display: none'; 00945 $this->addHTML( 00946 # Advanced settings 00947 $this->getFieldSetStart( 'config-advanced-settings' ) . 00948 # Object cache settings 00949 $this->parent->getRadioSet( array( 00950 'var' => 'wgMainCacheType', 00951 'label' => 'config-cache-options', 00952 'itemLabelPrefix' => 'config-cache-', 00953 'values' => $caches, 00954 'value' => $cacheval, 00955 ) ) . 00956 $this->parent->getHelpBox( 'config-cache-help' ) . 00957 "<div id=\"config-memcachewrapper\" style=\"$hidden\">" . 00958 $this->parent->getTextArea( array( 00959 'var' => '_MemCachedServers', 00960 'label' => 'config-memcached-servers', 00961 'help' => $this->parent->getHelpBox( 'config-memcached-help' ) 00962 ) ) . 00963 '</div>' . 00964 $this->getFieldSetEnd() 00965 ); 00966 $this->endForm(); 00967 } 00968 00972 public function getCCPartnerUrl() { 00973 $server = $this->getVar( 'wgServer' ); 00974 $exitUrl = $server . $this->parent->getUrl( array( 00975 'page' => 'Options', 00976 'SubmitCC' => 'indeed', 00977 'config__LicenseCode' => 'cc', 00978 'config_wgRightsUrl' => '[license_url]', 00979 'config_wgRightsText' => '[license_name]', 00980 'config_wgRightsIcon' => '[license_button]', 00981 ) ); 00982 $styleUrl = $server . dirname( dirname( $this->parent->getUrl() ) ) . 00983 '/skins/common/config-cc.css'; 00984 $iframeUrl = 'http://creativecommons.org/license/?' . 00985 wfArrayToCGI( array( 00986 'partner' => 'MediaWiki', 00987 'exit_url' => $exitUrl, 00988 'lang' => $this->getVar( '_UserLang' ), 00989 'stylesheet' => $styleUrl, 00990 ) ); 00991 return $iframeUrl; 00992 } 00993 00994 public function getCCChooser() { 00995 $iframeAttribs = array( 00996 'class' => 'config-cc-iframe', 00997 'name' => 'config-cc-iframe', 00998 'id' => 'config-cc-iframe', 00999 'frameborder' => 0, 01000 'width' => '100%', 01001 'height' => '100%', 01002 ); 01003 if ( $this->getVar( '_CCDone' ) ) { 01004 $iframeAttribs['src'] = $this->parent->getUrl( array( 'ShowCC' => 'yes' ) ); 01005 } else { 01006 $iframeAttribs['src'] = $this->getCCPartnerUrl(); 01007 } 01008 $wrapperStyle = ($this->getVar('_LicenseCode') == 'cc-choose') ? '' : 'display: none'; 01009 01010 return 01011 "<div class=\"config-cc-wrapper\" id=\"config-cc-wrapper\" style=\"$wrapperStyle\">\n" . 01012 Html::element( 'iframe', $iframeAttribs, '', false /* not short */ ) . 01013 "</div>\n"; 01014 } 01015 01016 public function getCCDoneBox() { 01017 $js = "parent.document.getElementById('config-cc-wrapper').style.height = '$1';"; 01018 // If you change this height, also change it in config.css 01019 $expandJs = str_replace( '$1', '54em', $js ); 01020 $reduceJs = str_replace( '$1', '70px', $js ); 01021 return 01022 '<p>'. 01023 Html::element( 'img', array( 'src' => $this->getVar( 'wgRightsIcon' ) ) ) . 01024 '  ' . 01025 htmlspecialchars( $this->getVar( 'wgRightsText' ) ) . 01026 "</p>\n" . 01027 "<p style=\"text-align: center\">" . 01028 Html::element( 'a', 01029 array( 01030 'href' => $this->getCCPartnerUrl(), 01031 'onclick' => $expandJs, 01032 ), 01033 wfMsg( 'config-cc-again' ) 01034 ) . 01035 "</p>\n" . 01036 "<script type=\"text/javascript\">\n" . 01037 # Reduce the wrapper div height 01038 htmlspecialchars( $reduceJs ) . 01039 "\n" . 01040 "</script>\n"; 01041 } 01042 01043 public function submitCC() { 01044 $newValues = $this->parent->setVarsFromRequest( 01045 array( 'wgRightsUrl', 'wgRightsText', 'wgRightsIcon' ) ); 01046 if ( count( $newValues ) != 3 ) { 01047 $this->parent->showError( 'config-cc-error' ); 01048 return; 01049 } 01050 $this->setVar( '_CCDone', true ); 01051 $this->addHTML( $this->getCCDoneBox() ); 01052 } 01053 01054 public function submit() { 01055 $this->parent->setVarsFromRequest( array( '_RightsProfile', '_LicenseCode', 01056 'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', 'wgLogo', 01057 'wgEnableUserEmail', 'wgEnotifUserTalk', 'wgEnotifWatchlist', 01058 'wgEmailAuthentication', 'wgMainCacheType', '_MemCachedServers', 01059 'wgUseInstantCommons' ) ); 01060 01061 if ( !in_array( $this->getVar( '_RightsProfile' ), 01062 array_keys( $this->parent->rightsProfiles ) ) ) 01063 { 01064 reset( $this->parent->rightsProfiles ); 01065 $this->setVar( '_RightsProfile', key( $this->parent->rightsProfiles ) ); 01066 } 01067 01068 $code = $this->getVar( '_LicenseCode' ); 01069 if ( $code == 'cc-choose' ) { 01070 if ( !$this->getVar( '_CCDone' ) ) { 01071 $this->parent->showError( 'config-cc-not-chosen' ); 01072 return false; 01073 } 01074 } elseif ( in_array( $code, array_keys( $this->parent->licenses ) ) ) { 01075 $entry = $this->parent->licenses[$code]; 01076 if ( isset( $entry['text'] ) ) { 01077 $this->setVar( 'wgRightsText', $entry['text'] ); 01078 } else { 01079 $this->setVar( 'wgRightsText', wfMsg( 'config-license-' . $code ) ); 01080 } 01081 $this->setVar( 'wgRightsUrl', $entry['url'] ); 01082 $this->setVar( 'wgRightsIcon', $entry['icon'] ); 01083 } else { 01084 $this->setVar( 'wgRightsText', '' ); 01085 $this->setVar( 'wgRightsUrl', '' ); 01086 $this->setVar( 'wgRightsIcon', '' ); 01087 } 01088 01089 $extsAvailable = $this->parent->findExtensions(); 01090 $extsToInstall = array(); 01091 foreach( $extsAvailable as $ext ) { 01092 if( $this->parent->request->getCheck( 'config_ext-' . $ext ) ) { 01093 $extsToInstall[] = $ext; 01094 } 01095 } 01096 $this->parent->setVar( '_Extensions', $extsToInstall ); 01097 01098 if( $this->getVar( 'wgMainCacheType' ) == 'memcached' ) { 01099 $memcServers = explode( "\n", $this->getVar( '_MemCachedServers' ) ); 01100 if( !$memcServers ) { 01101 $this->parent->showError( 'config-memcache-needservers' ); 01102 return false; 01103 } 01104 01105 foreach( $memcServers as $server ) { 01106 $memcParts = explode( ":", $server, 2 ); 01107 if ( !isset( $memcParts[0] ) 01108 || ( !IP::isValid( $memcParts[0] ) 01109 && ( gethostbyname( $memcParts[0] ) == $memcParts[0] ) ) ) { 01110 $this->parent->showError( 'config-memcache-badip', $memcParts[0] ); 01111 return false; 01112 } elseif( !isset( $memcParts[1] ) ) { 01113 $this->parent->showError( 'config-memcache-noport', $memcParts[0] ); 01114 return false; 01115 } elseif( $memcParts[1] < 1 || $memcParts[1] > 65535 ) { 01116 $this->parent->showError( 'config-memcache-badport', 1, 65535 ); 01117 return false; 01118 } 01119 } 01120 } 01121 return true; 01122 } 01123 01124 } 01125 01126 class WebInstaller_Install extends WebInstallerPage { 01127 public function isSlow() { 01128 return true; 01129 } 01130 01131 public function execute() { 01132 if( $this->getVar( '_UpgradeDone' ) ) { 01133 return 'skip'; 01134 } elseif( $this->getVar( '_InstallDone' ) ) { 01135 return 'continue'; 01136 } elseif( $this->parent->request->wasPosted() ) { 01137 $this->startForm(); 01138 $this->addHTML("<ul>"); 01139 $results = $this->parent->performInstallation( 01140 array( $this, 'startStage'), 01141 array( $this, 'endStage' ) 01142 ); 01143 $this->addHTML("</ul>"); 01144 // PerformInstallation bails on a fatal, so make sure the last item 01145 // completed before giving 'next.' Likewise, only provide back on failure 01146 $lastStep = end( $results ); 01147 $continue = $lastStep->isOK() ? 'continue' : false; 01148 $back = $lastStep->isOK() ? false : 'back'; 01149 $this->endForm( $continue, $back ); 01150 } else { 01151 $this->startForm(); 01152 $this->addHTML( $this->parent->getInfoBox( wfMsgNoTrans( 'config-install-begin' ) ) ); 01153 $this->endForm(); 01154 } 01155 return true; 01156 } 01157 01158 public function startStage( $step ) { 01159 $this->addHTML( "<li>" . wfMsgHtml( "config-install-$step" ) . wfMsg( 'ellipsis') ); 01160 if ( $step == 'extension-tables' ) { 01161 $this->startLiveBox(); 01162 } 01163 } 01164 01169 public function endStage( $step, $status ) { 01170 if ( $step == 'extension-tables' ) { 01171 $this->endLiveBox(); 01172 } 01173 $msg = $status->isOk() ? 'config-install-step-done' : 'config-install-step-failed'; 01174 $html = wfMsgHtml( 'word-separator' ) . wfMsgHtml( $msg ); 01175 if ( !$status->isOk() ) { 01176 $html = "<span class=\"error\">$html</span>"; 01177 } 01178 $this->addHTML( $html . "</li>\n" ); 01179 if( !$status->isGood() ) { 01180 $this->parent->showStatusBox( $status ); 01181 } 01182 } 01183 01184 } 01185 01186 class WebInstaller_Complete extends WebInstallerPage { 01187 01188 public function execute() { 01189 // Pop up a dialog box, to make it difficult for the user to forget 01190 // to download the file 01191 $lsUrl = $this->getVar( 'wgServer' ) . $this->parent->getURL( array( 'localsettings' => 1 ) ); 01192 if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && 01193 strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE' ) !== false ) { 01194 // JS appears the only method that works consistently with IE7+ 01195 $this->addHtml( "\n<script type=\"" . $GLOBALS['wgJsMimeType'] . 01196 '">jQuery( document ).ready( function() { document.location=' . 01197 Xml::encodeJsVar( $lsUrl) . "; } );</script>\n" ); 01198 } else { 01199 $this->parent->request->response()->header( "Refresh: 0;url=$lsUrl" ); 01200 } 01201 01202 $this->startForm(); 01203 $this->parent->disableLinkPopups(); 01204 $this->addHTML( 01205 $this->parent->getInfoBox( 01206 wfMsgNoTrans( 'config-install-done', 01207 $lsUrl, 01208 $this->getVar( 'wgServer' ) . 01209 $this->getVar( 'wgScriptPath' ) . '/index' . 01210 $this->getVar( 'wgScriptExtension' ), 01211 '<downloadlink/>' 01212 ), 'tick-32.png' 01213 ) 01214 ); 01215 $this->parent->restoreLinkPopups(); 01216 $this->endForm( false, false ); 01217 } 01218 } 01219 01220 class WebInstaller_Restart extends WebInstallerPage { 01221 01222 public function execute() { 01223 $r = $this->parent->request; 01224 if ( $r->wasPosted() ) { 01225 $really = $r->getVal( 'submit-restart' ); 01226 if ( $really ) { 01227 $this->parent->reset(); 01228 } 01229 return 'continue'; 01230 } 01231 01232 $this->startForm(); 01233 $s = $this->parent->getWarningBox( wfMsgNoTrans( 'config-help-restart' ) ); 01234 $this->addHTML( $s ); 01235 $this->endForm( 'restart' ); 01236 } 01237 01238 } 01239 01240 abstract class WebInstaller_Document extends WebInstallerPage { 01241 01242 protected abstract function getFileName(); 01243 01244 public function execute() { 01245 $text = $this->getFileContents(); 01246 $text = InstallDocFormatter::format( $text ); 01247 $this->parent->output->addWikiText( $text ); 01248 $this->startForm(); 01249 $this->endForm( false ); 01250 } 01251 01252 public function getFileContents() { 01253 return file_get_contents( dirname( __FILE__ ) . '/../../' . $this->getFileName() ); 01254 } 01255 01256 } 01257 01258 class WebInstaller_Readme extends WebInstaller_Document { 01259 protected function getFileName() { return 'README'; } 01260 } 01261 01262 class WebInstaller_ReleaseNotes extends WebInstaller_Document { 01263 protected function getFileName() { return 'RELEASE-NOTES'; } 01264 } 01265 01266 class WebInstaller_UpgradeDoc extends WebInstaller_Document { 01267 protected function getFileName() { return 'UPGRADE'; } 01268 } 01269 01270 class WebInstaller_Copying extends WebInstaller_Document { 01271 protected function getFileName() { return 'COPYING'; } 01272 } 01273