wiki.techinc.nl/includes/installer/WebInstaller.php

950 lines
23 KiB
PHP
Raw Normal View History

<?php
/**
* Core installer web interface.
*
* @file
* @ingroup Deployment
*/
/**
* Class for the core installer web interface.
2010-10-02 07:40:54 +00:00
*
2010-07-29 18:36:39 +00:00
* @ingroup Deployment
* @since 1.17
*/
class WebInstaller extends CoreInstaller {
2010-10-02 07:40:54 +00:00
/**
* @var WebInstallerOutput
*/
2010-10-02 07:40:54 +00:00
public $output;
2010-07-21 09:34:16 +00:00
/**
* WebRequest object.
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @var WebRequest
*/
2010-07-19 03:16:54 +00:00
public $request;
2010-07-21 09:34:16 +00:00
/**
* Cached session array.
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @var array
*/
2010-07-19 03:16:54 +00:00
public $session;
2010-10-02 07:40:54 +00:00
/**
* Captured PHP error text. Temporary.
*/
2010-07-19 03:16:54 +00:00
public $phpErrors;
/**
* The main sequence of page names. These will be displayed in turn.
* To add one:
* * Add it here
* * Add a config-page-<name> message
* * Add a WebInstaller_<name> class
*/
2010-07-19 03:16:54 +00:00
public $pageSequence = array(
'Language',
'Welcome',
'DBConnect',
'Upgrade',
'DBSettings',
'Name',
'Options',
'Install',
'Complete',
);
/**
2010-07-19 03:16:54 +00:00
* Out of sequence pages, selectable by the user at any time.
*/
2010-07-19 03:16:54 +00:00
public $otherPages = array(
'Restart',
'Readme',
'ReleaseNotes',
'Copying',
'UpgradeDoc', // Can't use Upgrade due to Upgrade step
);
/**
* Array of pages which have declared that they have been submitted, have validated
2010-07-19 03:16:54 +00:00
* their input, and need no further processing.
*/
2010-07-19 03:16:54 +00:00
public $happyPages;
/**
* List of "skipped" pages. These are pages that will automatically continue
* to the next page on any GET request. To avoid breaking the "back" button,
* they need to be skipped during a back operation.
*/
2010-07-19 03:16:54 +00:00
public $skippedPages;
/**
2010-07-19 03:16:54 +00:00
* Flag indicating that session data may have been lost.
*/
2010-07-19 03:16:54 +00:00
public $showSessionWarning = false;
2010-07-19 03:16:54 +00:00
public $tabIndex = 1;
2010-07-19 03:16:54 +00:00
public $currentPageName;
2010-10-02 07:40:54 +00:00
/**
2010-07-21 09:34:16 +00:00
* Constructor.
2010-10-02 07:40:54 +00:00
*
2010-08-21 15:20:23 +00:00
* @param $request WebRequest
2010-07-21 09:34:16 +00:00
*/
public function __construct( WebRequest $request ) {
parent::__construct();
$this->output = new WebInstallerOutput( $this );
$this->request = $request;
}
/**
* Main entry point.
2010-10-02 07:40:54 +00:00
*
2010-05-08 20:04:48 +00:00
* @param $session Array: initial session array
2010-10-02 07:40:54 +00:00
*
2010-05-08 20:04:48 +00:00
* @return Array: new session array
*/
2010-07-21 09:34:16 +00:00
public function execute( array $session ) {
$this->session = $session;
2010-10-02 07:40:54 +00:00
if ( isset( $session['settings'] ) ) {
$this->settings = $session['settings'] + $this->settings;
}
2010-10-02 07:40:54 +00:00
$this->exportVars();
$this->setupLanguage();
if( $this->getVar( '_InstallDone' ) && $this->request->getVal( 'localsettings' ) )
{
$ls = new LocalSettingsGenerator( $this );
$this->request->response()->header('Content-type: text/plain');
2010-10-02 07:40:54 +00:00
$this->request->response()->header(
'Content-Disposition: attachment; filename="LocalSettings.php"'
);
2010-10-02 07:40:54 +00:00
echo $ls->getText();
return $this->session;
}
if ( isset( $session['happyPages'] ) ) {
$this->happyPages = $session['happyPages'];
} else {
$this->happyPages = array();
}
2010-10-02 07:40:54 +00:00
if ( isset( $session['skippedPages'] ) ) {
$this->skippedPages = $session['skippedPages'];
} else {
$this->skippedPages = array();
}
2010-10-02 07:40:54 +00:00
$lowestUnhappy = $this->getLowestUnhappy();
# Special case for Creative Commons partner chooser box.
if ( $this->request->getVal( 'SubmitCC' ) ) {
$page = $this->getPageByName( 'Options' );
$this->output->useShortHeader();
$page->submitCC();
return $this->finish();
}
2010-10-02 07:40:54 +00:00
if ( $this->request->getVal( 'ShowCC' ) ) {
$page = $this->getPageByName( 'Options' );
$this->output->useShortHeader();
$this->output->addHTML( $page->getCCDoneBox() );
return $this->finish();
}
# Get the page name.
$pageName = $this->request->getVal( 'page' );
if ( in_array( $pageName, $this->otherPages ) ) {
# Out of sequence
$pageId = false;
$page = $this->getPageByName( $pageName );
} else {
# Main sequence
if ( !$pageName || !in_array( $pageName, $this->pageSequence ) ) {
$pageId = $lowestUnhappy;
} else {
$pageId = array_search( $pageName, $this->pageSequence );
}
# If necessary, move back to the lowest-numbered unhappy page
if ( $pageId > $lowestUnhappy ) {
$pageId = $lowestUnhappy;
if ( $lowestUnhappy == 0 ) {
# Knocked back to start, possible loss of session data.
$this->showSessionWarning = true;
}
}
2010-10-02 07:40:54 +00:00
$pageName = $this->pageSequence[$pageId];
$page = $this->getPageByName( $pageName );
}
# If a back button was submitted, go back without submitting the form data.
if ( $this->request->wasPosted() && $this->request->getBool( 'submit-back' ) ) {
if ( $this->request->getVal( 'lastPage' ) ) {
$nextPage = $this->request->getVal( 'lastPage' );
} elseif ( $pageId !== false ) {
# Main sequence page
# Skip the skipped pages
$nextPageId = $pageId;
2010-10-02 07:40:54 +00:00
do {
$nextPageId--;
$nextPage = $this->pageSequence[$nextPageId];
} while( isset( $this->skippedPages[$nextPage] ) );
} else {
$nextPage = $this->pageSequence[$lowestUnhappy];
}
2010-10-02 07:40:54 +00:00
$this->output->redirect( $this->getUrl( array( 'page' => $nextPage ) ) );
return $this->finish();
}
# Execute the page.
$this->currentPageName = $page->getName();
$this->startPageWrapper( $pageName );
$localSettings = $this->getLocalSettingsStatus();
2010-10-02 07:40:54 +00:00
if( !$localSettings->isGood() ) {
$this->showStatusBox( $localSettings );
$result = 'output';
} else {
$result = $page->execute();
}
2010-10-02 07:40:54 +00:00
$this->endPageWrapper();
if ( $result == 'skip' ) {
# Page skipped without explicit submission.
# Skip it when we click "back" so that we don't just go forward again.
$this->skippedPages[$pageName] = true;
$result = 'continue';
} else {
unset( $this->skippedPages[$pageName] );
}
# If it was posted, the page can request a continue to the next page.
if ( $result === 'continue' && !$this->output->headerDone() ) {
if ( $pageId !== false ) {
$this->happyPages[$pageId] = true;
}
2010-10-02 07:40:54 +00:00
$lowestUnhappy = $this->getLowestUnhappy();
if ( $this->request->getVal( 'lastPage' ) ) {
$nextPage = $this->request->getVal( 'lastPage' );
} elseif ( $pageId !== false ) {
$nextPage = $this->pageSequence[$pageId + 1];
} else {
$nextPage = $this->pageSequence[$lowestUnhappy];
}
2010-10-02 07:40:54 +00:00
if ( array_search( $nextPage, $this->pageSequence ) > $lowestUnhappy ) {
$nextPage = $this->pageSequence[$lowestUnhappy];
}
2010-10-02 07:40:54 +00:00
$this->output->redirect( $this->getUrl( array( 'page' => $nextPage ) ) );
}
2010-10-02 07:40:54 +00:00
return $this->finish();
}
2010-07-19 03:16:54 +00:00
public function getLowestUnhappy() {
if ( count( $this->happyPages ) == 0 ) {
return 0;
} else {
return max( array_keys( $this->happyPages ) ) + 1;
}
}
/**
* Start the PHP session. This may be called before execute() to start the PHP session.
*/
2010-07-19 03:16:54 +00:00
public function startSession() {
$sessPath = $this->getSessionSavePath();
2010-10-02 07:40:54 +00:00
if( $sessPath != '' ) {
if( strval( ini_get( 'open_basedir' ) ) != '' ) {
// we need to skip the following check when open_basedir is on.
// The session path probably *wont* be writable by the current
// user, and telling them to change it is bad. Bug 23021.
} elseif( !is_dir( $sessPath ) || !is_writeable( $sessPath ) ) {
$this->showError( 'config-session-path-bad', $sessPath );
return false;
}
} else {
// If the path is unset it'll default to some system bit, which *probably* is ok...
// not sure how to actually get what will be used.
}
2010-10-02 07:40:54 +00:00
if( wfIniGetBool( 'session.auto_start' ) || session_id() ) {
// Done already
return true;
}
$this->phpErrors = array();
set_error_handler( array( $this, 'errorHandler' ) );
session_start();
restore_error_handler();
2010-10-02 07:40:54 +00:00
if ( $this->phpErrors ) {
$this->showError( 'config-session-error', $this->phpErrors[0] );
return false;
}
2010-10-02 07:40:54 +00:00
return true;
}
/**
* Get the value of session.save_path
*
* Per http://www.php.net/manual/en/session.configuration.php#ini.session.save-path,
* this may have an initial integer value to indicate the depth of session
* storage (eg /tmp/a/b/c). Explode on ; and check and see if this part is
* there or not. Should also allow paths with semicolons in them (if you
* really wanted your session files stored in /tmp/some;dir) which PHP
* supposedly supports.
*
2010-05-08 20:04:48 +00:00
* @return String
*/
private function getSessionSavePath() {
$parts = explode( ';', ini_get( 'session.save_path' ), 2 );
return count( $parts ) == 1 ? $parts[0] : $parts[1];
}
/**
* Show an error message in a box. Parameters are like wfMsg().
*/
2010-07-19 03:16:54 +00:00
public function showError( $msg /*...*/ ) {
$args = func_get_args();
array_shift( $args );
$args = array_map( 'htmlspecialchars', $args );
$msg = wfMsgReal( $msg, $args, false, false, false );
$this->output->addHTML( $this->getErrorBox( $msg ) );
}
/**
2010-07-19 03:16:54 +00:00
* Temporary error handler for session start debugging.
*/
2010-07-19 03:16:54 +00:00
public function errorHandler( $errno, $errstr ) {
$this->phpErrors[] = $errstr;
}
/**
* Clean up from execute()
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @return array
*/
public function finish() {
$this->output->output();
2010-10-02 07:40:54 +00:00
$this->session['happyPages'] = $this->happyPages;
$this->session['skippedPages'] = $this->skippedPages;
$this->session['settings'] = $this->settings;
2010-10-02 07:40:54 +00:00
return $this->session;
}
/**
2010-07-19 03:16:54 +00:00
* Get a URL for submission back to the same script.
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @param $query: Array
*/
2010-07-19 03:16:54 +00:00
public function getUrl( $query = array() ) {
$url = $this->request->getRequestURL();
# Remove existing query
$url = preg_replace( '/\?.*$/', '', $url );
2010-10-02 07:40:54 +00:00
if ( $query ) {
$url .= '?' . wfArrayToCGI( $query );
}
2010-10-02 07:40:54 +00:00
return $url;
}
/**
2010-07-19 03:16:54 +00:00
* Get a WebInstallerPage from the main sequence, by ID.
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @param $id Integer
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @return WebInstallerPage
*/
2010-07-19 03:16:54 +00:00
public function getPageById( $id ) {
return $this->getPageByName( $this->pageSequence[$id] );
}
/**
2010-07-19 03:16:54 +00:00
* Get a WebInstallerPage by name.
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @param $pageName String
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @return WebInstallerPage
*/
2010-07-19 03:16:54 +00:00
public function getPageByName( $pageName ) {
// Totally lame way to force autoload of WebInstallerPage.php
class_exists( 'WebInstallerPage' );
2010-10-02 07:40:54 +00:00
$pageClass = 'WebInstaller_' . $pageName;
2010-10-02 07:40:54 +00:00
return new $pageClass( $this );
}
/**
2010-07-19 03:16:54 +00:00
* Get a session variable.
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @param $name String
* @param $default
*/
2010-07-19 03:16:54 +00:00
public function getSession( $name, $default = null ) {
if ( !isset( $this->session[$name] ) ) {
return $default;
} else {
return $this->session[$name];
}
}
/**
2010-07-19 03:16:54 +00:00
* Set a session variable.
*/
2010-07-19 03:16:54 +00:00
public function setSession( $name, $value ) {
$this->session[$name] = $value;
}
/**
2010-07-19 03:16:54 +00:00
* Get the next tabindex attribute value.
*/
2010-07-19 03:16:54 +00:00
public function nextTabIndex() {
return $this->tabIndex++;
}
/**
2010-07-19 03:16:54 +00:00
* Initializes language-related variables.
*/
2010-07-19 03:16:54 +00:00
public function setupLanguage() {
global $wgLang, $wgContLang, $wgLanguageCode;
2010-10-02 07:40:54 +00:00
if ( $this->getSession( 'test' ) === null && !$this->request->wasPosted() ) {
$wgLanguageCode = $this->getAcceptLanguage();
$wgLang = $wgContLang = Language::factory( $wgLanguageCode );
$this->setVar( 'wgLanguageCode', $wgLanguageCode );
$this->setVar( '_UserLang', $wgLanguageCode );
} else {
$wgLanguageCode = $this->getVar( 'wgLanguageCode' );
$wgLang = Language::factory( $this->getVar( '_UserLang' ) );
$wgContLang = Language::factory( $wgLanguageCode );
}
}
/**
2010-07-19 03:16:54 +00:00
* Retrieves MediaWiki language from Accept-Language HTTP header.
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @return string
*/
2010-07-19 03:16:54 +00:00
public function getAcceptLanguage() {
global $wgLanguageCode, $wgRequest;
$mwLanguages = Language::getLanguageNames();
$headerLanguages = array_keys( $wgRequest->getAcceptLang() );
2010-10-02 07:40:54 +00:00
foreach ( $headerLanguages as $lang ) {
if ( isset( $mwLanguages[$lang] ) ) {
return $lang;
}
}
2010-10-02 07:40:54 +00:00
return $wgLanguageCode;
}
/**
2010-07-19 03:16:54 +00:00
* Called by execute() before page output starts, to show a page list.
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @param $currentPageName String
*/
2010-07-19 03:16:54 +00:00
public function startPageWrapper( $currentPageName ) {
$s = "<div class=\"config-page-wrapper\">\n" .
"<div class=\"config-page-list\"><ul>\n";
$lastHappy = -1;
2010-10-02 07:40:54 +00:00
foreach ( $this->pageSequence as $id => $pageName ) {
$happy = !empty( $this->happyPages[$id] );
2010-10-02 07:40:54 +00:00
$s .= $this->getPageListItem(
$pageName,
$happy || $lastHappy == $id - 1,
$currentPageName
);
2010-10-02 07:40:54 +00:00
if ( $happy ) {
$lastHappy = $id;
}
}
2010-10-02 07:40:54 +00:00
$s .= "</ul><br/><ul>\n";
2010-10-02 07:40:54 +00:00
foreach ( $this->otherPages as $pageName ) {
$s .= $this->getPageListItem( $pageName, true, $currentPageName );
}
2010-10-02 07:40:54 +00:00
$s .= "</ul></div>\n". // end list pane
"<div class=\"config-page\">\n" .
Xml::element( 'h2', array(),
wfMsg( 'config-page-' . strtolower( $currentPageName ) ) );
$this->output->addHTMLNoFlush( $s );
}
/**
2010-07-19 03:16:54 +00:00
* Get a list item for the page list.
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @param $pageName String
* @param $enabled Boolean
* @param $currentPageName String
2010-10-02 07:40:54 +00:00
*
2010-07-21 09:34:16 +00:00
* @return string
*/
2010-07-19 03:16:54 +00:00
public function getPageListItem( $pageName, $enabled, $currentPageName ) {
$s = "<li class=\"config-page-list-item\">";
$name = wfMsg( 'config-page-' . strtolower( $pageName ) );
2010-10-02 07:40:54 +00:00
if ( $enabled ) {
$query = array( 'page' => $pageName );
2010-10-02 07:40:54 +00:00
if ( !in_array( $pageName, $this->pageSequence ) ) {
if ( in_array( $currentPageName, $this->pageSequence ) ) {
$query['lastPage'] = $currentPageName;
}
2010-10-02 07:40:54 +00:00
$link = Xml::element( 'a',
array(
'href' => $this->getUrl( $query )
),
$name
);
} else {
$link = htmlspecialchars( $name );
}
2010-10-02 07:40:54 +00:00
if ( $pageName == $currentPageName ) {
$s .= "<span class=\"config-page-current\">$link</span>";
} else {
$s .= $link;
}
} else {
$s .= Xml::element( 'span',
array(
'class' => 'config-page-disabled'
),
$name
);
}
2010-10-02 07:40:54 +00:00
$s .= "</li>\n";
2010-10-02 07:40:54 +00:00
return $s;
}
/**
2010-07-19 03:16:54 +00:00
* Output some stuff after a page is finished.
*/
2010-07-19 03:16:54 +00:00
public function endPageWrapper() {
$this->output->addHTMLNoFlush(
"</div>\n" .
"<br style=\"clear:both\"/>\n" .
"</div>" );
}
/**
2010-07-19 03:16:54 +00:00
* Get HTML for an error box with an icon.
2010-05-08 20:04:48 +00:00
*
* @param $text String: wikitext, get this with wfMsgNoTrans()
*/
2010-07-19 03:16:54 +00:00
public function getErrorBox( $text ) {
return $this->getInfoBox( $text, 'critical-32.png', 'config-error-box' );
}
/**
2010-07-19 03:16:54 +00:00
* Get HTML for a warning box with an icon.
2010-05-08 20:04:48 +00:00
*
* @param $text String: wikitext, get this with wfMsgNoTrans()
*/
2010-07-19 03:16:54 +00:00
public function getWarningBox( $text ) {
return $this->getInfoBox( $text, 'warning-32.png', 'config-warning-box' );
}
/**
2010-07-19 03:16:54 +00:00
* Get HTML for an info box with an icon.
2010-05-08 20:04:48 +00:00
*
* @param $text String: wikitext, get this with wfMsgNoTrans()
* @param $icon String: icon name, file in skins/common/images
* @param $class String: additional class name to add to the wrapper div
*/
2010-07-19 03:16:54 +00:00
public function getInfoBox( $text, $icon = 'info-32.png', $class = false ) {
$s =
"<div class=\"config-info $class\">\n" .
"<div class=\"config-info-left\">\n" .
Xml::element( 'img',
array(
'src' => '../skins/common/images/' . $icon,
'alt' => wfMsg( 'config-information' ),
)
) . "\n" .
"</div>\n" .
"<div class=\"config-info-right\">\n" .
$this->parse( $text ) . "\n" .
"</div>\n" .
"<div style=\"clear: left;\"></div>\n" .
"</div>\n";
return $s;
}
/**
* Get small text indented help for a preceding form field.
* Parameters like wfMsg().
*/
2010-07-19 03:16:54 +00:00
public function getHelpBox( $msg /*, ... */ ) {
$args = func_get_args();
array_shift( $args );
$args = array_map( 'htmlspecialchars', $args );
$text = wfMsgReal( $msg, $args, false, false, false );
$html = $this->parse( $text, true );
return
"<div class=\"config-help-wrapper\">\n" .
"<div class=\"config-help-message\">\n" .
$html .
"</div>\n" .
"<div class=\"config-show-help\">\n" .
"<a href=\"#\">" .
wfMsgHtml( 'config-show-help' ) .
"</a></div>\n" .
"<div class=\"config-hide-help\">\n" .
"<a href=\"#\">" .
wfMsgHtml( 'config-hide-help' ) .
"</a></div>\n</div>\n";
}
/**
2010-07-19 03:16:54 +00:00
* Output a help box.
*/
2010-07-19 03:16:54 +00:00
public function showHelpBox( $msg /*, ... */ ) {
$args = func_get_args();
$html = call_user_func_array( array( $this, 'getHelpBox' ), $args );
$this->output->addHTML( $html );
}
/**
2010-07-19 03:16:54 +00:00
* Show a short informational message.
* Output looks like a list.
2010-10-02 07:40:54 +00:00
*
2010-08-21 15:20:23 +00:00
* @param $msg string
*/
2010-07-19 03:16:54 +00:00
public function showMessage( $msg /*, ... */ ) {
$args = func_get_args();
array_shift( $args );
$html = '<div class="config-message">' .
$this->parse( wfMsgReal( $msg, $args, false, false, false ) ) .
"</div>\n";
$this->output->addHTML( $html );
}
2010-10-02 07:40:54 +00:00
2010-07-29 17:54:44 +00:00
/**
2010-08-21 15:20:23 +00:00
* @param $status Status
2010-07-29 17:54:44 +00:00
*/
public function showStatusMessage( Status $status ) {
$text = $status->getWikiText();
$this->output->addWikiText(
"<div class=\"config-message\">\n" .
$text .
"</div>"
);
}
/**
* Label a control by wrapping a config-input div around it and putting a
2010-07-19 03:16:54 +00:00
* label before it.
*/
2010-07-19 03:16:54 +00:00
public function label( $msg, $forId, $contents ) {
if ( strval( $msg ) == '' ) {
Remove most named character references from output Recommit of r66254 to trunk. This was just find extensions phase3 -iname '*.php' \! -iname '*.i18n.php' \! -iname 'Messages*.php' \! -iname '*_Messages.php' -exec sed -i 's/&nbsp;/\&#160;/g;s/&mdash;/―/g;s/&bull;/•/g;s/&aacute;/á/g;s/&acute;/´/g;s/&agrave;/à/g;s/&alpha;/α/g;s/&auml;/ä/g;s/&ccedil;/ç/g;s/&copy;/©/g;s/&darr;/↓/g;s/&deg;/°/g;s/&eacute;/é/g;s/&ecirc;/ê/g;s/&euml;/ë/g;s/&egrave;/è/g;s/&euro;/€/g;s/&harr;//g;s/&hellip;/…/g;s/&iacute;/í/g;s/&igrave;/ì/g;s/&larr;/←/g;s/&ldquo;/“/g;s/&middot;/·/g;s/&minus;/−/g;s/&ndash;/–/g;s/&oacute;/ó/g;s/&ocirc;/ô/g;s/&oelig;/œ/g;s/&ograve;/ò/g;s/&otilde;/õ/g;s/&ouml;/ö/g;s/&pound;/£/g;s/&prime;/′/g;s/&Prime;/″/g;s/&raquo;/»/g;s/&rarr;/→/g;s/&rdquo;/”/g;s/&Sigma;/Σ/g;s/&times;/×/g;s/&uacute;/ú/g;s/&uarr;/↑/g;s/&uuml;/ü/g;s/&yen;/¥/g' {} + followed by reading over every single line of the resulting diff and fixing a whole bunch of false positives. The reason for this change is given in <http://lists.wikimedia.org/pipermail/wikitech-l/2010-April/047617.html>. I cleared it with Tim and Brion on IRC before committing. It might cause a few problems, but I tried to be careful; please report any issues. I skipped all messages files. I plan to make a follow-up commit that alters wfMsgExt() with 'escapenoentities' to sanitize all the entities. That way, the only messages that will be problems will be ones that output raw HTML, and we want to get rid of those anyway. This should get rid of all named entities everywhere except messages. I skipped a few things like &nbsp that I noticed in manual inspection, because they weren't well-formed XML anyway. Also, to everyone who uses non-breaking spaces when they could use a normal space, or nothing at all, or CSS padding: I still hate you. Die.
2010-05-30 17:33:59 +00:00
$labelText = '&#160;';
} else {
$labelText = wfMsgHtml( $msg );
}
2010-10-02 07:40:54 +00:00
$attributes = array( 'class' => 'config-label' );
2010-10-02 07:40:54 +00:00
if ( $forId ) {
$attributes['for'] = $forId;
}
2010-10-02 07:40:54 +00:00
return
"<div class=\"config-input\">\n" .
Xml::tags( 'label',
$attributes,
$labelText ) . "\n" .
$contents .
"</div>\n";
}
/**
2010-07-19 03:16:54 +00:00
* Get a labelled text box to configure a variable.
2010-05-08 20:04:48 +00:00
*
* @param $params Array
* Parameters are:
* var: The variable to be configured (required)
* label: The message name for the label (required)
* attribs: Additional attributes for the input element (optional)
* controlName: The name for the input element (optional)
* value: The current value of the variable (optional)
*/
2010-07-19 03:16:54 +00:00
public function getTextBox( $params ) {
if ( !isset( $params['controlName'] ) ) {
$params['controlName'] = 'config_' . $params['var'];
}
2010-10-02 07:40:54 +00:00
if ( !isset( $params['value'] ) ) {
$params['value'] = $this->getVar( $params['var'] );
}
2010-10-02 07:40:54 +00:00
if ( !isset( $params['attribs'] ) ) {
$params['attribs'] = array();
}
2010-10-02 07:40:54 +00:00
return
$this->label(
$params['label'],
$params['controlName'],
Xml::input(
$params['controlName'],
30, // intended to be overridden by CSS
$params['value'],
$params['attribs'] + array(
'id' => $params['controlName'],
'class' => 'config-input-text',
'tabindex' => $this->nextTabIndex()
)
)
);
}
/**
2010-07-19 03:16:54 +00:00
* Get a labelled password box to configure a variable.
2010-05-08 20:04:48 +00:00
*
* Implements password hiding
2010-05-08 20:04:48 +00:00
* @param $params Array
* Parameters are:
* var: The variable to be configured (required)
* label: The message name for the label (required)
* attribs: Additional attributes for the input element (optional)
* controlName: The name for the input element (optional)
* value: The current value of the variable (optional)
*/
2010-07-19 03:16:54 +00:00
public function getPasswordBox( $params ) {
if ( !isset( $params['value'] ) ) {
$params['value'] = $this->getVar( $params['var'] );
}
2010-10-02 07:40:54 +00:00
if ( !isset( $params['attribs'] ) ) {
$params['attribs'] = array();
}
2010-10-02 07:40:54 +00:00
$params['value'] = $this->getFakePassword( $params['value'] );
$params['attribs']['type'] = 'password';
2010-10-02 07:40:54 +00:00
return $this->getTextBox( $params );
}
/**
2010-07-19 03:16:54 +00:00
* Get a labelled checkbox to configure a boolean variable.
2010-05-08 20:04:48 +00:00
*
* @param $params Array
* Parameters are:
* var: The variable to be configured (required)
* label: The message name for the label (required)
* attribs: Additional attributes for the input element (optional)
* controlName: The name for the input element (optional)
* value: The current value of the variable (optional)
*/
2010-07-19 03:16:54 +00:00
public function getCheckBox( $params ) {
if ( !isset( $params['controlName'] ) ) {
$params['controlName'] = 'config_' . $params['var'];
}
2010-10-02 07:40:54 +00:00
if ( !isset( $params['value'] ) ) {
$params['value'] = $this->getVar( $params['var'] );
}
2010-10-02 07:40:54 +00:00
if ( !isset( $params['attribs'] ) ) {
$params['attribs'] = array();
}
2010-10-02 07:40:54 +00:00
if( isset( $params['rawtext'] ) ) {
$labelText = $params['rawtext'];
} else {
$labelText = $this->parse( wfMsg( $params['label'] ) );
}
2010-10-02 07:40:54 +00:00
return
"<div class=\"config-input-check\">\n" .
"<label>\n" .
Xml::check(
$params['controlName'],
$params['value'],
$params['attribs'] + array(
'id' => $params['controlName'],
'class' => 'config-input-text',
'tabindex' => $this->nextTabIndex(),
)
) .
$labelText . "\n" .
"</label>\n" .
"</div>\n";
}
/**
2010-07-19 03:16:54 +00:00
* Get a set of labelled radio buttons.
*
2010-05-08 20:04:48 +00:00
* @param $params Array
* Parameters are:
* var: The variable to be configured (required)
* label: The message name for the label (required)
* itemLabelPrefix: The message name prefix for the item labels (required)
* values: List of allowed values (required)
* itemAttribs Array of attribute arrays, outer key is the value name (optional)
* commonAttribs Attribute array applied to all items
* controlName: The name for the input element (optional)
* value: The current value of the variable (optional)
*/
2010-07-19 03:16:54 +00:00
public function getRadioSet( $params ) {
if ( !isset( $params['controlName'] ) ) {
$params['controlName'] = 'config_' . $params['var'];
}
2010-10-02 07:40:54 +00:00
if ( !isset( $params['value'] ) ) {
$params['value'] = $this->getVar( $params['var'] );
}
2010-10-02 07:40:54 +00:00
if ( !isset( $params['label'] ) ) {
$label = '';
} else {
$label = $this->parse( wfMsgNoTrans( $params['label'] ) );
}
2010-10-02 07:40:54 +00:00
$s = "<label class=\"config-label\">\n" .
$label .
"</label>\n" .
"<ul class=\"config-settings-block\">\n";
foreach ( $params['values'] as $value ) {
$itemAttribs = array();
2010-10-02 07:40:54 +00:00
if ( isset( $params['commonAttribs'] ) ) {
$itemAttribs = $params['commonAttribs'];
}
2010-10-02 07:40:54 +00:00
if ( isset( $params['itemAttribs'][$value] ) ) {
$itemAttribs = $params['itemAttribs'][$value] + $itemAttribs;
}
2010-10-02 07:40:54 +00:00
$checked = $value == $params['value'];
$id = $params['controlName'] . '_' . $value;
$itemAttribs['id'] = $id;
$itemAttribs['tabindex'] = $this->nextTabIndex();
2010-10-02 07:40:54 +00:00
$s .=
'<li>' .
Xml::radio( $params['controlName'], $value, $checked, $itemAttribs ) .
Remove most named character references from output Recommit of r66254 to trunk. This was just find extensions phase3 -iname '*.php' \! -iname '*.i18n.php' \! -iname 'Messages*.php' \! -iname '*_Messages.php' -exec sed -i 's/&nbsp;/\&#160;/g;s/&mdash;/―/g;s/&bull;/•/g;s/&aacute;/á/g;s/&acute;/´/g;s/&agrave;/à/g;s/&alpha;/α/g;s/&auml;/ä/g;s/&ccedil;/ç/g;s/&copy;/©/g;s/&darr;/↓/g;s/&deg;/°/g;s/&eacute;/é/g;s/&ecirc;/ê/g;s/&euml;/ë/g;s/&egrave;/è/g;s/&euro;/€/g;s/&harr;//g;s/&hellip;/…/g;s/&iacute;/í/g;s/&igrave;/ì/g;s/&larr;/←/g;s/&ldquo;/“/g;s/&middot;/·/g;s/&minus;/−/g;s/&ndash;/–/g;s/&oacute;/ó/g;s/&ocirc;/ô/g;s/&oelig;/œ/g;s/&ograve;/ò/g;s/&otilde;/õ/g;s/&ouml;/ö/g;s/&pound;/£/g;s/&prime;/′/g;s/&Prime;/″/g;s/&raquo;/»/g;s/&rarr;/→/g;s/&rdquo;/”/g;s/&Sigma;/Σ/g;s/&times;/×/g;s/&uacute;/ú/g;s/&uarr;/↑/g;s/&uuml;/ü/g;s/&yen;/¥/g' {} + followed by reading over every single line of the resulting diff and fixing a whole bunch of false positives. The reason for this change is given in <http://lists.wikimedia.org/pipermail/wikitech-l/2010-April/047617.html>. I cleared it with Tim and Brion on IRC before committing. It might cause a few problems, but I tried to be careful; please report any issues. I skipped all messages files. I plan to make a follow-up commit that alters wfMsgExt() with 'escapenoentities' to sanitize all the entities. That way, the only messages that will be problems will be ones that output raw HTML, and we want to get rid of those anyway. This should get rid of all named entities everywhere except messages. I skipped a few things like &nbsp that I noticed in manual inspection, because they weren't well-formed XML anyway. Also, to everyone who uses non-breaking spaces when they could use a normal space, or nothing at all, or CSS padding: I still hate you. Die.
2010-05-30 17:33:59 +00:00
'&#160;' .
Xml::tags( 'label', array( 'for' => $id ), $this->parse(
wfMsgNoTrans( $params['itemLabelPrefix'] . strtolower( $value ) )
) ) .
"</li>\n";
}
2010-10-02 07:40:54 +00:00
$s .= "</ul>\n";
return $s;
}
/**
2010-07-19 03:16:54 +00:00
* Output an error or warning box using a Status object.
*/
2010-07-19 03:16:54 +00:00
public function showStatusBox( $status ) {
if( !$status->isGood() ) {
$text = $status->getWikiText();
2010-10-02 07:40:54 +00:00
if( $status->isOk() ) {
$box = $this->getWarningBox( $text );
} else {
$box = $this->getErrorBox( $text );
}
2010-10-02 07:40:54 +00:00
$this->output->addHTML( $box );
}
}
/**
* Convenience function to set variables based on form data.
* Assumes that variables containing "password" in the name are (potentially
* fake) passwords.
2010-05-08 20:04:48 +00:00
*
* @param $varNames Array
* @param $prefix String: the prefix added to variables to obtain form names
*/
2010-07-19 03:16:54 +00:00
public function setVarsFromRequest( $varNames, $prefix = 'config_' ) {
$newValues = array();
2010-10-02 07:40:54 +00:00
foreach ( $varNames as $name ) {
$value = trim( $this->request->getVal( $prefix . $name ) );
$newValues[$name] = $value;
2010-10-02 07:40:54 +00:00
if ( $value === null ) {
// Checkbox?
$this->setVar( $name, false );
} else {
if ( stripos( $name, 'password' ) !== false ) {
$this->setPassword( $name, $value );
} else {
$this->setVar( $name, $value );
}
}
}
2010-10-02 07:40:54 +00:00
return $newValues;
}
/**
2010-07-19 03:16:54 +00:00
* Get the starting tags of a fieldset.
2010-05-08 20:04:48 +00:00
*
* @param $legend String: message name
*/
2010-07-19 03:16:54 +00:00
public function getFieldsetStart( $legend ) {
return "\n<fieldset><legend>" . wfMsgHtml( $legend ) . "</legend>\n";
}
/**
2010-07-19 03:16:54 +00:00
* Get the end tag of a fieldset.
*/
2010-07-19 03:16:54 +00:00
public function getFieldsetEnd() {
return "</fieldset>\n";
}
/**
* Helper for Installer::docLink()
*/
2010-07-19 03:16:54 +00:00
public function getDocUrl( $page ) {
$url = "{$_SERVER['PHP_SELF']}?page=" . urlencode( $page );
2010-10-02 07:40:54 +00:00
if ( in_array( $this->currentPageName, $this->pageSequence ) ) {
$url .= '&lastPage=' . urlencode( $this->currentPageName );
}
2010-10-02 07:40:54 +00:00
return $url;
}
2010-10-02 07:40:54 +00:00
2010-07-20 13:53:03 +00:00
}