* Fixed a whole lot of XSS vulnerabilities in the installer. All require a live installer, i.e. with no LocalSettings.php present.
* Implemented taint support in the installer and fixed some false positives (and false negatives)
This commit is contained in:
parent
7460b7b7ec
commit
6237fe4bb5
8 changed files with 379 additions and 333 deletions
100
config/index.php
100
config/index.php
|
|
@ -92,7 +92,8 @@ $ourdb['ibm_db2']['rootuser'] = 'db2admin';
|
|||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<title>MediaWiki <?php echo( $wgVersion ); ?> Installation</title>
|
||||
<meta name="robots" content="noindex,nofollow"/>
|
||||
<title>MediaWiki <?php echo htmlspecialchars( $wgVersion ); ?> Installation</title>
|
||||
<style type="text/css">
|
||||
|
||||
@import "../skins/monobook/main.css";
|
||||
|
|
@ -210,7 +211,7 @@ $ourdb['ibm_db2']['rootuser'] = 'db2admin';
|
|||
<div id="content">
|
||||
<div id="bodyContent">
|
||||
|
||||
<h1>MediaWiki <?php print $wgVersion ?> Installation</h1>
|
||||
<h1>MediaWiki <?php print htmlspecialchars( $wgVersion ) ?> Installation</h1>
|
||||
|
||||
<?php
|
||||
$mainListOpened = false; # Is the main list (environement checking) opend ? Used by dieout
|
||||
|
|
@ -310,7 +311,7 @@ $conf = new ConfigData;
|
|||
install_version_checks();
|
||||
$self = 'Installer'; # Maintenance script name, to please Setup.php
|
||||
|
||||
print "<li>PHP " . phpversion() . " installed</li>\n";
|
||||
print "<li>PHP " . htmlspecialchars( phpversion() ) . " installed</li>\n";
|
||||
|
||||
error_reporting( 0 );
|
||||
$phpdatabases = array();
|
||||
|
|
@ -410,7 +411,7 @@ if( wfIniGetBool( "safe_mode" ) ) {
|
|||
$conf->safeMode = false;
|
||||
}
|
||||
|
||||
$sapi = php_sapi_name();
|
||||
$sapi = htmlspecialchars( php_sapi_name() );
|
||||
print "<li>PHP server API is $sapi; ";
|
||||
$script = defined('MW_INSTALL_PHP5_EXT') ? 'index.php5' : 'index.php';
|
||||
if( $wgUsePathInfo ) {
|
||||
|
|
@ -593,6 +594,9 @@ print "<li style='font-weight:bold;color:green;font-size:110%'>Environment check
|
|||
: $_SERVER["SERVER_ADMIN"];
|
||||
$conf->EmergencyContact = importPost( "EmergencyContact", $defaultEmail );
|
||||
$conf->DBtype = importPost( "DBtype", $DefaultDBtype );
|
||||
if ( !isset( $ourdb[$conf->DBtype] ) ) {
|
||||
$conf->DBtype = $DefaultDBtype;
|
||||
}
|
||||
|
||||
$conf->DBserver = importPost( "DBserver", "localhost" );
|
||||
$conf->DBname = importPost( "DBname", "wikidb" );
|
||||
|
|
@ -652,6 +656,8 @@ if( $conf->DBpassword != $conf->DBpassword2 ) {
|
|||
}
|
||||
if( !preg_match( '/^[A-Za-z_0-9]*$/', $conf->DBprefix ) ) {
|
||||
$errs["DBprefix"] = "Invalid table prefix";
|
||||
} else {
|
||||
untaint( $conf->DBprefix, TC_MYSQL );
|
||||
}
|
||||
|
||||
error_reporting( E_ALL );
|
||||
|
|
@ -728,7 +734,7 @@ $conf->MCServers = importRequest( "MCServers" );
|
|||
/* Test memcached servers */
|
||||
|
||||
if ( $conf->Shm == 'memcached' && $conf->MCServers ) {
|
||||
$conf->MCServerArray = array_map( 'trim', explode( ',', $conf->MCServers ) );
|
||||
$conf->MCServerArray = wfArrayMap( 'trim', explode( ',', $conf->MCServers ) );
|
||||
foreach ( $conf->MCServerArray as $server ) {
|
||||
$error = testMemcachedServer( $server );
|
||||
if ( $error ) {
|
||||
|
|
@ -781,7 +787,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
$errs["DBtype"] = "Unknown database type '$conf->DBtype'";
|
||||
continue;
|
||||
}
|
||||
print "<li>Database type: {$conf->DBtypename}</li>\n";
|
||||
print "<li>Database type: " . htmlspecialchars( $conf->DBtypename ) . "</li>\n";
|
||||
$dbclass = 'Database'.ucfirst($conf->DBtype);
|
||||
$wgDBtype = $conf->DBtype;
|
||||
$wgDBadminuser = "root";
|
||||
|
|
@ -812,7 +818,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
|
||||
$wgTitle = Title::newFromText( "Installation script" );
|
||||
error_reporting( E_ALL );
|
||||
print "<li>Loading class: $dbclass</li>\n";
|
||||
print "<li>Loading class: " . htmlspecialchars( $dbclass ) . "</li>\n";
|
||||
$dbc = new $dbclass;
|
||||
|
||||
if( $conf->DBtype == 'mysql' ) {
|
||||
|
|
@ -836,7 +842,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
}
|
||||
|
||||
# Attempt to connect
|
||||
echo( "<li>Attempting to connect to database server as $db_user..." );
|
||||
echo( "<li>Attempting to connect to database server as " . htmlspecialchars( $db_user ) . "..." );
|
||||
$wgDatabase = Database::newFromParams( $wgDBserver, $db_user, $db_pass, '', 1 );
|
||||
|
||||
# Check the connection and respond to errors
|
||||
|
|
@ -871,7 +877,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
case 2003:
|
||||
default:
|
||||
# General connection problem
|
||||
echo( "failed with error [$errno] $errtx.</li>\n" );
|
||||
echo( htmlspecialchars( "failed with error [$errno] $errtx." ) . "</li>\n" );
|
||||
$errs["DBserver"] = "Connection failed";
|
||||
break;
|
||||
} # switch
|
||||
|
|
@ -888,10 +894,11 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
$db_pass = $wgDBpassword;
|
||||
}
|
||||
|
||||
echo( "<li>Attempting to connect to database \"$wgDBname\" as \"$db_user\"..." );
|
||||
echo( "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) .
|
||||
"\" as \"" . htmlspecialchars( $db_user ) . "\"..." );
|
||||
$wgDatabase = $dbc->newFromParams($wgDBserver, $db_user, $db_pass, $wgDBname, 1);
|
||||
if (!$wgDatabase->isOpen()) {
|
||||
print " error: " . $wgDatabase->lastError() . "</li>\n";
|
||||
print " error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
|
||||
} else {
|
||||
$myver = $wgDatabase->getServerVersion();
|
||||
}
|
||||
|
|
@ -904,10 +911,11 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
// Changed !mysql to postgres check since it seems to only apply to postgres
|
||||
if( $useRoot && $conf->DBtype == 'postgres' ) {
|
||||
$wgDBsuperuser = $conf->RootUser;
|
||||
echo( "<li>Attempting to connect to database \"postgres\" as superuser \"$wgDBsuperuser\"..." );
|
||||
echo( "<li>Attempting to connect to database \"postgres\" as superuser \"" .
|
||||
htmlspecialchars( $wgDBsuperuser ) . "\"..." );
|
||||
$wgDatabase = $dbc->newFromParams($wgDBserver, $wgDBsuperuser, $conf->RootPW, "postgres", 1);
|
||||
if (!$wgDatabase->isOpen()) {
|
||||
print " error: " . $wgDatabase->lastError() . "</li>\n";
|
||||
print " error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
|
||||
$errs["DBserver"] = "Could not connect to database as superuser";
|
||||
$errs["RootUser"] = "Check username";
|
||||
$errs["RootPW"] = "and password";
|
||||
|
|
@ -915,10 +923,11 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
}
|
||||
$wgDatabase->initial_setup($conf->RootPW, 'postgres');
|
||||
}
|
||||
echo( "<li>Attempting to connect to database \"$wgDBname\" as \"$wgDBuser\"..." );
|
||||
echo( "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) .
|
||||
"\" as \"" . htmlspecialchars( $wgDBuser ) . "\"..." );
|
||||
$wgDatabase = $dbc->newFromParams($wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1);
|
||||
if (!$wgDatabase->isOpen()) {
|
||||
print " error: " . $wgDatabase->lastError() . "</li>\n";
|
||||
print " error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
|
||||
} else {
|
||||
$myver = $wgDatabase->getServerVersion();
|
||||
}
|
||||
|
|
@ -930,7 +939,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
continue;
|
||||
}
|
||||
|
||||
print "<li>Connected to {$conf->DBtype} $myver";
|
||||
print "<li>Connected to " . htmlspecialchars( "{$conf->DBtype} $myver" );
|
||||
if ($conf->DBtype == 'mysql') {
|
||||
if( version_compare( $myver, "4.0.14" ) < 0 ) {
|
||||
print "</li>\n";
|
||||
|
|
@ -1017,15 +1026,19 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
}
|
||||
}
|
||||
if ( $existingSchema && $existingSchema != $conf->DBschema ) {
|
||||
print "<li><strong>Warning:</strong> you requested the {$conf->DBschema} schema, " .
|
||||
"but the existing database has the $existingSchema schema. This upgrade script ".
|
||||
"can't convert it, so it will remain $existingSchema.</li>\n";
|
||||
$encExisting = htmlspecialchars( $existingSchema );
|
||||
$encRequested = htmlspecialchars( $conf->DBschema );
|
||||
print "<li><strong>Warning:</strong> you requested the $encRequested schema, " .
|
||||
"but the existing database has the $encExisting schema. This upgrade script ".
|
||||
"can't convert it, so it will remain $encExisting.</li>\n";
|
||||
$conf->setSchema( $existingSchema, $conf->DBengine );
|
||||
}
|
||||
if ( $existingEngine && $existingEngine != $conf->DBengine ) {
|
||||
print "<li><strong>Warning:</strong> you requested the {$conf->DBengine} storage " .
|
||||
"engine, but the existing database uses the $existingEngine engine. This upgrade " .
|
||||
"script can't convert it, so it will remain $existingEngine.</li>\n";
|
||||
$encExisting = htmlspecialchars( $existingEngine );
|
||||
$encRequested = htmlspecialchars( $conf->DBengine );
|
||||
print "<li><strong>Warning:</strong> you requested the $encRequested storage " .
|
||||
"engine, but the existing database uses the $encExisting engine. This upgrade " .
|
||||
"script can't convert it, so it will remain $encExisting.</li>\n";
|
||||
$conf->setSchema( $conf->DBschema, $existingEngine );
|
||||
}
|
||||
}
|
||||
|
|
@ -1066,7 +1079,8 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
}
|
||||
$wgDatabase->freeResult( $res );
|
||||
if ( !$found && $conf->DBengine != 'MyISAM' ) {
|
||||
echo "<li><strong>Warning:</strong> {$conf->DBengine} storage engine not available, " .
|
||||
echo "<li><strong>Warning:</strong> " . htmlspecialchars( $conf->DBengine ) .
|
||||
" storage engine not available, " .
|
||||
"using MyISAM instead</li>\n";
|
||||
$conf->setSchema( $conf->DBschema, 'MyISAM' );
|
||||
}
|
||||
|
|
@ -1105,10 +1119,10 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
|
|||
if( $wgDatabase2->isOpen() ) {
|
||||
# Nope, just close the test connection and continue
|
||||
$wgDatabase2->close();
|
||||
echo( "<li>User $wgDBuser exists. Skipping grants.</li>\n" );
|
||||
echo( "<li>User " . htmlspecialchars( $wgDBuser ) . " exists. Skipping grants.</li>\n" );
|
||||
} else {
|
||||
# Yes, so run the grants
|
||||
echo( "<li>Granting user permissions to $wgDBuser on $wgDBname..." );
|
||||
echo( "<li>" . htmlspecialchars( "Granting user permissions to $wgDBuser on $wgDBname..." ) );
|
||||
dbsource( "../maintenance/users.sql", $wgDatabase );
|
||||
echo( "success.</li>\n" );
|
||||
}
|
||||
|
|
@ -1213,7 +1227,9 @@ if( count( $errs ) ) {
|
|||
$list = getLanguageList();
|
||||
foreach( $list as $code => $name ) {
|
||||
$sel = ($code == $conf->LanguageCode) ? 'selected="selected"' : '';
|
||||
echo "\n\t\t<option value=\"$code\" $sel>$name</option>";
|
||||
$encCode = htmlspecialchars( $code );
|
||||
$encName = htmlspecialchars( $name );
|
||||
echo "\n\t\t<option value=\"$encCode\" $sel>$encName</option>";
|
||||
}
|
||||
echo "\n";
|
||||
?>
|
||||
|
|
@ -1380,7 +1396,11 @@ if( count( $errs ) ) {
|
|||
<div class="config-section">
|
||||
<div class="config-input">
|
||||
<label class='column'>Database type:</label>
|
||||
<?php if (isset($errs['DBpicktype'])) print "\t<span class='error'>$errs[DBpicktype]</span>\n"; ?>
|
||||
<?php
|
||||
if (isset($errs['DBpicktype'])) {
|
||||
print "\t<span class='error'>" . htmlspecialchars( $errs[DBpicktype] ) . "</span>\n";
|
||||
}
|
||||
?>
|
||||
<ul class='plain'><?php
|
||||
database_picker($conf);
|
||||
?></ul>
|
||||
|
|
@ -1524,7 +1544,7 @@ if( count( $errs ) ) {
|
|||
</div>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
window.onload = toggleDBarea('<?php echo $conf->DBtype; ?>',
|
||||
window.onload = toggleDBarea('<?php echo htmlspecialchars( Xml::encodeJsVar( $conf->DBtype ) ); ?>',
|
||||
<?php
|
||||
## If they passed in a root user name, don't populate it on page load
|
||||
echo strlen(importPost('RootUser', '')) ? 0 : 1;
|
||||
|
|
@ -1656,7 +1676,7 @@ function writeLocalSettings( $conf ) {
|
|||
}
|
||||
|
||||
# Add slashes to strings for double quoting
|
||||
$slconf = array_map( "escapePhpString", get_object_vars( $conf ) );
|
||||
$slconf = wfArrayMap( "escapePhpString", get_object_vars( $conf ) );
|
||||
if( $conf->License == 'gfdl1_2' || $conf->License == 'pd' || $conf->License == 'gfdl1_3' ) {
|
||||
# Needs literal string interpolation for the current style path
|
||||
$slconf['RightsIcon'] = $conf->RightsIcon;
|
||||
|
|
@ -1841,6 +1861,7 @@ function importVar( &$var, $name, $default = "" ) {
|
|||
} else {
|
||||
$retval = $default;
|
||||
}
|
||||
taint( $retval );
|
||||
return $retval;
|
||||
}
|
||||
|
||||
|
|
@ -1856,10 +1877,8 @@ function importRequest( $name, $default = "" ) {
|
|||
return importVar( $_REQUEST, $name, $default );
|
||||
}
|
||||
|
||||
$radioCount = 0;
|
||||
|
||||
function aField( &$conf, $field, $text, $type = "text", $value = "", $onclick = '' ) {
|
||||
global $radioCount;
|
||||
static $radioCount = 0;
|
||||
if( $type != "" ) {
|
||||
$xtype = "type=\"$type\"";
|
||||
} else {
|
||||
|
|
@ -1899,7 +1918,9 @@ function aField( &$conf, $field, $text, $type = "text", $value = "", $onclick =
|
|||
}
|
||||
|
||||
global $errs;
|
||||
if(isset($errs[$field])) echo "<span class='error'>" . $errs[$field] . "</span>\n";
|
||||
if(isset($errs[$field])) {
|
||||
echo "<span class='error'>" . htmlspecialchars( $errs[$field] ) . "</span>\n";
|
||||
}
|
||||
}
|
||||
|
||||
function getLanguageList() {
|
||||
|
|
@ -2042,7 +2063,7 @@ function getShellLocale( $wikiLang ) {
|
|||
return false;
|
||||
}
|
||||
|
||||
$lines = array_map( 'trim', $lines );
|
||||
$lines = wfArrayMap( 'trim', $lines );
|
||||
$candidatesByLocale = array();
|
||||
$candidatesByLang = array();
|
||||
foreach ( $lines as $line ) {
|
||||
|
|
@ -2086,6 +2107,17 @@ function getShellLocale( $wikiLang ) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function wfArrayMap( $function, $input ) {
|
||||
$ret = array_map( $function, $input );
|
||||
foreach ( $ret as $key => $value ) {
|
||||
$taint = istainted( $input[$key] );
|
||||
if ( $taint ) {
|
||||
taint( $ret[$key], $taint );
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="license">
|
||||
|
|
|
|||
|
|
@ -2955,6 +2955,21 @@ function wfWaitForSlaves( $maxLag ) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output some plain text in command-line mode or in the installer (updaters.inc).
|
||||
* Do not use it in any other context, its behaviour is subject to change.
|
||||
*/
|
||||
function wfOut( $s ) {
|
||||
static $lineStarted = false;
|
||||
global $wgCommandLineMode;
|
||||
if ( $wgCommandLineMode && !defined( 'MEDIAWIKI_INSTALL' ) ) {
|
||||
echo $s;
|
||||
} else {
|
||||
echo htmlspecialchars( $s );
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
/** Generate a random 32-character hexadecimal token.
|
||||
* @param mixed $salt Some sort of salt, if necessary, to add to random characters before hashing.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
function convertLinks() {
|
||||
global $wgDBtype;
|
||||
if( $wgDBtype == 'postgres' ) {
|
||||
print "Links table already ok on Postgres.\n";
|
||||
wfOut( "Links table already ok on Postgres.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
print "Converting links table to ID-ID...\n";
|
||||
wfOut( "Converting links table to ID-ID...\n" );
|
||||
|
||||
global $wgLang, $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname;
|
||||
global $noKeys, $logPerformance, $fh;
|
||||
|
|
@ -48,7 +48,7 @@ function convertLinks() {
|
|||
|
||||
$res = $dbw->query( "SELECT l_from FROM $links LIMIT 1" );
|
||||
if ( $dbw->fieldType( $res, 0 ) == "int" ) {
|
||||
print "Schema already converted\n";
|
||||
wfOut( "Schema already converted\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -58,13 +58,13 @@ function convertLinks() {
|
|||
$dbw->freeResult( $res );
|
||||
|
||||
if ( $numRows == 0 ) {
|
||||
print "Updating schema (no rows to convert)...\n";
|
||||
wfOut( "Updating schema (no rows to convert)...\n" );
|
||||
createTempTable();
|
||||
} else {
|
||||
if ( $logPerformance ) { $fh = fopen ( $perfLogFilename, "w" ); }
|
||||
$baseTime = $startTime = getMicroTime();
|
||||
# Create a title -> cur_id map
|
||||
print "Loading IDs from $cur table...\n";
|
||||
wfOut( "Loading IDs from $cur table...\n" );
|
||||
performanceLog ( "Reading $numRows rows from cur table...\n" );
|
||||
performanceLog ( "rows read vs seconds elapsed:\n" );
|
||||
|
||||
|
|
@ -82,13 +82,13 @@ function convertLinks() {
|
|||
if ($reportCurReadProgress) {
|
||||
if (($curRowsRead % $curReadReportInterval) == 0) {
|
||||
performanceLog( $curRowsRead . " " . (getMicroTime() - $baseTime) . "\n" );
|
||||
print "\t$curRowsRead rows of $cur table read.\n";
|
||||
wfOut( "\t$curRowsRead rows of $cur table read.\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
$dbw->freeResult( $res );
|
||||
$dbw->bufferResults( true );
|
||||
print "Finished loading IDs.\n\n";
|
||||
wfOut( "Finished loading IDs.\n\n" );
|
||||
performanceLog( "Took " . (getMicroTime() - $baseTime) . " seconds to load IDs.\n\n" );
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ function convertLinks() {
|
|||
createTempTable();
|
||||
performanceLog( "Resetting timer.\n\n" );
|
||||
$baseTime = getMicroTime();
|
||||
print "Processing $numRows rows from $links table...\n";
|
||||
wfOut( "Processing $numRows rows from $links table...\n" );
|
||||
performanceLog( "Processing $numRows rows from $links table...\n" );
|
||||
performanceLog( "rows inserted vs seconds elapsed:\n" );
|
||||
|
||||
|
|
@ -127,19 +127,19 @@ function convertLinks() {
|
|||
}
|
||||
}
|
||||
$dbw->freeResult($res);
|
||||
#print "rowOffset: $rowOffset\ttuplesAdded: $tuplesAdded\tnumBadLinks: $numBadLinks\n";
|
||||
#wfOut( "rowOffset: $rowOffset\ttuplesAdded: $tuplesAdded\tnumBadLinks: $numBadLinks\n" );
|
||||
if ( $tuplesAdded != 0 ) {
|
||||
if ($reportLinksConvProgress) {
|
||||
print "Inserting $tuplesAdded tuples into $links_temp...";
|
||||
wfOut( "Inserting $tuplesAdded tuples into $links_temp..." );
|
||||
}
|
||||
$dbw->query( implode("",$sqlWrite) );
|
||||
$totalTuplesInserted += $tuplesAdded;
|
||||
if ($reportLinksConvProgress)
|
||||
print " done. Total $totalTuplesInserted tuples inserted.\n";
|
||||
wfOut( " done. Total $totalTuplesInserted tuples inserted.\n" );
|
||||
performanceLog( $totalTuplesInserted . " " . (getMicroTime() - $baseTime) . "\n" );
|
||||
}
|
||||
}
|
||||
print "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n\n";
|
||||
wfOut( "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n\n" );
|
||||
performanceLog( "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n" );
|
||||
performanceLog( "Total execution time: " . (getMicroTime() - $startTime) . " seconds.\n" );
|
||||
if ( $logPerformance ) { fclose ( $fh ); }
|
||||
|
|
@ -149,25 +149,25 @@ function convertLinks() {
|
|||
if ( $overwriteLinksTable ) {
|
||||
$dbConn = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
|
||||
if (!($dbConn->isOpen())) {
|
||||
print "Opening connection to database failed.\n";
|
||||
wfOut( "Opening connection to database failed.\n" );
|
||||
return;
|
||||
}
|
||||
# Check for existing links_backup, and delete it if it exists.
|
||||
print "Dropping backup links table if it exists...";
|
||||
wfOut( "Dropping backup links table if it exists..." );
|
||||
$dbConn->query( "DROP TABLE IF EXISTS $links_backup", DB_MASTER);
|
||||
print " done.\n";
|
||||
wfOut( " done.\n" );
|
||||
|
||||
# Swap in the new table, and move old links table to links_backup
|
||||
print "Swapping tables '$links' to '$links_backup'; '$links_temp' to '$links'...";
|
||||
wfOut( "Swapping tables '$links' to '$links_backup'; '$links_temp' to '$links'..." );
|
||||
$dbConn->query( "RENAME TABLE links TO $links_backup, $links_temp TO $links", DB_MASTER );
|
||||
print " done.\n\n";
|
||||
wfOut( " done.\n\n" );
|
||||
|
||||
$dbConn->close();
|
||||
print "Conversion complete. The old table remains at $links_backup;\n";
|
||||
print "delete at your leisure.\n";
|
||||
wfOut( "Conversion complete. The old table remains at $links_backup;\n" );
|
||||
wfOut( "delete at your leisure.\n" );
|
||||
} else {
|
||||
print "Conversion complete. The converted table is at $links_temp;\n";
|
||||
print "the original links table is unchanged.\n";
|
||||
wfOut( "Conversion complete. The converted table is at $links_temp;\n" );
|
||||
wfOut( "the original links table is unchanged.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -179,16 +179,16 @@ function createTempTable() {
|
|||
$dbConn = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
|
||||
|
||||
if (!($dbConn->isOpen())) {
|
||||
print "Opening connection to database failed.\n";
|
||||
wfOut( "Opening connection to database failed.\n" );
|
||||
return;
|
||||
}
|
||||
$links_temp = $dbConn->tableName( 'links_temp' );
|
||||
|
||||
print "Dropping temporary links table if it exists...";
|
||||
wfOut( "Dropping temporary links table if it exists..." );
|
||||
$dbConn->query( "DROP TABLE IF EXISTS $links_temp");
|
||||
print " done.\n";
|
||||
wfOut( " done.\n" );
|
||||
|
||||
print "Creating temporary links table...";
|
||||
wfOut( "Creating temporary links table..." );
|
||||
if ( $noKeys ) {
|
||||
$dbConn->query( "CREATE TABLE $links_temp ( " .
|
||||
"l_from int(8) unsigned NOT NULL default '0', " .
|
||||
|
|
@ -200,7 +200,7 @@ function createTempTable() {
|
|||
"UNIQUE KEY l_from(l_from,l_to), " .
|
||||
"KEY (l_to))");
|
||||
}
|
||||
print " done.\n\n";
|
||||
wfOut( " done.\n\n" );
|
||||
}
|
||||
|
||||
function performanceLog( $text ) {
|
||||
|
|
|
|||
|
|
@ -7,34 +7,34 @@
|
|||
function wfInitStats( $options=array() ) {
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
|
||||
echo "Counting total edits...";
|
||||
wfOut( "Counting total edits..." );
|
||||
$edits = $dbr->selectField( 'revision', 'COUNT(*)', '', __METHOD__ );
|
||||
$edits += $dbr->selectField( 'archive', 'COUNT(*)', '', __METHOD__ );
|
||||
echo "{$edits}\nCounting number of articles...";
|
||||
wfOut( "{$edits}\nCounting number of articles..." );
|
||||
|
||||
global $wgContentNamespaces;
|
||||
$good = $dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $wgContentNamespaces, 'page_is_redirect' => 0, 'page_len > 0' ), __METHOD__ );
|
||||
echo "{$good}\nCounting total pages...";
|
||||
wfOut( "{$good}\nCounting total pages..." );
|
||||
|
||||
$pages = $dbr->selectField( 'page', 'COUNT(*)', '', __METHOD__ );
|
||||
echo "{$pages}\nCounting number of users...";
|
||||
wfOut( "{$pages}\nCounting number of users..." );
|
||||
|
||||
$users = $dbr->selectField( 'user', 'COUNT(*)', '', __METHOD__ );
|
||||
echo "{$users}\nCounting number of admins...";
|
||||
wfOut( "{$users}\nCounting number of admins..." );
|
||||
|
||||
$admin = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), __METHOD__ );
|
||||
echo "{$admin}\nCounting number of images...";
|
||||
wfOut( "{$admin}\nCounting number of images..." );
|
||||
|
||||
$image = $dbr->selectField( 'image', 'COUNT(*)', '', __METHOD__ );
|
||||
echo "{$image}\n";
|
||||
wfOut( "{$image}\n" );
|
||||
|
||||
if( !isset( $options['noviews'] ) ) {
|
||||
echo "Counting total page views...";
|
||||
wfOut( "Counting total page views..." );
|
||||
$views = $dbr->selectField( 'page', 'SUM(page_counter)', '', __METHOD__ );
|
||||
echo "{$views}\n";
|
||||
wfOut( "{$views}\n" );
|
||||
}
|
||||
|
||||
echo "\nUpdating site statistics...";
|
||||
wfOut( "\nUpdating site statistics..." );
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$values = array( 'ss_total_edits' => $edits,
|
||||
|
|
@ -53,5 +53,5 @@ function wfInitStats( $options=array() ) {
|
|||
$dbw->insert( 'site_stats', array_merge( $values, $conds, $views ), __METHOD__ );
|
||||
}
|
||||
|
||||
echo( "done.\n" );
|
||||
wfOut( "done.\n" );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ function populateCategory( $begin, $maxlag, $throttle, $force ) {
|
|||
__FUNCTION__
|
||||
);
|
||||
if( $row ) {
|
||||
echo "Category table already populated. Use php ".
|
||||
wfOut( "Category table already populated. Use php ".
|
||||
"maintenance/populateCategory.php\n--force from the command line ".
|
||||
"to override.\n";
|
||||
"to override.\n" );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -56,14 +56,14 @@ function populateCategory( $begin, $maxlag, $throttle, $force ) {
|
|||
# Use the row to update the category count
|
||||
$cat = Category::newFromName( $name );
|
||||
if( !is_object( $cat ) ) {
|
||||
echo "The category named $name is not valid?!\n";
|
||||
wfOut( "The category named $name is not valid?!\n" );
|
||||
} else {
|
||||
$cat->refreshCounts();
|
||||
}
|
||||
|
||||
++$i;
|
||||
if( !($i % REPORTING_INTERVAL) ) {
|
||||
echo "$name\n";
|
||||
wfOut( "$name\n" );
|
||||
wfWaitForSlaves( $maxlag );
|
||||
}
|
||||
usleep( $throttle*1000 );
|
||||
|
|
@ -76,10 +76,10 @@ function populateCategory( $begin, $maxlag, $throttle, $force ) {
|
|||
'IGNORE'
|
||||
)
|
||||
) {
|
||||
echo "Category population complete.\n";
|
||||
wfOut( "Category population complete.\n" );
|
||||
return true;
|
||||
} else {
|
||||
echo "Could not insert category population row.\n";
|
||||
wfOut( "Could not insert category population row.\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
define( 'BATCH_SIZE', 200 );
|
||||
|
||||
function populate_rev_parent_id( $db ) {
|
||||
echo "Populating rev_parent_id column\n";
|
||||
wfOut( "Populating rev_parent_id column\n" );
|
||||
$start = $db->selectField( 'revision', 'MIN(rev_id)', false, __FUNCTION__ );
|
||||
$end = $db->selectField( 'revision', 'MAX(rev_id)', false, __FUNCTION__ );
|
||||
if( is_null( $start ) || is_null( $end ) ){
|
||||
echo "...revision table seems to be empty.\n";
|
||||
wfOut( "...revision table seems to be empty.\n" );
|
||||
$db->insert( 'updatelog',
|
||||
array( 'ul_key' => 'populate rev_parent_id' ),
|
||||
__FUNCTION__,
|
||||
|
|
@ -16,12 +16,12 @@ function populate_rev_parent_id( $db ) {
|
|||
}
|
||||
# Do remaining chunk
|
||||
$end += BATCH_SIZE - 1;
|
||||
$blockStart = $start;
|
||||
$blockEnd = $start + BATCH_SIZE - 1;
|
||||
$blockStart = intval( $start );
|
||||
$blockEnd = intval( $start ) + BATCH_SIZE - 1;
|
||||
$count = 0;
|
||||
$changed = 0;
|
||||
while( $blockEnd <= $end ) {
|
||||
echo "...doing rev_id from $blockStart to $blockEnd\n";
|
||||
wfOut( "...doing rev_id from $blockStart to $blockEnd\n" );
|
||||
$cond = "rev_id BETWEEN $blockStart AND $blockEnd";
|
||||
$res = $db->select( 'revision',
|
||||
array('rev_id','rev_page','rev_timestamp','rev_parent_id'),
|
||||
|
|
@ -36,14 +36,14 @@ function populate_rev_parent_id( $db ) {
|
|||
# as timestamp can only decrease and never loops with IDs (from parent to parent)
|
||||
$previousID = $db->selectField( 'revision', 'rev_id',
|
||||
array( 'rev_page' => $row->rev_page, 'rev_timestamp' => $row->rev_timestamp,
|
||||
"rev_id < {$row->rev_id}" ),
|
||||
"rev_id < " . intval( $row->rev_id ) ),
|
||||
__FUNCTION__,
|
||||
array( 'ORDER BY' => 'rev_id DESC' ) );
|
||||
# If there are none, check the the highest ID with a lower timestamp
|
||||
if( !$previousID ) {
|
||||
# Get the highest older timestamp
|
||||
$lastTimestamp = $db->selectField( 'revision', 'rev_timestamp',
|
||||
array( 'rev_page' => $row->rev_page, "rev_timestamp < '{$row->rev_timestamp}'" ),
|
||||
array( 'rev_page' => $row->rev_page, "rev_timestamp < " . $db->addQuotes( $row->rev_timestamp ) ),
|
||||
__FUNCTION__,
|
||||
array( 'ORDER BY' => 'rev_timestamp DESC' ) );
|
||||
# If there is one, let the highest rev ID win
|
||||
|
|
@ -73,10 +73,10 @@ function populate_rev_parent_id( $db ) {
|
|||
__FUNCTION__,
|
||||
'IGNORE' );
|
||||
if( $logged ) {
|
||||
echo "rev_parent_id population complete ... {$count} rows [{$changed} changed]\n";
|
||||
wfOut( "rev_parent_id population complete ... {$count} rows [{$changed} changed]\n" );
|
||||
return true;
|
||||
} else {
|
||||
echo "Could not insert rev_parent_id population row.\n";
|
||||
wfOut( "Could not insert rev_parent_id population row.\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -45,7 +45,7 @@ class UserDupes {
|
|||
$fname = 'UserDupes::hasUniqueIndex';
|
||||
$info = $this->db->indexInfo( 'user', 'user_name', $fname );
|
||||
if( !$info ) {
|
||||
echo "WARNING: doesn't seem to have user_name index at all!\n";
|
||||
wfOut( "WARNING: doesn't seem to have user_name index at all!\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -92,11 +92,11 @@ class UserDupes {
|
|||
|
||||
$this->lock();
|
||||
|
||||
echo "Checking for duplicate accounts...\n";
|
||||
wfOut( "Checking for duplicate accounts...\n" );
|
||||
$dupes = $this->getDupes();
|
||||
$count = count( $dupes );
|
||||
|
||||
echo "Found $count accounts with duplicate records on ".wfWikiID().".\n";
|
||||
wfOut( "Found $count accounts with duplicate records on ".wfWikiID().".\n" );
|
||||
$this->trimmed = 0;
|
||||
$this->reassigned = 0;
|
||||
$this->failed = 0;
|
||||
|
|
@ -106,34 +106,34 @@ class UserDupes {
|
|||
|
||||
$this->unlock();
|
||||
|
||||
echo "\n";
|
||||
wfOut( "\n" );
|
||||
|
||||
if( $this->reassigned > 0 ) {
|
||||
if( $doDelete ) {
|
||||
echo "$this->reassigned duplicate accounts had edits reassigned to a canonical record id.\n";
|
||||
wfOut( "$this->reassigned duplicate accounts had edits reassigned to a canonical record id.\n" );
|
||||
} else {
|
||||
echo "$this->reassigned duplicate accounts need to have edits reassigned.\n";
|
||||
wfOut( "$this->reassigned duplicate accounts need to have edits reassigned.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
if( $this->trimmed > 0 ) {
|
||||
if( $doDelete ) {
|
||||
echo "$this->trimmed duplicate user records were deleted from ".wfWikiID().".\n";
|
||||
wfOut( "$this->trimmed duplicate user records were deleted from ".wfWikiID().".\n" );
|
||||
} else {
|
||||
echo "$this->trimmed duplicate user accounts were found on ".wfWikiID()." which can be removed safely.\n";
|
||||
wfOut( "$this->trimmed duplicate user accounts were found on ".wfWikiID()." which can be removed safely.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
if( $this->failed > 0 ) {
|
||||
echo "Something terribly awry; $this->failed duplicate accounts were not removed.\n";
|
||||
wfOut( "Something terribly awry; $this->failed duplicate accounts were not removed.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( $this->trimmed == 0 || $doDelete ) {
|
||||
echo "It is now safe to apply the unique index on user_name.\n";
|
||||
wfOut( "It is now safe to apply the unique index on user_name.\n" );
|
||||
return true;
|
||||
} else {
|
||||
echo "Run this script again with the --fix option to automatically delete them.\n";
|
||||
wfOut( "Run this script again with the --fix option to automatically delete them.\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -215,36 +215,36 @@ class UserDupes {
|
|||
|
||||
$firstRow = $this->db->fetchObject( $result );
|
||||
$firstId = $firstRow->user_id;
|
||||
echo "Record that will be used for '$name' is user_id=$firstId\n";
|
||||
wfOut( "Record that will be used for '$name' is user_id=$firstId\n" );
|
||||
|
||||
while( $row = $this->db->fetchObject( $result ) ) {
|
||||
$dupeId = $row->user_id;
|
||||
echo "... dupe id $dupeId: ";
|
||||
wfOut( "... dupe id $dupeId: " );
|
||||
$edits = $this->editCount( $dupeId );
|
||||
if( $edits > 0 ) {
|
||||
$this->reassigned++;
|
||||
echo "has $edits edits! ";
|
||||
wfOut( "has $edits edits! " );
|
||||
if( $doDelete ) {
|
||||
$this->reassignEdits( $dupeId, $firstId );
|
||||
$newEdits = $this->editCount( $dupeId );
|
||||
if( $newEdits == 0 ) {
|
||||
echo "confirmed cleaned. ";
|
||||
wfOut( "confirmed cleaned. " );
|
||||
} else {
|
||||
$this->failed++;
|
||||
echo "WARNING! $newEdits remaining edits for $dupeId; NOT deleting user.\n";
|
||||
wfOut( "WARNING! $newEdits remaining edits for $dupeId; NOT deleting user.\n" );
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
echo "(will need to reassign edits on fix)";
|
||||
wfOut( "(will need to reassign edits on fix)" );
|
||||
}
|
||||
} else {
|
||||
echo "ok, no edits. ";
|
||||
wfOut( "ok, no edits. " );
|
||||
}
|
||||
$this->trimmed++;
|
||||
if( $doDelete ) {
|
||||
$this->trimAccount( $dupeId );
|
||||
}
|
||||
echo "\n";
|
||||
wfOut( "\n" );
|
||||
}
|
||||
$this->db->freeResult( $result );
|
||||
}
|
||||
|
|
@ -306,12 +306,12 @@ class UserDupes {
|
|||
*/
|
||||
function reassignEditsOn( $table, $field, $from, $to ) {
|
||||
$fname = 'UserDupes::reassignEditsOn';
|
||||
echo "reassigning on $table... ";
|
||||
wfOut( "reassigning on $table... " );
|
||||
$this->db->update( $table,
|
||||
array( $field => $to ),
|
||||
array( $field => $from ),
|
||||
$fname );
|
||||
echo "ok. ";
|
||||
wfOut( "ok. " );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -321,9 +321,9 @@ class UserDupes {
|
|||
*/
|
||||
function trimAccount( $userid ) {
|
||||
$fname = 'UserDupes::trimAccount';
|
||||
echo "deleting...";
|
||||
wfOut( "deleting..." );
|
||||
$this->db->delete( 'user', array( 'user_id' => $userid ), $fname );
|
||||
echo " ok";
|
||||
wfOut( " ok" );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue