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