<p>Avoid exotic characters; something like <tt>mw_</tt> is good.</p>
</div>
-
+
<div class="config-input"><label class="column">Database charset</label>
<div>Select one:</div>
<ul class="plain">
if(!(isset($id)) or ($id == "") ) $id = $field;
$nolabel = ($type == "radio") || ($type == "hidden");
-
+
if ($type == 'radio')
$id .= $radioCount++;
-
+
if( $nolabel ) {
echo "\t\t<label>";
} else {
}
wfProfileOut( $fname );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
-
+
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
$ret = wfMsgWeirdKey ( $this->mTitle->getText() ) ;
} else {
$ret = wfMsg( $wgUser->isLoggedIn() ? 'noarticletext' : 'noarticletextanon' );
}
-
+
return "<div class='noarticletext'>$ret</div>";
} else {
$this->loadContent( $noredir );
if ( $this->mContentLoaded ) {
return $this->mContent;
}
-
+
$dbr =& $this->getDB();
$fname = 'Article::fetchContent';
$redir = $sk->makeKnownLink( $this->mRedirectedFrom, '', 'redirect=no' );
$s = wfMsg( 'redirectedfrom', $redir );
$wgOut->setSubtitle( $s );
-
+
// Check the parser cache again, for the target page
if( $pcache ) {
if( $wgOut->tryParserCache( $this, $wgUser ) ) {
$wgOut->setArticleBodyOnly(true);
$this->view();
}
-
+
function purge() {
global $wgUser, $wgRequest, $wgOut, $wgUseSquid;
wfProfileOut( $fname );
return false;
}
-
+
$this->mGoodAdjustment = (int)$this->isCountable( $text );
$this->mTotalAdjustment = 1;
'minor_edit' => $isminor,
'text' => $text
) );
-
+
$dbw->immediateCommit();
$dbw->begin();
$revisionId = $revision->insertOn( $dbw );
$lastRevision, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
$revisionId );
$dbw->commit();
-
+
// Update caches outside the main transaction
Article::onArticleEdit( $this->mTitle );
}
$urls = array();
# Invalidate caches of all articles using this article as a template
-
+
# Template namespace
# Purge all articles linking here
$titles = $this->mTitle->getTemplateLinksTo();
$fname = 'Article::showArticle';
wfProfileIn( $fname );
-
+
# Output the redirect
if( $this->isRedirect( $text ) )
$r = 'redirect=no';
else
$r = '';
$wgOut->redirect( $this->mTitle->getFullURL( $r ).$sectionanchor );
-
+
wfProfileOut( $fname );
}
$form = new ProtectionForm( $this );
$form->show();
}
-
+
/**
* action=unprotect handler (alias)
*/
function unprotect() {
$this->protect();
}
-
+
/**
* Update the article's restriction field, and leave a log entry.
*
$flat = Article::flattenRestrictions( $limit );
$protecting = ($flat != '');
-
+
if( wfRunHooks( 'ArticleProtect', array( &$this, &$wgUser,
$limit, $reason ) ) ) {
}
return true;
}
-
+
/**
* Take an array of page restrictions and flatten it to a string
* suitable for insertion into the page_restrictions field.
$wgOut->sysopRequired();
return;
}
-
+
if( wfReadOnly() ) {
$wgOut->readOnlyPage();
return;
$fname = 'Article::editUpdates';
wfProfileIn( $fname );
-
+
# Parse the text
$options = new ParserOptions;
$poutput = $wgParser->parse( $text, $this->mTitle, $options, true, true, $newid );
if ( 0 == mt_rand( 0, 999 ) ) {
# Periodically flush old entries from the recentchanges table.
global $wgRCMaxAge;
-
+
$dbw =& wfGetDB( DB_MASTER );
$cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
$recentchanges = $dbw->tableName( 'recentchanges' );
function onArticleDelete( $title ) {
global $wgMessageCache;
-
+
$title->touchLinks();
-
+
if( $title->getNamespace() == NS_MEDIAWIKI) {
$wgMessageCache->replace( $title->getDBkey(), false );
}
*/
function onArticleEdit( $title ) {
global $wgUseSquid, $wgPostCommitUpdateList, $wgUseFileCache;
-
+
$urls = array();
-
+
// Template namespace? Purge all articles linking here.
// FIXME: When a templatelinks table arrives, use it for all includes.
if ( $title->getNamespace() == NS_TEMPLATE) {
# Override this!
return false;
}
-
+
/**
* Check if a username+password pair is a valid login.
* The name will be normalized to MediaWiki's requirements, so
# Override this!
return false;
}
-
+
/**
* Modify options in the login template.
*
function autoCreate() {
return false;
}
-
+
/**
* Set the given password in the authentication database.
* Return true if successful.
function strict() {
return false;
}
-
+
/**
* When creating a user account, optionally fill in preferences and such.
* For instance, you might pull the email address or real name from the
function initUser( &$user ) {
# Override this to do something.
}
-
+
/**
* If you want to munge the case of an account name before the final
* check, now is your chance.
# Only scan ranges which start in this /16, this improves search speed
# Blocks should not cross a /16 boundary.
$range = substr( $iaddr, 0, 4 );
-
+
$options = '';
$db =& $this->getDBOptions( $options );
$ipblocks = $db->tableName( 'ipblocks' );
$success = true;
}
}
-
+
$db->freeResult( $res );
return $success;
}
$this->mRangeStart = sprintf( '%08X', $network );
$this->mRangeEnd = sprintf( '%08X', $network + (1 << (32 - $bits)) - 1 );
}
- }
+ }
}
/**
*/
class CacheManager {
var $mTitle, $mFileCache;
-
+
function CacheManager( &$title ) {
$this->mTitle =& $title;
$this->mFileCache = '';
}
-
+
function fileCacheName() {
global $wgFileCacheDirectory;
if( !$this->mFileCache ) {
$key = $this->mTitle->getPrefixedDbkey();
$hash = md5( $key );
$key = str_replace( '.', '%2E', urlencode( $key ) );
-
+
$hash1 = substr( $hash, 0, 1 );
$hash2 = substr( $hash, 0, 2 );
$this->mFileCache = "{$wgFileCacheDirectory}/{$hash1}/{$hash2}/{$key}.html";
-
+
if($this->useGzip())
$this->mFileCache .= '.gz';
-
+
wfDebug( " fileCacheName() - {$this->mFileCache}\n" );
}
return $this->mFileCache;
function isFileCached() {
return file_exists( $this->fileCacheName() );
}
-
+
function fileCacheTime() {
return wfTimestamp( TS_MW, filemtime( $this->fileCacheName() ) );
}
-
+
function isFileCacheGood( $timestamp ) {
global $wgCacheEpoch;
-
+
if( !$this->isFileCached() ) return false;
-
+
$cachetime = $this->fileCacheTime();
$good = (( $timestamp <= $cachetime ) &&
( $wgCacheEpoch <= $cachetime ));
-
+
wfDebug(" isFileCacheGood() - cachetime $cachetime, touched {$timestamp} epoch {$wgCacheEpoch}, good $good\n");
return $good;
}
global $wgUseGzip;
return $wgUseGzip;
}
-
+
/* In handy string packages */
function fetchRawText() {
return file_get_contents( $this->fileCacheName() );
}
-
+
function fetchPageText() {
if( $this->useGzip() ) {
/* Why is there no gzfile_get_contents() or gzdecode()? */
return $this->fetchRawText();
}
}
-
+
/* Working directory to/from output */
function loadFromFileCache() {
global $wgOut, $wgMimeType, $wgOutputEncoding, $wgContLanguageCode;
wfDebug(" loadFromFileCache()\n");
-
+
$filename=$this->fileCacheName();
$wgOut->sendCacheControl();
header( "Content-type: $wgMimeType; charset={$wgOutputEncoding}" );
header( "Content-language: $wgContLanguageCode" );
-
+
if( $this->useGzip() ) {
if( wfClientAcceptsGzip() ) {
header( 'Content-Encoding: gzip' );
}
readfile( $filename );
}
-
+
function checkCacheDirs() {
$filename = $this->fileCacheName();
$mydir2=substr($filename,0,strrpos($filename,'/')); # subdirectory level 2
$mydir1=substr($mydir2,0,strrpos($mydir2,'/')); # subdirectory level 1
-
+
if(!file_exists($mydir1)) { mkdir($mydir1,0775); } # create if necessary
if(!file_exists($mydir2)) { mkdir($mydir2,0775); }
}
-
+
function saveToFileCache( $origtext ) {
$text = $origtext;
if(strcmp($text,'') == 0) return '';
-
+
wfDebug(" saveToFileCache()\n", false);
-
+
$this->checkCacheDirs();
-
+
$f = fopen( $this->fileCacheName(), 'w' );
if($f) {
$now = wfTimestampNow();
$this->skin =& $skin;
$this->preCacheMessages();
}
-
+
function newFromUser( &$user ) {
$sk =& $user->getSkin();
if( $user->getOption('usenewrc') ) {
$s .= $this->skin->commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
}
}
-
+
/**
* Check whether to enable RC-Patrol features
* @return bool
return $wgUseRCPatrol && $wgUser->isLoggedIn() &&
( !$wgOnlySysopsCanPatrol || $wgUser->isAllowed( 'patrol' ) );
}
-
+
/**
* Make user link (or user contributions for unregistered users)
* @param int $userId
return $this->skin->makeLinkObj( $userPage, $encName );
}
}
-
+
/**
* @param int $userId
* @param string $userText
global $wgUser, $wgDisableAnonTalk, $wgSysopUserBans;
$talkable = !( $wgDisableAnonTalk && 0 == $userId );
$blockable = ( $wgSysopUserBans || 0 == $userId );
-
+
$items = array();
if( $talkable ) {
$items[] = $this->userTalkLink( $userId, $userText );
if( $blockable && $wgUser->isAllowed( 'block' ) ) {
$items[] = $this->blockLink( $userId, $userText );
}
-
+
if( $items ) {
return ' (' . implode( ' | ', $items ) . ')';
} else {
return '';
}
}
-
+
/**
* @param int $userId
* @param string $userText
function userTalkLink( $userId, $userText ) {
global $wgContLang;
$talkname = $wgContLang->getNsText( NS_TALK ); # use the shorter name
-
+
$userTalkPage = Title::makeTitle( NS_USER_TALK, $userText );
$userTalkLink = $this->skin->makeLinkObj( $userTalkPage, $talkname );
return $userTalkLink;
}
-
+
/**
* @param int $userId
* @param string $userText
}
$rc->userlink = $this->userLink( $rc_user, $rc_user_text );
-
+
$rc->lastlink = $lastLink;
$rc->curlink = $curLink;
$rc->difflink = $diffLink;
}
return $ret;
}
-
+
/**
* Enhanced RC group
*/
$this->rcCacheIndex++;
return $r;
}
-
+
function maybeWatchedLink( $link, $watched=false ) {
if( $watched ) {
// FIXME: css style might be more appropriate
return $link;
}
}
-
+
/**
* Generate HTML for an arrow or placeholder graphic
* @param string $dir one of '', 'd', 'l', 'r'
$encAlt = htmlspecialchars( $alt );
return "<img src=\"$encUrl\" width=\"12\" height=\"12\" alt=\"$encAlt\" />";
}
-
+
/**
* Generate HTML for a right- or left-facing arrow,
* depending on language direction.
$dir = $wgContLang->isRTL() ? 'l' : 'r';
return $this->arrow( $dir, '+' );
}
-
+
/**
* Generate HTML for a down-facing arrow
* depending on language direction.
function downArrow() {
return $this->arrow( 'd', '-' );
}
-
+
/**
* Generate HTML for a spacer image
* @return string HTML <img> tag
*/
function open( $server, $user, $password, $dbName ) {
global $wguname;
-
+
# Test for missing mysql.so
# First try to load it
if (!@extension_loaded('mysql')) {
if ( !$success ) {
$this->reportConnectionError();
}
-
+
global $wgDBmysql5;
if( $wgDBmysql5 ) {
// Tell the server we're communicating with it in UTF-8.
// This may engage various charset conversions.
$this->query( 'SET NAMES utf8' );
}
-
+
$this->mOpened = $success;
return $success;
}
if ( $myError ) {
$error = $myError;
}
-
+
if ( $this->mFailFunction ) {
if ( !is_int( $this->mFailFunction ) ) {
$ff = $this->mFailFunction;
$opts[] = 'IGNORE';
return implode(' ', $opts);
}
-
+
/**
* UPDATE wrapper, takes a condition array and a SET array
*
$s=str_replace(array('%','_'),array('\%','\_'),$s);
return $s;
}
-
+
/**
* Returns an appropriately quoted sequence value for inserting a new row.
* MySQL has autoincrement fields, so this is just NULL. But the PostgreSQL
}
wfLogDBError( "Connection error: $error\n" );
-
+
$text = str_replace( '$1', $error, $noconnect );
$text .= wfGetSiteNotice();
$this->mPassword = $password;
$this->mDBname = $dbName;
$this->mSchemas = array($wgDBschema,'public');
-
+
$success = false;
-
+
if ( '' != $dbName ) {
# start a database connection
$hstring="";
}
return $this->mConn;
}
-
+
/**
* Closes a database connection, if it is open
* Returns success, true if already closed
return true;
}
}
-
+
function doQuery( $sql ) {
return $this->mLastResult=pg_query( $this->mConn , $sql);
}
-
+
function queryIgnore( $sql, $fname = '' ) {
return $this->query( $sql, $fname, true );
}
-
+
function freeResult( $res ) {
if ( !@pg_free_result( $res ) ) {
wfDebugDieBacktrace( "Unable to free PostgreSQL result\n" );
}
}
-
+
function fetchObject( $res ) {
@$row = pg_fetch_object( $res );
# FIXME: HACK HACK HACK HACK debug
-
+
# TODO:
# hashar : not sure if the following test really trigger if the object
# fetching failled.
}
function numFields( $res ) { return pg_num_fields( $res ); }
function fieldName( $res, $n ) { return pg_field_name( $res, $n ); }
-
+
/**
* This must be called after nextSequenceVal
*/
function affectedRows() {
return pg_affected_rows( $this->mLastResult );
}
-
+
/**
* Returns information about an index
* If errors are explicitly ignored, returns NULL on failure
if ( !$res ) {
return NULL;
}
-
+
while ( $row = $this->fetchObject( $res ) ) {
if ( $row->Key_name == $index ) {
return $row;
while ($row = $this->fetchObject( $res ))
return true;
return false;
-
+
}
function fieldInfo( $table, $field ) {
return $retVal;
}
-
+
/** @todo FIXME */
function startTimer( $timeout ) {
wfDebugDieBacktrace( 'Database::startTimer() error : mysql_thread_id() not implemented for postgre' );
case 'old':
case 'group':
return '"' . $name . '"';
-
+
default:
return $name;
}
# occurred in MySQL
function replace( $table, $uniqueIndexes, $rows, $fname = 'Database::replace' ) {
$table = $this->tableName( $table );
-
+
if (count($rows)==0) {
return;
}
$res =$this->query($sql);
$row=$this->fetchObject($res);
if ($row->ftype=="varchar") {
- $size=$row->size-4;
+ $size=$row->size-4;
} else {
$size=$row->size;
}
$this->freeResult( $res );
return $size;
}
-
+
function lowPriorityOption() {
return '';
}
function limitResult($sql, $limit,$offset) {
return "$sql LIMIT $limit ".(is_numeric($offset)?" OFFSET {$offset} ":"");
}
-
+
/**
* Returns an SQL expression for a simple conditional.
* Uses CASE on PostgreSQL.
function getSoftwareLink() {
return "[http://www.postgresql.org/ PostgreSQL]";
}
-
+
/**
* @return string Version information from the database
*/
{
var $mSource, $mTarget;
var $monthNames = '', $rxDM, $rxMD, $rxDMY, $rxYDM, $rxMDY, $rxYMD;
-
+
var $regexes, $pDays, $pMonths, $pYears;
var $rules, $xMonths;
-
+
/**
* @todo document
*/
function DateFormatter() {
global $wgContLang;
-
+
$this->monthNames = $this->getMonthRegex();
for ( $i=1; $i<=12; $i++ ) {
$this->xMonths[$wgContLang->lc( $wgContLang->getMonthName( $i ) )] = $i;
$this->prxY = '\[\[(\d{1,4}([ _]BC|))]]';
$this->prxISO1 = '\[\[(-?\d{4})]]-\[\[(\d{2})-(\d{2})]]';
$this->prxISO2 = '\[\[(-?\d{4})-(\d{2})-(\d{2})]]';
-
+
# Real regular expressions
- $this->regexes[DF_DMY] = "/{$this->prxDM} *,? *{$this->prxY}{$this->regexTrail}";
+ $this->regexes[DF_DMY] = "/{$this->prxDM} *,? *{$this->prxY}{$this->regexTrail}";
$this->regexes[DF_YDM] = "/{$this->prxY} *,? *{$this->prxDM}{$this->regexTrail}";
$this->regexes[DF_MDY] = "/{$this->prxMD} *,? *{$this->prxY}{$this->regexTrail}";
$this->regexes[DF_YMD] = "/{$this->prxY} *,? *{$this->prxMD}{$this->regexTrail}";
$this->regexes[DF_MD] = "/{$this->prxMD}{$this->regexTrail}";
$this->regexes[DF_ISO1] = "/{$this->prxISO1}{$this->regexTrail}";
$this->regexes[DF_ISO2] = "/{$this->prxISO2}{$this->regexTrail}";
-
+
# Extraction keys
# See the comments in replace() for the meaning of the letters
$this->keys[DF_DMY] = 'jFY';
$this->rules[DF_ALL][DF_DM] = DF_DM;
$this->rules[DF_NONE][DF_ISO2] = DF_ISO1;
}
-
+
/**
* @static
*/
}
}
return $dateFormatter;
- }
-
+ }
+
/**
* @param $preference
* @param $text
}
$format = $this->targets[$this->mTarget];
-
+
# Construct new date
$text = '';
$fail = false;
-
+
for ( $p=0; $p < strlen( $format ); $p++ ) {
$char = $format{$p};
switch ( $char ) {
}
return $text;
}
-
+
/**
* @todo document
*/
# Also note that this will only protect _pages in the wiki_.
# Uploaded files will remain readable. Make your upload
# directory name unguessable, or use .htaccess to protect it.
-$wgWhitelistRead = false;
+$wgWhitelistRead = false;
/**
* Permission keys given to users in each group.
$wgUseExternalEditor, $wgUseRCPatrol;
$fname = 'DifferenceEngine::showDiffPage';
wfProfileIn( $fname );
-
+
# If external diffs are enabled both globally and for the user,
# we'll use the application/x-external-editor interface to call
# an external diff tool like kompare, kdiff3, etc.
global $wgInputEncoding,$wgServer,$wgScript,$wgLang;
$wgOut->disable();
header ( "Content-type: application/x-external-editor; charset=".$wgInputEncoding );
- $url1=$this->mTitle->getFullURL("action=raw&oldid=".$this->mOldid);
+ $url1=$this->mTitle->getFullURL("action=raw&oldid=".$this->mOldid);
$url2=$this->mTitle->getFullURL("action=raw&oldid=".$this->mNewid);
$special=$wgLang->getNsText(NS_SPECIAL);
$control=<<<CONTROL
if ( $this->mNewRev->isCurrent() ) {
$wgOut->setArticleFlag( true );
}
-
+
$wgOut->suppressQuickbar();
$oldTitle = $this->mOldPage->getPrefixedText();
*/
function getDiffBody() {
global $wgUseExternalDiffEngine, $wgContLang, $wgMemc, $wgDBname;
-
+
// Cacheable?
$key = false;
if ( $this->mOldid && $this->mNewid ) {
return $difftext;
}
}
-
+
if ( !$this->loadText() ) {
return false;
}
-
+
$otext = $wgContLang->segmentForDiff($this->mOldtext);
$ntext = $wgContLang->segmentForDiff($this->mNewtext);
if ( $wgUseExternalDiffEngine ) {
$this->mPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $t ) );
$this->mNewtitle = "<a href='$newLink'>{$this->mPagetitle}</a>";
}
-
+
$this->mNewUser = $this->mNewRev->getUserText();
$this->mNewComment = $this->mNewRev->getComment();
-
+
// Load the old revision object
$this->mOldRev = false;
if( $this->mOldid ) {
$oldLink = $this->mOldPage->escapeLocalUrl( 'oldid=' . $this->mOldid );
$this->mOldtitle = "<a href='$oldLink'>" . htmlspecialchars( wfMsg( 'revisionasof', $t ) ) . '</a>';
-
+
$this->mOldUser = $this->mOldRev->getUserText();
$this->mOldComment = $this->mOldRev->getComment();
}
-
+
return true;
}
// Whether it succeeds or fails, we don't want to try again
$this->mTextLoaded = 2;
}
-
+
if ( !$this->loadRevisionData() ) {
return false;
}
$this->mNewtext = $this->mNewRev->getText();
return true;
}
-
-
+
+
}
// A PHP diff engine for phpwiki. (Taken from phpwiki-1.3.3)
function diff ($from_lines, $to_lines) {
$fname = '_DiffEngine::diff';
wfProfileIn( $fname );
-
+
$n_from = sizeof($from_lines);
$n_to = sizeof($to_lines);
for ($xi = $skip; $xi < $n_from - $endskip; $xi++) {
$xhash[$this->_line_hash($from_lines[$xi])] = 1;
}
-
+
for ($yi = $skip; $yi < $n_to - $endskip; $yi++) {
$line = $to_lines[$yi];
if ( ($this->ychanged[$yi] = empty($xhash[$this->_line_hash($line)])) )
return $line;
}
}
-
+
/* Divide the Largest Common Subsequence (LCS) of the sequences
* [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally
else
for ($i = $ylim - 1; $i >= $yoff; $i--)
$ymatches[$this->yv[$i]][] = $i;
-
+
$this->lcs = 0;
$this->seq[0]= $yoff - 1;
$this->in_seq = array();
$ymids[0] = array();
-
+
$numer = $xlim - $xoff + $nchunks - 1;
$x = $xoff;
for ($chunk = 0; $chunk < $nchunks; $chunk++) {
if ($chunk > 0)
for ($i = 0; $i <= $this->lcs; $i++)
$ymids[$i][$chunk-1] = $this->seq[$i];
-
+
$x1 = $xoff + (int)(($numer + ($xlim-$xoff)*$chunk) / $nchunks);
for ( ; $x < $x1; $x++) {
$line = $flip ? $this->yv[$x] : $this->xv[$x];
}
wfProfileOut( "$fname-chunk" );
}
-
+
$seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff);
$ymid = $ymids[$this->lcs];
for ($n = 0; $n < $nchunks - 1; $n++) {
$seps[] = $flip ? array($y1, $x1) : array($x1, $y1);
}
$seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim);
-
+
wfProfileOut( $fname );
return array($this->lcs, $seps);
}
function _lcs_pos ($ypos) {
$fname = '_DiffEngine::_lcs_pos';
wfProfileIn( $fname );
-
+
$end = $this->lcs;
if ($end == 0 || $ypos > $this->seq[$end]) {
$this->seq[++$this->lcs] = $ypos;
else
$end = $mid;
}
-
+
USE_ASSERTS && assert($ypos != $this->seq[$end]);
-
+
$this->in_seq[$this->seq[$end]] = false;
$this->seq[$end] = $ypos;
$this->in_seq[$ypos] = 1;
function _compareseq ($xoff, $xlim, $yoff, $ylim) {
$fname = '_DiffEngine::_compareseq';
wfProfileIn( $fname );
-
+
// Slide down the bottom initial diagonal.
while ($xoff < $xlim && $yoff < $ylim
&& $this->xv[$xoff] == $this->yv[$yoff]) {
wfProfileIn( $fname );
$i = 0;
$j = 0;
-
+
USE_ASSERTS && assert('sizeof($lines) == sizeof($changed)');
$len = sizeof($lines);
$other_len = sizeof($other_changed);
-
+
while (1) {
/*
* Scan forwards to find beginning of another run of changes.
*/
while ($j < $other_len && $other_changed[$j])
$j++;
-
+
while ($i < $len && ! $changed[$i]) {
USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
$i++; $j++;
while ($j < $other_len && $other_changed[$j])
$j++;
}
-
+
if ($i == $len)
break;
-
+
$start = $i;
-
+
// Find the end of this run of changes.
while (++$i < $len && $changed[$i])
continue;
-
+
do {
/*
* Record the length of this run of changes, so that
* we can later determine whether the run has grown.
*/
$runlength = $i - $start;
-
+
/*
* Move the changed region back, so long as the
* previous unchanged line matches the last changed one.
continue;
USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
}
-
+
/*
* Set CORRESPONDING to the end of the changed run, at the last
* point where it corresponds to a changed run in the other file.
* CORRESPONDING == LEN means no such point has been found.
*/
$corresponding = $j < $other_len ? $i : $len;
-
+
/*
* Move the changed region forward, so long as the
* first changed line matches the following unchanged one.
$changed[$i++] = 1;
while ($i < $len && $changed[$i])
$i++;
-
+
USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
$j++;
if ($j < $other_len && $other_changed[$j]) {
}
}
} while ($runlength != $i - $start);
-
+
/*
* If possible, move the fully-merged run of changes
* back to a corresponding run in the other file.
$mapped_from_lines, $mapped_to_lines) {
$fname = 'MappedDiff::MappedDiff';
wfProfileIn( $fname );
-
+
assert(sizeof($from_lines) == sizeof($mapped_from_lines));
assert(sizeof($to_lines) == sizeof($mapped_to_lines));
function WordLevelDiff ($orig_lines, $closing_lines) {
$fname = 'WordLevelDiff::WordLevelDiff';
wfProfileIn( $fname );
-
+
list ($orig_words, $orig_stripped) = $this->_split($orig_lines);
list ($closing_words, $closing_stripped) = $this->_split($closing_lines);
function _changed( $orig, $closing ) {
$fname = 'TableDiffFormatter::_changed';
wfProfileIn( $fname );
-
+
$diff = new WordLevelDiff( $orig, $closing );
$del = $diff->orig();
$add = $diff->closing();
*/
function edit() {
global $wgOut, $wgUser, $wgRequest, $wgTitle;
-
+
if ( ! wfRunHooks( 'AlternateEdit', array( &$this ) ) )
return;
-
+
$fname = 'EditPage::edit';
wfProfileIn( $fname );
wfDebug( "$fname: enter\n" );
}
wfProfileIn( "$fname-business-end" );
-
+
$this->isConflict = false;
// css / js subpages of user pages get a special treatment
$this->isCssJsSubpage = $wgTitle->isCssJsSubpage();
-
+
/* Notice that we can't use isDeleted, because it returns true if article is ever deleted
* no matter it's current state
*/
}
}
}
-
+
if(!$this->mTitle->getArticleID() && ('initial' == $this->formtype || $this->firsttime )) { # new article
$this->showIntro();
}
return;
}
}
-
+
# First time through: get contents, set time for conflict
# checking, etc.
if ( 'initial' == $this->formtype || $this->firsttime ) {
} else {
$this->preview = $request->getCheck( 'wpPreview' );
$this->diff = $request->getCheck( 'wpDiff' );
-
+
if( !$this->preview ) {
if ( $this->tokenOk( $request ) ) {
# Some browsers will not report any submit button
if( !preg_match( '/^\d{14}$/', $this->starttime )) {
$this->starttime = null;
}
-
+
$this->recreate = $request->getCheck( 'wpRecreate' );
$this->minoredit = $request->getCheck( 'wpMinoredit' );
$this->live = $request->getCheck( 'live' );
$this->editintro = $request->getText( 'editintro' );
-
+
wfProfileOut( $fname );
}
*/
function attemptSave() {
global $wgSpamRegex, $wgFilterCallback, $wgUser, $wgOut;
-
+
$fname = 'EditPage::attemptSave';
wfProfileIn( $fname );
wfProfileIn( "$fname-checks" );
wfProfileOut( $fname );
return true;
}
-
+
wfProfileOut( "$fname-checks" );
-
+
# If article is new, insert it.
$aid = $this->mTitle->getArticleID( GAID_FOR_UPDATE );
if ( 0 == $aid ) {
wfProfileOut( $fname );
return;
}
-
+
# Don't save a new article if it's blank.
if ( ( '' == $this->textbox1 ) ) {
$wgOut->redirect( $this->mTitle->getFullURL() );
$isComment=($this->section=='new');
$this->mArticle->insertNewArticle( $this->textbox1, $this->summary,
$this->minoredit, $this->watchthis, false, $isComment);
-
+
wfProfileOut( $fname );
return false;
}
$this->mArticle->clear(); # Force reload of dates, etc.
$this->mArticle->forUpdate( true ); # Lock the article
-
+
if( $this->mArticle->getTimestamp() != $this->edittime ) {
$this->isConflict = true;
if( $this->section == 'new' ) {
}
}
}
-
+
if ( $this->isConflict ) {
wfProfileOut( $fname );
return true;
}
-
+
# All's well
wfProfileIn( "$fname-sectionanchor" );
$sectionanchor = '';
wfProfileIn( $fname );
$sk =& $wgUser->getSkin();
-
+
wfRunHooks( 'EditPage::showEditForm:initial', array( &$this ) ) ;
-
+
$wgOut->setRobotpolicy( 'noindex,nofollow' );
# Enabled article-related sidebar, toplinks, etc.
if( !empty( $matches[2] ) ) {
$this->summary = "/* ". trim($matches[2])." */ ";
}
- }
+ }
}
} else {
$s = wfMsg( 'editing', $this->mTitle->getPrefixedText() );
</textarea>
" );
-
+
$wgOut->addWikiText( $copywarn );
$wgOut->addHTML( "
wfProfileOut( $fname );
}
-
+
/**
* Append preview output to $wgOut.
* Includes category rendering if this is a category page.
'editform.wpTextbox1.value,' .
htmlspecialchars( '"' . $liveAction . '"' ) . ')"';
}
-
+
function getLastDelete() {
$dbr =& wfGetDB( DB_SLAVE );
$fname = 'EditPage::getLastDelete';
}
$toparse = $this->textbox1;
-
+
# If we're adding a comment, we need to show the
# summary as the headline
if($this->section=="new" && $this->summary!="") {
$toparse="== {$this->summary} ==\n\n".$toparse;
}
-
+
if ( $this->mMetaData != "" ) $toparse .= "\n" . $this->mMetaData ;
$parserOutput = $wgParser->parse( $this->mArticle->preSaveTransform( $toparse ) ."\n\n",
? $this->unmakesafe( $text )
: $text;
}
-
+
/**
* Filter an output field through a Unicode armoring process if it is
* going to an old browser with known broken Unicode editing issues.
? $codedText
: $this->makesafe( $codedText );
}
-
+
/**
* A number of web browsers are known to corrupt non-ASCII characters
* in a UTF-8 text editing environment. To protect against this,
function makesafe( $invalue ) {
// Armor existing references for reversability.
$invalue = strtr( $invalue, array( "&#x" => "�" ) );
-
+
$bytesleft = 0;
$result = "";
$working = 0;
}
return $result;
}
-
+
/**
* Reverse the previously applied transliteration of non-ASCII characters
* back to UTF-8. Used to protect data from corruption by broken web browsers
$hexstring .= $invalue{$i};
$i++;
} while( ctype_xdigit( $invalue{$i} ) && ( $i < strlen( $invalue ) ) );
-
+
// Do some sanity checks. These aren't needed for reversability,
// but should help keep the breakage down if the editor
// breaks one of the entities whilst editing.
// reverse the transform that we made for reversability reasons.
return strtr( $result, array( "�" => "&#x" ) );
}
-
+
function noCreatePermission() {
global $wgOut;
$wgOut->setPageTitle( wfMsg( 'nocreatetitle' ) );
* @var array
* @access private
*/
-
+
/**
* Exif tags grouped by category, the tagname itself is the key and the type
* is the value, in the case of more than one possible value type they are
* Filtered and formatted Exif data, see FormatExif::getFormattedData()
*/
var $mFormattedExifData;
-
+
/**#@-*/
-
+
/**#@+
* @var string
* @access private
*/
-
+
/**
* The file being processed
*/
* The basename of the file being processed
*/
var $basename;
-
+
/**
* The private log to log to
*/
var $log = 'exif';
-
+
/**#@-*/
/**
'YResolution' => MW_EXIF_RATIONAL, # Image resolution in height direction
'ResolutionUnit' => MW_EXIF_SHORT, # Unit of X and Y resolution #(p26)
),
-
+
# Tags relating to recording offset
'offset' => array(
'StripOffsets' => MW_EXIF_SHORT.','.MW_EXIF_LONG, # Image data location
'JPEGInterchangeFormat' => MW_EXIF_SHORT.','.MW_EXIF_LONG, # Offset to JPEG SOI
'JPEGInterchangeFormatLength' => MW_EXIF_SHORT.','.MW_EXIF_LONG, # Bytes of JPEG data
),
-
+
# Tags relating to image data characteristics
'characteristics' => array(
'TransferFunction' => MW_EXIF_SHORT, # Transfer function
'YCbCrCoefficients' => MW_EXIF_RATIONAL, # Color space transformation matrix coefficients #p27
'ReferenceBlackWhite' => MW_EXIF_RATIONAL # Pair of black and white reference values
),
-
+
# Other tags
'other' => array(
'DateTime' => MW_EXIF_ASCII, # File change date and time
'Copyright' => MW_EXIF_ASCII, # Copyright holder
),
),
-
+
# Exif IFD Attribute Information (p30-31)
'exif' => array(
# Tags relating to version
'ExifVersion' => MW_EXIF_UNDEFINED, # Exif version
'FlashpixVersion' => MW_EXIF_UNDEFINED, # Supported Flashpix version #p32
),
-
+
# Tags relating to Image Data Characteristics
'characteristics' => array(
'ColorSpace' => MW_EXIF_SHORT, # Color space information #p32
),
-
+
# Tags relating to image configuration
'configuration' => array(
'ComponentsConfiguration' => MW_EXIF_UNDEFINED, # Meaning of each component #p33
'PixelYDimension' => MW_EXIF_SHORT.','.MW_EXIF_LONG, # Valid image width
'PixelXDimension' => MW_EXIF_SHORT.','.MW_EXIF_LONG, # Valind image height
),
-
+
# Tags relating to related user information
'user' => array(
'MakerNote' => MW_EXIF_UNDEFINED, # Manufacturer notes
'UserComment' => MW_EXIF_UNDEFINED, # User comments #p34
),
-
+
# Tags relating to related file information
'related' => array(
'RelatedSoundFile' => MW_EXIF_ASCII, # Related audio file
),
-
+
# Tags relating to date and time
'dateandtime' => array(
'DateTimeOriginal' => MW_EXIF_ASCII, # Date and time of original data generation #p36
'SubSecTimeOriginal' => MW_EXIF_ASCII, # DateTimeOriginal subseconds
'SubSecTimeDigitized' => MW_EXIF_ASCII, # DateTimeDigitized subseconds
),
-
+
# Tags relating to picture-taking conditions (p31)
'conditions' => array(
'ExposureTime' => MW_EXIF_RATIONAL, # Exposure time
'DeviceSettingDescription' => MW_EXIF_UNDEFINED, # Desice settings description
'SubjectDistanceRange' => MW_EXIF_SHORT, # Subject distance range #p51
),
-
+
'other' => array(
'ImageUniqueID' => MW_EXIF_ASCII, # Unique image ID
),
),
-
+
# GPS Attribute Information (p52)
'gps' => array(
'GPSVersionID' => MW_EXIF_BYTE, # GPS tag version
$this->file = $file;
$this->basename = basename( $this->file );
-
+
$this->makeFlatExifTags();
-
+
$this->debugFile( $this->basename, __FUNCTION__, true );
wfSuppressWarnings();
$data = exif_read_data( $this->file );
* containing random gibberish.
*/
$this->mRawExifData = $data ? $data : array();
-
+
$this->makeFilteredData();
$this->makeFormattedData();
-
+
$this->debugFile( __FUNCTION__, false );
}
-
+
/**#@+
* @access private
*/
function makeFlatExifTags() {
$this->extractTags( $this->mExifTags );
}
-
+
/**
* A recursing extractor function used by makeFlatExifTags()
*
}
}
}
-
+
/**
* Make $this->mFilteredExifData
*/
function makeFilteredData() {
$this->mFilteredExifData = $this->mRawExifData;
-
+
foreach( $this->mFilteredExifData as $k => $v ) {
if ( !in_array( $k, array_keys( $this->mFlatExifTags ) ) ) {
$this->debug( $v, __FUNCTION__, "'$k' is not a valid Exif tag" );
return $this->mFormattedExifData;
}
/**#@-*/
-
+
/**
* The version of the output format
*
return false;
}
}
-
+
function isASCII( $in ) {
if ( preg_match( "/[^\x0a\x20-\x7e]/", $in ) ) {
$this->debug( $in, __FUNCTION__, 'found a character not in our whitelist' );
return false;
}
-
+
if ( preg_match( "/^\s*$/", $in ) ) {
$this->debug( $in, __FUNCTION__, 'input consisted solely of whitespace' );
return false;
}
-
+
return true;
}
return false;
}
}
-
+
function isRational( $in ) {
if ( @preg_match( "/^(\d+)\/(\d+[1-9]|[1-9]\d*)$/", $in, $m ) ) { # Avoid division by zero
return $this->isLong( $m[1] ) && $this->isLong( $m[2] );
$class = ucfirst( __CLASS__ );
if ( $type === 'array' )
$in = print_r( $in, true );
-
+
if ( $action === true )
wfDebugLog( $this->log, "$class::$fname: accepted: '$in' (type: $type)\n");
elseif ( $action === false )
* @access private
*/
var $mExif;
-
+
/**
* Constructor
*
function FormatExif( $exif ) {
$this->mExif = $exif;
}
-
+
/**
* Numbers given by Exif user agents are often magical, that is they
* should be replaced by a detailed explanation depending on their
*/
function getFormattedData() {
global $wgLang;
-
+
$tags =& $this->mExif;
$resolutionunit = !isset( $tags['ResolutionUnit'] ) || $tags['ResolutionUnit'] == 2 ? 2 : 3;
unset( $tags['ResolutionUnit'] );
-
+
foreach( $tags as $tag => $val ) {
switch( $tag ) {
case 'Compression':
break;
}
break;
-
+
case 'PhotometricInterpretation':
switch( $val ) {
case 2: case 6:
break;
}
break;
-
+
case 'Orientation':
switch( $val ) {
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
break;
}
break;
-
+
case 'PlanarConfiguration':
switch( $val ) {
case 1: case 2:
break;
}
break;
-
+
// TODO: YCbCrSubSampling
// TODO: YCbCrPositioning
-
+
case 'XResolution':
case 'YResolution':
switch( $resolutionunit ) {
break;
}
break;
-
+
// TODO: YCbCrCoefficients #p27 (see annex E)
case 'ExifVersion': case 'FlashpixVersion':
$tags[$tag] = "$val"/100;
break;
-
+
case 'ColorSpace':
switch( $val ) {
case 1: case 'FFFF.H':
break;
}
break;
-
+
case 'ComponentsConfiguration':
switch( $val ) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6:
break;
}
break;
-
+
case 'DateTime':
case 'DateTimeOriginal':
case 'DateTimeDigitized':
$tags[$tag] = $wgLang->timeanddate( wfTimestamp(TS_MW, $val) );
break;
-
+
case 'ExposureProgram':
switch( $val ) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
case 'SubjectDistance':
$tags[$tag] = $this->msg( $tag, '', $this->formatNum( $val ) );
break;
-
+
case 'MeteringMode':
switch( $val ) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 255:
break;
}
break;
-
+
case 'LightSource':
switch( $val ) {
case 0: case 1: case 2: case 3: case 4: case 9: case 10: case 11:
break;
}
break;
-
+
// TODO: Flash
case 'FocalPlaneResolutionUnit':
switch( $val ) {
break;
}
break;
-
+
case 'SensingMethod':
switch( $val ) {
case 1: case 2: case 3: case 4: case 5: case 7: case 8:
break;
}
break;
-
+
case 'FileSource':
switch( $val ) {
case 3:
break;
}
break;
-
+
case 'SceneType':
switch( $val ) {
case 1:
break;
}
break;
-
+
case 'CustomRendered':
switch( $val ) {
case 0: case 1:
break;
}
break;
-
+
case 'ExposureMode':
switch( $val ) {
case 0: case 1: case 2:
break;
}
break;
-
+
case 'WhiteBalance':
switch( $val ) {
case 0: case 1:
break;
}
break;
-
+
case 'SceneCaptureType':
switch( $val ) {
case 0: case 1: case 2: case 3:
break;
}
break;
-
+
case 'GainControl':
switch( $val ) {
case 0: case 1: case 2: case 3: case 4:
break;
}
break;
-
+
case 'Contrast':
switch( $val ) {
case 0: case 1: case 2:
break;
}
break;
-
+
case 'Saturation':
switch( $val ) {
case 0: case 1: case 2:
break;
}
break;
-
+
case 'Sharpness':
switch( $val ) {
case 0: case 1: case 2:
break;
}
break;
-
+
case 'SubjectDistanceRange':
switch( $val ) {
case 0: case 1: case 2: case 3:
break;
}
break;
-
+
case 'GPSLatitudeRef':
case 'GPSDestLatitudeRef':
switch( $val ) {
break;
}
break;
-
+
case 'GPSLongitudeRef':
case 'GPSDestLongitudeRef':
switch( $val ) {
break;
}
break;
-
+
case 'GPSStatus':
switch( $val ) {
case 'A': case 'V':
break;
}
break;
-
+
case 'GPSMeasureMode':
switch( $val ) {
case 2: case 3:
break;
}
break;
-
+
case 'GPSSpeedRef':
case 'GPSDestDistanceRef':
switch( $val ) {
break;
}
break;
-
+
case 'GPSTrackRef':
case 'GPSImgDirectionRef':
case 'GPSDestBearingRef':
break;
}
break;
-
+
case 'GPSDateStamp':
$tags[$tag] = $wgLang->date( substr( $val, 0, 4 ) . substr( $val, 5, 2 ) . substr( $val, 8, 2 ) . '000000' );
break;
-
+
// This is not in the Exif standard, just a special
// case for our purposes which enables wikis to wikify
// the make, model and software name to link to their articles.
case 'Software':
$tags[$tag] = $this->msg( $tag, '', $val );
break;
-
+
case 'ExposureTime':
// Show the pretty fraction as well as decimal version
$tags[$tag] = wfMsg( 'exif-exposuretime-format',
$this->formatFraction( $val ), $this->formatNum( $val ) );
break;
-
+
case 'FNumber':
$tags[$tag] = wfMsg( 'exif-fnumber-format',
$this->formatNum( $val ) );
break;
-
+
case 'FocalLength':
$tags[$tag] = wfMsg( 'exif-focallength-format',
$this->formatNum( $val ) );
break;
-
+
default:
$tags[$tag] = $this->formatNum( $val );
break;
*/
function msg( $tag, $val, $arg = null ) {
global $wgContLang;
-
+
if ($val === '')
$val = 'value';
return wfMsg( $wgContLang->lc( "exif-$tag-$val" ), $arg );
else
return $num;
}
-
+
/**
* Format a rational number, reducing fractions
*
*/
while( $b != 0 ) {
$remainder = $a % $b;
-
+
// tail recursion...
$a = $b;
$b = $remainder;
$this->sink = new DumpOutput();
$this->text = $text;
}
-
+
/**
* Set the DumpOutput or DumpFilter object which will receive
* various row objects and XML output for filtering. Filters
function setOutputSink( &$sink ) {
$this->sink =& $sink;
}
-
+
function openStream() {
$output = $this->writer->openStream();
$this->sink->writeOpenStream( $output );
function allPages() {
return $this->dumpFrom( '' );
}
-
+
/**
* Dumps a series of page and revision records for those pages
* in the database falling within the page_id range given.
}
return $this->dumpFrom( $condition );
}
-
+
/**
* @param Title $title
*/
'page_namespace=' . $title->getNamespace() .
' AND page_title=' . $this->db->addQuotes( $title->getDbKey() ) );
}
-
+
function pageByName( $name ) {
$title = Title::newFromText( $name );
if( is_null( $title ) ) {
return $this->pageByTitle( $title );
}
}
-
+
function pagesByName( $names ) {
foreach( $names as $name ) {
$this->pageByName( $name );
}
}
-
+
// -------------------- private implementation below --------------------
-
+
function dumpFrom( $cond = '' ) {
$fname = 'WikiExporter::dumpFrom';
wfProfileIn( $fname );
-
+
$page = $this->db->tableName( 'page' );
$revision = $this->db->tableName( 'revision' );
$text = $this->db->tableName( 'text' );
-
+
if( $this->history == MW_EXPORT_FULL ) {
$join = 'page_id=rev_page';
} elseif( $this->history == MW_EXPORT_CURRENT ) {
return new WikiError( "$fname given invalid history dump type." );
}
$where = ( $cond == '' ) ? '' : "$cond AND";
-
+
if( $this->buffer == MW_EXPORT_STREAM ) {
$prev = $this->db->bufferResults( false );
}
$result = $this->db->query( $sql, $fname );
$wrapper = $this->db->resultObject( $result );
$this->outputStream( $wrapper );
-
+
if( $this->buffer == MW_EXPORT_STREAM ) {
$this->db->bufferResults( $prev );
}
-
+
wfProfileOut( $fname );
}
-
+
/**
* Runs through a query result set dumping page and revision records.
* The result set should be sorted/grouped by page to avoid duplicate
}
class XmlDumpWriter {
-
+
/**
* Returns the export schema version.
* @return string
function schemaVersion() {
return "0.3";
}
-
+
/**
* Opens the XML output stream's root <mediawiki> element.
* This does not include an xml directive, so is safe to include
"\n" .
$this->siteInfo();
}
-
+
function siteInfo() {
$info = array(
$this->sitename(),
implode( "\n ", $info ) .
"\n </siteinfo>\n";
}
-
+
function sitename() {
global $wgSitename;
return wfElement( 'sitename', array(), $wgSitename );
}
-
+
function generator() {
global $wgVersion;
return wfElement( 'generator', array(), "MediaWiki $wgVersion" );
}
-
+
function homelink() {
$page = Title::newFromText( wfMsgForContent( 'mainpage' ) );
return wfElement( 'base', array(), $page->getFullUrl() );
}
-
+
function caseSetting() {
global $wgCapitalLinks;
// "case-insensitive" option is reserved for future
$sensitivity = $wgCapitalLinks ? 'first-letter' : 'case-sensitive';
return wfElement( 'case', array(), $sensitivity );
}
-
+
function namespaces() {
global $wgContLang;
$spaces = " <namespaces>\n";
$spaces .= " </namespaces>";
return $spaces;
}
-
+
/**
* Closes the output stream with the closing root element.
* Call when finished dumping things.
return "</mediawiki>\n";
}
-
+
/**
* Opens a <page> section on the output stream, with data
* from the given database row.
}
return $out;
}
-
+
/**
* Closes a <page> section on the output stream.
*
function closePage() {
return " </page>\n";
}
-
+
/**
* Dumps a <revision> section on the output stream, with
* data filled in from the given database row.
function writeRevision( $row ) {
$fname = 'WikiExporter::dumpRev';
wfProfileIn( $fname );
-
+
$out = " <revision>\n";
$out .= " " . wfElement( 'id', null, strval( $row->rev_id ) ) . "\n";
-
+
$ts = wfTimestamp( TS_ISO_8601, $row->rev_timestamp );
$out .= " " . wfElement( 'timestamp', null, $ts ) . "\n";
-
+
$out .= " <contributor>\n";
if( $row->rev_user ) {
$out .= " " . wfElementClean( 'username', null, strval( $row->rev_user_text ) ) . "\n";
$out .= " " . wfElementClean( 'ip', null, strval( $row->rev_user_text ) ) . "\n";
}
$out .= " </contributor>\n";
-
+
if( $row->rev_minor_edit ) {
$out .= " <minor/>\n";
}
if( $row->rev_comment != '' ) {
$out .= " " . wfElementClean( 'comment', null, strval( $row->rev_comment ) ) . "\n";
}
-
+
if( isset( $row->old_text ) ) {
// Raw text from the database may have invalid chars
$text = strval( Revision::getRevisionText( $row ) );
array( 'id' => $row->rev_text_id ),
"" ) . "\n";
}
-
+
$out .= " </revision>\n";
-
+
wfProfileOut( $fname );
return $out;
}
function writeOpenStream( $string ) {
$this->write( $string );
}
-
+
function writeCloseStream( $string ) {
$this->write( $string );
}
-
+
function writeOpenPage( $page, $string ) {
$this->write( $string );
}
-
+
function writeClosePage( $string ) {
$this->write( $string );
}
-
+
function writeRevision( $rev, $string ) {
$this->write( $string );
}
-
+
/**
* Override to write to a different stream type.
* @return bool
*/
class DumpFileOutput extends DumpOutput {
var $handle;
-
+
function DumpFileOutput( $file ) {
$this->handle = fopen( $file, "wt" );
}
-
+
function write( $string ) {
fputs( $this->handle, $string );
}
function DumpFilter( &$sink ) {
$this->sink =& $sink;
}
-
+
function writeOpenStream( $string ) {
$this->sink->writeOpenStream( $string );
}
-
+
function writeCloseStream( $string ) {
$this->sink->writeCloseStream( $string );
}
-
+
function writeOpenPage( $page, $string ) {
$this->sendingThisPage = $this->pass( $page, $string );
if( $this->sendingThisPage ) {
$this->sink->writeOpenPage( $page, $string );
}
}
-
+
function writeClosePage( $string ) {
if( $this->sendingThisPage ) {
$this->sink->writeClosePage( $string );
$this->sendingThisPage = false;
}
}
-
+
function writeRevision( $rev, $string ) {
if( $this->sendingThisPage ) {
$this->sink->writeRevision( $rev, $string );
}
}
-
+
/**
* Override for page-based filter types.
* @return bool
class DumpNamespaceFilter extends DumpFilter {
var $invert = false;
var $namespaces = array();
-
+
function DumpNamespaceFilter( &$sink, $param ) {
parent::DumpFilter( $sink );
-
+
$constants = array(
"NS_MAIN" => NS_MAIN,
"NS_TALK" => NS_TALK,
"NS_HELP_TALK" => NS_HELP_TALK,
"NS_CATEGORY" => NS_CATEGORY,
"NS_CATEGORY_TALK" => NS_CATEGORY_TALK );
-
+
if( $param{0} == '!' ) {
$this->invert = true;
$param = substr( $param, 1 );
}
-
+
foreach( explode( ',', $param ) as $key ) {
$key = trim( $key );
if( isset( $constants[$key] ) ) {
}
}
}
-
+
function pass( $page ) {
$match = isset( $this->namespaces[$page->page_namespace] );
return $this->invert xor $match;
*/
class DumpLatestFilter extends DumpFilter {
var $page, $pageString, $rev, $revString;
-
+
function writeOpenPage( $page, $string ) {
$this->page = $page;
$this->pageString = $string;
}
-
+
function writeClosePage( $string ) {
if( $this->rev ) {
$this->sink->writeOpenPage( $this->page, $this->pageString );
$this->page = null;
$this->pageString = null;
}
-
+
function writeRevision( $rev, $string ) {
if( $rev->rev_id == $this->page->page_latest ) {
$this->rev = $rev;
$this->sinks = $sinks;
$this->count = count( $sinks );
}
-
+
function writeOpenStream( $string ) {
for( $i = 0; $i < $this->count; $i++ ) {
$this->sinks[$i]->writeOpenStream( $string );
}
}
-
+
function writeCloseStream( $string ) {
for( $i = 0; $i < $this->count; $i++ ) {
$this->sinks[$i]->writeCloseStream( $string );
}
}
-
+
function writeOpenPage( $page, $string ) {
for( $i = 0; $i < $this->count; $i++ ) {
$this->sinks[$i]->writeOpenPage( $page, $string );
}
}
-
+
function writeClosePage( $string ) {
for( $i = 0; $i < $this->count; $i++ ) {
$this->sinks[$i]->writeClosePage( $string );
}
}
-
+
function writeRevision( $rev, $string ) {
for( $i = 0; $i < $this->count; $i++ ) {
$this->sinks[$i]->writeRevision( $rev, $string );
function xmlsafe( $string ) {
$fname = 'xmlsafe';
wfProfileIn( $fname );
-
+
/**
* The page may contain old data which has not been properly normalized.
* Invalid UTF-8 sequences or forbidden control characters will make our
* XML output invalid, so be sure to strip them out.
*/
$string = UtfNormal::cleanUp( $string );
-
+
$string = htmlspecialchars( $string );
wfProfileOut( $fname );
return $string;
$this->mCharset = $wgInputEncoding;
$this->mMode = $mode;
}
-
+
function edit() {
global $wgOut, $wgScript, $wgScriptPath, $wgServer, $wgLang;
$wgOut->disable();
$name=$this->mTitle->getText();
$pos=strrpos($name,".")+1;
header ( "Content-type: application/x-external-editor; charset=".$this->mCharset );
-
+
# $type can be "Edit text", "Edit file" or "Diff text" at the moment
# See the protocol specifications at [[m:Help:External editors/Tech]] for
# details.
- if(!isset($this->mMode)) {
- $type="Edit text";
+ if(!isset($this->mMode)) {
+ $type="Edit text";
$url=$this->mTitle->getFullURL("action=edit&internaledit=true");
# *.wiki file extension is used by some editors for syntax
# highlighting, so we follow that convention
}
$extension=substr($name, $pos);
}
- $special=$wgLang->getNsText(NS_SPECIAL);
+ $special=$wgLang->getNsText(NS_SPECIAL);
$control = <<<CONTROL
[Process]
Type=$type
/* Preloaded modules might exist, especially ones serving multiple protocols */
if (!class_exists($class)) {
if (!include_once($class.'.php'))
- return false;
+ return false;
}
$store=new $class();
return $store->fetchFromURL($url);
}
return $wgExternalLoadBalancers[$cluster];
}
-
+
function &getSlave( $cluster ) {
$lb =& $this->getLoadBalancer( $cluster );
return $lb->getConnection( DB_SLAVE );
function &getMaster( $cluster ) {
$lb =& $this->getLoadBalancer( $cluster );
return $lb->getConnection( DB_MASTER );
- }
+ }
function getTable( &$db ) {
$table = $db->getLBInfo( 'blobs table' );
}
return $table;
}
-
+
function fetchFromURL($url) {
global $wgExternalServers;
#
}
return $ret;
}
-
+
/**
* Fetch a blob item out of the database; a cache of the last-loaded
* blob will be kept so that multiple loads out of a multi-item blob
wfDebug( "ExternalStoreDB::fetchBlob cache hit on $cacheID\n" );
return $wgExternalBlobCache[$cacheID];
}
-
+
wfDebug( "ExternalStoreDB::fetchBlob cache miss on $cacheID\n" );
-
+
$dbr =& $this->getSlave( $cluster );
$ret = $dbr->selectField( $this->getTable( $dbr ), 'blob_text', array( 'blob_id' => $id ) );
if( $itemID !== false ) {
// Unserialise object; caller extracts item
$ret = unserialize( $ret );
}
-
+
$wgExternalBlobCache = array( $cacheID => &$ret );
return $ret;
}
var $Date = '';
var $Author = '';
/**#@-*/
-
+
/**#@+
* @todo document
*/
$this->Author = $Author;
$this->Comments = $Comments;
}
-
+
/**
* @static
*/
$string = preg_replace( '/[\x00-\x08\x0b\x0c\x0e-\x1f]/', '', $string );
return htmlspecialchars( $string );
}
-
+
function getTitle() { return $this->xmlEncode( $this->Title ); }
function getUrl() { return $this->xmlEncode( $this->Url ); }
function getDescription() { return $this->xmlEncode( $this->Description ); }
* Abstract function, override!
* @abstract
*/
-
+
/**
* Generate Header of the feed
*/
function outHeader() {
# print "<feed>";
}
-
+
/**
* Generate an item
* @param $item
function outItem( $item ) {
# print "<item>...</item>";
}
-
+
/**
* Generate Footer of the feed
*/
# print "</feed>";
}
/**#@-*/
-
+
/**
* Setup and send HTTP headers. Don't send any content;
* content might end up being cached and re-sent with
*/
function httpHeaders() {
global $wgOut;
-
+
# We take over from $wgOut, excepting its cache header info
$wgOut->disable();
$mimetype = $this->contentType();
header( "Content-type: $mimetype; charset=UTF-8" );
$wgOut->sendCacheControl();
-
+
}
-
+
/**
* Return an internet media type to be sent in the headers.
*
$allowedctypes = array('application/xml','text/xml','application/rss+xml','application/atom+xml');
return (in_array($ctype, $allowedctypes) ? $ctype : 'application/xml');
}
-
+
/**
* Output the initial XML headers with a stylesheet for legibility
* if someone finds it in a browser.
*/
function outXmlHeader() {
global $wgServer, $wgStylePath;
-
+
$this->httpHeaders();
echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
echo '<?xml-stylesheet type="text/css" href="' .
function formatTime( $ts ) {
return gmdate( 'D, d M Y H:i:s \G\M\T', wfTimestamp( TS_UNIX, $ts ) );
}
-
+
/**
* Ouput an RSS 2.0 header
*/
function outHeader() {
global $wgVersion;
-
+
$this->outXmlHeader();
?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<lastBuildDate><?php print $this->formatTime( wfTimestampNow() ) ?></lastBuildDate>
<?php
}
-
+
/**
* Output an RSS 2.0 item
* @param FeedItem item to be output
*/
function outHeader() {
global $wgVersion, $wgOut;
-
+
$this->outXmlHeader();
- ?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="<?php print $this->getLanguage() ?>">
+ ?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="<?php print $this->getLanguage() ?>">
<id><?php print $this->getFeedId() ?></id>
<title><?php print $this->getTitle() ?></title>
<link rel="self" type="application/atom+xml" href="<?php print $this->getSelfUrl() ?>"/>
<updated><?php print $this->formatTime( wfTimestampNow() ) ?>Z</updated>
<subtitle><?php print $this->getDescription() ?></subtitle>
<generator>MediaWiki <?php print $wgVersion ?></generator>
-
+
<?php
}
-
+
/**
* Atom 1.0 requires a unique, opaque IRI as a unique indentifier
* for every feed we create. For now just use the URL, but who
function getFeedId() {
return $this->getSelfUrl();
}
-
+
/**
* Atom 1.0 requests a self-reference to the feed.
* @return string
global $wgRequest;
return htmlspecialchars( $wgRequest->getFullRequestURL() );
}
-
+
/**
* @todo document
*/
<?php if( $item->getDate() ) { ?>
<updated><?php print $this->formatTime( $item->getDate() ) ?>Z</updated>
<?php } ?>
-
+
<summary type="html"><?php print $item->getDescription() ?></summary>
<?php if( $item->getAuthor() ) { ?><author><name><?php print $item->getAuthor() ?></name></author><?php }?>
</entry>
<?php if( $item->getComments() ) { ?><dc:comment><?php print $item->getComments() ?></dc:comment><?php }?>
*/
}
-
+
/**
* @todo document
*/
if ( is_object( $wgMessageCache ) )
$transstat = $wgMessageCache->getTransform();
-
+
if( is_object( $wgMessageCache ) ) {
if ( ! $transform )
$wgMessageCache->disableTransform();
if ( is_object( $wgMessageCache ) && ! $transform )
$wgMessageCache->setTransform( $transstat );
-
+
return $message;
}
$replacementKeys['$' . ($n + 1)] = $param;
$message = strtr( $message, $replacementKeys );
}
-
+
return $message;
}
function wfMkdirParents( $fullDir, $mode ) {
$parts = explode( '/', $fullDir );
$path = '';
-
+
foreach ( $parts as $dir ) {
$path .= $dir . '/';
if ( !is_dir( $path ) ) {
$protocols = array();
foreach ($wgUrlProtocols as $protocol)
$protocols[] = preg_quote( $protocol, '/' );
-
+
return implode( '|', $protocols );
}
*/
function wfIsWellFormedXml( $text ) {
$parser = xml_parser_create( "UTF-8" );
-
+
# case folding violates XML standard, turn it off
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
-
+
if( !xml_parse( $parser, $text, true ) ) {
$err = xml_error_string( xml_get_error_code( $parser ) );
$position = xml_get_current_byte_index( $parser );
function wfShellExec( $cmd )
{
global $IP;
-
+
if ( php_uname( 's' ) == 'Linux' ) {
$time = ini_get( 'max_execution_time' );
$mem = ini_get( 'memory_limit' );
*/
function wfUsePHP( $req_ver ) {
$php_ver = PHP_VERSION;
-
+
if ( version_compare( $php_ver, (string)$req_ver, '<' ) )
wfDebugDieBacktrace( "PHP $req_ver required--this is only $php_ver" );
}
/** string $rights Contain rights values : "foo,bar,bla" */
var $rights;
/**#@-*/
-
+
/** Constructor */
function Group() {
$this->clear();
// be sure it's an integer
$this->id = intval($this->id);
-
+
if($this->id) {
// By ID
$dbr =& wfGetDB( DB_SLAVE );
$this->description = $row->gr_description;
$this->rights = $row->gr_rights;
$this->dataLoaded = true;
- }
-
+ }
+
/** Initialise a new row in the database */
function addToDatabase() {
if ( Group::getStaticGroups() ) {
wfDebugDieBacktrace( "Can't modify groups in static mode" );
}
if($this->id == 0) { return; }
-
+
$fname = 'Group::save';
$dbw =& wfGetDB( DB_MASTER );
-
+
$dbw->update( 'groups',
array( /* SET */
'gr_name' => $this->name,
'gr_id' => $this->id
), $fname
);
-
+
$wgMemc->set( Group::getCacheKey( $this->id ), $this, 3600 );
}
wfDebugDieBacktrace( "Can't modify groups in static mode" );
}
if($this->id == 0) { return; }
-
+
$fname = 'Group::delete';
$dbw =& wfGetDB( DB_MASTER );
$wgMemc->delete( Group::getCacheKey( $this->id ) );
}
-
+
/**
* Get memcached key
* @static
function newFromId($id) {
global $wgMemc, $wgDBname;
$fname = 'Group::newFromId';
-
+
$staticGroups =& Group::getStaticGroups();
if ( $staticGroups ) {
if ( array_key_exists( $id, $staticGroups ) ) {
wfDebug( "$fname loaded group $id from cache\n" );
return $group;
}
-
+
$group = new Group();
$group->id = $id;
$group->loadFromDatabase();
/** @param string $name Group database name */
function newFromName($name) {
$fname = 'Group::newFromName';
-
+
$staticGroups =& Group::getStaticGroups();
if ( $staticGroups ) {
$id = Group::idFromName( $name );
return null;
}
}
-
+
$g = new Group();
$g->name = $name;
$g->loadFromDatabase();
$this->loadFromDatabase();
return $this->getMessage( $this->name );
}
-
+
function getNameForContent() {
$this->loadFromDatabase();
return $this->getMessageForContent( $this->name );
$this->loadFromDatabase();
$this->name = $name;
}
-
+
function getId() { return $this->id; }
function setId($id) {
$this->id = intval($id);
$this->dataLoaded = false;
}
-
+
function getDescription() {
return $this->description;
}
}
return $this->fieldset( $this->mName.'-'.$varname, $s );
}
-
+
/**
* @access private
* @param string $varname Name of the textareabox.
function textareabox ( $varname, $value='', $size=20 ) {
if ( $this->mRequest->wasPosted() ) {
$value = $this->mRequest->getText( $varname, $value );
- }
+ }
$value = htmlspecialchars( $value );
return '<div><label>'.wfMsg( $this->mName.'-'.$varname ).
"<textarea name=\"{$varname}\" rows=\"5\" cols=\"{$size}\">$value</textarea></label></div>\n";
function HTMLSelectGroups($selectname, $selectmsg, $selected=array(), $multiple=false, $size=6, $reverse=false) {
$groups = User::getAllGroups();
$out = htmlspecialchars( wfMsg( $selectmsg ) );
-
+
if( $multiple ) {
$attribs = array(
'name' => $selectname . '[]',
$attribs = array( 'name' => $selectname );
}
$out .= wfElement( 'select', $attribs, null );
-
+
foreach( $groups as $group ) {
$attribs = array( 'value' => $group );
if( $multiple ) {
global $wgAvailableRights;
$out = '<select name="editgroup-getrights[]" multiple="multiple">';
$groupRights = explode(',',$selected);
-
+
foreach($wgAvailableRights as $right) {
-
+
// check box when right exist
if(in_array($right, $groupRights)) { $selected = 'selected="selected" '; }
else { $selected = ''; }
-
+
$out .= '<option value="'.$right.'" '.$selected.'>'.$right."</option>\n";
}
$out .= "</select>\n";
* Get item by hash
*/
function getItem( $hash ) {}
-
+
# Set the "default text"
# This concept is an odd property of the current DB schema, whereby each text item has a revision
# associated with it. The default text is the text of the associated revision. There may, however,
function HistoryBlobStub( $hash = '', $oldid = 0 ) {
$this->mHash = $hash;
}
-
+
/**
* Sets the location (old_id) of the main object to which this object
* points
if( !in_array( 'object', $flags ) ) {
return false;
}
-
+
if( in_array( 'gzip', $flags ) ) {
// This shouldn't happen, but a bug in the compress script
// may at times gzip-compress a HistoryBlob object row.
} else {
$obj = unserialize( $row->old_text );
}
-
+
if( !is_object( $obj ) ) {
// Correct for old double-serialization bug.
$obj = unserialize( $obj );
}
-
+
// Save this item for reference; if pulling many
// items in a row we'll likely use it again.
$obj->uncompress();
function HistoryBlobCurStub( $curid = 0 ) {
$this->mCurId = $curid;
}
-
+
/**
* Sets the location (cur_id) of the main object to which this object
* points
* in here than would normally be necessary.
*/
function wfRunHooks($event, $args = null) {
-
+
global $wgHooks;
$fname = 'wfRunHooks';
wfProfileIn( $fname );
wfProfileOut( $fname );
return true;
}
-
+
if (!is_array($wgHooks[$event])) {
wfDebugDieBacktrace("Hooks array for event '$event' is not an array!\n");
wfProfileOut( $fname );
return false;
}
-
+
foreach ($wgHooks[$event] as $index => $hook) {
-
+
$object = NULL;
$method = NULL;
$func = NULL;
$data = NULL;
$have_data = false;
-
+
/* $hook can be: a function, an object, an array of $function and $data,
* an array of just a function, an array of object and method, or an
* array of object, method, and data.
*/
-
+
if (is_array($hook)) {
if (count($hook) < 1) {
wfDebugDieBacktrace("Empty array in hooks for " . $event . "\n");
} else {
wfDebugDieBacktrace("Unknown datatype in hooks for " . $event . "\n");
}
-
+
/* We put the first data element on, if needed. */
-
+
if ($have_data) {
$hook_args = array_merge(array($data), $args);
} else {
$hook_args = $args;
}
-
-
+
+
if ( isset( $object ) ) {
$func = get_class( $object ) . '::' . $method;
}
$retval = call_user_func_array($func, $hook_args);
}
wfProfileOut( $func );
-
+
/* String return is an error; false return means stop processing. */
-
+
if (is_string($retval)) {
global $wgOut;
$wgOut->fatalError($retval);
return false;
}
}
-
+
wfProfileOut( $fname );
return true;
}
function newFromTitle( $title ) {
return new Image( $title );
}
-
+
function Image( $title ) {
if( !is_object( $title ) ) {
wfDebugDieBacktrace( 'Image constructor given bogus title.' );
*/
function getCacheKeys( $shared = false ) {
global $wgDBname, $wgUseSharedUploads, $wgSharedUploadDBname, $wgCacheSharedUploads;
-
+
$foundCached = false;
$hashedName = md5($this->name);
$keys = array( "$wgDBname:Image:$hashedName" );
}
return $keys;
}
-
+
/**
* Try to load image metadata from memcached. Returns true on success.
*/
$wgMemc->delete( $keys[0] );
}
}
-
+
/**
* Load metadata from the file itself
*/
$this->fileExists = file_exists( $this->imagePath );
$this->fromSharedDirectory = false;
$gis = array();
-
+
if (!$this->fileExists) wfDebug("$fname: ".$this->imagePath." not found locally!\n");
# If the file is not found, and a shared upload directory is used, look for it there.
- if (!$this->fileExists && $wgUseSharedUploads && $wgSharedUploadDirectory) {
+ if (!$this->fileExists && $wgUseSharedUploads && $wgSharedUploadDirectory) {
# In case we're on a wgCapitalLinks=false wiki, we
# capitalize the first letter of the filename before
# looking it up in the shared repository.
if ( $this->fileExists ) {
$magic=& wfGetMimeMagic();
-
+
$this->mime = $magic->guessMimeType($this->imagePath,true);
$this->type = $magic->getMediaType($this->imagePath,$this->mime);
-
+
# Get size in bytes
$this->size = filesize( $this->imagePath );
$magic=& wfGetMimeMagic();
-
+
# Height and width
if( $this->mime == 'image/svg' ) {
wfSuppressWarnings();
$gis = getimagesize( $this->imagePath );
wfRestoreWarnings();
}
-
+
wfDebug("$fname: ".$this->imagePath." loaded, ".$this->size." bytes, ".$this->mime.".\n");
}
else {
$gis[1]= 0; //height
$gis[2]= 0; //unknown
$gis[3]= ""; //width height string
-
+
$this->mime = NULL;
$this->type = MEDIATYPE_UNKNOWN;
wfDebug("$fname: ".$this->imagePath." NOT FOUND!\n");
}
-
+
$this->width = $gis[0];
$this->height = $gis[1];
-
+
#NOTE: $gis[2] contains a code for the image type. This is no longer used.
-
+
#NOTE: we have to set this flag early to avoid load() to be called
# be some of the functions below. This may lead to recursion or other bad things!
# as ther's only one thread of execution, this should be safe anyway.
$this->dataLoaded = true;
-
-
+
+
if ($this->fileExists && $wgShowEXIF) $this->metadata = serialize ( $this->retrieveExifData() ) ;
else $this->metadata = serialize ( array() ) ;
-
+
if ( isset( $gis['bits'] ) ) $this->bits = $gis['bits'];
else $this->bits = 0;
-
+
wfProfileOut( $fname );
}
global $wgUseSharedUploads, $wgSharedUploadDBname, $wgSharedUploadDBprefix, $wgContLang;
$fname = 'Image::loadFromDB';
wfProfileIn( $fname );
-
+
$dbr =& wfGetDB( DB_SLAVE );
-
+
$this->checkDBSchema($dbr);
-
+
$row = $dbr->selectRow( 'image',
array( 'img_size', 'img_width', 'img_height', 'img_bits',
'img_media_type', 'img_major_mime', 'img_minor_mime', 'img_metadata' ),
$this->imagePath = $this->getFullPath(true);
$this->name = $name;
$this->loadFromRow( $row );
-
+
// Check for rows from a previous schema, quietly upgrade them
if ( is_null($this->type) ) {
$this->upgradeRow();
}
}
}
-
+
if ( !$row ) {
$this->size = 0;
$this->width = 0;
$this->height = $row->img_height;
$this->bits = $row->img_bits;
$this->type = $row->img_media_type;
-
+
$major= $row->img_major_mime;
$minor= $row->img_minor_mime;
-
+
if (!$major) $this->mime = "unknown/unknown";
else {
if (!$minor) $minor= "unknown";
$this->mime = $major.'/'.$minor;
}
-
+
$this->metadata = $row->img_metadata;
if ( $this->metadata == "" ) $this->metadata = serialize ( array() ) ;
-
+
$this->dataLoaded = true;
}
// This avoids breaking replication in MySQL
$dbw->selectDB( $wgSharedUploadDBname );
}
-
+
$this->checkDBSchema($dbw);
-
+
if (strpos($this->mime,'/')!==false) {
list($major,$minor)= explode('/',$this->mime,2);
}
$major= $this->mime;
$minor= "unknown";
}
-
+
wfDebug("$fname: upgrading ".$this->name." to 1.5 schema\n");
-
+
$dbw->update( 'image',
array(
'img_width' => $this->width,
}
wfProfileOut( $fname );
}
-
+
/**
* Return the name of this image
* @access public
function getURL() {
if ( !$this->url ) {
$this->load();
- if($this->fileExists) {
+ if($this->fileExists) {
$this->url = Image::imageUrl( $this->name, $this->fromSharedDirectory );
} else {
$this->url = '';
}
return $this->url;
}
-
+
function getViewURL() {
if( $this->mustRender()) {
if( $this->canRender() ) {
$this->load();
return $this->mime;
}
-
+
/**
* Return the type of the media in the file.
* Use the value returned by this function with the MEDIATYPE_xxx constants.
*/
function canRender() {
global $wgUseImageMagick;
-
+
if( $this->getWidth()<=0 || $this->getHeight()<=0 ) return false;
-
+
$mime= $this->getMimeType();
-
+
if (!$mime || $mime==='unknown' || $mime==='unknown/unknown') return false;
-
+
#if it's SVG, check if there's a converter enabled
if ($mime === 'image/svg') {
global $wgSVGConverters, $wgSVGConverter;
-
+
if ($wgSVGConverter && isset( $wgSVGConverters[$wgSVGConverter])) {
wfDebug( "Image::canRender: SVG is ready!\n" );
return true;
wfDebug( "Image::canRender: SVG renderer missing\n" );
}
}
-
+
#image formats available on ALL browsers
if ( $mime === 'image/gif'
|| $mime === 'image/png'
|| $mime === 'image/jpeg' ) return true;
-
+
#image formats that can be converted to the above formats
if ($wgUseImageMagick) {
#convertable by ImageMagick (there are more...)
if ( $mime === 'image/vnd.wap.wbmp'
|| $mime === 'image/x-xbitmap' ) return true;
}
-
+
return false;
}
-
+
/**
* Return true if the file is of a type that can't be directly
*/
function mustRender() {
$mime= $this->getMimeType();
-
+
if ( $mime === "image/gif"
|| $mime === "image/png"
|| $mime === "image/jpeg" ) return false;
-
+
return true;
}
-
+
/**
* Determines if this media file may be shown inline on a page.
*
function allowInlineDisplay() {
return $this->canRender();
}
-
+
/**
* Determines if this media file is in a format that is unlikely to
* contain viruses or malicious content. It uses the global
function isSafeFile() {
if ($this->allowInlineDisplay()) return true;
if ($this->isTrustedFile()) return true;
-
+
global $wgTrustedMediaFormats;
-
+
$type= $this->getMediaType();
$mime= $this->getMimeType();
#wfDebug("Image::isSafeFile: type= $type, mime= $mime\n");
-
+
if (!$type || $type===MEDIATYPE_UNKNOWN) return false; #unknown type, not trusted
if ( in_array( $type, $wgTrustedMediaFormats) ) return true;
-
+
if ($mime==="unknown/unknown") return false; #unknown type, not trusted
if ( in_array( $mime, $wgTrustedMediaFormats) ) return true;
-
+
return false;
}
-
+
/** Returns true if the file is flagged as trusted. Files flagged that way
* can be linked to directly, even if that is not allowed for this type of
* file normally.
* Return the URL of an image, provided its name.
*
* @param string $name Name of the image, without the leading "Image:"
- * @param boolean $fromSharedDirectory Should this be in $wgSharedUploadPath?
+ * @param boolean $fromSharedDirectory Should this be in $wgSharedUploadPath?
* @return string URL of $name image
* @access public
* @static
} else {
$base = $wgUploadBaseUrl;
$path = $wgUploadPath;
- }
+ }
$url = "{$base}{$path}" . wfGetHashPath($name, $fromSharedDirectory) . "{$name}";
return wfUrlencode( $url );
}
$url.= '&r=1';
}
} else {
- $name = $this->thumbName( $width );
+ $name = $this->thumbName( $width );
if($this->fromSharedDirectory) {
$base = '';
$path = $wgSharedUploadPath;
*/
function thumbName( $width ) {
$thumb = $width."px-".$this->name;
-
+
if( $this->mustRender() ) {
if( $this->canRender() ) {
# Rasterize to PNG (for SVG vector images, etc)
if( is_null( $thumb ) ) return '';
return $thumb->getUrl();
}
-
+
/**
* As createThumb, but returns a ThumbnailImage object. This can
* provide access to the actual file, the real size of the thumb,
return $this->renderThumb( $width );
}
$this->load();
-
+
if ($this->canRender()) {
if ( $width > $this->width * $height / $this->height )
$width = floor( $this->width * $height / $this->height );
$thumb = $this->renderThumb( $width );
}
else $thumb= NULL; #not a bitmap or renderable image, don't try.
-
+
if( is_null( $thumb ) ) {
$thumb = $this->iconThumb();
}
return $thumb;
}
-
+
/**
* @return ThumbnailImage
*/
function iconThumb() {
global $wgStylePath, $wgStyleDirectory;
-
+
$try = array( 'fileicon-' . $this->extension . '.png', 'fileicon.png' );
foreach( $try as $icon ) {
$path = '/common/images/icons/' . $icon;
}
return null;
}
-
+
/**
* Create a thumbnail of the image having the specified width.
* The thumbnail will not be created if the width is larger than the
$fname = 'Image::renderThumb';
wfProfileIn( $fname );
-
+
$width = intval( $width );
$this->load();
wfProfileOut( $fname );
return null;
}
-
+
# Sanity check $width
if( $width <= 0 || $this->width <= 0) {
# BZZZT
wfProfileOut( $fname );
return $thumb;
}
-
+
$height = round( $this->height * $width / $this->width );
-
+
list( $isScriptUrl, $url ) = $this->thumbUrl( $width );
if ( $isScriptUrl && $useScript ) {
// Use thumb.php to render the image
}
}
}
-
+
$thumb = new ThumbnailImage( $url, $width, $height, $thumbPath );
wfProfileOut( $fname );
return $thumb;
function reallyRenderThumb( $thumbPath, $width, $height ) {
global $wgSVGConverters, $wgSVGConverter,
$wgUseImageMagick, $wgImageMagickConvertCommand;
-
+
$this->load();
-
+
if( $this->mime === "image/svg" ) {
#Right now we have only SVG
-
+
global $wgSVGConverters, $wgSVGConverter;
if( isset( $wgSVGConverters[$wgSVGConverter] ) ) {
global $wgSVGConverterPath;
$cmd = $wgImageMagickConvertCommand .
" -quality 85 -background white -size {$width} ".
wfEscapeShellArg($this->imagePath) . " -resize {$width}x{$height} " .
- wfEscapeShellArg($thumbPath);
+ wfEscapeShellArg($thumbPath);
wfDebug("reallyRenderThumb: running ImageMagick: $cmd\n");
wfProfileIn( 'convert' );
$conv = wfShellExec( $cmd );
return $err;
}
list( $loader, $colorStyle, $saveType ) = $typemap[$this->mime];
-
+
if( !function_exists( $loader ) ) {
$err = "Incomplete GD library configuration: missing function $loader";
wfDebug( "$err\n" );
} elseif( $colorStyle == 'bits' ) {
$truecolor = ( $this->bits > 8 );
}
-
+
$src_image = call_user_func( $loader, $this->imagePath );
if ( $truecolor ) {
$dst_image = imagecreatetruecolor( $width, $height );
imagedestroy( $dst_image );
imagedestroy( $src_image );
}
-
+
#
# Check for zero-sized thumbnails. Those can be generated when
# no disk space is available or some other error occurs
imageinterlace( $dst_image );
imagejpeg( $dst_image, $thumbPath, 95 );
}
-
+
/**
* Get all thumbnail names previously generated for this image
*/
// This generates an error on failure, hence the @
$handle = @opendir( $dir );
-
+
if ( $handle ) {
while ( false !== ( $file = readdir($handle) ) ) {
if ( $file{0} != '.' ) {
} else {
$files = array();
}
-
+
return $files;
}
wfPurgeSquidServers( $urls );
}
}
-
+
function checkDBSchema(&$db) {
# img_name must be unique
if ( !$db->indexUnique( 'image', 'img_name' ) && !$db->indexExists('image','PRIMARY') ) {
wfDebugDieBacktrace( 'Database schema not up to date, please run maintenance/archives/patch-image_name_unique.sql' );
}
-
+
#new fields must exist
if ( !$db->fieldExists( 'image', 'img_media_type' )
|| !$db->fieldExists( 'image', 'img_metadata' )
|| !$db->fieldExists( 'image', 'img_width' ) ) {
-
+
wfDebugDieBacktrace( 'Database schema not up to date, please run maintenance/update.php' );
}
}
function nextHistoryLine() {
$fname = 'Image::nextHistoryLine()';
$dbr =& wfGetDB( DB_SLAVE );
-
+
$this->checkDBSchema($dbr);
-
+
if ( $this->historyLine == 0 ) {// called for the first time, return line from cur
$this->historyRes = $dbr->select( 'image',
array(
function resetHistory() {
$this->historyLine = 0;
}
-
+
/**
* Return the full filesystem path to the file. Note that this does
* not mean that a file actually exists under that location.
*/
function getFullPath( $fromSharedRepository = false ) {
global $wgUploadDirectory, $wgSharedUploadDirectory;
-
+
$dir = $fromSharedRepository ? $wgSharedUploadDirectory :
$wgUploadDirectory;
-
+
// $wgSharedUploadDirectory may be false, if thumb.php is used
if ( $dir ) {
- $fullpath = $dir . wfGetHashPath($this->name, $fromSharedRepository) . $this->name;
+ $fullpath = $dir . wfGetHashPath($this->name, $fromSharedRepository) . $this->name;
} else {
$fullpath = false;
}
global $wgHashedUploadDirectory, $wgHashedSharedUploadDirectory;
return $shared ? $wgHashedSharedUploadDirectory : $wgHashedUploadDirectory;
}
-
+
/**
* Record an image upload in the upload log and the image table
*/
if ( $license != '' ) {
$filedesc = $desc == '' ? '' : '== ' . wfMsg ( 'filedesc' ) . " ==\n" . $desc . "\n";
$textdesc = $filedesc .
- '== ' . wfMsgForContent ( 'license' ) . " ==\n" . '{{' . $license . '}}' . "\n";
+ '== ' . wfMsgForContent ( 'license' ) . " ==\n" . '{{' . $license . '}}' . "\n";
} else {
$textdesc = $desc;
}
$major= $this->mime;
$minor= "unknown";
}
-
+
# Test to see if the row exists using INSERT IGNORE
# This avoids race conditions by locking the row until the commit, and also
# doesn't deadlock. SELECT FOR UPDATE causes a deadlock for every race condition.
'oi_user_text' => 'img_user_text',
), array( 'img_name' => $this->name ), $fname
);
-
+
# Update the current image row
$dbw->update( 'image',
array( /* SET */
$minor = false;
$watch = $watch || $wgUser->isWatched( $descTitle );
$suppressRC = true; // There's already a log entry, so don't double the RC load
-
+
if( $descTitle->exists() ) {
// TODO: insert a null revision into the page history for this update.
if( $watch ) {
$wgUser->addWatch( $descTitle );
}
-
+
# Invalidate the cache for the description page
$descTitle->invalidateCache();
$purgeURLs[] = $descTitle->getInternalURL();
// New image; create the description page.
$article->insertNewArticle( $textdesc, $desc, $minor, $watch, $suppressRC );
}
-
+
# Invalidate cache for all pages using this image
$linksTo = $this->getLinksTo();
-
+
if ( $wgUseSquid ) {
$u = SquidUpdate::newFromTitles( $linksTo, $purgeURLs );
array_push( $wgPostCommitUpdateList, $u );
}
Title::touchArray( $linksTo );
-
+
$log = new LogPage( 'upload' );
$log->addEntry( 'upload', $descTitle, $desc );
function getLinksTo( $options = '' ) {
$fname = 'Image::getLinksTo';
wfProfileIn( $fname );
-
+
if ( $options ) {
$db =& wfGetDB( DB_MASTER );
} else {
$encName = $db->addQuotes( $this->name );
$sql = "SELECT page_namespace,page_title,page_id FROM $page,$imagelinks WHERE page_id=il_from AND il_to=$encName $options";
$res = $db->query( $sql, $fname );
-
+
$retVal = array();
if ( $db->numRows( $res ) ) {
while ( $row = $db->fetchObject( $res ) ) {
$exif = new Exif( $this->imagePath );
return $exif->getFilteredData();
}
-
+
function getExifData() {
global $wgRequest;
if ( $this->metadata === '0' )
return array();
-
+
$purge = $wgRequest->getVal( 'action' ) == 'purge';
$ret = unserialize( $this->metadata );
$oldver = isset( $ret['MEDIAWIKI_EXIF_VERSION'] ) ? $ret['MEDIAWIKI_EXIF_VERSION'] : 0;
$newver = Exif::version();
-
+
if ( !count( $ret ) || $purge || $oldver != $newver ) {
$this->purgeMetadataCache();
$this->updateExifData( $newver );
if ( isset( $ret['MEDIAWIKI_EXIF_VERSION'] ) )
unset( $ret['MEDIAWIKI_EXIF_VERSION'] );
$format = new FormatExif( $ret );
-
+
return $format->getFormattedData();
}
function updateExifData( $version ) {
$fname = 'Image:updateExifData';
-
+
if ( $this->getImagePath() === false ) # Not a local image
return;
-
+
# Get EXIF data from image
$exif = $this->retrieveExifData();
if ( count( $exif ) ) {
} else {
$this->metadata = '0';
}
-
+
# Update EXIF data in database
$dbw =& wfGetDB( DB_MASTER );
-
+
$this->checkDBSchema($dbw);
-
+
$dbw->update( 'image',
array( 'img_metadata' => $this->metadata ),
array( 'img_name' => $this->name ),
$fname
);
}
-
+
/**
* Returns true if the image does not come from the shared
* image repository.
*/
function wfImageDir( $fname ) {
global $wgUploadDirectory, $wgHashedUploadDirectory;
-
+
if (!$wgHashedUploadDirectory) { return $wgUploadDirectory; }
$hash = md5( $fname );
global $wgUploadDirectory, $wgHashedUploadDirectory,
$wgSharedUploadDirectory, $wgHashedSharedUploadDirectory;
$dir = $shared ? $wgSharedUploadDirectory : $wgUploadDirectory;
- $hashdir = $shared ? $wgHashedSharedUploadDirectory : $wgHashedUploadDirectory;
+ $hashdir = $shared ? $wgHashedSharedUploadDirectory : $wgHashedUploadDirectory;
if (!$hashdir) { return $dir.'/'.$subdir; }
$hash = md5( $fname );
$oldumask = umask(0);
-
+
# Suppress warning messages here; if the file itself can't
# be written we'll worry about it then.
wfSuppressWarnings();
-
+
$archive = $dir.'/'.$subdir;
if ( ! is_dir( $archive ) ) { mkdir( $archive, 0777 ); }
$archive .= '/' . $hash{0};
function wfGetSVGsize( $filename ) {
$width = 256;
$height = 256;
-
+
// Read a chunk of the file
$f = fopen( $filename, "rt" );
if( !$f ) return false;
$chunk = fread( $f, 4096 );
fclose( $f );
-
+
// Uber-crappy hack! Run through a real XML parser.
if( !preg_match( '/<svg\s*([^>]*)\s*>/s', $chunk, $matches ) ) {
return false;
if( preg_match( '/\bheight\s*=\s*("[^"]+"|\'[^\']+\')/s', $tag, $matches ) ) {
$height = wfScaleSVGUnit( trim( substr( $matches[1], 1, -1 ) ) );
}
-
+
return array( $width, $height, 'SVG',
"width=\"$width\" height=\"$height\"" );
}
/**
* @return string The thumbnail URL
- */
+ */
function getUrl() {
return $this->url;
}
-
+
/**
* Return HTML <img ... /> tag for the thumbnail, will include
* width and height attributes and a blank alt text (as required).
<?php
if ( ! defined( 'MEDIAWIKI' ) )
die();
-
+
/**
* @package MediaWiki
*/
} else {
$nb = '';
}
-
+
$textlink = $this->mShowFilename ?
$sk->makeKnownLinkObj( $nt, htmlspecialchars( $wgLang->truncate( $nt->getText(), 20, '...' ) ) ) . "<br />\n" :
'' ;
$thumb = $img->getThumbnail( 120, 120 );
$vpad = floor( ( 150 - $thumb->height ) /2 ) - 2;
$s .= '<td><div class="gallerybox">' . '<div class="thumb" style="padding: ' . $vpad . 'px 0;">';
-
+
# ATTENTION: The newline after <div class="gallerytext"> is needed to accommodate htmltidy which
# in version 4.8.6 generated crackpot html in its absence, see:
# http://bugzilla.wikimedia.org/show_bug.cgi?id=1765 -Ævar
$r .= '|}';
return $r;
}
-
+
/**
* Get a list of EXIF metadata items which should be displayed when
* the metadata table is collapsed.
$icon->toHtml() .
'</a></div>' );
}
-
+
$showLink = true;
}
$info = wfMsg( 'fileinfo',
ceil($this->img->getSize()/1024.0),
$this->img->getMimeType() );
-
+
if (!$this->img->isSafeFile()) {
$warning = wfMsg( 'mediawarning' );
$wgOut->addWikiText( <<<END
$sk = $wgUser->getSkin();
$wgOut->addHTML( '<br /><ul>' );
- if( $wgUser->isAllowed( 'reupload' ) ) {
+ if( $wgUser->isAllowed( 'reupload' ) ) {
$wgOut->addWikiText( "<li>\n<div>". wfMsg( 'uploadnewversion', $this->getUploadUrl() ) ."</div>\n</li>\n" );
}
$wgOut->addHTML( '<li>' );
function doDelete() {
global $wgOut, $wgUser, $wgRequest, $wgUseSquid, $wgInternalServer;
global $wgPostCommitUpdateList;
-
+
$fname = 'ImagePage::doDelete';
$reason = $wgRequest->getVal( 'wpReason' );
* @var string
*/
var $msg;
-
+
/**
* @var array
*/
*/
var $html;
/**#@-*/
-
+
/**
* Constrictor
*
$tmp = $this->getLicenses();
$this->makeHtml( $tmp );
}
-
+
/**#@+
* @access private
*/
function makeLicenses() {
$levels = array();
$lines = explode( "\n", $this->msg );
-
+
foreach ( $lines as $line ) {
if ( strpos( $line, '*' ) !== 0 )
continue;
else {
list( $level, $line ) = $this->trimStars( $line );
-
+
if ( strpos( $line, '|' ) !== false ) {
$obj = new License( $line );
$this->stackItem( $this->licenses, $levels, $obj );
}
}
}
-
+
function trimStars( $str ) {
$i = $count = 0;
-
+
wfSuppressWarnings();
while ($str[$i++] == '*')
++$count;
wfRestoreWarnings();
-
+
return array( $count, ltrim( $str, '* ' ) );
}
-
+
function stackItem( &$list, $path, $item ) {
$position =& $list;
if ( $path )
$val = str_repeat( /*   */ "\xc2\xa0", $depth * 2 ) . $val;
return str_repeat( "\t", $depth ) . wfElement( 'option', $attribs, $val ) . "\n";
}
-
+
function msg( $str ) {
$out = wfMsg( $str );
return wfEmptyMsg( $str, $out ) ? $str : $out;
}
-
+
/**#@-*/
-
+
/**
* Accessor for $this->licenses
*
* @var string
*/
var $template;
-
+
/**
* @var string
*/
*/
function License( $str ) {
list( $text, $template ) = explode( '|', strrev( $str ), 2 );
-
+
$this->template = strrev( $template );
$this->text = strrev( $text );
}
function setArray( $array ) {
$this->data = $array;
}
-
+
/**
* Do the query and add the results to the LinkCache object
* Return an array mapping PDBK to ID
function getPageLinks() { return $this->mPageLinks; }
function getGoodLinks() { return $this->mGoodLinks; }
function getBadLinks() { return array_keys( $this->mBadLinks ); }
-
+
/**
* Add a title to the link cache, return the page_id or zero if non-existent
* @param string $title Title to add
return 0;
}
}
-
+
/**
* Add a title to the link cache, return the page_id or zero if non-existent
* @param Title $nt Title to add
}
$t = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>";
-
+
wfProfileOut( $fname );
return $t;
} elseif ( $nt->isAlwaysKnown() ) {
wfProfileOut( $fname );
return $text;
}
-
+
$u = $nt->escapeLocalURL( $query );
if ( '' != $nt->getFragment() ) {
if( $nt->getPrefixedDbkey() == '' ) {
$style = $this->getInternalLinkAttributesObj( $nt, $text );
if ( $aprops !== '' ) $aprops = ' ' . $aprops;
-
+
list( $inside, $trail ) = Linker::splitTrail( $trail );
$r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
wfProfileOut( $fname );
$text = htmlspecialchars( $nt->getPrefixedText() );
}
$style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
-
+
list( $inside, $trail ) = Linker::splitTrail( $trail );
$s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
$thumb = false, $manual_thumb = '' )
{
global $wgContLang, $wgUser, $wgThumbLimits;
-
+
$img = new Image( $nt );
if ( !$img->allowInlineDisplay() ) {
return $this->makeKnownLinkObj( $nt );
$url = $img->getViewURL();
$prefix = $postfix = '';
-
+
wfDebug( "makeImageLinkObj: '$width'x'$height'\n" );
-
+
if ( 'center' == $align )
{
$prefix = '<div class="center">';
$align = $wgContLang->isRTL() ? 'left' : 'right';
}
-
+
if ( $width === false ) {
$wopt = $wgUser->getOption( 'thumbsize' );
if( !isset( $wgThumbLimits[$wopt] ) ) {
$wopt = User::getDefaultOption( 'thumbsize' );
}
-
+
$width = min( $img->getWidth(), $wgThumbLimits[$wopt] );
}
-
+
return $prefix.$this->makeThumbLinkObj( $img, $label, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
}
$s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
return str_replace("\n", ' ', $s);
}
-
+
/**
* Pass a title object, not a title string
*/
wfProfileOut( $fname );
return $s;
}
-
+
/** @todo document */
function makeMediaLink( $name, /* wtf?! */ $url, $alt = '' ) {
$nt = Title::makeTitleSafe( NS_IMAGE, $name );
### HOTFIX. Instead of breaking, return empty string.
return $text;
} else {
- $name = $title->getDBKey();
+ $name = $title->getDBKey();
$img = new Image( $title );
if( $img->exists() ) {
$url = $img->getURL();
$text = $alt;
}
$u = htmlspecialchars( $url );
- return "<a href=\"{$u}\" class='$class' title=\"{$alt}\">{$text}</a>";
+ return "<a href=\"{$u}\" class='$class' title=\"{$alt}\">{$text}</a>";
}
}
function formatComment($comment, $title = NULL) {
$fname = 'Linker::formatComment';
wfProfileIn( $fname );
-
+
global $wgContLang;
$comment = str_replace( "\n", " ", $comment );
$comment = htmlspecialchars( $comment );
wfProfileOut( $fname );
return $comment;
}
-
+
/**
* Wrap a comment in standard punctuation and formatting if
* it's non-empty, otherwise return empty string.
$this->mOptions = array( 'FOR UPDATE' );
}
$this->mDb =& wfGetDB( DB_MASTER );
-
+
if ( !is_object( $title ) ) {
wfDebugDieBacktrace( "The calling convention to LinksUpdate::LinksUpdate() has changed. " .
"Please see Article::editUpdates() for an invocation example.\n" );
$this->mImages =& $this->mParserOutput->getImages();
$this->mTemplates =& $this->mParserOutput->getTemplates();
$this->mCategories =& $this->mParserOutput->getCategories();
-
+
}
/**
$existing = $this->getExistingCategories();
$this->incrTableUpdate( 'categorylinks', 'cl', $this->getCategoryDeletions( $existing ),
$this->getCategoryInsertions( $existing ) );
-
+
# I think this works out to a set XOR operation, the idea is to invalidate all
# categories which were added, deleted or changed
# FIXME: surely there's a more appropriate place to put this update?
$categoryUpdates = array_diff_assoc( $existing, $this->mCategories ) + array_diff_assoc( $this->mCategories, $existing );
$this->invalidateCategories( $categoryUpdates );
-
+
wfProfileOut( $fname );
}
$existing = $this->getExistingCategories();
$categoryUpdates = array_diff_assoc( $existing, $this->mCategories ) + array_diff_assoc( $this->mCategories, $existing );
-
+
$this->dumbTableUpdate( 'pagelinks', $this->getLinkInsertions(), 'pl_from' );
$this->dumbTableUpdate( 'imagelinks', $this->getImageInsertions(), 'il_from' );
$this->dumbTableUpdate( 'categorylinks', $this->getCategoryInsertions(), 'cl_from' );
# Update the cache of all the category pages
$this->invalidateCategories( $categoryUpdates );
-
+
wfProfileOut( $fname );
}
), $fname
);
}
- }
+ }
function dumbTableUpdate( $table, $insertions, $fromField ) {
$fname = 'LinksUpdate::dumbTableUpdate';
function getImageDeletions( $existing ) {
return array_diff_key( $existing, $this->mImages );
}
-
+
/**
* Given an array of existing categories, returns those categories which are not in $this
* and thus should be deleted.
$this->mErrorConnection = false;
$this->mLastError = 'All servers busy';
}
-
+
if ( $i !== false && $this->isOpen( $i ) ) {
# Wait for the session master pos for a short time
if ( $this->mWaitForFile ) {
*/
function getLagTimes() {
global $wgDBname;
-
+
$expiry = 5;
$requestRate = 10;
'move' => 'movelogpage'
);
wfRunHooks( 'LogPageLogName', array( &$typeText ) );
-
+
return str_replace( '_', ' ', wfMsg( $typeText[$type] ) );
}
'move' => 'movelogpagetext'
);
wfRunHooks( 'LogPageLogHeader', array( &$headerText ) );
-
+
return wfMsg( $headerText[$type] );
}
'block/unblock' => 'unblocklogentry',
'protect/protect' => 'protectedarticle',
'protect/unprotect' => 'unprotectedarticle',
-
+
// TODO: This whole section should be moved to extensions/Makesysop/SpecialMakesysop.php
'rights/rights' => 'bureaucratlogentry',
'rights/addgroup' => 'addgrouplogentry',
'rights/rngroup' => 'renamegrouplogentry',
'rights/chgroup' => 'changegrouplogentry',
-
+
'delete/delete' => 'deletedarticle',
'delete/restore' => 'undeletedarticle',
'upload/upload' => 'uploadedimage',
$this->open( $filename );
$this->loadHeader();
}
-
+
/**
* The file must be seekable, such as local filesystem.
* Remote URLs probably won't work.
$this->resourceLength = 0;
$this->handle = fopen( $filename, 'rb' );
}
-
+
/**
* Does this appear to be a valid MacBinary archive?
* @return bool
function isValid() {
return $this->valid;
}
-
+
/**
* Get length of data fork
* @return int
function dataForkLength() {
return $this->dataLength;
}
-
+
/**
* Copy the data fork to an external file or resource.
* @param resource $destination
if( !$this->isValid() ) {
return false;
}
-
+
// Data fork appears immediately after header
fseek( $this->handle, 128 );
return $this->copyBytesTo( $destination, $this->dataLength );
}
-
+
/**
*
*/
function close() {
fclose( $this->handle );
}
-
+
// --------------------------------------------------------------
-
+
/**
* Check if the given file appears to be MacBinary-encoded,
* as Internet Explorer on Mac OS may provide for unknown types.
*/
function loadHeader() {
$fname = 'MacBinary::loadHeader';
-
+
fseek( $this->handle, 0 );
$head = fread( $this->handle, 128 );
$this->hexdump( $head );
-
+
if( strlen( $head ) < 128 ) {
wfDebug( "$fname: couldn't read full MacBinary header\n" );
return false;
}
-
+
if( $head{0} != "\x00" || $head{74} != "\x00" ) {
wfDebug( "$fname: header bytes 0 and 74 not null\n" );
return false;
}
-
+
$signature = substr( $head, 102, 4 );
$a = unpack( "ncrc", substr( $head, 124, 2 ) );
$storedCRC = $a['crc'];
return false;
}
}
-
+
$nameLength = ord( $head{1} );
if( $nameLength < 1 || $nameLength > 63 ) {
wfDebug( "$fname: invalid filename size $nameLength\n" );
return false;
}
$this->filename = substr( $head, 2, $nameLength );
-
+
$forks = unpack( "Ndata/Nresource", substr( $head, 83, 8 ) );
$this->dataLength = $forks['data'];
$this->resourceLength = $forks['resource'];
$maxForkLength = 0x7fffff;
-
+
if( $this->dataLength < 0 || $this->dataLength > $maxForkLength ) {
wfDebug( "$fname: invalid data fork length $this->dataLength\n" );
return false;
}
-
+
if( $this->resourceLength < 0 || $this->resourceLength > $maxForkLength ) {
wfDebug( "$fname: invalid resource fork size $this->resourceLength\n" );
return false;
}
-
+
wfDebug( "$fname: appears to be MacBinary $this->version, data length $this->dataLength\n" );
$this->valid = true;
return true;
}
-
+
/**
* Calculate a 16-bit CRC value as for MacBinary headers.
* Adapted from perl5 Convert::BinHex by Eryq,
}
return $crc;
}
-
+
/**
* @param resource $destination
* @param int $bytesToCopy
fwrite( $destination, $buffer );
}
}
-
+
/**
* Hex dump of the header for debugging
* @access private
function hexdump( $data ) {
global $wgDebugLogFile;
if( !$wgDebugLogFile ) return;
-
+
$width = 16;
$at = 0;
for( $remaining = strlen( $data ); $remaining > 0; $remaining -= $width ) {
*/
var $mId, $mSynonyms, $mCaseSensitive, $mRegex;
var $mRegexStart, $mBaseRegex, $mVariableRegex;
- var $mModified;
+ var $mModified;
/**#@-*/
function MagicWord($id = 0, $syn = '', $cs = false) {
*/
function &get( $id ) {
global $wgMagicWords;
-
+
if ( !is_array( $wgMagicWords ) ) {
wfDebugDieBacktrace( "Incorrect initialisation order, \$wgMagicWords does not exist\n" );
}
}
return $wgMagicWords[$id];
}
-
+
# Initialises this object with an ID
function load( $id ) {
- global $wgContLang;
+ global $wgContLang;
$this->mId = $id;
$wgContLang->getMagic( $this );
}
-
+
/**
* Preliminary initialisation
* @access private
$this->mVariableStartToEndRegex = str_replace( "\\$1", "(.*?)",
"/^(?:{$this->mBaseRegex})$/{$case}" );
}
-
+
/**
* Gets a regex representing matching the word
*/
}
return $this->mBaseRegex;
}
-
+
/**
* Returns true if the text contains the word
* @return bool
$wgMagicFound = false;
$text = preg_replace_callback( $this->getRegexStart(), 'pregRemoveAndRecord', $text );
return $wgMagicFound;
- }
+ }
/**
var $html = '';
var $mathml = '';
var $conservativeness = 0;
-
+
function MathRenderer( $tex ) {
$this->tex = $tex;
}
-
+
function setOutputMode( $mode ) {
$this->mode = $mode;
}
global $wgTmpDirectory, $wgInputEncoding;
global $wgTexvc;
$fname = 'MathRenderer::render';
-
+
if( $this->mode == MW_MATH_SOURCE ) {
# No need to render or parse anything more!
return ('$ '.htmlspecialchars( $this->tex ).' $');
}
-
+
if( !$this->_recall() ) {
# Ensure that the temp and output directories are available before continuing...
if( !file_exists( $wgTmpDirectory ) ) {
} elseif( !is_dir( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) {
return $this->_error( 'math_bad_tmpdir' );
}
-
+
if( function_exists( 'is_executable' ) && !is_executable( $wgTexvc ) ) {
return $this->_error( 'math_notexvc' );
}
escapeshellarg( $wgTmpDirectory ).' '.
escapeshellarg( $this->tex ).' '.
escapeshellarg( $wgInputEncoding );
-
+
if ( wfIsWindows() ) {
# Invoke it within cygwin sh, because texvc expects sh features in its default shell
$cmd = 'sh -c ' . wfEscapeShellArg( $cmd );
wfDebug( "TeX: $cmd\n" );
$contents = `$cmd`;
wfDebug( "TeX output:\n $contents\n---\n" );
-
+
if (strlen($contents) == 0) {
return $this->_error( 'math_unknown_error' );
}
-
+
$retval = substr ($contents, 0, 1);
if (($retval == 'C') || ($retval == 'M') || ($retval == 'L')) {
if ($retval == 'C')
else
$this->conservativeness = 0;
$outdata = substr ($contents, 33);
-
+
$i = strpos($outdata, "\000");
-
+
$this->html = substr($outdata, 0, $i);
$this->mathml = substr($outdata, $i+1);
} else if (($retval == 'c') || ($retval == 'm') || ($retval == 'l')) {
default: return $this->_error( 'math_unknown_error', $errbit );
}
}
-
+
$this->hash = substr ($contents, 1, 32);
if (!preg_match("/^[a-f0-9]{32}$/", $this->hash)) {
return $this->_error( 'math_unknown_error' );
}
-
+
if( !file_exists( "$wgTmpDirectory/{$this->hash}.png" ) ) {
return $this->_error( 'math_image_error' );
}
-
+
$hashpath = $this->_getHashPath();
if( !file_exists( $hashpath ) ) {
if( !@wfMkdirParents( $hashpath, 0755 ) ) {
} elseif( !is_dir( $hashpath ) || !is_writable( $hashpath ) ) {
return $this->_error( 'math_bad_output' );
}
-
+
if( !rename( "$wgTmpDirectory/{$this->hash}.png", "$hashpath/{$this->hash}.png" ) ) {
return $this->_error( 'math_output_error' );
}
-
+
# Now save it back to the DB:
if ( !wfReadOnly() ) {
$outmd5_sql = pack('H32', $this->hash);
-
+
$md5_sql = pack('H32', $this->md5); # Binary packed, not hex
-
+
$dbw =& wfGetDB( DB_MASTER );
$dbw->replace( 'math', array( 'math_inputhash' ),
array(
), $fname, array( 'IGNORE' )
);
}
-
+
}
-
+
return $this->_doRender();
}
-
+
function _error( $msg, $append = '' ) {
$mf = htmlspecialchars( wfMsg( 'math_failure' ) );
$munk = htmlspecialchars( wfMsg( 'math_unknown_error' ) );
$source = htmlspecialchars($this->tex);
return "<strong class='error'>$mf ($errmsg$append): $source</strong>\n";
}
-
+
function _recall() {
global $wgMathDirectory;
$fname = 'MathRenderer::_recall';
# Tailing 0x20s can get dropped by the database, add it back on if necessary:
$xhash = unpack( 'H32md5', $rpage->math_outputhash . " " );
$this->hash = $xhash ['md5'];
-
+
$this->conservativeness = $rpage->math_html_conservativeness;
$this->html = $rpage->math_html;
$this->mathml = $rpage->math_mathml;
-
+
if( file_exists( $this->_getHashPath() . "/{$this->hash}.png" ) ) {
return true;
}
$hashpath . "/{$this->hash}.png" );
}
}
-
+
}
-
+
# Missing from the database and/or the render cache
return false;
}
if ( $wgLocalMessageCache === false ) {
return;
}
-
+
$filename = "$wgLocalMessageCache/messages-$wgDBname";
wfSuppressWarnings();
if ( $wgLocalMessageCache === false ) {
return;
}
-
+
$filename = "$wgLocalMessageCache/messages-$wgDBname";
$oldUmask = umask( 0 );
wfMkdirParents( $wgLocalMessageCache, 0777 );
*/
function loadFromDB() {
global $wgAllMessagesEn, $wgLang;
-
+
$fname = 'MessageCache::loadFromDB';
$dbr =& wfGetDB( DB_SLAVE );
if ( !$dbr ) {
if ( !array_key_exists( $uckey, $this->mCache ) ) {
$this->mCache[$uckey] = false;
}
- }
+ }
$dbr->freeResult( $res );
}
if ( is_array( $this->mCache ) ) {
$this->mCache[$title] = $text;
$this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry );
-
+
# Save to local cache
if ( $wgLocalMessageCache !== false ) {
$serialized = serialize( $this->mCache );
* @package MediaWiki
*/
class MimeMagic {
-
+
/**
* Mapping of media types to arrays of mime types.
* This is used by findMediaType and getMediaType, respectively
*/
var $mMediaTypes= NULL;
-
+
/** Map of mime type aliases
*/
var $mMimeTypeAliases= NULL;
-
+
/** map of mime types to file extensions (as a space seprarated list)
*/
var $mMimeToExt= NULL;
-
+
/** map of file extensions types to mime types (as a space seprarated list)
*/
var $mExtToMime= NULL;
-
+
/** Initializes the MimeMagic object. This is called by wfGetMimeMagic when instantiation
* the global MimeMagic singleton object.
*
/*
* --- load mime.types ---
*/
-
+
global $wgMimeTypeFile;
-
+
$types= MM_WELL_KNOWN_MIME_TYPES;
-
+
if ($wgMimeTypeFile) {
if (is_file($wgMimeTypeFile) and is_readable($wgMimeTypeFile)) {
wfDebug("MimeMagic::MimeMagic: loading mime types from $wgMimeTypeFile\n");
-
+
$types.= "\n";
$types.= file_get_contents($wgMimeTypeFile);
}
else wfDebug("MimeMagic::MimeMagic: can't load mime types from $wgMimeTypeFile\n");
}
else wfDebug("MimeMagic::MimeMagic: no mime types file defined, using build-ins only.\n");
-
+
$types= str_replace(array("\r\n","\n\r","\n\n","\r\r","\r"),"\n",$types);
$types= str_replace("\t"," ",$types);
-
+
$this->mMimeToExt= array();
$this->mToMime= array();
-
+
$lines= explode("\n",$types);
foreach ($lines as $s) {
$s= trim($s);
if (empty($s)) continue;
if (strpos($s,'#')===0) continue;
-
+
$s= strtolower($s);
$i= strpos($s,' ');
-
+
if ($i===false) continue;
-
+
#print "processing MIME line $s<br>";
-
+
$mime= substr($s,0,$i);
$ext= trim(substr($s,$i+1));
-
+
if (empty($ext)) continue;
-
+
if (@$this->mMimeToExt[$mime]) $this->mMimeToExt[$mime] .= ' '.$ext;
else $this->mMimeToExt[$mime]= $ext;
-
+
$extensions= explode(' ',$ext);
-
+
foreach ($extensions as $e) {
$e= trim($e);
if (empty($e)) continue;
-
+
if (@$this->mExtToMime[$e]) $this->mExtToMime[$e] .= ' '.$mime;
else $this->mExtToMime[$e]= $mime;
}
}
-
+
/*
* --- load mime.info ---
*/
-
+
global $wgMimeInfoFile;
-
+
$info= MM_WELL_KNOWN_MIME_INFO;
-
+
if ($wgMimeInfoFile) {
if (is_file($wgMimeInfoFile) and is_readable($wgMimeInfoFile)) {
wfDebug("MimeMagic::MimeMagic: loading mime info from $wgMimeInfoFile\n");
-
+
$info.= "\n";
$info.= file_get_contents($wgMimeInfoFile);
}
else wfDebug("MimeMagic::MimeMagic: can't load mime info from $wgMimeInfoFile\n");
}
else wfDebug("MimeMagic::MimeMagic: no mime info file defined, using build-ins only.\n");
-
+
$info= str_replace(array("\r\n","\n\r","\n\n","\r\r","\r"),"\n",$info);
$info= str_replace("\t"," ",$info);
-
+
$this->mMimeTypeAliases= array();
$this->mMediaTypes= array();
-
+
$lines= explode("\n",$info);
foreach ($lines as $s) {
$s= trim($s);
if (empty($s)) continue;
if (strpos($s,'#')===0) continue;
-
+
$s= strtolower($s);
$i= strpos($s,' ');
-
+
if ($i===false) continue;
-
+
#print "processing MIME INFO line $s<br>";
-
+
$match= array();
if (preg_match('!\[\s*(\w+)\s*\]!',$s,$match)) {
$s= preg_replace('!\[\s*(\w+)\s*\]!','',$s);
$mtype= trim(strtoupper($match[1]));
}
else $mtype= MEDIATYPE_UNKNOWN;
-
+
$m= explode(' ',$s);
-
+
if (!isset($this->mMediaTypes[$mtype])) $this->mMediaTypes[$mtype]= array();
-
+
foreach ($m as $mime) {
$mime= trim($mime);
if (empty($mime)) continue;
-
+
$this->mMediaTypes[$mtype][]= $mime;
}
-
+
if (sizeof($m)>1) {
$main= $m[0];
for ($i=1; $i<sizeof($m); $i+= 1) {
}
}
}
-
+
}
-
+
/** returns a list of file extensions for a given mime type
* as a space separated string.
*/
function getExtensionsForType($mime) {
$mime= strtolower($mime);
-
+
$r= @$this->mMimeToExt[$mime];
-
+
if (@!$r and isset($this->mMimeTypeAliases[$mime])) {
$mime= $this->mMimeTypeAliases[$mime];
$r= @$this->mMimeToExt[$mime];
}
-
+
return $r;
}
-
+
/** returns a list of mime types for a given file extension
* as a space separated string.
*/
function getTypesForExtension($ext) {
$ext= strtolower($ext);
-
+
$r= @$this->mExtToMime[$ext];
return $r;
}
-
+
/** returns a single mime type for a given file extension.
* This is always the first type from the list returned by getTypesForExtension($ext).
*/
function guessTypesForExtension($ext) {
$m= $this->getTypesForExtension( $ext );
if( is_null($m) ) return NULL;
-
+
$m= trim( $m );
$m= preg_replace('/\s.*$/','',$m);
-
+
return $m;
}
-
-
+
+
/** tests if the extension matches the given mime type.
* returns true if a match was found, NULL if the mime type is unknown,
* and false if the mime type is known but no matches where found.
*/
function isMatchingExtension($extension,$mime) {
$ext= $this->getExtensionsForType($mime);
-
+
if (!$ext) {
return NULL; //unknown
}
-
+
$ext= explode(' ',$ext);
-
+
$extension= strtolower($extension);
if (in_array($extension,$ext)) {
return true;
}
-
+
return false;
}
-
+
/** returns true if the mime type is known to represent
* an image format supported by the PHP GD library.
*/
'image/x-photoshop',
'application/x-shockwave-flash',
);
-
+
return in_array( $mime, $types );
}
-
+
/**
* Returns true if the extension represents a type which can
* be reliably detected from its content. Use this to determine
);
return in_array( strtolower( $extension ), $types );
}
-
-
+
+
/** mime type detection. This uses detectMimeType to detect the mim type of the file,
* but applies additional checks to determine some well known file formats that may be missed
* or misinterpreter by the default mime detection (namely xml based formats like XHTML or SVG).
function guessMimeType( $file, $useExt=true ) {
$fname = 'MimeMagic::guessMimeType';
$mime= $this->detectMimeType($file,$useExt);
-
+
// Read a chunk of the file
$f = fopen( $file, "rt" );
if( !$f ) return "unknown/unknown";
$head = fread( $f, 1024 );
fclose( $f );
-
+
$sub4 = substr( $head, 0, 4 );
if ( $sub4 == "\x01\x00\x09\x00" || $sub4 == "\xd7\xcd\xc6\x9a" ) {
// WMF kill kill kill
// The former of the above two checks is theoretically prone to false positives
$mime = "application/x-msmetafile";
}
-
+
if (strpos($mime,"text/")===0 || $mime==="application/xml") {
-
+
$xml_type= NULL;
$script_type= NULL;
-
+
/*
* look for XML formats (XHTML and SVG)
*/
$mime==="text/html" ||
$mime==="text/xml" ||
$mime==="application/xml") {
-
+
if (substr($head,0,5)=="<?xml") $xml_type= "ASCII";
elseif (substr($head,0,8)=="\xef\xbb\xbf<?xml") $xml_type= "UTF-8";
elseif (substr($head,0,10)=="\xfe\xff\x00<\x00?\x00x\x00m\x00l") $xml_type= "UTF-16BE";
elseif (substr($head,0,10)=="\xff\xfe<\x00?\x00x\x00m\x00l\x00") $xml_type= "UTF-16LE";
-
+
if ($xml_type) {
if ($xml_type!=="UTF-8" && $xml_type!=="ASCII") $head= iconv($xml_type,"ASCII//IGNORE",$head);
-
+
$match= array();
$doctype= "";
$tag= "";
-
+
if (preg_match('%<!DOCTYPE\s+[\w-]+\s+PUBLIC\s+["'."'".'"](.*?)["'."'".'"].*>%sim',$head,$match)) $doctype= $match[1];
if (preg_match('%<(\w+).*>%sim',$head,$match)) $tag= $match[1];
-
+
#print "<br>ANALYSING $file ($mime): doctype= $doctype; tag= $tag<br>";
-
+
if (strpos($doctype,"-//W3C//DTD SVG")===0) $mime= "image/svg";
elseif ($tag==="svg") $mime= "image/svg";
elseif (strpos($doctype,"-//W3C//DTD XHTML")===0) $mime= "text/html";
elseif ($tag==="html") $mime= "text/html";
-
+
$test_more= false;
}
}
-
+
/*
* look for shell scripts
*/
if (!$xml_type) {
$script_type= NULL;
-
+
#detect by shebang
if (substr($head,0,2)=="#!") $script_type= "ASCII";
elseif (substr($head,0,5)=="\xef\xbb\xbf#!") $script_type= "UTF-8";
elseif (substr($head,0,7)=="\xfe\xff\x00#\x00!") $script_type= "UTF-16BE";
elseif (substr($head,0,7)=="\xff\xfe#\x00!") $script_type= "UTF-16LE";
-
+
if ($script_type) {
if ($script_type!=="UTF-8" && $script_type!=="ASCII") $head= iconv($script_type,"ASCII//IGNORE",$head);
-
+
$match= array();
$prog= "";
-
+
if (preg_match('%/?([^\s]+/)(w+)%sim',$head,$match)) $script= $match[2];
-
+
$mime= "application/x-$prog";
}
}
-
+
/*
* look for PHP
*/
if( !$xml_type && !$script_type ) {
-
+
if( ( strpos( $head, '<?php' ) !== false ) ||
( strpos( $head, '<? ' ) !== false ) ||
( strpos( $head, "<?\n" ) !== false ) ||
( strpos( $head, "<?\t" ) !== false ) ||
( strpos( $head, "<?=" ) !== false ) ||
-
+
( strpos( $head, "<\x00?\x00p\x00h\x00p" ) !== false ) ||
( strpos( $head, "<\x00?\x00 " ) !== false ) ||
( strpos( $head, "<\x00?\x00\n" ) !== false ) ||
( strpos( $head, "<\x00?\x00\t" ) !== false ) ||
( strpos( $head, "<\x00?\x00=" ) !== false ) ) {
-
+
$mime= "application/x-php";
}
}
-
+
}
-
+
if (isset($this->mMimeTypeAliases[$mime])) $mime= $this->mMimeTypeAliases[$mime];
-
+
wfDebug("$fname: final mime type of $file: $mime\n");
return $mime;
}
-
+
/** Internal mime type detection, please use guessMimeType() for application code instead.
* Detection is done using an external program, if $wgMimeDetectorCommand is set.
* Otherwise, the fileinfo extension and mime_content_type are tried (in this order), if they are available.
*/
function detectMimeType( $file, $useExt=true ) {
$fname = 'MimeMagic::detectMimeType';
-
+
global $wgMimeDetectorCommand;
-
+
$m= NULL;
if ($wgMimeDetectorCommand) {
$fn= wfEscapeShellArg($file);
$m= `$wgMimeDetectorCommand $fn`;
}
else if (function_exists("finfo_open") && function_exists("finfo_file")) {
-
+
# This required the fileinfo extension by PECL,
# see http://pecl.php.net/package/fileinfo
# This must be compiled into PHP
#
# If you may need to load the fileinfo extension at runtime, set
# $wgLoadFileinfoExtension in LocalSettings.php
-
+
$mime_magic_resource = finfo_open(FILEINFO_MIME); /* return mime type ala mimetype extension */
-
+
if ($mime_magic_resource) {
$m= finfo_file($mime_magic_resource, $file);
-
+
finfo_close($mime_magic_resource);
}
else wfDebug("$fname: finfo_open failed on ".FILEINFO_MIME."!\n");
}
else if (function_exists("mime_content_type")) {
-
+
# NOTE: this function is available since PHP 4.3.0, but only if
# PHP was compiled with --with-mime-magic or, before 4.3.2, with --enable-mime-magic.
#
#
# Also note that this has been DEPRECATED in favor of the fileinfo extension by PECL, see above.
# see http://www.php.net/manual/en/ref.mime-magic.php for details.
-
+
$m= mime_content_type($file);
}
else wfDebug("$fname: no magic mime detector found!\n");
-
+
if ($m) {
#normalize
$m= preg_replace('![;, ].*$!','',$m); #strip charset, etc
$m= trim($m);
$m= strtolower($m);
-
+
if (strpos($m,'unknown')!==false) $m= NULL;
else {
wfDebug("$fname: magic mime type of $file: $m\n");
return $m;
}
}
-
+
#if still not known, use getimagesize to find out the type of image
#TODO: skip things that do not have a well-known image extension? Would that be safe?
wfSuppressWarnings();
$gis = getimagesize( $file );
wfRestoreWarnings();
-
+
$notAnImage= false;
-
+
if ($gis && is_array($gis) && $gis[2]) {
switch ($gis[2]) {
case IMAGETYPE_GIF: $m= "image/gif"; break;
case IMAGETYPE_WBMP: $m= "image/vnd.wap.wbmp"; break;
case IMAGETYPE_XBM: $m= "image/x-xbitmap"; break;
}
-
+
if ($m) {
wfDebug("$fname: image mime type of $file: $m\n");
return $m;
}
else $notAnImage= true;
}
-
+
#if desired, look at extension as a fallback.
if ($useExt) {
$i = strrpos( $file, '.' );
$e= strtolower( $i ? substr( $file, $i + 1 ) : '' );
-
+
$m= $this->guessTypesForExtension($e);
-
+
#TODO: if $notAnImage is set, do not trust the file extension if
# the results is one of the image types that should have been recognized
# by getimagesize
-
+
if ($m) {
wfDebug("$fname: extension mime type of $file: $m\n");
return $m;
}
}
-
- #unknown type
+
+ #unknown type
wfDebug("$fname: failed to guess mime type for $file!\n");
return "unknown/unknown";
}
-
+
/**
* Determine the media type code for a file, using its mime type, name and possibly
* its contents.
*/
function getMediaType($path=NULL,$mime=NULL) {
if( !$mime && !$path ) return MEDIATYPE_UNKNOWN;
-
+
#if mime type is unknown, guess it
if( !$mime ) $mime= $this->guessMimeType($path,false);
#special code for ogg - detect if it's video (theora),
#else label it as sound.
if( $mime=="application/ogg" && file_exists($path) ) {
-
+
// Read a chunk of the file
$f = fopen( $path, "rt" );
if( !$f ) return MEDIATYPE_UNKNOWN;
$head = fread( $f, 256 );
fclose( $f );
-
+
$head= strtolower( $head );
-
+
#This is an UGLY HACK, file should be parsed correctly
if( strpos($head,'theora')!==false ) return MEDIATYPE_VIDEO;
elseif( strpos($head,'vorbis')!==false ) return MEDIATYPE_AUDIO;
elseif( strpos($head,'flac')!==false ) return MEDIATYPE_AUDIO;
elseif( strpos($head,'speex')!==false ) return MEDIATYPE_AUDIO;
else return MEDIATYPE_MULTIMEDIA;
- }
-
+ }
+
#check for entry for full mime type
if( $mime ) {
$type= $this->findMediaType($mime);
if( $type!==MEDIATYPE_UNKNOWN ) return $type;
}
-
+
#check for entry for file extension
$e= NULL;
if( $path ) {
$i = strrpos( $path, '.' );
$e= strtolower( $i ? substr( $path, $i + 1 ) : '' );
-
+
#TODO: look at multi-extension if this fails, parse from full path
-
+
$type= $this->findMediaType('.'.$e);
if( $type!==MEDIATYPE_UNKNOWN ) return $type;
}
-
+
#check major mime type
if( $mime ) {
$i= strpos($mime,'/');
if( $type!==MEDIATYPE_UNKNOWN ) return $type;
}
}
-
+
if( !$type ) $type= MEDIATYPE_UNKNOWN;
-
+
return $type;
}
-
+
/** returns a media code matching the given mime type or file extension.
* File extensions are represented by a string starting with a dot (.) to
* distinguish them from mime types.
* @access private
*/
function findMediaType($extMime) {
-
+
if (strpos($extMime,'.')===0) { #if it's an extension, look up the mime types
$m= $this->getTypesForExtension(substr($extMime,1));
if (!$m) return MEDIATYPE_UNKNOWN;
-
+
$m= explode(' ',$m);
}
else { #normalize mime type
if (isset($this->mMimeTypeAliases[$extMime])) {
$extMime= $this->mMimeTypeAliases[$extMime];
}
-
+
$m= array($extMime);
}
-
+
foreach ($m as $mime) {
foreach ($this->mMediaTypes as $type => $codes) {
if (in_array($mime,$codes,true)) return $type;
}
}
-
+
return MEDIATYPE_UNKNOWN;
}
}
function addHeader( $name, $val ) { array_push( $this->mHeaders, $name.': '.$val ) ; }
function redirect( $url, $responsecode = '302' ) { $this->mRedirect = $url; $this->mRedirectCode = $responsecode; }
function setStatusCode( $statusCode ) { $this->mStatusCode = $statusCode; }
-
+
# To add an http-equiv meta tag, precede the name with "http:"
function addMeta( $name, $val ) { array_push( $this->mMetatags, array( $name, $val ) ); }
function addKeyword( $text ) { array_push( $this->mKeywords, $text ); }
$name .= ' - '.$taction;
}
}
-
+
$this->setHTMLTitle( wfMsg( 'pagetitle', $name ) );
}
function getHTMLTitle() { return $this->mHTMLtitle; }
function ParserOptions( $options = null ) {
return wfSetVar( $this->mParserOptions, $options );
}
-
+
/**
* Set the revision ID which will be seen by the wiki text parser
* for things such as embedded {{REVISIONID}} variable use.
$this->enableClientCache( false );
}
}
-
+
function addParserOutput( &$parserOutput ) {
$this->addParserOutputNoText( $parserOutput );
$this->addHTML( $parserOutput->getText() );
$time = wfReportTime();
return $time;
}
-
+
/**
* Produce a "user is blocked" page
*/
}
$ret .= "<meta $a=\"{$tag[0]}\" content=\"{$tag[1]}\" />\n";
}
-
+
$p = $this->mRobotpolicy;
if( $p !== '' && $p != 'index,follow' ) {
// http://www.robotstxt.org/wc/meta-user.html
$s = wfMsgWikiHtml( 'histlegend' );
$s .= '<form action="' . $wgTitle->escapeLocalURL( '-' ) . '" method="get">';
$prefixedkey = htmlspecialchars($wgTitle->getPrefixedDbKey());
-
+
// The following line is SUPPOSED to have double-quotes around the
// $prefixedkey variable, because htmlspecialchars() doesn't escape
// single-quotes.
// consideration and cooperation.
//
$s .= "<input type='hidden' name='title' value=\"{$prefixedkey}\" />\n";
-
+
$s .= $this->submitButton();
$s .= '<ul id="pagehistory">' . "\n";
return $s;
* First pass--just handle <nowiki> sections, pass the rest off
* to internalParse() which does all the real work.
*/
-
+
global $wgUseTidy, $wgContLang;
$fname = 'Parser::parse';
wfProfileIn( $fname );
wfRunHooks( 'ParserBeforeTidy', array( &$this, &$text ) );
$text = Sanitizer::normalizeCharReferences( $text );
-
+
if ($wgUseTidy) {
$text = Parser::tidy($text);
}
if ( !is_array( $state ) ) {
return $text;
}
-
+
# Must expand in reverse order, otherwise nested tags will be corrupted
foreach( array_reverse( $state, true ) as $tag => $contentDict ) {
if( $tag != 'nowiki' && $tag != 'html' ) {
$fc = substr ( $x , 0 , 1 ) ;
if ( preg_match( '/^(:*)\{\|(.*)$/', $x, $matches ) ) {
$indent_level = strlen( $matches[1] );
-
+
$attributes = $this->unstripForHTML( $matches[2] );
$t[$k] = str_repeat( '<dl><dd>', $indent_level ) .
}
return $retVal;
}
-
+
/**
* Render a forced-blue link inline; protect against double expansion of
* URLs if we're in a mode that prepends full URL prefixes to internal links.
$link = $sk->makeKnownLinkObj( $nt, $text, $query, $inside, $prefix );
return $this->armorLinks( $link ) . $trail;
}
-
+
/**
* Insert a NOPARSE hacky thing into any inline links in a chunk that's
* going to go through further parsing steps before inline URL expansion.
if ($lastOpeningBrace >= 0) {
$pos = strpos ($text, $openingBraceStack[$lastOpeningBrace]['braceEnd'], $i);
-
+
if (false !== $pos && (-1 == $nextPos || $pos < $nextPos)){
$rule = null;
$nextPos = $pos;
}
$pos = strpos ($text, '|', $i);
-
+
if (false !== $pos && (-1 == $nextPos || $pos < $nextPos)){
$rule = null;
$nextPos = $pos;
$matchingCallback = $fn;
}
}
-
+
if ($matchingCount == 0) {
$i += $count - 1;
continue;
$pieceStart = $openingBraceStack[$lastOpeningBrace]['startAt'] - $matchingCount;
$pieceEnd = $i + $matchingCount;
-
+
if( is_callable( $matchingCallback ) ) {
$cbArgs = array (
'text' => substr($text, $pieceStart, $pieceEnd - $pieceStart),
}
else
$openingBraceStack[$lastOpeningBrace]['parts'][] = substr($text, $openingBraceStack[$lastOpeningBrace]['partStart'], $i - $openingBraceStack[$lastOpeningBrace]['partStart']);
-
+
$openingBraceStack[$lastOpeningBrace]['partStart'] = $i + 1;
}
}
$mwLocalE =& MagicWord::get( MAG_LOCALURLE );
$mwFull =& MagicWord::get( MAG_FULLURL );
$mwFullE =& MagicWord::get( MAG_FULLURLE );
-
+
if ( $mwLocal->matchStartAndRemove( $part1 ) ) {
$func = 'getLocalURL';
# Remove <noinclude> sections and <includeonly> tags
$text = preg_replace( '/<noinclude>.*?<\/noinclude>/s', '', $text );
$text = strtr( $text, array( '<includeonly>' => '' , '</includeonly>' => '' ) );
-
+
if( $this->mOutputType == OT_HTML ) {
# Strip <nowiki>, <pre>, etc.
$text = $this->strip( $text, $this->mStripState );
return $text;
}
}
-
+
/**
* Translude an interwiki link.
*/
global $wgLegalTitleChars;
$tc = "[$wgLegalTitleChars]";
$np = str_replace( array( '(', ')' ), array( '', '' ), $tc ); # No parens
-
+
$namespacechar = '[ _0-9A-Za-z\x80-\xff]'; # Namespaces can use non-ascii!
$conpat = "/^({$np}+) \\(({$tc}+)\\)$/";
return $text;
}
-
+
/**
* Fetch the user's signature text, if any, and normalize to
* validated, ready-to-insert wikitext.
if ( '' == $nick ) {
$nick = $name;
}
-
+
if( $user->getOption( 'fancysig' ) ) {
// A wikitext signature.
$valid = $this->validateSig( $nick );
return $nick;
}
}
-
+
// Plain text linking to the user's homepage
global $wgContLang;
$page = $user->getUserPage();
wfEscapeWikIText( $nick ) .
"]]";
}
-
+
/**
* We want to enforce two rules on wikitext sigs here:
* 1) Expand any templates at save time (forced subst:)
function setHook( $tag, $callback ) {
$oldVal = @$this->mTagHooks[$tag];
$this->mTagHooks[$tag] = $callback;
-
+
return $oldVal;
}
function disableCache() {
$this->mOutput->mCacheTime = -1;
}
-
+
/**
* Callback from the Sanitizer for expanding items found in HTML attribute
* values, so they can be safely tested and escaped.
$text = $this->unstripForHTML( $text );
return $text;
}
-
+
function unstripForHTML( $text ) {
$text = $this->unstrip( $text, $this->mStripState );
$text = $this->unstripNoWiki( $text, $this->mStripState );
function addTemplate( $title, $id ) {
$ns = $title->getNamespace();
- $dbk = $title->getDBkey();
+ $dbk = $title->getDBkey();
if ( !isset( $this->mTemplates[$ns] ) ) {
$this->mTemplates[$ns] = array();
}
}
return $instance;
}
-
+
/**
* Setup a cache pathway with a given back-end storage mechanism.
* May be a memcached client or a BagOStuff derivative.
# Fix allowed HTML
$old_n = $n;
$ext = strtoupper($this->attrs['NAME']);
-
+
switch($ext) {
case 'B':
case 'STRONG':
# Comments are parsed out
$ret .= '';
break;
-
+
# Links
case 'LINK':
case 'LINKOPTION':
$ret .= $this->sub_makeXHTML($parser);
break;
-
+
case 'TEMPLATE':
$parts = $this->sub_makeXHTML($parser);
$parts = explode('|', $parts);
$ret .= $parser->mCurrentTemplateOptions["{$x}"];
break;
- # Internal use, not generated by wiki2xml parser
+ # Internal use, not generated by wiki2xml parser
case 'IGNORE':
$ret .= $this->sub_makeXHTML($parser);
$ret .= $this->sub_makeXHTML($parser, $type);
$parser->mListType = $oldtype;
break;
-
+
# Something else entirely
default:
$ret .= '<'.$n.'>';
$this->debug( "$message\n" );
}
$entry =& $this->mCollated[$functionname];
-
+
$elapsedcpu = $this->getCpuTime() - $octime;
$elapsedreal = $this->getTime() - $ortime;
$entry['real'] += $elapsedreal;
$entry['real_sq'] += $elapsedreal*$elapsedreal;
$entry['count']++;
-
+
}
}
- function getFunctionReport() {
+ function getFunctionReport() {
/* Implement in output subclasses */
}
list($a,$b)=explode(" ",$time);
return (float)($a+$b);
}
-
+
function debug( $s ) {
if (function_exists( 'wfDebug' ) ) {
wfDebug( $s );
global $wgUDPProfilerHost;
global $wgUDPProfilerPort;
global $wgDBname;
-
+
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$plength=0;
$packet="";
class Profiler {
var $mStack = array (), $mWorkStack = array (), $mCollated = array ();
var $mCalls = array (), $mTotals = array ();
-
+
function Profiler()
{
// Push an entry for the pre-profile setup time onto the stack
} else {
$this->profileIn( '-total' );
}
-
+
}
function profileIn($functionname) {
trim( sprintf( "%7.3f", $delta * 1000.0 ) ),
$space, $fname );
}
-
+
function micro2Float( $micro ) {
list( $whole, $fractional ) = explode( ' ', $micro );
return (float)$whole + (float)$fractional;
}
-
+
function microDelta( $start, $end ) {
return $this->micro2Float( $end ) -
$this->micro2Float( $start );
return $ru['ru_utime.tv_sec'].' '.$ru['ru_utime.tv_usec'] / 1e6;
}
- function getFunctionReport() {
+ function getFunctionReport() {
$width = 140;
$nameWidth = $width - 65;
$format = "%-{$nameWidth}s %6d %13.3f %13.3f %13.3f%% %9d (%13.3f -%13.3f) [%d]\n";
class ProtectionForm {
var $mRestrictions = array();
var $mReason = '';
-
+
function ProtectionForm( &$article ) {
global $wgRequest, $wgUser;
global $wgRestrictionTypes, $wgRestrictionLevels;
$this->mArticle =& $article;
$this->mTitle =& $article->mTitle;
-
+
if( $this->mTitle ) {
foreach( $wgRestrictionTypes as $action ) {
// Fixme: this form currently requires individual selections,
$this->mRestrictions[$action] = implode( '', $this->mTitle->getRestrictions( $action ) );
}
}
-
+
// The form will be available in read-only to show levels.
$this->disabled = !$wgUser->isAllowed( 'protect' ) || wfReadOnly() || $wgUser->isBlocked();
$this->disabledAttrib = $this->disabled
? array( 'disabled' => 'disabled' )
: array();
-
+
if( $wgRequest->wasPosted() ) {
$this->mReason = $wgRequest->getText( 'mwProtect-reason' );
foreach( $wgRestrictionTypes as $action ) {
}
}
}
-
+
function show() {
global $wgOut;
-
+
$wgOut->setRobotpolicy( 'noindex,nofollow' );
if( is_null( $this->mTitle ) ||
$wgOut->fatalError( wfMsg( 'badarticleerror' ) );
return;
}
-
+
if( $this->save() ) {
$wgOut->redirect( $this->mTitle->getFullUrl() );
return;
}
-
+
$wgOut->setPageTitle( wfMsg( 'confirmprotect' ) );
$wgOut->setSubtitle( wfMsg( 'protectsub', $this->mTitle->getPrefixedText() ) );
-
+
$wgOut->addWikiText(
wfMsg( $this->disabled ? "protect-viewtext" : "protect-text",
$this->mTitle->getPrefixedText() ) );
-
+
$wgOut->addHTML( $this->buildForm() );
-
+
$this->showLogExtract( $wgOut );
}
-
+
function save() {
global $wgRequest, $wgUser;
if( !$wgRequest->wasPosted() ) {
return false;
}
-
+
if( $this->disabled ) {
return false;
}
-
+
$token = $wgRequest->getVal( 'wpEditToken' );
if( !$wgUser->matchEditToken( $token ) ) {
$wgOut->fatalError( wfMsg( 'sessionfailure' ) );
return false;
}
-
+
$ok = $this->mArticle->updateRestrictions( $this->mRestrictions, $this->mReason );
if( !$ok ) {
$wgOut->fatalError( "Unknown error at restriction save time." );
}
return $ok;
}
-
+
function buildForm() {
global $wgUser;
-
+
$out = '';
if( !$this->disabled ) {
$out .= $this->buildScript();
'name' => 'wpEditToken',
'value' => $wgUser->editToken() ) );
}
-
+
$out .= "<table id='mwProtectSet'>";
$out .= "<tbody>";
$out .= "<tr>\n";
$out .= "</td>\n";
}
$out .= "</tr>\n";
-
+
// JavaScript will add another row with a value-chaining checkbox
-
+
$out .= "</tbody>\n";
$out .= "</table>\n";
-
+
if( !$this->disabled ) {
$out .= "<table>\n";
$out .= "<tbody>\n";
$out .= "</form>\n";
$out .= $this->buildCleanupScript();
}
-
+
return $out;
}
-
+
function buildSelector( $action, $selected ) {
global $wgRestrictionLevels;
$id = 'mwProtect-level-' . $action;
'size' => count( $wgRestrictionLevels ),
'onchange' => 'protectLevelsUpdate(this)',
) + $this->disabledAttrib;
-
+
$out = wfOpenElement( 'select', $attribs );
foreach( $wgRestrictionLevels as $key ) {
$out .= $this->buildOption( $key, $selected );
$out .= "</select>\n";
return $out;
}
-
+
function buildOption( $key, $selected ) {
$text = ( $key == '' )
? wfMsg( 'protect-default' )
array( 'value' => $key ) + $selectedAttrib,
$text );
}
-
+
function buildReasonInput() {
$id = 'mwProtect-reason';
return wfElement( 'label', array(
'name' => $id,
'id' => $id ) );
}
-
+
function buildSubmit() {
return wfElement( 'input', array(
'type' => 'submit',
'value' => wfMsg( 'confirm' ) ) );
}
-
+
function buildScript() {
global $wgStylePath;
return '<script type="text/javascript" src="' .
htmlspecialchars( $wgStylePath . "/common/protect.js" ) .
'"></script>';
}
-
+
function buildCleanupScript() {
return '<script type="text/javascript">protectInitialize("mwProtectSet","' .
wfEscapeJsString( wfMsg( 'protect-unchain' ) ) . '")</script>';
}
-
+
/**
* @param OutputPage $out
* @access private
}
$ip = wfGetIP();
-
+
# Get MemCached key
$skip = false;
if ( $wgUseMemCached ) {
function wfIsLocallyBlockedProxy( $ip ) {
global $wgProxyList;
$fname = 'wfIsLocallyBlockedProxy';
-
+
if ( !$wgProxyList ) {
return false;
}
wfProfileIn( $fname );
-
+
if ( !is_array( $wgProxyList ) ) {
# Load from the specified file
$wgProxyList = array_map( 'trim', file( $wgProxyList ) );
}
-
+
if ( !is_array( $wgProxyList ) ) {
$ret = false;
} elseif ( array_search( $ip, $wgProxyList ) !== false ) {
*/
function isCached() {
global $wgMiserMode;
-
+
return $this->isExpensive() && $wgMiserMode;
}
*/
function doQuery( $offset, $limit, $shownavigation=true ) {
global $wgUser, $wgOut, $wgContLang;
-
+
$sname = $this->getName();
$fname = get_class($this) . '::doQuery';
$sql = $this->getSQL();
*/
function doFeed( $class = '' ) {
global $wgFeedClasses;
-
+
if( isset($wgFeedClasses[$class]) ) {
$feed = new $wgFeedClasses[$class](
$this->feedTitle(),
} else {
$this->mRequest = $request;
}
-
+
$ctype = $this->mRequest->getText( 'ctype' );
$smaxage = $this->mRequest->getInt( 'smaxage', $wgSquidMaxage );
$maxage = $this->mRequest->getInt( 'maxage', $wgSquidMaxage );
$this->mOldId = $this->mRequest->getInt( 'oldid' );
# special case for 'generated' raw things: user css/js
$gen = $this->mRequest->getText( 'gen' );
-
+
if($gen == 'css') {
$this->mGen = $gen;
if($smaxage == '') $smaxage = $wgSquidMaxage;
$this->mContentType = $ctype;
}
}
-
+
function view() {
global $wgOut, $wgScript;
'Raw pages must be accessed through the primary script entry point.' );
return;
}
-
+
header( "Content-type: ".$this->mContentType.'; charset='.$this->mCharset );
# allow the client to cache this for 24 hours
header( 'Cache-Control: s-maxage='.$this->mSmaxage.', max-age='.$this->mMaxage );
} else {
return $this->getArticleText();
}
- }
+ }
function getArticleText() {
global $wgParser;
-
+
if( $this->mTitle ) {
$text = '';
return $this->parseArticleText( $text );
}
-
+
# Bad title or page does not exist
if( $this->mContentType == 'text/x-wiki' ) {
# Don't return a 404 response for CSS or JavaScript;
$parser->Options( new ParserOptions() ); // We don't want this to be user-specific
$parser->Title( $wgTitle );
$parser->OutputType( OT_HTML );
-
+
return $parser->replaceVariables( $text );
} else
return $text;
socket_close( $conn );
}
}
-
+
// E-mail notifications
global $wgUseEnotif;
if( $wgUseEnotif ) {
$this->mAttribs['rc_minor'],
$this->mAttribs['rc_last_oldid'] );
}
-
+
}
# Marks a certain row as patrolled
if( trim( $text ) == '' ) {
return '';
}
-
+
# Unquoted attribute
# Since we quote this later, this can be anything distinguishable
# from the end of the attribute
if( !isset( $whitelist[$attribute] ) ) {
continue;
}
-
+
$raw = Sanitizer::getTagAttributeCallback( $set );
$value = Sanitizer::normalizeAttributeValue( $raw );
-
+
# Strip javascript "expression" from stylesheets.
# http://msdn.microsoft.com/workshop/author/dhtml/overview/recalc.asp
if( $attribute == 'style' ) {
$stripped = Sanitizer::decodeCharReferences( $value );
-
+
// Remove any comments; IE gets token splitting wrong
$stripped = preg_replace( '!/\\*.*?\\*/!S', ' ', $stripped );
$value = htmlspecialchars( $stripped );
-
+
// ... and continue checks
$stripped = preg_replace( '!\\\\([0-9A-Fa-f]{1,6})[ \\n\\r\\t\\f]?!e',
'codepointToUtf8(hexdec("$1"))', $stripped );
if ( $attribute === 'id' )
$value = Sanitizer::escapeId( $value );
-
+
# Templates and links may be expanded in later parsing,
# creating invalid or dangerous output. Suppress this.
$value = strtr( $value, array(
'RFC' => 'RFC',
'PMID' => 'PMID',
) );
-
+
# Stupid hack
$value = preg_replace_callback(
'/(' . wfUrlProtocols() . ')/',
array( 'Sanitizer', 'armorLinksCallback' ),
$value );
-
+
// If this attribute was previously set, override it.
// Output should only have one attribute of each name.
$attribs[$attribute] = "$attribute=\"$value\"";
'%3A' => ':',
'%' => '.'
);
-
+
$id = urlencode( Sanitizer::decodeCharReferences( strtr( $id, ' ', '_' ) ) );
return str_replace( array_keys( $replace ), array_values( $replace ), $id );
}
-
+
/**
* Regex replace callback for armoring links against further processing.
* @param array $matches
function armorLinksCallback( $matches ) {
return str_replace( ':', ':', $matches[1] );
}
-
+
/**
* Return an associative array of attribute names and values from
* a partial tag string. Attribute names are forces to lowercase,
*/
function decodeTagAttributes( $text ) {
$attribs = array();
-
+
if( trim( $text ) == '' ) {
return $attribs;
}
- $pairs = array();
+ $pairs = array();
if( !preg_match_all(
MW_ATTRIBS_REGEX,
$text,
}
return $attribs;
}
-
+
/**
* Pick the appropriate attribute value from a match set from the
* MW_ATTRIBS_REGEX matches.
wfDebugDieBacktrace( "Tag conditions not met. This should never happen and is a bug." );
}
}
-
+
/**
* Normalize whitespace and character references in an XML source-
* encoded text for an attribute value.
' ',
Sanitizer::normalizeCharReferences( $text ) ) );
}
-
+
/**
* Ensure that any entities and character references are legal
* for XML and XHTML specifically. Any stray bits will be
return $ret;
}
}
-
+
/**
* If the named entity is defined in the HTML 4.0/XHTML 1.0 DTD,
* return the named entity reference as is. Otherwise, returns
return "&$name;";
}
}
-
+
function decCharReference( $codepoint ) {
$point = intval( $codepoint );
if( Sanitizer::validateCodepoint( $point ) ) {
return null;
}
}
-
+
function hexCharReference( $codepoint ) {
$point = hexdec( $codepoint );
if( Sanitizer::validateCodepoint( $point ) ) {
return null;
}
}
-
+
/**
* Returns true if a given Unicode codepoint is a valid character in XML.
* @param int $codepoint
array( 'Sanitizer', 'decodeCharReferencesCallback' ),
$text );
}
-
+
/**
* @param string $matches
* @return string
# Last case should be an ampersand by itself
return $matches[0];
}
-
+
/**
* Return UTF-8 string for a codepoint if that is a valid
* character reference, otherwise U+FFFD REPLACEMENT CHARACTER.
return UTF8_REPLACEMENT;
}
}
-
+
/**
* If the named entity is defined in the HTML 4.0/XHTML 1.0 DTD,
* return the UTF-8 encoding of that character. Otherwise, returns
return "&$name;";
}
}
-
+
/**
* Fetch the whitelist of acceptable attributes for a given
* element name.
? $list[$element]
: array();
}
-
+
/**
* @return array
*/
'height', # deprecated
'bgcolor' # deprecated
);
-
+
# Numbers refer to sections in HTML 4.01 standard describing the element.
# See: http://www.w3.org/TR/html4/
$whitelist = array (
'div' => $block,
'center' => $common, # deprecated
'span' => $block, # ??
-
+
# 7.5.5
'h1' => $block,
'h2' => $block,
'h4' => $block,
'h5' => $block,
'h6' => $block,
-
+
# 7.5.6
# address
-
+
# 8.2.4
# bdo
-
+
# 9.2.1
'em' => $common,
'strong' => $common,
'var' => $common,
# abbr
# acronym
-
+
# 9.2.2
'blockquote' => array_merge( $common, array( 'cite' ) ),
# q
-
+
# 9.2.3
'sub' => $common,
'sup' => $common,
-
+
# 9.3.1
'p' => $block,
-
+
# 9.3.2
'br' => array( 'id', 'class', 'title', 'style', 'clear' ),
-
+
# 9.3.4
'pre' => array_merge( $common, array( 'width' ) ),
-
+
# 9.4
'ins' => array_merge( $common, array( 'cite', 'datetime' ) ),
'del' => array_merge( $common, array( 'cite', 'datetime' ) ),
-
+
# 10.2
'ul' => array_merge( $common, array( 'type' ) ),
'ol' => array_merge( $common, array( 'type', 'start' ) ),
'li' => array_merge( $common, array( 'type', 'value' ) ),
-
+
# 10.3
'dl' => $common,
'dd' => $common,
'dt' => $common,
-
+
# 11.2.1
'table' => array_merge( $common,
array( 'summary', 'width', 'border', 'frame',
'rules', 'cellspacing', 'cellpadding',
'align', 'bgcolor', 'frame', 'rules',
'border' ) ),
-
+
# 11.2.2
'caption' => array_merge( $common, array( 'align' ) ),
-
+
# 11.2.3
'thead' => array_merge( $common, $tablealign ),
'tfoot' => array_merge( $common, $tablealign ),
'tbody' => array_merge( $common, $tablealign ),
-
+
# 11.2.4
'colgroup' => array_merge( $common, array( 'span', 'width' ), $tablealign ),
'col' => array_merge( $common, array( 'span', 'width' ), $tablealign ),
-
+
# 11.2.5
'tr' => array_merge( $common, array( 'bgcolor' ), $tablealign ),
-
+
# 11.2.6
'td' => array_merge( $common, $tablecell, $tablealign ),
'th' => array_merge( $common, $tablecell, $tablealign ),
-
+
# 15.2.1
'tt' => $common,
'b' => $common,
'strike' => $common,
's' => $common,
'u' => $common,
-
+
# 15.2.2
'font' => array_merge( $common, array( 'size', 'color', 'face' ) ),
# basefont
-
+
# 15.3
'hr' => array_merge( $common, array( 'noshade', 'size', 'width' ) ),
-
+
# XHTML Ruby annotation text module, simple ruby only.
# http://www.w3c.org/TR/ruby/
'ruby' => $common,
);
return $whitelist;
}
-
+
/**
* Take a fragment of (potentially invalid) HTML and return
* a version with any tags removed, encoded suitably for literal
function stripAllTags( $text ) {
# Actual <tags>
$text = preg_replace( '/ < .*? > /x', '', $text );
-
+
# Normalize &entities and whitespace
$text = Sanitizer::normalizeAttributeValue( $text );
-
+
# Will be placed into "double-quoted" attributes,
# make sure remaining bits are safe.
$text = str_replace(
array('<', '>', '"'),
array('<', '>', '"'),
$text );
-
+
return $text;
}
if ( $title->exists() ) {
return $title;
}
-
+
# Now try Word-Caps-Breaking-At-Word-Breaks, for hyphenated names etc
$title = Title::newFromText( preg_replace_callback(
'/\b([\w\x80-\xff]+)\b/',
if ( $title->exists() ) {
return $title;
}
-
+
global $wgCapitalLinks, $wgContLang;
if( !$wgCapitalLinks ) {
// Catch differs-by-first-letter-case-only
$resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), false ) ) );
return new MySQLSearchResultSet( $resultSet, $this->searchTerms );
}
-
-
+
+
/**
* Return a partial WHERE clause to exclude redirects, if so set
* @return string
return 'AND page_is_redirect=0';
}
}
-
+
/**
* Return a partial WHERE clause to limit the search to the given namespaces
* @return string
}
return 'AND page_namespace IN (' . $namespaces . ')';
}
-
+
/**
* Return a LIMIT clause to limit results on the query.
* @return string
function queryRanking( $filteredTerm, $fulltext ) {
return '';
}
-
+
/**
* Construct the full SQL query to do the search.
* The guts shoulds be constructed in queryMain()
*/
function updateTitle( $id, $title ) {
$dbw =& wfGetDB( DB_MASTER );
-
+
$dbw->update( 'searchindex',
array( 'si_title' => $title ),
array( 'si_page' => $id ),
$this->mResultSet = $resultSet;
$this->mTerms = $terms;
}
-
+
function termMatches() {
return $this->mTerms;
}
-
+
function numRows() {
return $this->mResultSet->numRows();
}
-
+
function next() {
$row = $this->mResultSet->fetchObject();
if( $row === false ) {
*/
class SearchMySQL4 extends SearchMySQL {
var $strictMatching = true;
-
+
/** @todo document */
function SearchMySQL4( &$db ) {
$this->db =& $db;
} else {
wfDebug( "Can't understand search query '{$filteredText}'\n" );
}
-
+
$searchon = $this->db->strencode( $searchon );
$field = $this->getIndexField( $fulltext );
return " MATCH($field) AGAINST('$searchon' IN BOOLEAN MODE) ";
*/
class SearchTsearch2 extends SearchEngine {
var $strictMatching = false;
-
+
function SearchTsearch2( &$db ) {
$this->db =& $db;
$this->db->setSchema('tsearch');
$this->mRanking = true;
}
-
+
function getIndexField( $fulltext ) {
return $fulltext ? 'si_text' : 'si_title';
}
} else {
wfDebug( "Can't understand search query '{$this->filteredText}'\n" );
}
-
+
$searchon = preg_replace('/(\s+)/','&',$searchon);
$searchon = $this->db->strencode( $searchon );
return $searchon;
else
return "";
}
-
+
function queryMain( $filteredTerm, $fulltext ) {
$match = $this->parseQuery( $filteredTerm, $fulltext );
require_once( 'SearchEngine.php' );
$search = SearchEngine::create();
$lc = $search->legalSearchChars() . '&#;';
-
+
if( $this->mText === false ) {
$search->updateTitle($this->mId,
Title::indexTitle( $this->mNamespace, $this->mTitle ));
var $settings = array();
var $localVHosts = array();
- /** */
+ /** */
function get( $setting, $wiki, $suffix, $params = array() ) {
if ( array_key_exists( $setting, $this->settings ) ) {
if ( array_key_exists( $wiki, $this->settings[$setting] ) ) {
}
}
}
-
+
?>
global $wgValidSkinNames;
return $wgValidSkinNames;
}
-
+
/**
* Normalize a skin preference value to a form that can be loaded.
* If a skin can't be found, it will fall back to the configured
function normalizeKey( $key ) {
global $wgDefaultSkin;
$skinNames = Skin::getSkinNames();
-
+
if( $key == '' ) {
// Don't return the default immediately;
// in a misconfiguration we need to fall back.
if( isset( $skinNames[$key] ) ) {
return $key;
}
-
+
// Older versions of the software used a numeric setting
// in the user preferences.
$fallback = array(
if( isset( $fallback[$key] ) ){
$key = $fallback[$key];
}
-
+
if( isset( $skinNames[$key] ) ) {
return $key;
} else {
return 'standard';
}
}
-
+
/**
* Factory method for loading a skin of a given type
* @param string $key 'monobook', 'standard', etc
*/
function &newFromKey( $key ) {
$key = Skin::normalizeKey( $key );
-
+
$skinNames = Skin::getSkinNames();
$skinName = $skinNames[$key];
-
+
global $IP;
# Grab the skin class and initialise it. Each skin checks for PHPTal
$out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
$this->addMetadataLinks($out);
-
+
$this->mRevisionId = $out->mRevisionId;
wfProfileOut( $fname );
global $wgUser, $wgContLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
$s = '';
-
+
if( $wgAllowUserCss && $wgUser->isLoggedIn() ) { # logged in
if($wgTitle->isCssSubpage() && $this->userCanPreview( $action ) ) {
$s .= $wgRequest->getText('wpTextbox1');
$embed = "<span dir='$dir'>";
$pop = '</span>';
$t = $embed . implode ( "$pop | $embed" , $wgOut->mCategoryLinks ) . $pop;
-
+
$msg = count( $wgOut->mCategoryLinks ) === 1 ? 'categories1' : 'categories';
$s = $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Categories' ),
wfMsg( $msg ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
}
return $s;
}
-
+
/**
* Return URL options for the 'edit page' link.
* This may include an 'oldid' specifier, if the current page view is such.
*/
function editUrlOptions() {
global $wgArticle;
-
+
if( $this->mRevisionId && ! $wgArticle->isCurrent() ) {
return "action=edit&oldid=" . intval( $this->mRevisionId );
} else {
return new PHPTAL( $file . '.pt', $repository, $cache_dir );
}
}
-
+
/**
* Output the string, or print error message if it's
* an error object of the appropriate type.
$this->tpl->setTemplateRepository( $repository );
}
}
-
+
function set( $name, $value ) {
$this->tpl->$name = $value;
}
-
+
function setRef($name, &$value) {
$this->set( $name, $value );
}
-
+
function setTranslator( &$t ) {
$this->tpl->setTranslator( $t );
}
-
+
function execute() {
/*
try {
$classes[] = 'new';
$query = 'action=edit';
}
-
+
$text = wfMsg( $message );
if ( $text == "<$message>" ) {
$text = html_entity_decode($text);
}
-
+
return array(
'class' => implode( ' ', $classes ),
'text' => $text,
);
}
}
-
+
wfRunHooks( 'SkinTemplateTabs', array( &$this , &$content_actions ) ) ;
} else {
/* show special page tab */
}
wfRunHooks( 'SkinTemplateContentActions', array( &$content_actions ) );
-
+
wfProfileOut( $fname );
return $content_actions;
}
'href' => $wgTitle->getLocalURL( "oldid=$revid" )
);
}
-
+
wfRunHooks( 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink', array( &$this, &$nav_urls, &$oldid, &$revid ) );
}
# If we use the site's dynamic CSS, throw that in, too
if ( $wgUseSiteCss ) {
- $query = "action=raw&ctype=text/css&smaxage=$wgSquidMaxage";
+ $query = "action=raw&ctype=text/css&smaxage=$wgSquidMaxage";
$sitecss .= '@import "' . $this->makeNSUrl('Common.css', $query, NS_MEDIAWIKI) . '";' . "\n";
- $sitecss .= '@import "' . $this->makeNSUrl(ucfirst($this->skinname) . '.css', $query, NS_MEDIAWIKI) . '";' . "\n";
+ $sitecss .= '@import "' . $this->makeNSUrl(ucfirst($this->skinname) . '.css', $query, NS_MEDIAWIKI) . '";' . "\n";
$sitecss .= '@import "' . $this->makeUrl('-','action=raw&gen=css' . $siteargs) . '";' . "\n";
}
$fname = "wfSpecialAllMessages";
wfProfileIn( $fname );
-
+
wfProfileIn( "$fname-setup");
$ot = $wgRequest->getText( 'ot' );
-
+
$navText = wfMsg( 'allmessagestext' );
$wgMessageCache->enableTransform();
wfProfileOut( "$fname-setup" );
-
+
wfProfileIn( "$fname-output" );
if ($ot == 'php') {
$navText .= makePhp($messages);
$wgOut->addHTML( makeHTMLText( $messages ) );
}
wfProfileOut( "$fname-output" );
-
+
wfProfileOut( $fname );
}
global $wgLang, $wgUser, $wgLanguageCode, $wgContLanguageCode;
$fname = "makeHTMLText";
wfProfileIn( $fname );
-
+
$sk =& $wgUser->getSkin();
$talk = $wgLang->getNsText( NS_TALK );
$mwnspace = $wgLang->getNsText( NS_MEDIAWIKI );
<tr>
<th>" . wfMsgHtml('allmessagescurrent') . "</th>
</tr>";
-
+
wfProfileIn( "$fname-check" );
# This is a nasty hack to avoid doing independent existence checks
# without sending the links and table through the slow wiki parser.
$changed = ($m['statmsg'] != $m['msg']);
$message = htmlspecialchars( $m['statmsg'] );
$mw = htmlspecialchars( $m['msg'] );
-
+
#$pageLink = $sk->makeLinkObj( $titleObj, htmlspecialchars( $key ) );
#$talkLink = $sk->makeLinkObj( $talkPage, htmlspecialchars( $talk ) );
if( isset( $pageExists[NS_MEDIAWIKI][$title] ) ) {
# GET values
$from = $wgRequest->getVal( 'from' );
$namespace = $wgRequest->getInt( 'namespace' );
-
+
$namespaces = $wgContLang->getNamespaces();
$indexPage = new SpecialAllpages();
wfMsg( 'allinnamespace', $namespaces[$namespace] ) :
wfMsg( 'allarticles' )
);
-
+
if ( isset($par) ) {
$indexPage->showChunk( $namespace, $par, $specialPage->including() );
} elseif ( isset($from) ) {
$frombox = "<input type='text' size='20' name='from' id='nsfrom' value=\""
. htmlspecialchars ( $from ) . '"/>';
$submitbutton = '<input type="submit" value="' . wfMsgHtml( 'allpagessubmit' ) . '" />';
-
+
$out = "<div class='namespaceoptions'><form method='get' action='{$wgScript}'>";
$out .= '<input type="hidden" name="title" value="'.$t->getPrefixedText().'" />';
$out .= "
global $wgMemc, $wgDBname;
$key = "$wgDBname:allpages:ns:$namespace";
$lines = $wgMemc->get( $key );
-
+
if( !is_array( $lines ) ) {
$firstTitle = $dbr->selectField( 'page', 'page_title', $where, $fname, array( 'LIMIT' => 1 ) );
$lastTitle = $firstTitle;
-
+
# This array is going to hold the page_titles in order.
$lines = array( $firstTitle );
-
+
# If we are going to show n rows, we need n+1 queries to find the relevant titles.
$done = false;
for( $i = 0; !$done; ++$i ) {
}
$wgMemc->add( $key, $lines, 3600 );
}
-
+
// If there are only two or less sections, don't even display them.
// Instead, display the first section directly.
if( count( $lines ) <= 2 ) {
}
$out .= '</table>';
$nsForm = $this->namespaceForm ( $namespace, '', false );
-
+
# Is there more?
if ( $including ) {
$out2 = '';
global $wgOut, $wgUser, $wgContLang;
$fname = 'indexShowChunk';
-
+
$sk = $wgUser->getSkin();
$fromTitle = null;
$namespace = $fromNS;
}
$fromKey = is_null( $fromTitle ) ? '' : $fromTitle->getDBkey();
-
+
$dbr =& wfGetDB( DB_SLAVE );
$res = $dbr->select( 'page',
array( 'page_namespace', 'page_title', 'page_is_redirect' ),
function isExpensive() {
return true;
}
-
+
function isSyndicated() { return false; }
function getSQL() {
WHERE page_namespace=".NS_MAIN." AND page_is_redirect=0
AND page_latest=rev_id";
}
-
+
function sortDescending() {
return false;
}
$this->BlockExpiry = $wgRequest->getVal( 'wpBlockExpiry', wfMsg('ipbotheroption') );
$this->BlockOther = $wgRequest->getVal( 'wpBlockOther', '' );
}
-
+
function showForm( $err ) {
global $wgOut, $wgUser, $wgRequest, $wgSysopUserBans;
}
$token = htmlspecialchars( $wgUser->editToken() );
-
+
$wgOut->addHTML( "
<form id=\"blockip\" method=\"post\" action=\"{$action}\">
<table border='0'>
function doSubmit() {
global $wgOut, $wgUser, $wgSysopUserBans, $wgSysopRangeBans;
-
+
$userId = 0;
$this->BlockAddress = trim( $this->BlockAddress );
$rxIP = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
}
} else {
# Username block
- if ( $wgSysopUserBans ) {
+ if ( $wgSysopUserBans ) {
$userId = User::idFromName( $this->BlockAddress );
if ( $userId == 0 ) {
$this->showForm( wfMsg( 'nosuchusershort', htmlspecialchars( $this->BlockAddress ) ) );
$this->showForm( wfMsg( 'ipb_expiry_invalid' ) );
return;
}
-
+
$expiry = wfTimestamp( TS_MW, $expiry );
}
-
+
# Create block
# Note: for a user block, ipb_address is only for display purposes
$ban = new Block( $this->BlockAddress, $userId, $wgUser->getID(),
$this->BlockReason, wfTimestampNow(), 0, $expiry );
-
+
if (wfRunHooks('BlockIp', array(&$ban, &$wgUser))) {
-
+
$ban->insert();
-
+
wfRunHooks('BlockIpComplete', array($ban, $wgUser));
-
+
# Make log entry
$log = new LogPage( 'block' );
$log->addEntry( 'block', Title::makeTitle( NS_USER, $this->BlockAddress ),
global $wgBlockOpenProxies, $wgOut, $wgProxyKey;
$ip = wfGetIP();
-
+
if ( !$wgBlockOpenProxies || $_REQUEST['ip'] != md5( $ip . $wgProxyKey ) ) {
$wgOut->addWikiText( wfMsg( "disabled" ) );
return;
*/
function wfSpecialBooksources( $par ) {
global $wgRequest;
-
+
$isbn = $par;
if( empty( $par ) ) {
$isbn = $wgRequest->getVal( 'isbn' );
}
$isbn = preg_replace( '/[^0-9X]/', '', $isbn );
-
+
$bsl = new BookSourceList( $isbn );
$bsl->show();
}
$this->showList();
}
}
-
+
function showList() {
global $wgOut, $wgContLang;
$fname = "BookSourceList::showList()";
-
+
# First, see if we have a custom list setup in
# [[Wikipedia:Book sources]] or equivalent.
$bstitle = Title::makeTitleSafe( NS_PROJECT, wfMsg( "booksources" ) );
$bsarticle = new Article( $bstitle );
if( $bsarticle->exists() ) {
$bstext = $bsarticle->getContent( false );
- if( $bstext ) {
+ if( $bstext ) {
$bstext = str_replace( "MAGICNUMBER", $this->mIsbn, $bstext );
$wgOut->addWikiText( $bstext );
return;
}
}
-
+
# Otherwise, use the list of links in the default Language.php file.
$s = wfMsgWikiHtml( 'booksourcetext' ) . "<ul>\n";
$bs = $wgContLang->getBookstoreList() ;
$wgOut->addHTML( $s );
}
-
+
function askForm() {
global $wgOut, $wgTitle;
$fname = "BookSourceList::askForm()";
-
+
$action = $wgTitle->escapeLocalUrl();
$isbn = htmlspecialchars( wfMsg( "isbn" ) );
$go = htmlspecialchars( wfMsg( "go" ) );
function getName() {
return 'BrokenRedirects';
}
-
+
function isExpensive( ) { return true; }
function isSyndicated() { return false; }
$from = $skin->makeKnownLinkObj( $fromObj ,'', 'redirect=no' );
$edit = $skin->makeBrokenLinkObj( $fromObj , "(".wfMsg("qbedit").")" , 'redirect=no');
$to = $skin->makeBrokenLinkObj( $toObj );
-
+
return "$from $edit → $to";
}
}
*/
function wfSpecialBrokenRedirects() {
list( $limit, $offset ) = wfCheckLimits();
-
+
$sbr = new BrokenRedirectsPage();
-
+
return $sbr->doQuery( $offset, $limit );
}
GROUP BY cl_to";
return $s;
}
-
+
function sortDescending() {
return false;
}
}
}
- /** */
+ /** */
function confirmAndShow( $user ) {
if( $user->confirmEmail() ) {
$this->showSuccess();
function showEmpty( $err ) {
require_once( 'templates/Confirmemail.php' );
global $wgOut, $wgUser;
-
+
$tpl = new ConfirmemailTemplate();
$tpl->set( 'error', $err );
$tpl->set( 'edittoken', $wgUser->editToken() );
-
+
$title = Title::makeTitle( NS_SPECIAL, 'Confirmemail' );
$tpl->set( 'action', $title->getLocalUrl() );
-
-
+
+
$wgOut->addTemplate( $tpl );
}
/** */
function showSuccess() {
global $wgOut, $wgRequest, $wgUser;
-
+
if( $wgUser->isLoggedIn() ) {
$wgOut->addWikiText( wfMsg( 'confirmemail_loggedin' ) );
} else {
function isExpensive( ) {
return 1;
}
-
+
function isSyndicated() { return false; }
/**
function sortDescending() {
return false;
}
-
+
/**
* @return string an sqlquery
*/
function getName() {
return 'Disambiguations';
}
-
+
function isExpensive( ) { return true; }
function isSyndicated() { return false; }
function getPageHeader( ) {
global $wgUser;
$sk = $wgUser->getSkin();
-
+
#FIXME : probably need to add a backlink to the maintenance page.
return '<p>'.wfMsg("disambiguationstext", $sk->makeKnownLink(wfMsgForContent('disambiguationspage')) )."</p><br />\n";
}
function getSQL() {
$dbr =& wfGetDB( DB_SLAVE );
extract( $dbr->tableNames( 'page', 'pagelinks' ) );
-
+
$dp = Title::newFromText(wfMsgForContent("disambiguationspage"));
$id = $dp->getArticleId();
$dns = $dp->getNamespace();
function getOrder() {
return '';
}
-
+
function formatResult( $skin, $result ) {
$title = Title::newFromId( $result->value );
$dp = Title::makeTitle( $result->namespace, $result->title );
$from = $skin->makeKnownLinkObj( $title,'');
$edit = $skin->makeBrokenLinkObj( $title, "(".wfMsg("qbedit").")" , 'redirect=no');
$to = $skin->makeKnownLinkObj( $dp,'');
-
+
return "$from $edit => $to";
}
}
*/
function wfSpecialDisambiguations() {
list( $limit, $offset ) = wfCheckLimits();
-
+
$sd = new DisambiguationsPage();
-
+
return $sd->doQuery( $offset, $limit );
}
?>
function getName() {
return 'DoubleRedirects';
}
-
+
function isExpensive( ) { return true; }
function isSyndicated() { return false; }
function getOrder() {
return '';
}
-
+
function formatResult( $skin, $result ) {
$fname = 'DoubleRedirectsPage::formatResult';
$titleA = Title::makeTitle( $result->namespace, $result->title );
if ( !$result ) {
return '';
}
-
+
$titleB = Title::makeTitle( $result->nsb, $result->tb );
$titleC = Title::makeTitle( $result->nsc, $result->tc );
$edit = $skin->makeBrokenLinkObj( $titleA, "(".wfMsg("qbedit").")" , 'redirect=no');
$linkB = $skin->makeKnownLinkObj( $titleB, '', 'redirect=no' );
$linkC = $skin->makeKnownLinkObj( $titleC );
-
+
return "$linkA $edit " . wfMsgHtml( 'doubleredirectsarrow' )
. " $linkB " . wfMsgHtml( 'doubleredirectsarrow' ) . " $linkC";
}
*/
function wfSpecialDoubleRedirects() {
list( $limit, $offset ) = wfCheckLimits();
-
+
$sdr = new DoubleRedirectsPage();
-
+
return $sdr->doQuery( $offset, $limit );
}
$wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
return;
}
-
+
if( !$wgUser->canSendEmail() ) {
wfDebug( "User can't send.\n" );
$wgOut->errorpage( "mailnologin", "mailnologintext" );
return;
}
-
+
$action = $wgRequest->getVal( 'action' );
$target = isset($par) ? $par : $wgRequest->getVal( 'target' );
if ( "" == $target ) {
$wgOut->errorpage( "notargettitle", "notargettext" );
return;
}
-
+
$nt = Title::newFromURL( $target );
if ( is_null( $nt ) ) {
wfDebug( "Target is invalid title.\n" );
$wgOut->errorpage( "notargettitle", "notargettext" );
return;
}
-
+
$nu = User::newFromName( $nt->getText() );
if( is_null( $nu ) || !$nu->canReceiveEmail() ) {
wfDebug( "Target is invalid user or can't receive.\n" );
$emm = wfMsg( "emailmessage" );
$ems = wfMsg( "emailsend" );
$encSubject = htmlspecialchars( $this->subject );
-
+
$titleObj = Title::makeTitle( NS_SPECIAL, "Emailuser" );
$action = $titleObj->escapeLocalURL( "target=" .
urlencode( $this->target->getName() ) . "&action=submit" );
function doSubmit() {
global $wgOut, $wgUser;
-
+
$to = new MailAddress( $this->target );
$from = new MailAddress( $wgUser );
$subject = $this->subject;
-
+
if( wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$this->text ) ) ) {
-
+
$mailResult = userMailer( $to, $from, $subject, $this->text );
-
+
if( WikiError::isError( $mailResult ) ) {
$wgOut->addHTML( wfMsg( "usermailererror" ) . $mailResult);
} else {
function wfSpecialExport( $page = '' ) {
global $wgOut, $wgRequest;
global $wgExportAllowHistory;
-
+
if( $wgRequest->getVal( 'action' ) == 'submit') {
$page = $wgRequest->getText( 'pages' );
if( $wgExportAllowHistory ) {
# Pre-check the 'current version only' box in the UI
$curonly = true;
}
-
+
if( $page != '' ) {
$wgOut->disable();
header( "Content-type: application/xml; charset=utf-8" );
$pages = explode( "\n", $page );
-
+
$db =& wfGetDB( DB_SLAVE );
$history = $curonly ? MW_EXPORT_CURRENT : MW_EXPORT_FULL;
$exporter = new WikiExporter( $db, $history );
$exporter->closeStream();
return;
}
-
+
$wgOut->addWikiText( wfMsg( "exporttext" ) );
$titleObj = Title::makeTitle( NS_SPECIAL, "Export" );
$action = $titleObj->escapeLocalURL( 'action=submit' );
/** Entry point */
function wfSpecialGroups() {
global $wgRequest;
-
+
$form = new GroupsForm($wgRequest);
$form->execute();
}
var $mPosted, $mRequest, $mSaveprefs, $mChangeAllowed;
var $mNewName, $mDescription, $mOldName, $mRights, $mId;
var $mAdd, $mEdit;
-
+
/** Escaped local url name*/
var $action, $location;
/** Constructor*/
function GroupsForm ( &$request ) {
global $wgUser;
-
+
$this->mPosted = $request->wasPosted();
$this->mRequest =& $request;
$this->mName = 'groups';
} elseif ( $this->mEdit ) {
if ( $this->mPosted ) {
$wgOut->redirect( $this->location );
- } else {
+ } else {
$this->switchForm();
$this->editGroupForm( $this->mId );
}
global $wgOut;
$this->mNewName = trim($this->mNewName);
-
+
if ( $this->mNewName == '' ) {
$this->editGroupForm( $this->mGroupID, 'groups-noname' );
return false;
return;
}
}
-
+
// save stuff
$g->setName($this->mNewName);
$g->setDescription($this->mDescription);
if( is_array( $this->mRights ) ) {
$g->setRights( implode(',',$this->mRights) );
}
-
+
$g->save();
-
+
// Make the log entry
$log = new LogPage( 'rights' );
$dummyTitle = Title::makeTitle( 0, '' );
*/
function switchForm() {
global $wgOut;
-
- // group selection
+
+ // group selection
$wgOut->addHTML( "<form name=\"ulgroup\" action=\"$this->action\" method=\"post\">\n" );
$wgOut->addHTML( $this->fieldset( 'lookup-group',
HTMLSelectGroups('id', $this->mName.'-group-edit', array(0 => $this->mRequest->getVal('id')) ) .
$s .= "|}\n";
$wgOut->addWikiText( $s );
}
-
+
function showRecord() {
global $wgOut;
-
+
$groups =& Group::getAllGroups();
$rec = serialize( $groups );
// Split it into lines
*/
function wfSpecialImagelist() {
global $wgUser, $wgOut, $wgLang, $wgRequest, $wgMiserMode;
-
+
$sort = $wgRequest->getVal( 'sort' );
$wpIlMatch = $wgRequest->getText( 'wpIlMatch' );
$dbr =& wfGetDB( DB_SLAVE );
*/
function wfSpecialImport( $page = '' ) {
global $wgUser, $wgOut, $wgRequest, $wgTitle, $wgImportSources;
-
+
###
# $wgOut->addWikiText( "Special:Import is not ready for this beta release, sorry." );
# return;
###
-
+
if( $wgRequest->wasPosted() && $wgRequest->getVal( 'action' ) == 'submit') {
switch( $wgRequest->getVal( "source" ) ) {
case "upload":
default:
$source = new WikiError( "Unknown import source type" );
}
-
+
if( WikiError::isError( $source ) ) {
$wgOut->addWikiText( wfEscapeWikiText( $source->getMessage() ) );
} else {
}
}
}
-
+
$action = $wgTitle->escapeLocalUrl( 'action=submit' );
-
+
if( $wgUser->isAllowed( 'importupload' ) ) {
$wgOut->addWikiText( wfMsg( "importtext" ) );
$wgOut->addHTML( "
$wgOut->addWikiText( wfMsg( 'importnosources' ) );
}
}
-
+
if( !empty( $wgImportSources ) ) {
$wgOut->addHTML( "
<fieldset>
var $text = "";
var $comment = "";
var $minor = false;
-
+
function setTitle( $text ) {
$this->title = Title::newFromText( $text );
}
-
+
function setTimestamp( $ts ) {
# 2003-08-05T18:30:02Z
$this->timestamp = wfTimestamp( TS_MW, $ts );
}
-
+
function setUsername( $user ) {
$this->user_text = $user;
}
-
+
function setUserIP( $ip ) {
$this->user_text = $ip;
}
-
+
function setText( $text ) {
$this->text = $text;
}
-
+
function setComment( $text ) {
$this->comment = $text;
}
-
+
function setMinor( $minor ) {
$this->minor = (bool)$minor;
}
-
+
function getTitle() {
return $this->title;
}
-
+
function getTimestamp() {
return $this->timestamp;
}
-
+
function getUser() {
return $this->user_text;
}
-
+
function getText() {
return $this->text;
}
-
+
function getComment() {
return $this->comment;
}
-
+
function getMinor() {
return $this->minor;
}
function importOldRevision() {
$fname = "WikiImporter::importOldRevision";
$dbw =& wfGetDB( DB_MASTER );
-
+
# Sneak a single revision into place
$user = User::newFromName( $this->getUser() );
if( $user ) {
// avoid memory leak...?
$linkCache =& LinkCache::singleton();
$linkCache->clear();
-
+
$article = new Article( $this->title );
$pageId = $article->getId();
if( $pageId == 0 ) {
# must create the page...
$pageId = $article->insertOn( $dbw );
}
-
+
# FIXME: Check for exact conflicts
# FIXME: Use original rev_id optionally
# FIXME: blah blah blah
-
+
#if( $numrows > 0 ) {
# return wfMsg( "importhistoryconflict" );
#}
-
+
# Insert the row
$revision = new Revision( array(
'page' => $pageId,
) );
$revId = $revision->insertOn( $dbw );
$article->updateIfNewerOn( $dbw, $revision );
-
+
return true;
}
var $mPageCallback = null;
var $mRevisionCallback = null;
var $lastfield;
-
+
function WikiImporter( $source ) {
$this->setRevisionCallback( array( &$this, "importRevision" ) );
$this->mSource = $source;
}
-
+
function throwXmlError( $err ) {
$this->debug( "FAILURE: $err" );
wfDebug( "WikiImporter XML error: $err\n" );
}
-
+
# --------------
-
+
function doImport() {
if( empty( $this->mSource ) ) {
return new WikiErrorMsg( "importnotext" );
}
-
+
$parser = xml_parser_create( "UTF-8" );
-
+
# case folding violates XML standard, turn it off
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
-
+
xml_set_object( $parser, $this );
xml_set_element_handler( $parser, "in_start", "" );
-
+
$offset = 0; // for context extraction on error reporting
do {
$chunk = $this->mSource->readChunk();
$offset += strlen( $chunk );
} while( $chunk !== false && !$this->mSource->atEnd() );
xml_parser_free( $parser );
-
+
return true;
}
-
+
function debug( $data ) {
#wfDebug( "IMPORT: $data\n" );
}
-
+
function notice( $data ) {
global $wgCommandLineMode;
if( $wgCommandLineMode ) {
$wgOut->addHTML( "<li>$data</li>\n" );
}
}
-
+
/**
* Sets the action to perform as each new page in the stream is reached.
* @param callable $callback
$this->mPageCallback = $callback;
return $previous;
}
-
+
/**
* Sets the action to perform as each page revision is reached.
* @param callable $callback
$this->mRevisionCallback = $callback;
return $previous;
}
-
+
/**
* Default per-revision callback, performs the import.
* @param WikiRevision $revision
$this->debug( "-- Comment: " . $revision->comment );
$this->debug( "-- Text: " . $revision->text );
}
-
+
/**
* Notify the callback function when a new <page> is reached.
* @param Title $title
call_user_func( $this->mPageCallback, $title );
}
}
-
-
+
+
# XML parser callbacks from here out -- beware!
function donothing( $parser, $x, $y="" ) {
#$this->debug( "donothing" );
}
-
+
function in_start( $parser, $name, $attribs ) {
$this->debug( "in_start $name" );
if( $name != "mediawiki" ) {
}
xml_set_element_handler( $parser, "in_mediawiki", "out_mediawiki" );
}
-
+
function in_mediawiki( $parser, $name, $attribs ) {
$this->debug( "in_mediawiki $name" );
if( $name == 'siteinfo' ) {
}
xml_set_element_handler( $parser, "donothing", "donothing" );
}
-
-
+
+
function in_siteinfo( $parser, $name, $attribs ) {
// no-ops for now
$this->debug( "in_siteinfo $name" );
return $this->throwXMLerror( "Element <$name> not allowed in <siteinfo>." );
}
}
-
+
function out_siteinfo( $parser, $name ) {
if( $name == "siteinfo" ) {
xml_set_element_handler( $parser, "in_mediawiki", "out_mediawiki" );
}
}
-
+
function in_page( $parser, $name, $attribs ) {
$this->debug( "in_page $name" );
return $this->throwXMLerror( "Element <$name> not allowed in a <page>." );
}
}
-
+
function out_page( $parser, $name ) {
$this->debug( "out_page $name" );
if( $name != "page" ) {
return $this->throwXMLerror( "Expected </page>, got </$name>" );
}
xml_set_element_handler( $parser, "in_mediawiki", "out_mediawiki" );
-
+
$this->workTitle = NULL;
$this->workRevision = NULL;
}
-
+
function in_nothing( $parser, $name, $attribs ) {
$this->debug( "in_nothing $name" );
return $this->throwXMLerror( "No child elements allowed here; got <$name>" );
}
xml_set_element_handler( $parser, "in_$this->parenttag", "out_$this->parenttag" );
xml_set_character_data_handler( $parser, "donothing" );
-
+
switch( $this->appendfield ) {
case "title":
$this->workTitle = $this->appenddata;
$this->appendfield = "";
$this->appenddata = "";
}
-
+
function in_revision( $parser, $name, $attribs ) {
$this->debug( "in_revision $name" );
switch( $name ) {
return $this->throwXMLerror( "Element <$name> not allowed in a <revision>." );
}
}
-
+
function out_revision( $parser, $name ) {
$this->debug( "out_revision $name" );
if( $name != "revision" ) {
return $this->throwXMLerror( "Expected </revision>, got </$name>" );
}
xml_set_element_handler( $parser, "in_page", "out_page" );
-
+
$out = call_user_func_array( $this->mRevisionCallback,
array( &$this->workRevision, &$this ) );
if( !empty( $out ) ) {
$wgOut->addHTML( "<li>" . $out . "</li>\n" );
}
}
-
+
function in_contributor( $parser, $name, $attribs ) {
$this->debug( "in_contributor $name" );
switch( $name ) {
$this->throwXMLerror( "Invalid tag <$name> in <contributor>" );
}
}
-
+
function out_contributor( $parser, $name ) {
$this->debug( "out_contributor $name" );
if( $name != "contributor" ) {
$this->mString = $string;
$this->mRead = false;
}
-
+
function atEnd() {
return $this->mRead;
}
-
+
function readChunk() {
if( $this->atEnd() ) {
return false;
function ImportStreamSource( $handle ) {
$this->mHandle = $handle;
}
-
+
function atEnd() {
return feof( $this->mHandle );
}
-
+
function readChunk() {
return fread( $this->mHandle, 32768 );
}
-
+
function newFromFile( $filename ) {
$file = @fopen( $filename, 'rt' );
if( !$file ) {
function newFromUpload( $fieldname = "xmlimport" ) {
global $wgOut;
-
+
$upload =& $_FILES[$fieldname];
-
+
if( !isset( $upload ) ) {
return new WikiErrorMsg( 'importnofile' );
}
return new WikiErrorMsg( 'importnofile' );
}
}
-
+
function newFromURL( $url ) {
# fopen-wrappers are normally turned off for security.
ini_set( "allow_url_fopen", true );
ini_set( "allow_url_fopen", false );
return $ret;
}
-
+
function newFromInterwiki( $interwiki, $page ) {
$base = Title::getInterwikiLink( $interwiki );
if( empty( $base ) ) {
*/
function wfSpecialIpblocklist() {
global $wgUser, $wgOut, $wgRequest;
-
+
$ip = $wgRequest->getVal( 'wpUnblockAddress', $wgRequest->getVal( 'ip' ) );
$reason = $wgRequest->getText( 'wpUnblockReason' );
$action = $wgRequest->getText( 'action' );
-
+
$ipu = new IPUnblockForm( $ip, $reason );
if ( "success" == $action ) {
*/
class IPUnblockForm {
var $ip, $reason;
-
+
function IPUnblockForm( $ip, $reason ) {
$this->ip = $ip;
$this->reason = $reason;
}
-
+
function showForm( $err ) {
global $wgOut, $wgUser, $wgSysopUserBans;
$wgOut->addWikitext( "<span class='error'>{$err}</span>\n" );
}
$token = htmlspecialchars( $wgUser->editToken() );
-
+
$wgOut->addHTML( "
<form id=\"unblockip\" method=\"post\" action=\"{$action}\">
<table border='0'>
</form>\n" );
}
-
+
function doSubmit() {
global $wgOut, $wgUser;
function showList( $msg ) {
global $wgOut;
-
+
$wgOut->setPagetitle( wfMsg( "ipblocklist" ) );
if ( "" != $msg ) {
$wgOut->setSubtitle( $msg );
global $wgRequest;
list( $this->limit, $this->offset ) = $wgRequest->getLimitOffset();
$this->counter = 0;
-
+
$paging = '<p>' . wfViewPrevNext( $this->offset, $this->limit,
Title::makeTitle( NS_SPECIAL, 'Ipblocklist' ),
'ip=' . urlencode( $this->ip ) ) . "</p>\n";
$wgOut->addHTML( $paging );
-
+
$search = $this->searchForm();
$wgOut->addHTML( $search );
$wgOut->addHTML( "</ul>\n" );
$wgOut->addHTML( $paging );
}
-
+
function searchForm() {
global $wgTitle;
return
*/
function addRow( $block, $tag ) {
global $wgOut, $wgUser, $wgLang;
-
+
if( $this->ip != '' ) {
if( $block->mAuto ) {
if( stristr( $block->mId, $this->ip ) == false ) {
}
}
}
-
+
// Loading blocks is fast; displaying them is slow.
// Quick hack for paging.
$this->counter++;
if( $this->counter - $this->offset > $this->limit ) {
return;
}
-
+
$fname = 'IPUnblockForm-addRow';
wfProfileIn( $fname );
-
+
static $sk=null, $msg=null;
-
+
if( is_null( $sk ) )
$sk = $wgUser->getSkin();
if( is_null( $msg ) ) {
}
$msg['blocklistline'] = wfMsg( 'blocklistline' );
}
-
+
# Hide addresses blocked by User::spreadBlocks, for privacy
$addr = $block->mAuto ? "#{$block->mId}" : $block->mAddress;
-
+
$name = $block->getByName();
$ulink = $sk->makeKnownLinkObj( Title::makeTitle( NS_USER, $name ), $name );
$formattedTime = $wgLang->timeanddate( $block->mTimestamp, true );
-
+
if ( $block->mExpiry === "" ) {
$formattedExpiry = $msg['infiniteblock'];
} else {
$formattedExpiry = wfMsgReplaceArgs( $msg['expiringblock'],
array( $wgLang->timeanddate( $block->mExpiry, true ) ) );
}
-
+
$line = wfMsgReplaceArgs( $msg['blocklistline'], array( $formattedTime, $ulink, $addr, $formattedExpiry ) );
-
+
$wgOut->addHTML( "<li>{$line}" );
-
+
if ( !$block->mAuto ) {
$titleObj = Title::makeTitle( NS_SPECIAL, "Contributions" );
$wgOut->addHTML( ' (' . $sk->makeKnownLinkObj($titleObj, $msg['contribslink'], "target={$block->mAddress}") . ')' );
}
-
+
if ( $wgUser->isAllowed('block') ) {
$titleObj = Title::makeTitle( NS_SPECIAL, "Ipblocklist" );
$wgOut->addHTML( ' (' . $sk->makeKnownLinkObj($titleObj, $msg['unblocklink'], 'action=unblock&ip=' . urlencode( $addr ) ) . ')' );
function isExpensive() { return( true ); }
function isSyndicated() { return( false ); }
function sortDescending() { return( false ); }
-
+
function getSQL() {
$dbr =& wfGetDB( DB_SLAVE );
extract( $dbr->tableNames( 'page' ) );
return( 'SELECT page_title AS title, page_namespace AS namespace, page_namespace AS value FROM ' . $page . ' WHERE page_is_redirect = 1' );
}
-
+
function formatResult( $skin, $result ) {
global $wgContLang;
-
+
# Make a link to the redirect itself
$rd_title = Title::makeTitle( $result->namespace, $result->title );
$rd_link = $skin->makeKnownLinkObj( $rd_title, '', 'redirect=no' );
-
+
# Find out where the redirect leads
$rd_page = new Article( &$rd_title, 0 );
$rd_text = $rd_page->getContent( true ); # Don't follow the redirect
-
+
# Make a link to the destination page
$tp_title = Title::newFromRedirect( $rd_text );
$tp_link = $skin->makeKnownLinkObj( $tp_title );
-
+
# Format the whole thing and return it
return( $rd_link . ' → ' . $tp_link );
-
+
}
}
class ListUsersPage extends QueryPage {
var $requestedGroup = '';
var $requestedUser = '';
-
+
function getName() {
return 'Listusers';
}
*/
function getPageHeader( ) {
global $wgScript;
-
+
// Various variables used for the form
$action = htmlspecialchars( $wgScript );
$title = Title::makeTitle( NS_SPECIAL, 'Listusers' );
// get all group names and IDs
$groups = User::getAllGroups();
-
+
// we want a default empty group
$out.= '<option value=""></option>';
-
+
// build the dropdown list menu using datas from the database
foreach ( $groups as $group ) {
$selected = ($group == $this->requestedGroup);
// OK button, end of form.
$out .= '<input type="submit" value="' . wfMsgHtml( 'allpagessubmit' ) . '" /></form>';
// congratulations the form is now build
- return $out;
+ return $out;
}
-
+
function getSQL() {
$dbr =& wfGetDB( DB_SLAVE );
$user = $dbr->tableName( 'user' );
$user_groups = $dbr->tableName( 'user_groups' );
-
+
// We need to get an 'atomic' list of users, so that we
// don't break the list half-way through a user's group set
// and so that lists by group will show all group memberships.
// For now we'll just grab the number of memberships, so
// we can then do targetted checks on those who are in
// non-default groups as we go down the list.
-
+
$userspace = NS_USER;
$sql = "SELECT 'Listusers' as type, $userspace AS namespace, user_name AS title, " .
"user_name as value, user_id, COUNT(ug_group) as numgroups " .
"LEFT JOIN $user_groups ON user_id=ug_user " .
$this->userQueryWhere( $dbr ) .
" GROUP BY user_name";
-
+
return $sql;
}
-
+
function userQueryWhere( &$dbr ) {
$conds = $this->userQueryConditions();
return empty( $conds )
? ""
: "WHERE " . $dbr->makeList( $conds, LIST_AND );
}
-
+
function userQueryConditions() {
$conds = array();
if( $this->requestedGroup != '' ) {
}
return $conds;
}
-
+
function linkParameters() {
$conds = array();
if( $this->requestedGroup != '' ) {
}
return $conds;
}
-
+
function sortDescending() {
return false;
}
function formatResult( $skin, $result ) {
-
+
$userPage = Title::makeTitle( $result->namespace, $result->title );
$name = $skin->makeLinkObj( $userPage, htmlspecialchars( $userPage->getText() ) );
-
+
if( !isset( $result->numgroups ) || $result->numgroups > 0 ) {
$dbr =& wfGetDB( DB_SLAVE );
$result = $dbr->select( 'user_groups',
$groups[] = User::getGroupName( $row->ug_group );
}
$dbr->freeResult( $result );
-
+
if( count( $groups ) > 0 ) {
$name .= ' (' .
$skin->makeLink( wfMsgForContent( 'administrators' ),
}
return $name;
- }
+ }
}
/**
$slu = new ListUsersPage();
-
+
/**
* Get some parameters
*/
*/
class DBLockForm {
var $reason = '';
-
+
function DBLockForm() {
global $wgRequest;
$this->reason = $wgRequest->getText( 'wpLockReason' );
}
-
+
function showForm( $err ) {
global $wgOut, $wgUser;
return true;
}
function isSyndicated() { return false; }
-
+
function getSQL() {
$dbr =& wfGetDB( DB_SLAVE );
extract( $dbr->tableNames( 'page', 'pagelinks' ) );
$this->major = $major;
$this->minor = $minor;
}
-
+
function getName() { return 'MIMEsearch'; }
-
+
/**
* Due to this page relying upon extra fields being passed in the SELECT it
* will fail if it's set as expensive and misermode is on
*/
function isExpensive() { return true; }
function isSyndicated() { return false; }
-
+
function linkParameters() {
$arr = array( $this->major, $this->minor );
$mime = implode( '/', $arr );
$image = $dbr->tableName( 'image' );
$major = $dbr->addQuotes( $this->major );
$minor = $dbr->addQuotes( $this->minor );
-
+
return
"SELECT 'MIMEsearch' AS type,
" . NS_IMAGE . " AS namespace,
img_name AS title,
img_major_mime AS value,
-
+
img_size,
img_width,
img_height,
$dimensions = wfMsg( 'widthheight', $result->img_width, $result->img_height );
$user = $skin->makeLinkObj( Title::makeTitle( NS_USER, $result->img_user_text ), $result->img_user_text );
$time = $wgLang->timeanddate( $result->img_timestamp );
-
+
return "($download) $plink .. $dimensions .. $bytes .. $user .. $time";
}
}
if ( $major == '' or $minor == '' or !wfSpecialMIMEsearchValidType( $major ) )
return;
$wpp = new MIMEsearchPage( $major, $minor );
-
+
list( $limit, $offset ) = wfCheckLimits();
$wpp->doQuery( $offset, $limit );
}
$wgOut->addWikiText( wfMsg( 'perfdisabled' ) );
return;
}
-
+
# Get parameters from the URL
$submitmll = $wgRequest->getVal( 'submitmll' );
# Call the subfunction requested by the user
switch( $subfunction ) {
case 'disambiguations': return wfSpecialDisambiguations();
-
+
# doubleredirects & brokenredirects are old maintenance subpages.
case 'doubleredirects': return wfSpecialDoubleRedirects();
case 'brokenredirects': return wfSpecialBrokenRedirects();
-
+
case 'selflinks': return wfSpecialSelfLinks() ;
case 'mispeelings': return wfSpecialMispeelings() ;
case 'missinglanguagelinks': return wfSpecialMissingLanguageLinks();
}
-
+
if ( !is_null( $submitmll ) ) return wfSpecialMissingLanguageLinks() ;
$sk = $wgUser->getSkin();
# Generate page output
-
+
$r = wfMsg('maintnancepagetext') ;
-
+
# Links to subfunctions
$r .= "<ul>\n" ;
$r .= "<li>".$sk->makeKnownLink( sns().':Disambiguations', wfMsg('disambiguations')) . "</li>\n";
$r .= htmlspecialchars(wfMsg('missinglanguagelinksbutton'), ENT_QUOTES);
$r .= "\" />\n" ;
$r .= "<select name=\"thelang\">\n" ;
-
+
$a = $wgContLang->getLanguageNames();
$ak = array_keys ( $a ) ;
foreach ( $ak AS $k ) {
$wgContLang->getNsText( NS_SPECIAL ) . ':Maintenance',
wfMsg( 'maintenancebacklink' ) ) ;
$t = wfMsg ( $subfunction ) ;
-
+
$s = '<table width="100%" border="0"><tr><td>';
$s .= '<h2>'.$t.'</h2></td><td align="right">';
$s .= "{$r}</td></tr></table>\n" ;
*/
function wfSpecialMissingLanguageLinks() {
global $wgUser, $wgOut, $wgContLang, $wgRequest;
-
+
$fname = 'wfSpecialMissingLanguageLinks';
$thelang = $wgRequest->getText( 'thelang' );
if ( $thelang == 'w' ) $thelang = 'en' ; # Fix for international wikis
$nt = Title::makeTitle( $result->namespace, $result->title );
$text = $wgContLang->convert( $nt->getPrefixedText() );
-
+
$plink = $skin->makeKnownLink( $nt->getPrefixedText(), $text );
-
+
$nl = wfMsg( 'ncategories', $result->value );
$nlink = $skin->makeKnownLink( $wgContLang->specialPage( 'Categories' ), $nl, 'article=' . $nt->getPrefixedURL() );
$nt = Title::makeTitle( $result->namespace, $result->title );
$text = $wgContLang->convert( $nt->getPrefixedText() );
-
+
$plink = $skin->makeKnownLink( $nt->getPrefixedText(), $text );
-
+
$nl = wfMsg( 'nlinks', $result->value );
$nlink = $skin->makeKnownLink( $nt->getPrefixedText() . '#filelinks', $nl );
pl_namespace AS namespace,
pl_title AS title,
COUNT(*) AS value,
-
+
page_namespace
FROM $pagelinks
LEFT JOIN $page ON pl_namespace=page_namespace AND pl_title=page_title
$nt = Title::makeTitle( $result->namespace, $result->title );
$text = $wgContLang->convert( $nt->getPrefixedText() );
-
+
if ( $this->isCached() )
$plink = $skin->makeKnownLink( $nt->getPrefixedText(), $text );
else {
? $skin->makeBrokenLink( $nt->getPrefixedText(), $text )
: $skin->makeKnownLink( $nt->getPrefixedText(), $text );
}
-
+
$nl = wfMsg( 'nlinks', $result->value );
$nlink = $skin->makeKnownLink( $wgContLang->specialPage( 'Whatlinkshere' ), $nl, 'target=' . $nt->getPrefixedURL() );
GROUP BY cl_to
";
}
-
+
function sortDescending() { return true; }
/**
$nt = Title::makeTitle( $result->namespace, $result->title );
$text = $wgContLang->convert( $nt->getText() );
-
+
$plink = $skin->makeLinkObj( $nt, htmlspecialchars( $text ) );
-
+
$nlinks = wfMsg( 'nlinks', $result->value );
return "$plink ($nlinks)";
}
$nt = Title::makeTitle( $result->namespace, $result->title );
$text = $wgContLang->convert( $nt->getPrefixedText() );
-
+
$plink = $skin->makeKnownLinkObj( $nt, $text );
-
+
$nl = wfMsg( 'nrevisions', $result->value );
$nlink = $skin->makeKnownLinkObj( $nt, $nl, 'action=history' );
class MovePageForm {
var $oldTitle, $newTitle, $reason; # Text input
var $moveTalk, $deleteAndMove;
-
+
function MovePageForm( $par ) {
global $wgRequest;
$target = isset($par) ? $par : $wgRequest->getVal( 'target' );
$this->moveTalk = $wgRequest->getBool( 'wpMovetalk', true );
$this->deleteAndMove = $wgRequest->getBool( 'wpDeleteAndMove' ) && $wgRequest->getBool( 'wpConfirm' );
}
-
+
function showForm( $err ) {
global $wgOut, $wgUser;
return;
}
$oldTitle = $ot->getPrefixedText();
-
+
$encOldTitle = htmlspecialchars( $oldTitle );
if( $this->newTitle == '' ) {
# Show the current title as a default
}
$moveTalkChecked = $this->moveTalk ? ' checked="checked"' : '';
-
+
$wgOut->addHTML( "
<form id=\"movepage\" method=\"post\" action=\"{$action}\">
<table border='0'>
function doSubmit() {
global $wgOut, $wgUser, $wgRequest;
$fname = "MovePageForm::doSubmit";
-
+
if ( $wgUser->pingLimiter( 'move' ) ) {
$wgOut->rateLimited();
return;
}
-
+
# Variables beginning with 'o' for old article 'n' for new article
$ot = Title::newFromText( $this->oldTitle );
}
wfRunHooks( 'SpecialMovepageAfterMove', array( &$this , &$ot , &$nt ) ) ;
-
+
# Move talk page if
# (1) the checkbox says to,
# (2) the namespaces are not themselves talk namespaces, and of course
if ( ( $wgRequest->getVal('wpMovetalk') == 1 ) &&
!$ot->isTalkPage() &&
!$nt->isTalkPage() ) {
-
+
$ott = $ot->getTalkPage();
$ntt = $nt->getTalkPage();
# Stay silent on the subject of talk.
$talkmoved = '';
}
-
+
# Give back result to user.
$titleObj = Title::makeTitle( NS_SPECIAL, 'Movepage' );
$success = $titleObj->getFullURL(
$talkmoved = $wgRequest->getVal('talkmoved');
$text = wfMsg( 'pagemovedtext', $oldtitle, $newtitle );
-
+
# Temporarily disable raw html wikitext option out of XSS paranoia
$marchingantofdoom = $wgRawHtml;
$wgRawHtml = false;
*/
class NewPagesPage extends QueryPage {
var $namespace;
-
+
function NewPagesPage( $namespace = NS_MAIN ) {
$this->namespace = $namespace;
}
return $s;
}
-
+
function feedItemDesc( $row ) {
if( isset( $row->rev_id ) ) {
$revision = Revision::newFromId( $row->rev_id );
*/
function wfSpecialNewpages($par, $specialPage) {
global $wgRequest, $wgContLang;
-
+
list( $limit, $offset ) = wfCheckLimits();
$namespace = NS_MAIN;
-
+
if ( $par ) {
$bits = preg_split( '/\s*,\s*/', trim( $par ) );
foreach ( $bits as $bit ) {
function getFile() { return $this->mFile; }
function isListed() { return $this->mListed; }
/**#@-*/
-
+
/**#@+
* Accessor and mutator
*/
function includable( $x = NULL ) { return wfSetVar( $this->mIncludable, $x ); }
function including( $x = NULL ) { return wfSetVar( $this->mIncluding, $x ); }
/**#@-*/
-
+
/**
* Checks if the given user (identified by an object) can execute this
* special page (as defined by $mRestriction)
}
}
}
-
+
/**
* @access private
*/
$wgUser->getID()
)
);
-
-
+
+
if ($wgAllowRealName) {
$wgOut->addHTML(
$this->addRow(
} else {
$invalidSig = '';
}
-
+
$wgOut->addHTML(
$this->addRow(
'<label for="wpNick">' . wfMsg( 'yournick' ) . '</label>',
$languages[$wgContLanguageCode] = $wgContLanguageCode;
}
ksort( $languages );
-
+
/**
* If a bogus value is set, default to the content language.
* Otherwise, no default is selected and the user ends up
# GET values
$from = $wgRequest->getVal( 'from' );
$namespace = $wgRequest->getInt( 'namespace' );
-
+
$namespaces = $wgContLang->getNamespaces();
$indexPage = new SpecialPrefixIndex();
wfMsg( 'allarticles' )
);
-
+
if ( isset($par) ) {
$indexPage->showChunk( $namespace, $par, $specialPage->including() );
} elseif ( isset($from) ) {
global $wgOut, $wgUser, $wgContLang;
$fname = 'indexShowChunk';
-
+
$sk = $wgUser->getSkin();
$fromTitle = Title::newFromURL( $from );
}
$fromKey = is_null( $fromTitle ) ? '' : $fromTitle->getDBkey();
-
+
$dbr =& wfGetDB( DB_SLAVE );
$res = $dbr->select( 'page',
$n = 0;
$out = '<table style="background: inherit;" border="0" width="100%">';
-
+
$namespaces = $wgContLang->getFormattedNamespaces();
while( ($n < $this->maxPerPage) && ($s = $dbr->fetchObject( $res )) ) {
$t = Title::makeTitle( $s->page_namespace, $s->page_title );
$out .= '</tr>';
}
$out .= '</table>';
-
+
if ( $including ) {
$out2 = '';
} else {
// Dump everything here
$nondefaults = array();
-
+
wfAppendToArrayIfNotDefault( 'days', $days, $defaults, $nondefaults);
wfAppendToArrayIfNotDefault( 'limit', $limit , $defaults, $nondefaults);
wfAppendToArrayIfNotDefault( 'hideminor', $hideminor, $defaults, $nondefaults);
if ($key != 'namespace' && $key != 'invert')
$out .= wfElement('input', array( 'type' => 'hidden', 'name' => $key, 'value' => $value));
}
-
+
$out .= '<input type="hidden" name="title" value="'.$t->getPrefixedText().'" />';
$out .= "
<div id='nsselect' class='recentchanges'>
$days = $wgRequest->getInt( 'days' );
$target = isset($par) ? $par : $wgRequest->getText( 'target' );
$hideminor = $wgRequest->getBool( 'hideminor' ) ? 1 : 0;
-
+
$wgOut->setPagetitle( wfMsg( 'recentchangeslinked' ) );
$sk = $wgUser->getSkin();
return;
}
$id = $nt->getArticleId();
-
+
$wgOut->setSubtitle( htmlspecialchars( wfMsg( 'rclsub', $nt->getPrefixedText() ) ) );
if ( ! $days ) {
} else { $cmq = ''; }
extract( $dbr->tableNames( 'recentchanges', 'categorylinks', 'pagelinks', 'revision', 'page' ) );
-
+
// If target is a Category, use categorylinks and invert from and to
if( $nt->getNamespace() == NS_CATEGORY ) {
$catkey = $dbr->addQuotes( $nt->getDBKey() );
$list = ChangesList::newFromUser( $wgUser );
$s = $list->beginRecentChangesList();
$count = $dbr->numRows( $res );
-
+
$counter = 1;
while ( $limit ) {
if ( 0 == $count ) { break; }
*/
function wfSpecialSearch( $par = '' ) {
global $wgRequest, $wgUser;
-
+
$search = $wgRequest->getText( 'search', $par );
$searchPage = new SpecialSearch( $wgRequest, $wgUser );
if( $wgRequest->getVal( 'fulltext' ) ||
*/
function SpecialSearch( &$request, &$user ) {
list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, 'searchlimit' );
-
+
if( $request->getCheck( 'searchx' ) ) {
$this->namespaces = $this->powerSearch( $request );
} else {
$this->searchRedirects = $request->getcheck( 'redirs' ) ? true : false;
}
-
+
/**
* If an exact title match can be found, jump straight ahead to
* @param string $term
function goResult( $term ) {
global $wgOut;
global $wgGoToEdit;
-
+
$this->setupPage( $term );
# Try to go to page as entered.
$wgOut->redirect( $t->getFullURL() );
return;
}
-
+
# No match, generate an edit URL
$t = Title::newFromText( $term );
if( is_null( $t ) ) {
return $this->showResults( $term );
}
-
+
/**
* @param string $term
* @access public
function showResults( $term ) {
$fname = 'SpecialSearch::showResults';
wfProfileIn( $fname );
-
+
$this->setupPage( $term );
-
+
global $wgUser, $wgOut;
$sk = $wgUser->getSkin();
$wgOut->addWikiText( wfMsg( 'searchresulttext' ) );
-
+
#if ( !$this->parseQuery() ) {
if( '' === trim( $term ) ) {
$wgOut->setSubtitle( '' );
wfProfileOut( $fname );
return;
}
-
+
global $wgDisableTextSearch;
if ( $wgDisableTextSearch ) {
global $wgForwardSearchUrl;
$search->showRedirects = $this->searchRedirects;
$titleMatches = $search->searchTitle( $term );
$textMatches = $search->searchText( $term );
-
+
$num = ( $titleMatches ? $titleMatches->numRows() : 0 )
+ ( $textMatches ? $textMatches->numRows() : 0);
if ( $num >= $this->limit ) {
$wgOut->addWikiText( '==' . wfMsg( 'notitlematches' ) . "==\n" );
}
}
-
+
if( $textMatches ) {
if( $textMatches->numRows() ) {
$wgOut->addWikiText( '==' . wfMsg( 'textmatches' ) . "==\n" );
$wgOut->addWikiText( '==' . wfMsg( 'notextmatches' ) . "==\n" );
}
}
-
+
if ( $num == 0 ) {
$wgOut->addWikiText( wfMsg( 'nonefound' ) );
}
$wgOut->addHTML( $this->powerSearchBox( $term ) );
wfProfileOut( $fname );
}
-
+
#------------------------------------------------------------------
# Private methods below this line
-
+
/**
*
*/
$wgOut->setArticleRelated( false );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
}
-
+
/**
* Extract default namespaces to search from the given user's
* settings, returning a list of index numbers.
}
return $arr;
}
-
+
/**
* Extract "power search" namespace settings from the request object,
* returning a list of index numbers to search.
}
return $arr;
}
-
+
/**
* Reconstruct the 'power search' options for links
* @return array
$opt['searchx'] = 1;
return $opt;
}
-
+
/**
* @param SearchResultSet $matches
* @param string $terms partial regexp for highlighting terms
function showMatches( &$matches ) {
$fname = 'SpecialSearch::showMatches';
wfProfileIn( $fname );
-
+
global $wgContLang;
$tm = $wgContLang->convertForSearchResult( $matches->termMatches() );
$terms = implode( '|', $tm );
-
+
global $wgOut;
$off = $this->offset + 1;
$out = "<ol start='{$off}'>\n";
wfProfileOut( $fname );
return $out;
}
-
+
/**
* Format a single hit result
* @param SearchResult $result
$pat1 = "/(.*)($terms)(.{0,$max})/i";
$lineno = 0;
-
+
$extract = '';
wfProfileIn( "$fname-extract" );
foreach ( $lines as $line ) {
wfProfileOut( $fname );
return "<li>{$link} ({$size}){$extract}</li>\n";
}
-
+
function powerSearchBox( $term ) {
$namespaces = '';
foreach( SearchEngine::searchableNamespaces() as $ns => $name ) {
$namespaces .= " <label><input type='checkbox' value=\"1\" name=\"" .
"ns{$ns}\"{$checked} />{$name}</label>\n";
}
-
+
$checked = $this->searchRedirects
? ' checked="checked"'
: '';
$redirect = "<input type='checkbox' value='1' name=\"redirs\"{$checked} />\n";
-
+
$searchField = '<input type="text" name="search" value="' .
htmlspecialchars( $term ) ."\" size=\"16\" />\n";
-
+
$searchButton = '<input type="submit" name="searchx" value="' .
htmlspecialchars( wfMsg('powersearch') ) . "\" />\n";
-
+
$ret = wfMsg( 'powersearchtext',
$namespaces, $redirect, $searchField,
'', '', '', '', '', # Dummy placeholders
$searchButton );
-
+
$title = Title::makeTitle( NS_SPECIAL, 'Search' );
$action = $title->escapeLocalURL();
return "<br /><br />\n<form id=\"powersearch\" method=\"get\" " .
function isExpensive() {
return true;
}
-
+
function isSyndicated() {
return false;
}
$dbr =& wfGetDB( DB_SLAVE );
$page = $dbr->tableName( 'page' );
$name = $dbr->addQuotes( $this->getName() );
-
+
return
"SELECT $name as type,
page_namespace as namespace,
FROM $page FORCE INDEX (page_len)
WHERE page_namespace=".NS_MAIN." AND page_is_redirect=0";
}
-
+
function sortDescending() {
return false;
}
*/
function wfSpecialSpecialpages() {
global $wgOut, $wgUser, $wgAvailableRights;
-
+
$wgOut->setRobotpolicy( 'index,nofollow' );
$sk = $wgUser->getSkin();
-
+
# Get listable pages, in a 2-d array with the first dimension being user right
$pages = SpecialPage::getPages();
# Yeah, that was pointless. Thanks for coming.
return;
}
-
+
/** Put them into a sortable array */
$sortedPages = array();
foreach ( $pages as $name => $page ) {
$sortedPages[$page->getDescription()] = $page->getTitle();
}
}
-
+
/** Sort */
if ( $wgSortSpecialPages ) {
ksort( $sortedPages );
$res = $dbr->query( $sql, $fname );
$userRow = $dbr->fetchObject( $res );
$users = $userRow->total;
- }
+ }
$sql = "SELECT COUNT(*) AS total FROM $user_groups WHERE ug_group='sysop'";
$res = $dbr->query( $sql, $fname );
$row = $dbr->fetchObject( $res );
$admins = $row->total;
-
+
if ($action == 'raw') {
$wgOut->disable();
header( 'Pragma: nocache' );
$wgLang->formatNum( $edits ),
$wgLang->formatNum( sprintf( '%.2f', $total ? $edits / $total : 0 ) ),
$wgLang->formatNum( sprintf( '%.2f', $edits ? $views / $edits : 0 ) ) );
-
+
$text .= "\n==" . wfMsg( 'userstats' ) . "==\n";
-
+
$text .= wfMsg( 'userstatstext',
$wgLang->formatNum( $users ),
$wgLang->formatNum( $admins ),
// should logically be after #admins, danm backwards compatability!
$wgLang->formatNum( sprintf( '%.2f', $admins / $users * 100 ) )
);
-
+
$wgOut->addWikiText( $text );
}
}
*/
class UncategorizedPagesPage extends PageQueryPage {
var $requestedNamespace = NS_MAIN;
-
+
function getName() {
return "Uncategorizedpages";
}
return true;
}
function isSyndicated() { return false; }
-
+
function getSQL() {
$dbr =& wfGetDB( DB_SLAVE );
extract( $dbr->tableNames( 'page', 'categorylinks' ) );
*/
function getTextFromRow( $row ) {
$fname = 'PageArchive::getTextFromRow';
-
+
if( is_null( $row->ar_text_id ) ) {
// An old row from MediaWiki 1.4 or previous.
// Text is embedded in this row in classic compression format.
return Revision::getRevisionText( $text );
}
}
-
+
/**
* Fetch (and decompress if necessary) the stored text of the most
);
$revision = null;
$newRevId = $previousRevId;
-
+
while( $row = $dbw->fetchObject( $result ) ) {
if( $row->ar_text_id ) {
// Revision was deleted in 1.5+; text is in
}
function execute() {
-
+
if( is_null( $this->mTargetObj ) ) {
return $this->showList();
}
function getName() {
return 'Unusedimages';
}
-
+
function sortDescending() {
return false;
}
function getSQL() {
global $wgCountCategorizedImagesAsUsed;
$dbr =& wfGetDB( DB_SLAVE );
-
+
if ( $wgCountCategorizedImagesAsUsed ) {
extract( $dbr->tableNames( 'page', 'image', 'imagelinks', 'categorylinks' ) );
-
+
return 'SELECT img_name as title, img_user, img_user_text, img_timestamp as value, img_description
FROM ((('.$page.' AS I LEFT JOIN '.$categorylinks.' AS L ON I.page_id = L.cl_from)
LEFT JOIN '.$imagelinks.' AS P ON I.page_title = P.il_to)
WHERE I.page_namespace = '.NS_IMAGE.' AND L.cl_from IS NULL AND P.il_to IS NULL';
} else {
extract( $dbr->tableNames( 'image','imagelinks' ) );
-
+
return 'SELECT img_name as title, img_user, img_user_text, img_timestamp as value, img_description' .
' FROM '.$image.' LEFT JOIN '.$imagelinks.' ON img_name=il_to WHERE il_to IS NULL ';
}
}
-
+
function formatResult( $skin, $result ) {
global $wgLang, $wgContLang;
$title = Title::makeTitle( NS_IMAGE, $result->title );
-
+
$imageUrl = htmlspecialchars( Image::imageUrl( $result->title ) );
$return =
# The 'desc' linking to the image page
. ' . . '.$skin->makeLinkObj( Title::makeTitle( NS_USER, $result->img_user_text ), $result->img_user_text)
# If there is a description, show it
. $skin->commentBlock( $wgContLang->convert( $result->img_description ) );
-
+
return $return;
}
-
+
function getPageHeader() {
return wfMsg( "unusedimagestext" );
}
WHERE wl_title IS NULL AND page_is_redirect = 0
";
}
-
+
function sortDescending() { return false; }
function formatResult( $skin, $result ) {
$nt = Title::makeTitle( $result->namespace, $result->title );
$text = $wgContLang->convert( $nt->getPrefixedText() );
-
+
$plink = $skin->makeKnownLinkObj( $nt, htmlspecialchars( $text ) );
$wlink = $skin->makeKnownLinkObj( $nt, wfMsgHtml( 'watch' ), 'action=watch' );
-
+
return $plink . ' (' . $wlink . ')';
}
}
*/
function wfSpecialUnwatchedpages() {
global $wgUser, $wgOut;
-
+
if ( ! $wgUser->isAllowed( 'unwatchedpages' ) )
return $wgOut->permissionRequired( 'unwatchedpages' );
-
+
list( $limit, $offset ) = wfCheckLimits();
$wpp = new UnwatchedpagesPage();
if( !$nt->userCanEdit() ) {
return $this->uploadError( wfMsgWikiHtml( 'protectedpage' ) );
}
-
+
/**
* In some cases we may forbid overwriting of existing files.
*/
return $this->uploadError( $veri->toString() );
}
}
-
+
/**
* Provide an opportunity for extensions to add futher checks
*/
*/
if ( ! $this->mIgnoreWarning ) {
$warning = '';
-
+
global $wgCapitalLinks;
if( $wgCapitalLinks ) {
$filtered = ucfirst( $filtered );
$license = wfMsgHtml( 'license' );
$nolicense = wfMsgHtml( 'nolicense' );
$licenseshtml = $licenses->getHtml();
-
+
$ulb = wfMsgHtml( 'uploadbtn' );
$watchChecked = $wgUser->getOption( 'watchdefault' )
? 'checked="checked"'
: '';
-
+
$wgOut->addHTML( "
<form id='upload' method='post' enctype='multipart/form-data' action=\"$action\">
<table border='0'>
</td>
</tr>
<tr>" );
-
+
if ( $licenseshtml != '' ) {
global $wgStylePath;
$wgOut->addHTML( "
$copystatus = htmlspecialchars( $this->mUploadCopyStatus );
$filesource = wfMsgHtml ( 'filesource' );
$uploadsource = htmlspecialchars( $this->mUploadSource );
-
+
$wgOut->addHTML( "
<td align='right' nowrap='nowrap'><label for='wpUploadCopyStatus'>$filestatus:</label></td>
<td><input tabindex='5' type='text' name='wpUploadCopyStatus' id='wpUploadCopyStatus' value=\"$copystatus\" size='40' /></td>
<tr>
");
}
-
-
+
+
$wgOut->addHtml( "
<td></td>
<td>
<td></td>
<td align='left'><input tabindex='9' type='submit' name='wpUpload' value=\"{$ulb}\" /></td>
</tr>
-
+
<tr>
<td></td>
<td align='left'>
$wgOut->addHTML( "
</td>
</tr>
-
+
</table>
</form>" );
}
unlink( $this->mUploadTempName );
}
}
-
+
/**
* Check if there's an overwrite conflict and, if so, if restrictions
* forbid this user from performing the upload.
// But if it does, fall through to previous behavior
return false;
}
-
+
$error = '';
if( $img->exists() ) {
global $wgUser, $wgOut;
}
}
}
-
+
if( $error ) {
$errorText = wfMsg( $error, wfEscapeWikiText( $img->getName() ) );
return new WikiError( $wgOut->parse( $errorText ) );
}
-
+
// Rockin', go ahead and upload
return true;
}
} else {
$this->mUploadOldVersion = '';
}
-
+
if ( $this->mStashed ) {
if (!$mfs->rename($tempName,$this->mSavedFile)) {
$wgOut->fileRenameError($tempName, $this->mSavedFile );
unlink($tempName);
return $stash;
}
-
+
/**
* Stash a file in a temporary directory for later processing,
* and save the necessary descriptive info into the session.
# Couldn't save the file.
return false;
}
-
+
$key = mt_rand( 0, 0x7fffffff );
$_SESSION['wsUploadData'][$key] = array(
'mUploadTempName' => $stash,
if( !$wgCommandLineMode && !isset( $_COOKIE[session_name()] ) ) {
User::SetupSession();
}
-
+
$form = new LoginForm( $wgRequest );
$form->execute();
}
var $mName, $mPassword, $mRetype, $mReturnto, $mCookieCheck, $mPosted;
var $mAction, $mCreateaccount, $mCreateaccountMail, $mMailmypassword;
var $mLoginattempt, $mRemember, $mEmail, $mDomain;
-
+
/**
* Constructor
* @param webrequest $request A webrequest object passed by reference
$this->mLoginattempt = $request->getCheck( 'wpLoginattempt' );
$this->mAction = $request->getVal( 'action' );
$this->mRemember = $request->getCheck( 'wpRemember' );
-
+
if( $wgEnableEmail ) {
$this->mEmail = $request->getText( 'wpEmail' );
} else {
} else {
$this->mRealName = '';
}
-
+
if( !$wgAuth->validDomain( $this->mDomain ) ) {
$this->mDomain = 'invaliddomain';
}
*/
function addNewAccountMailPassword() {
global $wgOut;
-
+
if ('' == $this->mEmail) {
$this->mainLoginForm( wfMsg( 'noemail', htmlspecialchars( $this->mName ) ) );
return;
$u->saveSettings();
$result = $this->mailPasswordInternal($u);
-
+
$wgOut->setPageTitle( wfMsg( 'accmailtitle' ) );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$wgOut->setArticleRelated( false );
-
+
if( WikiError::isError( $result ) ) {
$this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) );
} else {
$this->mainLoginForm( wfMsg( 'badretype' ) );
return false;
}
-
+
$name = trim( $this->mName );
$u = User::newFromName( $name );
if ( is_null( $u ) ) {
$this->mainLoginForm( wfMsg( 'noname' ) );
return false;
}
-
+
if ( wfReadOnly() ) {
$wgOut->readOnlyPage();
return false;
}
-
+
if ( 0 != $u->idForName() ) {
$this->mainLoginForm( wfMsg( 'userexists' ) );
return false;
return false;
}
}
-
+
if( !wfRunHooks( 'AbortNewAccount', array( $u ) ) ) {
// Hook point to add extra creation throttles and blocks
wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" );
return $this->initUser( $u );
}
-
+
/**
* Actually add a user to the database.
* Give it a User object that has been initialised with a name.
$u->setEmail( $this->mEmail );
$u->setRealName( $this->mRealName );
$u->setToken();
-
+
global $wgAuth;
$wgAuth->initUser( $u );
$u->setOption( 'rememberpassword', $this->mRemember ? 1 : 0 );
-
+
return $u;
}
$wgUser->setCookies();
$wgUser->saveSettings();
-
+
if( $this->hasSessionCookie() ) {
return $this->successfulLogin( wfMsg( 'loginsuccess', $wgUser->getName() ) );
} else {
global $wgOut;
# Run any hooks; ignore results
-
+
wfRunHooks('UserLoginComplete', array(&$wgUser));
-
+
$wgOut->setPageTitle( wfMsg( 'loginsuccesstitle' ) );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$wgOut->setArticleRelated( false );
/** */
function userNotPrivilegedMessage() {
global $wgOut;
-
+
$wgOut->setPageTitle( wfMsg( 'whitelistacctitle' ) );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$wgOut->setArticleRelated( false );
$wgOut->addWikiText( wfMsg( 'whitelistacctext' ) );
-
+
$wgOut->returnToMain( false );
}
$link .= '</a>';
$template->set( 'link', wfMsgHtml( $linkmsg, $link ) );
-
+
$template->set( 'name', $this->mName );
$template->set( 'password', $this->mPassword );
$template->set( 'retype', $this->mRetype );
$template->set( 'useemail', $wgEnableEmail );
$template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) or $this->mRemember );
$wgAuth->modifyUITemplate( $template );
-
+
$wgOut->setPageTitle( wfMsg( 'userlogin' ) );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$wgOut->setArticleRelated( false );
global $wgDisableCookieCheck;
return ( $wgDisableCookieCheck ) ? true : ( isset( $_COOKIE[session_name()] ) );
}
-
+
/**
* @access private
*/
global $wgUser, $wgOut;
if (wfRunHooks('UserLogout', array(&$wgUser))) {
-
+
$wgUser->logout();
wfRunHooks('UserLogoutComplete', array(&$wgUser));
-
+
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$wgOut->addHTML( wfMsg( 'logouttext' ) );
$wgOut->returnToMain();
-
+
}
}
$this->mPosted = $request->wasPosted();
$this->mRequest =& $request;
$this->mName = 'userrights';
-
+
$titleObj = Title::makeTitle( NS_SPECIAL, 'Userrights' );
$this->action = $titleObj->escapeLocalURL();
}
if($u->getID() == 0) {
$wgOut->addWikiText( wfMsg( 'nosuchusershort', htmlspecialchars( $username ) ) );
return;
- }
+ }
$oldGroups = $u->getGroups();
$newGroups = $oldGroups;
$logcomment = ' ';
- // remove then add groups
+ // remove then add groups
if(isset($removegroup)) {
$newGroups = array_diff($newGroups, $removegroup);
foreach( $removegroup as $group ) {
}
}
$newGroups = array_unique( $newGroups );
-
+
wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) );
wfDebug( 'newGroups: ' . print_r( $newGroups, true ) );
*/
function switchForm() {
global $wgOut;
-
+
// user selection
$wgOut->addHTML( "<form name=\"uluser\" action=\"$this->action\" method=\"post\">\n" );
$wgOut->addHTML( $this->fieldset( 'lookup-user',
*/
function editUserGroupsForm($username) {
global $wgOut, $wgUser;
-
+
$user = User::newFromName($username);
if( is_null( $user ) || $user->getID() == 0 ) {
$wgOut->addWikiText( wfMsg( 'nosuchusershort', wfEscapeWikiText( $username ) ) );
return;
}
-
+
$groups = $user->getGroups();
$wgOut->addHTML( "<form name=\"editGroup\" action=\"$this->action\" method=\"post\">\n".
$db =& wfGetDB( DB_SLAVE );
$topics = array();
-
+
# NOTE : This query returns only the topics to vote on
$res = $db->select( 'validate', '*', array( 'val_page' => 0 ), 'SpecialValidate::getTopicList' );
while( $topic = $db->fetchObject($res) ) {
ksort( $topics );
return $topics;
}
-
+
# Merges one dataset into another
function mergeInto( &$source, &$dest ) {
$ret = false;
$this->setRevision( $article, $revision, $data );
}
}
-
+
# Clears all votes prior to the given revision
function clearOldRevisions( &$article, $revision ) {
$tmp = $this->voteCache;
}
}
}
-
+
# Updates the votes for the given revision from the FORM data
function updateRevision( &$article, $revision ) {
global $wgRequest;
-
+
if( isset( $this->voteCache[$this->getRevisionTimestamp( $revision )] ) ) {
$data = $this->voteCache[$this->getRevisionTimestamp( $revision )];
} else {
}
$nv = $wgRequest->getArray( "re_v_{$revision}", array() );
$nc = $wgRequest->getArray( "re_c_{$revision}", array() );
-
+
foreach( $nv as $x => $y ) {
$data[$x]->value = $y;
$data[$x]->comment = $nc[$x];
}
krsort( $data );
-
+
$this->setRevision( $article, $revision, $data );
}
-
+
# Sets a specific revision to both cache and database
function setRevision( &$article, $revision, &$data ) {
global $wgUser;
}
}
}
-
+
# Returns a map identifying the current user
function identifyUser( $user = "" ) {
global $wgUser;
? array( 'val_user' => 0, 'val_ip' => $user )
: array( 'val_user' => $user );
}
-
+
# Deletes a specific vote set in both cache and database
function deleteRevisionVote( &$article, $revision ) {
$ts = $this->getRevisionTimestamp( $revision );
unset( $this->voteCache[$ts] );
}
-
+
# Reads the entire vote list for this user for the given article
function getVoteList( $id, $user = "" ) {
$db =& wfGetDB( DB_SLAVE );
-
+
# NOTE : This query gets the votes for a single user on a single page.
# Assuming most people will use the "merge" feature,
# this will be only a single entry.
return $revisions;
}
-
+
# Reads a partial vote list for this user for all articles
function getAllVoteLists( $user , $offset , $limit ) {
$db =& wfGetDB( DB_SLAVE );
$a = $this->identifyUser($user) ;
$b = array ( "ORDER BY" => "val_page,val_revision" , "OFFSET" => $offset , "LIMIT" => $limit ) ;
$res = $db->select( 'validate', '*', $a , 'getAllVotesList' , $b );
-
+
$votes = array();
while( $vote = $db->fetchObject($res) ) {
$votes[$vote->val_page][$vote->val_revision][$vote->val_type] = $vote;
}
$db->freeResult($res);
-
+
return $votes ;
}
-
+
# This functions adds a topic to the database
function addTopic( $topic, $limit ) {
$db =& wfGetDB( DB_MASTER );
$db->delete( 'validate', array( 'val_type' => $id ), 'SpecialValidate::deleteTopic' );
unset( $this->topicList[$id] );
}
-
+
# This function returns a link text to the page validation statistics
function getStatisticsLink( &$article ) {
global $wgUser;
# HTML generation functions from this point on
-
+
# Returns the metadata string for a revision
function getMetadata( $rev_id, &$article ) {
global $wgUser;
$metadata .= ': '. $sk->commentBlock( $x->rev_comment, $article->getTitle() );
return $metadata;
}
-
+
# Generates a link to the topic description
function getTopicLink($s) {
$t = Title::newFromText ( wfMsg ( 'val_topic_desc_page' ) ) ;
$r .= "\">{$s}</a>" ;
return $r ;
}
-
+
# Generates HTML from a wiki text, e.g., a wfMsg
function getParsedWiki ( $text ) {
global $wgOut, $wgTitle, $wgParser ;
$data[$x]->comment = "";
}
}
- ksort( $data ) ;
-
+ ksort( $data ) ;
+
# Generate form
$table_class = $focus ? 'revisionform_focus' : 'revisionform_default';
$ret = "<form method='post'><table class='{$table_class}'>\n";
$ret .= "<th>\n";
$ret .= $this->getTopicLink ( $this->topicList[$x]->val_comment ) ;
$ret .= "</th>\n";
-
+
$tlx = $this->topicList[$x];
$vote = "";
$max = $tlx->val_value;
if ( $a == 0 ) {
$vote .= " ";
}
- }
+ }
$ret .= "<td nowrap>{$vote}</td>\n";
-
+
$ret .= "<td width='100%'><input size='50' style='width:98%' maxlength='250' type='text' name='re_c{$idx}' value='{$y->comment}'/>";
$ret .= "</td></tr>\n";
}
$ret .= "<input type='checkbox' name='re_merge_{$revision}' value='1'{$checked} />" . $this->getParsedWiki( wfMsg( 'val_merge_old' ) ) . " \n";
$ret .= "<input type='checkbox' name='re_clear_{$revision}' value='1'{$checked} />" . $this->getParsedWiki( wfMsg( 'val_clear_old' ) ) . " \n";
$ret .= "<input type='submit' name='re_submit[{$revision}]' value=\"" . wfMsgHtml( "ok" ) . "\" />\n";
-
+
if( $focus ) $ret .= "<br/>\n<small>" . $this->getParsedWiki ( wfMsg( "val_form_note" ) ) . "</small>";
$ret .= "</td></tr>\n";
$ret .= "</table></form>\n\n";
return $ret;
}
-
+
# Generates the page from the validation tab
function validatePageForm( &$article, $revision ) {
global $wgOut, $wgRequest, $wgUser;
-
+
$ret = "";
$this->page_id = $article->getID();
$this->topicList = $this->getTopicList();
if ( $this->getNoTopicsWarning() ) return "" ;
$this->voteCache = $this->getVoteList( $article->getID() );
-
+
# Check for POST data
$re = $wgRequest->getArray( 're_submit' );
if ( isset( $re ) ) {
} else {
$ret .= $this->getParsedWiki( wfMsg ('val_votepage_intro') );
}
-
+
# Make sure the requested revision exists
$rev = $this->getRevisionFromId($revision);
$ts = $rev->rev_timestamp;
if( !isset( $this->voteCache[$ts] ) ) {
$this->voteCache[$ts] = array();
}
-
+
# Sort revisions list, newest first
krsort( $this->voteCache );
-
+
# Output
$title = $article->getTitle();
$title = $title->getPrefixedText();
}
$ret .= $this->getStatisticsLink( $article );
$ret .= "<p>" . $this->getUserRatingsLink( $wgUser->getID(), wfMsg( 'val_show_my_ratings' ) ) . "</p>";
- return $ret ;
+ return $ret ;
}
-
+
# This function performs the "management" mode on Special:Validate
function manageTopics() {
global $wgRequest, $wgValidationMaxTopics;
$this->topicList = $this->getTopicList();
-
+
$r = "" ; # Return value
$iamsure = true ; # Sure by default, see checkbox below # $wgRequest->getVal( "iamsure", "0" ) == 1;
-
+
if( $iamsure && $wgRequest->getVal( "m_add", "--" ) != "--" ) {
if ( count ( $this->topicList ) >= $wgValidationMaxTopics ) { # Catching this in case someone tries a manually edited URL...
$ret .= "<p><b>" . wfMsg ( 'val_max_topics' , $wgValidationMaxTopics ) . "</b></p>" ;
$id = array_shift( $id );
$this->deleteTopic( $id );
}
-
+
# FIXME: Wikitext this
$r .= "<p>" . $this->getParsedWiki( wfMsg( 'val_warning' ) ) . "</p>\n";
$r .= "<form method='post'>\n";
$r .= "<td><input type='submit' name='m_del[" . intval( $x ) . "]' value='" . htmlspecialchars( wfMsg( 'val_del' ) ) . "'/></td>\n";
$r .= "</tr>\n";
}
-
+
# Add topic, or too-many-topics warning
if ( count ( $this->topicList ) >= $wgValidationMaxTopics ) {
$r .= "<tr><td colspan='4' align='center'>" ;
$r .= '</td>' . "\n";
$r .= "</tr>" ;
}
-
+
$r .= "</table>\n";
-# This is fot the checkbox "I am sure" for actions, which was found to be unituitive
+# This is fot the checkbox "I am sure" for actions, which was found to be unituitive
# $r .= '<p><input type="checkbox" name="iamsure" id="iamsure" value="1"/>';
# $r .= '<label for="iamsure">' . $this->getParsedWiki( wfMsg( 'val_iamsure' ) ) . "</label></p>\n";
$r .= "</form>\n";
return $r;
}
-
+
# Generates an ID for both logged-in users and anons; $res is an object from an SQL query
function make_user_id( &$res ) {
return $res->val_user == 0 ? $res->val_ip : $res->val_user;
$sk = $wgUser->getSkin();
$title = $article->getTitle();
$wgOut->setPageTitle( str_replace( '$1', $title->getPrefixedText(), wfMsg( 'val_validation_of' ) ) );
-
+
$data = array();
$users = array();
$topics = array();
$topics[$x->val_type] = true;
}
$db->freeResult($res);
-
+
# Sorting lists of topics and users
ksort( $users );
ksort( $topics );
-
+
$ts = $this->getRevisionTimestamp( $revision );
$url = $this->getRevisionLink( $article, $revision, wfTimestamp( TS_DB, $ts ) );
# Table headers
- $ret = "" ;
+ $ret = "" ;
$ret .= "<p><b>" . str_replace( '$1', $url, wfMsg( 'val_revision_of' ) ) . "</b></p>\n";
$ret .= "<table>\n";
$ret .= "<tr><th>" . $this->getParsedWiki ( wfMsg('val_details_th') ) . "</th>" ;
-
+
foreach( $topics as $t => $dummy ) {
$ret .= '<th>' . $sk->commentBlock( $this->topicList[$t]->val_comment, $article->getTitle() ) . '</th>';
}
$ret .= "</table>";
$ret .= "<p>" . $this->getStatisticsLink( $article ) . "</p>";
$ret .= "<p>" . $this->getUserRatingsLink( $wgUser->getID(), wfMsg( 'val_show_my_ratings' ) ) . "</p>";
-
+
return $ret;
}
-
+
function showList( &$article ) {
global $wgOut, $wgUser , $wgRequest;
$this->page_id = $article->getID();
$title = $article->getTitle();
$wgOut->setPageTitle( wfMsg( 'val_validation_of', $title->getPrefixedText() ) );
-
+
$offset = $wgRequest->getVal ( "offset" , 0 ) ;
$limit = $wgRequest->getVal ( "limit" , 25 ) ;
-
+
# Collecting statistic data
# Unfortunately, it has to read all the data, though it will only display a part
$db =& wfGetDB( DB_SLAVE );
# Paging
$statistics = array_slice ( $statistics , $offset , $limit ) ;
-
+
foreach( $statistics as $ts => $data ) {
$rev_id = $this->getRevisionId( $ts );
$revision_link = $this->getRevisionLink( $article, $rev_id, wfTimestamp( TS_DB, $ts ) );
return $ret;
}
-
+
function getRatingText( $value, $max ) {
if( $max == 2 && $value == 1 ) {
$ret = wfMsg ( "val_no" ) . " ";
$sk = $wgUser->getSkin();
$r = array () ;
$user = $wgRequest->getVal( "user" );
-
+
if ( $mode == "userstats" ) {
$nt = Title::newFromText( 'Special:Validate' );
} else {
$nt = $wgTitle ;
}
-
+
$base = "action=validate&mode={$mode}&" ;
if ( $user != "" ) $base .= "user={$user}&" ;
$base .= "limit={$limit}&offset=" ;
-
+
if ( $offset > 0 ) {
$o = $offset - $limit ;
$t = $offset-$limit+1 ;
$r[] = $sk->makeKnownLinkObj( $nt, "{$t} <<" , $base.$o );
}
-
+
$s1 = $offset + 1 ;
$s2 = $s1 + $lastcount - 1 ;
$r[] = $s1 . " - " . $s2 ;
-
+
if ( $lastcount == $limit ) {
$o = $offset + $limit ;
$t = $offset+$limit+1 ;
$r[] = $sk->makeKnownLinkObj( $nt, ">> {$t}" , $base.$o );
}
-
+
$r = implode ( " | " , $r ) ;
return $r ;
}
-
- function showUserStats( $user ) {
+
+ function showUserStats( $user ) {
global $wgOut, $wgUser, $wgRequest;
$this->topicList = $this->getTopicList();
if ( $this->getNoTopicsWarning() ) return "" ;
$sk = $wgUser->getSkin();
-
+
$offset = $wgRequest->getVal( "offset" , 0 );
$limit = $wgRequest->getVal( "limit" , 25 );
$data = $this->getAllVoteLists( $user , $offset , $limit ) ;
-
+
if( $user == $wgUser->getID() ) {
$wgOut->setPageTitle ( wfMsg ( 'val_my_stats_title' ) );
} elseif( !User::IsIP( $user ) ) {
} else {
$wgOut->setPageTitle( wfMsg( 'val_user_stats_title', $user ) );
}
-
+
$ret = "" ;
$ret = "<table>\n";
-
+
$linecount = 0 ;
$lastpage = -1 ;
$lastrevision = -1 ;
$ret .= "</tr>";
}
$ret .= "</table>";
-
-
+
+
$s = $this->navBar ( $offset , $limit , $linecount ) ;
if ( $s != "" ) $ret = $s . "<br/>" . $ret . "<br/>" . $s ;
-
+
return $ret;
}
-
+
function getNoTopicsWarning () {
global $wgOut ;
if ( !isset ( $this->topicList ) ) # Just making sure, shouldn't be necessary...
*/
function wfSpecialValidate( $page = '' ) {
global $wgOut, $wgRequest, $wgUseValidation, $wgUser;
-
+
if( !$wgUseValidation ) {
$wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
return;
* @access private
*/
var $langObj;
-
+
/**
* Constructor
*/
*/
function execute() {
global $wgOut;
-
+
$wgOut->addWikiText(
$this->MediaWikiCredits() .
$this->extensionCredits() .
/**#@+
* @access private
*/
-
+
/**
* @static
*/
function MediaWikiCredits() {
global $wgVersion;
-
+
$dbr =& wfGetDB( DB_SLAVE );
-
+
$ret =
"__NOTOC__
<div dir='ltr'>
This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''',
copyright (C) 2001-2006 Magnus Manske, Brion Vibber, Lee Daniel Crocker,
Tim Starling, Erik Möller, and others.
-
+
MediaWiki is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
MediaWiki is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU General Public License]
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
or [http://www.gnu.org/copyleft/gpl.html read it online]
-
+
* [http://www.mediawiki.org/ MediaWiki]: $wgVersion
* [http://www.php.net/ PHP]: " . phpversion() . " (" . php_sapi_name() . ")
* " . $dbr->getSoftwareLink() . ": " . $dbr->getServerVersion() . "
function extensionCredits() {
global $wgExtensionCredits, $wgExtensionFunctions, $wgSkinExtensionFunction;
-
+
if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunction ) )
return '';
'other' => 'Other',
);
wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) );
-
+
$out = "\n* Extensions:\n";
foreach ( $extensionTypes as $type => $text ) {
if ( count( @$wgExtensionCredits[$type] ) ) {
$out .= "** $text:\n";
-
+
usort( $wgExtensionCredits[$type], array( $this, 'compare' ) );
-
+
foreach ( $wgExtensionCredits[$type] as $extension ) {
wfSuppressWarnings();
$out .= $this->formatCredits(
$ret = "* Hooks:\n";
foreach ($myWgHooks as $hook => $hooks)
$ret .= "** $hook:" . $this->langObj->listToText( $hooks ) . "\n";
-
+
return $ret;
}
$ip = str_replace( '--', ' - ', htmlspecialchars( wfGetIP() ) );
return "<!-- visited from $ip -->\n";
}
-
+
/**#@-*/
}
GROUP BY cl_to
";
}
-
+
function sortDescending() { return true; }
/**
$nt = Title::makeTitle( $result->namespace, $result->title );
$text = $wgContLang->convert( $nt->getText() );
-
+
$plink = $this->isCached() ?
$skin->makeLinkObj( $nt, htmlspecialchars( $text ) ) :
$skin->makeBrokenLinkObj( $nt, htmlspecialchars( $text ) );
-
+
$nlinks = wfMsg( 'nlinks', $result->value );
return "$plink ($nlinks)";
}
*/
class WantedPagesPage extends QueryPage {
var $nlinks;
-
+
function WantedPagesPage( $inc = false, $nlinks = true ) {
$this->setListoutput( $inc );
$this->nlinks = $nlinks;
// If there are no rows we get an error seeking.
$db->dataSeek( $res, 0 );
}
-
-
+
+
function formatResult( $skin, $result ) {
global $wgContLang;
$plink = $this->isCached() ?
$skin->makeLinkObj( $nt, $text ) :
$skin->makeBrokenLink( $nt->getPrefixedText(), $text );
-
+
$nl = wfMsg( 'nlinks', $result->value );
$nlink = $skin->makeKnownLink( $wgContLang->specialPage( 'Whatlinkshere' ), $nl, 'target=' . $nt->getPrefixedURL() );
*/
function wfSpecialWantedpages( $par = null, $specialPage ) {
$inc = $specialPage->including();
-
+
if ( $inc ) {
@list( $limit, $nlinks ) = explode( '/', $par, 2 );
$limit = (int)$limit;
} else {
$andHideBotsOptional = "AND rc_this_oldid=page_latest";
}
-
-
+
+
# Show watchlist header
$header = '';
if( $wgUser->getOption( 'enotifwatchlistpages' ) && $wgEnotifWatchlist) {
$wgLang->formatNum( $npages ), '',
$specialTitle->getFullUrl( 'edit=yes' ) );
$wgOut->addWikiText( $header );
-
+
if ( $wgEnotifWatchlist && $wgShowUpdatedMarker ) {
$wgOut->addHTML( '<form action="' .
$specialTitle->escapeLocalUrl() .
$wgLang->formatNum( round($days*24) ) ) . '<br />' , false );
$wgOut->addHTML( "\n" . wlCutoffLinks( $days, 'Watchlist', $nondefaults ) . "<br />\n" );
-
+
$sk = $wgUser->getSkin();
$s = $sk->makeKnownLink(
$wgContLang->specialPage( 'Watchlist' ),
wfArrayToCGI( array('hideBots' => 1-$hideBots ), $nondefaults ) );
$wgOut->addHTML( wfMsgHtml( "wlhideshowbots", " $s" ) );
}
-
+
if ( $numRows == 0 ) {
$wgOut->addWikitext( "<br />" . wfMsg( 'watchnochange' ), false );
$wgOut->addHTML( "</p>\n" );
var $request, $par;
var $limit, $from, $dir, $target;
var $selfTitle, $skin;
-
+
function WhatLinksHerePage( &$request, $par = null ) {
global $wgUser;
$this->request =& $request;
function execute() {
global $wgUser, $wgOut;
-
+
$this->limit = min( $this->request->getInt( 'limit', 50 ), 5000 );
if ( $this->limit <= 0 ) {
$this->limit = 50;
if ( $this->dir != 'prev' ) {
$this->dir = 'next';
}
-
+
$targetString = isset($this->par) ? $this->par : $this->request->getVal( 'target' );
if (is_null($targetString)) {
$fname = 'WhatLinksHerePage::showIndirectLinks';
$dbr =& wfGetDB( DB_READ );
-
+
extract( $dbr->tableNames( 'pagelinks', 'templatelinks', 'page' ) );
// Some extra validation
// Before start? No make sense
$dir = 'next';
}
-
+
// Make the query
$plConds = array(
'page_id=pl_from',
'pl_namespace' => $target->getNamespace(),
'pl_title' => $target->getDBkey(),
);
-
+
$tlConds = array(
'page_id=tl_from',
'tl_namespace' => $target->getNamespace(),
'tl_title' => $target->getDBkey(),
);
-
+
if ( $from ) {
if ( 'prev' == $dir ) {
$offsetCond = "page_id < $from";
$plConds[] = $offsetCond;
}
$fields = array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' );
-
+
$plRes = $dbr->select( array( 'pagelinks', 'page' ), $fields,
$plConds, $fname, $options );
$tlRes = $dbr->select( array( 'templatelinks', 'page' ), $fields,
$tlConds, $fname, $options );
-
+
if ( !$dbr->numRows( $plRes ) && !$dbr->numRows( $tlRes ) ) {
if ( 0 == $level ) {
$wgOut->addWikiText( wfMsg( 'nolinkshere' ) );
}
return;
- }
+ }
// Read the rows into an array and remove duplicates
// templatelinks comes second so that the templatelinks row overwrites the
// Sort by key and then change the keys to 0-based indices
ksort( $rows );
$rows = array_values( $rows );
-
+
$numRows = count( $rows );
-
+
// Work out the start and end IDs, for prev/next links
if ( $dir == 'prev' ) {
// Descending order
}
// Assume that the ID specified in $from exists, so there must be another page
$nextId = $from;
-
+
// Reverse order ready for display
$rows = array_reverse( $rows );
} else {
}
$prevId = $from;
}
-
+
if ( 0 == $level ) {
$wgOut->addWikiText( wfMsg( 'linkshere' ) );
}
$isredir = wfMsg( 'isredirect' );
$istemplate = wfMsg( 'istemplate' );
-
+
if( $level == 0 ) {
$prevnext = $this->getPrevNext( $limit, $prevId, $nextId );
$wgOut->addHTML( $prevnext );
}
-
+
$wgOut->addHTML( '<ul>' );
foreach ( $rows as $row ) {
$nt = Title::makeTitle( $row->page_namespace, $row->page_title );
// FIXME? Cultural assumption, hard-coded punctuation
$wgOut->addHTML( ' (' . implode( ', ', $props ) . ') ' );
}
-
+
if ( $row->page_is_redirect ) {
if ( $level < 2 ) {
$this->showIndirectLinks( $level + 1, $nt, 500 );
$wgOut->addHTML( "</li>\n" );
}
$wgOut->addHTML( "</ul>\n" );
-
+
if( $level == 0 ) {
$wgOut->addHTML( $prevnext );
}
$fname = 'SquidUpdate::purge';
wfProfileIn( $fname );
-
+
$maxsocketspersquid = 8; // socket cap per Squid
$urlspersocket = 400; // 400 seems to be a good tradeoff, opening a socket takes a while
$firsturl = $urlArr[0];
return;
}
}
-
+
header( 'Content-Length: ' . $stat['size'] );
-
+
$type = wfGetType( $fname );
if ( $type and $type!="unknown/unknown") {
header("Content-type: $type");
} else {
header('Content-type: application/x-wiki');
}
-
+
readfile( $fname );
}
# used for thumbnails (thumb.php)
if ($wgTrivialMimeDetection) {
$ext= strtolower(strrchr($filename, '.'));
-
+
switch ($ext) {
case '.gif': return 'image/gif';
case '.png': return 'image/png';
case '.jpg': return 'image/jpeg';
case '.jpeg': return 'image/jpeg';
}
-
+
return 'unknown/unknown';
}
else {
wfProfileOut( $fname );
return false;
}
-
+
if( $this->mDbkeyform == '_' ) {
# FIXME: Is this necessary? Shouldn't be allowed anyway...
wfProfileOut( $fname );
wfProfileOut( $fname );
return false;
}
-
+
if( $action == 'create' ) {
if( ( $this->isTalkPage() && !$wgUser->isAllowed( 'createtalk' ) ) ||
( !$this->isTalkPage() && !$wgUser->isAllowed( 'createpage' ) ) ) {
$toucharr[] = $row->pl_from;
}
$dbw->freeResult( $res );
-
+
if( $this->getNamespace() == NS_CATEGORY ) {
// Categories show up in a separate set of links as well
$res = $dbw->select( 'categorylinks',
}
$dbw->freeResult( $res );
}
-
+
if (!count($toucharr))
return;
$dbw->update( 'page', /* SET */ array( 'page_touched' => $dbw->timestamp() ),
|| strlen( $name ) > $wgMaxNameChars
|| $name != $wgContLang->ucfirst( $name ) )
return false;
-
+
// Ensure that the name can't be misresolved as a different title,
// such as with extra namespace keys at the start.
$parsed = Title::newFromText( $name );
}
$this->mRegistration = wfTimestamp( TS_MW );
-
+
wfProfileOut( $fname );
}
} else {
wfDebug( "User::loadFromSession() got from cache!\n" );
}
-
+
if ( isset( $_SESSION['wsToken'] ) ) {
$passwordCorrect = $_SESSION['wsToken'] == $user->mToken;
} else if ( isset( $_COOKIE["{$wgDBname}Token"] ) ) {
$this->mGroups[] = $row->ug_group;
}
$implicitGroups = array( '*', 'user' );
-
+
global $wgAutoConfirmAge;
$accountAge = time() - wfTimestampOrNull( TS_UNIX, $this->mRegistration );
if( $accountAge >= $wgAutoConfirmAge ) {
$implicitGroups[] = 'autoconfirmed';
}
-
+
$effectiveGroups = array_merge( $implicitGroups, $this->mGroups );
$this->mRights = $this->getGroupPermissions( $effectiveGroups );
}
array( $field => $id ), $fname );
return $ok !== false;
}
-
+
/**
* Add or update the
* @param string $field
wfDebug( "$fname: set on ($field, $id)\n" );
return true;
}
-
+
/**
* Clear the new messages flag for the given user
* @param string $field
wfDebug( "$fname: killed on ($field, $id)\n" );
return true;
}
-
+
/**
* Update the 'You have new messages!' status.
* @param bool $val
if( wfReadOnly() ) {
return;
}
-
+
$this->loadFromDatabase();
$this->mNewtalk = $val;
$fname = 'User::setNewtalk';
-
+
if( $this->isAnon() ) {
$field = 'user_ip';
$id = $this->getName();
$field = 'user_id';
$id = $this->getId();
}
-
+
if( $val ) {
$changed = $this->updateNewtalk( $field, $id );
} else {
$changed = $this->deleteNewtalk( $field, $id );
}
-
+
if( $changed ) {
if( $this->isAnon() ) {
// Anons have a separate memcached space, since
# get the user skin
$userSkin = $this->getOption( 'skin' );
$userSkin = $wgRequest->getVal('useskin', $userSkin);
-
+
$this->mSkin =& Skin::newFromKey( $userSkin );
wfProfileOut( $fname );
}
$title->getText() == $this->getName() ) {
$this->setNewtalk( false );
}
-
+
if( !$wgUseEnotif ) {
return;
}
// add in language specific options, if any
$extra = $wgContLang->getExtraHashOptions();
$confstr .= $extra;
-
+
// Give a chance for extensions to modify the hash, if they have
// extra options or other effects on the parser cache.
wfRunHooks( 'PageRenderingHash', array( &$confstr ) );
array_keys( $wgGroupPermissions ),
array( '*', 'user', 'autoconfirmed' ) );
}
-
+
}
?>
$this->name = strval( $name );
}
}
-
+
/**
* Return formatted and quoted address to insert into SMTP headers
* @return string
$timestamp = time();
$dest = $to->toString();
-
+
$headers['From'] = $from->toString();
$headers['To'] = $dest;
if ( $replyto ) {
}
$dest = $to->toString();
-
+
$wgErrorString = '';
set_error_handler( 'mailErrorHandler' );
wfDebug( "Sending mail via internal mail() function to $dest\n" );
if( $userCondition ) {
$dbr =& wfGetDB( DB_MASTER );
extract( $dbr->tableNames( 'watchlist' ) );
-
+
$res = $dbr->select( 'watchlist', array( 'wl_user' ),
array(
'wl_title' => $title->getDBkey(),
$userCondition,
'wl_notificationtimestamp IS NULL',
), $fname );
-
+
# if anyone is watching ... set up the email message text which is
# common for all receipients ...
if ( $dbr->numRows( $res ) > 0 ) {
$this->summary = $summary;
$this->minorEdit = $minorEdit;
$this->oldid = $oldid;
-
+
$this->composeCommonMailtext();
$watchingUser = new User();
-
+
# ... now do for all watching users ... if the options fit
for ($i = 1; $i <= $dbr->numRows( $res ); $i++) {
-
+
$wuser = $dbr->fetchObject( $res );
$watchingUser->setID($wuser->wl_user);
if ( ( $enotifwatchlistpage && $watchingUser->getOption('enotifwatchlistpages') ) ||
# ... adjust remaining text and page edit time placeholders
# which needs to be personalized for each user
$this->composeAndSendPersonalisedMail( $watchingUser );
-
+
} # if the watching user has an email address in the preferences
}
}
$pagetitle = $this->title->getPrefixedText();
$keys['$PAGETITLE'] = $pagetitle;
$keys['$PAGETITLE_URL'] = $this->title->getFullUrl();
-
+
$keys['$PAGEMINOREDIT'] = $medit;
$keys['$PAGESUMMARY'] = $summary;
$body = str_replace( '$WATCHINGUSERNAME', $watchingUser->getName() , $this->body );
$timecorrection = $watchingUser->getOption( 'timecorrection' );
-
+
# $PAGEEDITDATE is the time and date of the page change
# expressed in terms of individual local time of the notification
# recipient, i.e. watching user
function addWatch() {
$fname = 'WatchedItem::addWatch';
wfProfileIn( $fname );
-
+
// Use INSERT IGNORE to avoid overwriting the notification timestamp
// if there's already an entry for this page
$dbw =& wfGetDB( DB_MASTER );
WatchedItem::doDuplicateEntries( $ot->getSubjectPage(), $nt->getSubjectPage() );
WatchedItem::doDuplicateEntries( $ot->getTalkPage(), $nt->getTalkPage() );
}
-
+
/**
* @static
* @access private
);
}
$dbw->freeResult( $res );
-
+
if( empty( $values ) ) {
// Nothing to do
return true;
}
return $arr;
}
-
+
/**
* If magic_quotes_gpc option is on, run the global arrays
* through fix_magic_quotes to strip out the stupid slashes.
$this->fix_magic_quotes( $_SERVER );
}
}
-
+
/**
* Recursively normalizes UTF-8 strings in the given array.
* @param array $data string or array
}
return $data;
}
-
+
/**
* Fetch a value from the given array or return $default if it's not set.
*
return (string)$val;
}
}
-
+
/**
* Fetch an array from the input or return $default if it's not set.
* If source was scalar, will return an array with a single element.
function getInt( $name, $default = 0 ) {
return intval( $this->getVal( $name, $default ) );
}
-
+
/**
* Fetch an integer value from the input or return null if empty.
* Guaranteed to return an integer or null; non-numeric input will
? intval( $val )
: null;
}
-
+
/**
* Fetch a boolean value from the input or return $default if not set.
* Guaranteed to return true or false, with normal PHP semantics for
function getBool( $name, $default = false ) {
return $this->getVal( $name, $default ) ? true : false;
}
-
+
/**
* Return true if the named value is set in the input, whatever that
* value is (even "0"). Return false if the named value is not set.
$val = $this->getVal( $name, NULL );
return isset( $val );
}
-
+
/**
* Fetch a text string from the given array or return $default if it's not
* set. \r is stripped from the text, and with some language modules there
return str_replace( "\r\n", "\n",
$wgContLang->recodeInput( $val ) );
}
-
+
/**
* Extracts the given named values into an array.
* If no arguments are given, returns all input values.
* No transformation is performed on the values.
*/
- function getValues() {
+ function getValues() {
$names = func_get_args();
if ( count( $names ) == 0 ) {
$names = array_keys( $_REQUEST );
function wasPosted() {
return $_SERVER['REQUEST_METHOD'] == 'POST';
}
-
+
/**
* Returns true if there is a session cookie set.
* This does not necessarily mean that the user is logged in!
function checkSessionCookie() {
return isset( $_COOKIE[ini_get('session.name')] );
}
-
+
/**
* Return the path portion of the request URI.
* @return string
return preg_replace( '!^[^:]+://[^/]+/!', '/', $base );
}
}
-
+
/**
* Return the request URI with the canonical service and hostname.
* @return string
global $wgServer;
return $wgServer . $this->getRequestURL();
}
-
+
/**
* Take an arbitrary query and rewrite the present URL to include it
* @param string $query Query string fragment; do not include initial '?'
$basequery .= '&' . urlencode( $var ) . '=' . urlencode( $val );
}
$basequery .= '&' . $query;
-
+
# Trim the extra &
$basequery = substr( $basequery, 1 );
return $wgTitle->getLocalURL( $basequery );
}
-
+
/**
* HTML-safe version of appendQuery().
* @param string $query Query string fragment; do not include initial '?'
function escapeAppendQuery( $query ) {
return htmlspecialchars( $this->appendQuery( $query ) );
}
-
+
/**
* Check for limit and offset parameters on the input, and return sensible
* defaults if not given. The limit must be positive and is capped at 5000.
*/
function getLimitOffset( $deflimit = 50, $optionname = 'rclimit' ) {
global $wgUser;
-
+
$limit = $this->getInt( 'limit', 0 );
if( $limit < 0 ) $limit = 0;
if( ( $limit == 0 ) && ( $optionname != '' ) ) {
}
if( $limit <= 0 ) $limit = $deflimit;
if( $limit > 5000 ) $limit = 5000; # We have *some* limits...
-
+
$offset = $this->getInt( 'offset', 0 );
if( $offset < 0 ) $offset = 0;
-
+
return array( $limit, $offset );
}
-
+
/**
* Return the path to the temporary file where PHP has stored the upload.
* @param string $key
}
return $_FILES[$key]['tmp_name'];
}
-
+
/**
* Return the size of the upload, or 0.
* @param string $key
}
return $_FILES[$key]['size'];
}
-
+
/**
* Return the upload error or 0
* @param string $key
}
return $_FILES[$key]['error'];
}
-
+
/**
* Return the original filename of the uploaded file, as reported by
* the submitting user agent. HTML-style character entities are
return NULL;
}
$name = $_FILES[$key]['name'];
-
+
# Safari sends filenames in HTML-encoded Unicode form D...
# Horrid and evil! Let's try to make some kind of sense of it.
$name = Sanitizer::decodeCharReferences( $name );
class FauxRequest extends WebRequest {
var $data = null;
var $wasPosted = false;
-
+
function FauxRequest( $data, $wasPosted = false ) {
if( is_array( $data ) ) {
$this->data = $data;
function getVal( $name, $default = NULL ) {
return $this->getGPCVal( $this->data, $name, $default );
}
-
+
function getText( $name, $default = '' ) {
# Override; don't recode since we're using internal data
return $this->getVal( $name, $default );
}
-
- function getValues() {
+
+ function getValues() {
return $this->data;
}
function wasPosted() {
return $this->wasPosted;
}
-
+
function checkSessionCookie() {
return false;
}
-
+
function getRequestURL() {
wfDebugDieBacktrace( 'FauxRequest::getRequestURL() not implemented' );
}
-
+
function appendQuery( $query ) {
wfDebugDieBacktrace( 'FauxRequest::appendQuery() not implemented' );
}
-
+
}
?>
#____________________________________________________________________________________
#Action methods
-
+
function act_view ( $action ) {
global $wgOut , $wgSquidMaxage , $wgArticle ;
$wgOut->setSquidMaxage( $wgSquidMaxage );
$wgArticle->view();
}
-
+
function act_print ( $action ) {
global $wgArticle ;
$wgArticle->view () ;
}
-
+
function act_dublincore ( $action ) {
global $wgArticle , $wgEnableDublinCoreRdf ;
if( !$wgEnableDublinCoreRdf ) {
wfDublinCoreRdf( $wgArticle );
}
}
-
+
function act_creativecommons ( $action ) {
global $wgArticle , $wgEnableCreativeCommonsRdf ;
if( !$wgEnableCreativeCommonsRdf ) {
wfCreativeCommonsRdf( $wgArticle );
}
}
-
+
function act_credits ( $action ) {
global $wgArticle ;
require_once( 'includes/Credits.php' );
showCreditsPage( $wgArticle );
}
-
+
function act_submit ( $action ) {
global $wgCommandLineMode , $wgRequest ;
if( !$wgCommandLineMode && !$wgRequest->checkSessionCookie() ) {
}
$this->act_edit ( $action ) ;
}
-
+
function act_edit ( $action ) {
global $wgRequest , $wgUseExternalEditor , $wgUser , $wgArticle ;
$internal = $wgRequest->getVal( 'internaledit' );
$extedit->edit();
}
}
-
+
function act_history ( $action ) {
global $wgTitle , $wgArticle , $wgSquidMaxage ;
if ($_SERVER['REQUEST_URI'] == $wgTitle->getInternalURL('action=history')) {
$history = new PageHistory( $wgArticle );
$history->history();
}
-
+
function act_raw ( $action ) {
global $wgArticle ;
require_once( 'includes/RawPage.php' );
$raw = new RawPage( $wgArticle );
$raw->view();
}
-
-
+
+
function action_unknown ( $action ) {
global $wgArticle , $wgOut ;
if (wfRunHooks('UnknownAction', array($action, $wgArticle))) {
$wgOut->errorpage( 'nosuchaction', 'nosuchactiontext' );
}
}
-
-
+
+
function act_watch ( $action ) { $this->article_action ( $action ) ; }
function act_unwatch ( $action ) { $this->article_action ( $action ) ; }
function act_delete ( $action ) { $this->article_action ( $action ) ; }
$wgArticle->$action() ;
}
-
+
} ; # end of class MediaWikiType
-
+
#global $wgRequest , $wgOut , $wgTitle , $wgContLang ;
#global $action , $title , $curid ;
OutputPage::setEncodings(); # Not really used yet
$up->doUpdate();
}
wfProfileOut( 'main-updates' );
-
+
#global $wgLoadBalancer , $wgOut , $wgPostCommitUpdateList ;
wfProfileIn( 'main-cleanup' );
wfDebug( "Request ended normally\n" );
-
+
?>
function WikiError( $message ) {
$this->mMessage = $message;
}
-
+
/**
* @return string Plaintext error message to display
*/
function getMessage() {
return $this->mMessage;
}
-
+
/**
* In following PEAR_Error model this could be formatted differently,
* but so far it's not.
function toString() {
return $this->getMessage();
}
-
+
/**
* Returns true if the given object is a WikiError-descended
* error object, false otherwise.
wfDebug( "WikiXmlError: " . $this->getMessage() . "\n" );
}
- /** @return string */
+ /** @return string */
function getMessage() {
return sprintf( '%s at line %d, col %d (byte %d%s): %s',
$this->mMessage,
$this->mContext,
xml_error_string( $this->mXmlError ) );
}
-
+
function _extractContext( $context, $offset ) {
if( is_null( $context ) ) {
return null;
* @param string $text input text
* @return array langcode => converted_string
* @access public
- */
+ */
function convertToAllVariants($text) {
$len = strlen($text);
$q = "CONV ALL $len\n$text";
*/
function wf_ctype_parse_args( $fname, $args ) {
$ret = null;
-
+
$cnt = count( $args );
-
+
if ( $cnt !== 1 )
trigger_error( "$fname() expects exactly 1 parameter $cnt given", E_USER_WARNING );
-
+
$in = array_pop( $args );
if ( is_int( $in ) ) {
else if ( $in < -128 )
return array( null, true );
}
-
+
if ( is_string( $in ) )
if ( $in === '' )
return array( null, true );
}
}
- /** @todo document */
+ /** @todo document */
function testChunkRegression() {
# Check for regression against a chunking bug
$text = "\x46\x55\xb8" .
"\xad" . # bad tail
"\x7d" .
"\xd9\x95";
-
+
$expect = "\x4e\x30" .
"\xef\xbf\xbd" .
"\x3a" .
"\xef\xbf\xbd" .
"\x7d" .
"\xd9\x95";
-
+
$this->assertEquals(
bin2hex( $expect ),
bin2hex( UtfNormal::cleanUp( $text ) ) );
}
- /** @todo document */
+ /** @todo document */
function testOverlongRegression() {
$text = "\x67" .
"\x1a" . # forbidden ascii
bin2hex( UtfNormal::cleanUp( $text ) ) );
}
- /** @todo document */
+ /** @todo document */
function testSurrogateRegression() {
$text = "\xed\xb4\x96" . # surrogate 0xDD16
"\x83" . # bad tail
$str = preg_replace( '/[\x00-\x08\x0b\x0c\x0e-\x1f]/', UTF8_REPLACEMENT, $str );
$str = str_replace( UTF8_FFFE, UTF8_REPLACEMENT, $str );
$str = str_replace( UTF8_FFFF, UTF8_REPLACEMENT, $str );
-
+
# UnicodeString constructor fails if the string ends with a head byte.
# Add a junk char at the end, we'll strip it off
return rtrim( utf8_normalize( $str . "\x01", UNORM_NFC ), "\x01" );
function showDiffs( $a, $b ) {
$ota = explode( "\n", str_replace( "\r\n", "\n", $a ) );
$nta = explode( "\n", str_replace( "\r\n", "\n", $b ) );
-
+
$diffs =& new Diff( $ota, $nta );
$formatter =& new TableDiffFormatter();
$funky = $formatter->format( $diffs );
while( true ) {
$n++;
echo "$n\n";
-
+
$str = randomString( $size, true);
$clean = UtfNormal::cleanUp( $str );
$norm = donorm( $str );
showDiffs( $clean, $norm );
die();
}
-
-
+
+
$str = '';
$clean = '';
$norm = '';
# Tests that should mark invalid characters due to using long
# sequences beyond what is now considered legal.
'2.1.5', '2.1.6', '2.2.4', '2.2.5', '2.2.6', '2.3.5',
-
+
# Literal 0xffff, which is illegal
'2.2.3' );
if( $len == 0 ) {
$len = strlen( substr( $stripped, 0, strpos( $stripped, '|' ) ) );
}
-
+
global $columns;
$ok = $same ^ ($test >= 3 );
global $exceptions;
$ok ^= in_array( $test, $exceptions );
-
+
$ok &= ($columns == $len);
-
+
$total++;
if( $ok ) {
$success++;
$string );
$string = str_replace( UTF8_FFFE, UTF8_REPLACEMENT, $string );
$string = str_replace( UTF8_FFFF, UTF8_REPLACEMENT, $string );
-
+
# UnicodeString constructor fails if the string ends with a
# head byte. Add a junk char at the end, we'll strip it off.
return rtrim( utf8_normalize( $string . "\x01", UNORM_NFC ), "\x01" );
else
return UtfNormal::NFC( $string );
}
-
+
/**
* Convert a UTF-8 string to normal form D, canonical decomposition.
* Fast return for pure ASCII strings.
else
return $string;
}
-
+
/**
* Convert a UTF-8 string to normal form KC, compatibility composition.
* This may cause irreversible information loss, use judiciously.
else
return $string;
}
-
+
/**
* Convert a UTF-8 string to normal form KD, compatibility decomposition.
* This may cause irreversible information loss, use judiciously.
else
return $string;
}
-
+
/**
* Load the basic composition data if necessary
* @access private
require_once( 'UtfNormalData.inc' );
}
}
-
+
/**
* Returns true if the string is _definitely_ in NFC.
* Returns false if not or uncertain.
# ASCII is always valid NFC!
# If it's pure ASCII, let it through.
if( !preg_match( '/[\x80-\xff]/', $string ) ) return true;
-
+
UtfNormal::loadData();
global $utfCheckNFC, $utfCombiningClass;
$len = strlen( $string );
function quickIsNFCVerify( &$string ) {
# Screen out some characters that eg won't be allowed in XML
$string = preg_replace( '/[\x00-\x08\x0b\x0c\x0e-\x1f]/', UTF8_REPLACEMENT, $string );
-
+
# ASCII is always valid NFC!
# If we're only ever given plain ASCII, we can avoid the overhead
# of initializing the decomposition tables by skipping out early.
if( !preg_match( '/[\x80-\xff]/', $string ) ) return true;
-
+
static $checkit = null, $tailBytes = null, $utfCheckOrCombining = null;
if( !isset( $checkit ) ) {
# Load/build some scary lookup tables...
UtfNormal::loadData();
global $utfCheckNFC, $utfCombiningClass;
-
+
$utfCheckOrCombining = array_merge( $utfCheckNFC, $utfCombiningClass );
# Head bytes for sequences which we should do further validity checks
array( 0xc0, 0xc1, 0xe0, 0xed, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff ) ) );
-
+
# Each UTF-8 head byte is followed by a certain
# number of tail bytes.
$tailBytes = array();
$tailBytes[chr($n)] = $remaining;
}
}
-
+
# Chop the text into pure-ASCII and non-ASCII areas;
# large ASCII parts can be handled much more quickly.
# Don't chop up Unicode areas for punctuation, though,
preg_match_all(
'/([\x00-\x7f]+|[\x80-\xff][\x00-\x40\x5b-\x5f\x7b-\xff]*)/',
$string, $matches );
-
+
$looksNormal = true;
$base = 0;
$replace = array();
foreach( $matches[1] as $str ) {
$chunk = strlen( $str );
-
+
if( $str{0} < "\x80" ) {
# ASCII chunk: guaranteed to be valid UTF-8
# and in normal form C, so skip over it.
$base += $chunk;
continue;
}
-
+
# We'll have to examine the chunk byte by byte to ensure
# that it consists of valid UTF-8 sequences, and to see
# if any of them might not be normalized.
#
# Since PHP is not the fastest language on earth, some of
# this code is a little ugly with inner loop optimizations.
-
+
$head = '';
$len = $chunk + 1; # Counting down is faster. I'm *so* sorry.
-
+
for( $i = -1; --$len; ) {
if( $remaining = $tailBytes[$c = $str{++$i}] ) {
# UTF-8 head byte!
# 0xed is relatively frequent in Korean, which
# abuts the surrogate area, so we're doing
# this check separately to speed things up.
-
+
if( $sequence >= UTF8_SURROGATE_FIRST ) {
# Surrogates are legal only in UTF-16 code.
# They are totally forbidden here in UTF-8
($n < 0xc2 && $sequence <= UTF8_OVERLONG_A)
|| ($n == 0xe0 && $sequence <= UTF8_OVERLONG_B)
|| ($n == 0xf0 && $sequence <= UTF8_OVERLONG_C)
-
+
# U+FFFE and U+FFFF are explicitly forbidden in Unicode.
|| ($n == 0xef &&
($sequence == UTF8_FFFE)
|| ($sequence == UTF8_FFFF) )
-
+
# Unicode has been limited to 21 bits; longer
# sequences are not allowed.
|| ($n >= 0xf0 && $sequence > UTF8_MAX) ) {
-
+
$replace[] = array( UTF8_REPLACEMENT,
$base + $i + 1 - strlen( $sequence ),
strlen( $sequence ) );
}
}
}
-
+
if( isset( $utfCheckOrCombining[$sequence] ) ) {
# If it's NO or MAYBE, we'll have to rip
# the string apart and put it back together.
# That's going to be mighty slow.
$looksNormal = false;
}
-
+
# The sequence is legal!
$head = '';
} elseif( $c < "\x80" ) {
}
return $looksNormal;
}
-
+
# These take a string and run the normalization on them, without
# checking for validity or any optimization etc. Input must be
# VALID UTF-8!
function NFC( $string ) {
return UtfNormal::fastCompose( UtfNormal::NFD( $string ) );
}
-
+
/**
* @param string $string
* @return string
return UtfNormal::fastCombiningSort(
UtfNormal::fastDecompose( $string, $utfCanonicalDecomp ) );
}
-
+
/**
* @param string $string
* @return string
function NFKC( $string ) {
return UtfNormal::fastCompose( UtfNormal::NFKD( $string ) );
}
-
+
/**
* @param string $string
* @return string
return UtfNormal::fastCombiningSort(
UtfNormal::fastDecompose( $string, $utfCompatibilityDecomp ) );
}
-
-
+
+
/**
* Perform decomposition of a UTF-8 string into either D or KD form
* (depending on which decomposition map is passed to us).
$hangulPoint = UNICODE_HANGUL_FIRST +
UNICODE_HANGUL_TCOUNT *
(UNICODE_HANGUL_VCOUNT * $lIndex + $vIndex);
-
+
# Hardcode the limited-range UTF-8 conversion:
$startChar = chr( $hangulPoint >> 12 & 0x0f | 0xe0 ) .
chr( $hangulPoint >> 6 & 0x3f | 0x80 ) .
# $tIndex = utf8ToCodepoint( $c ) - UNICODE_HANGUL_TBASE;
$tIndex = ord( $c{2} ) - 0xa7;
if( $tIndex < 0 ) $tIndex = ord( $c{2} ) - 0x80 + (0x11c0 - 0x11a7);
-
+
# Increment the code point by $tIndex, without
# the function overhead of decoding and recoding UTF-8
#
$startChar{1} = chr( $mid );
}
$startChar{2} = chr( $tail );
-
+
# If there's another jamo char after this, *don't* try to merge it.
$lastHangul = 1;
continue;
$out .= $startChar . $combining;
return $out;
}
-
+
/**
* This is just used for the benchmark, comparing how long it takes to
* interate through a string without really doing anything of substance.
#$delta = (benchTime() - $start) / BENCH_CYCLES;
sort( $deltas );
$delta = $deltas[0]; # Take shortest time
-
+
$rate = intval( strlen( $data ) / $delta );
$same = (0 == strcmp( $data, $out ) );
-
+
printf( " %20s %6.1fms %8d bytes/s (%s)\n", $form, $delta*1000.0, $rate, ($same ? 'no change' : 'changed' ) );
return $out;
}
$name = $columns[1];
$canonicalCombiningClass = $columns[3];
$decompositionMapping = $columns[5];
-
+
$source = codepointToUtf8( hexdec( $codepoint ) );
if( $canonicalCombiningClass != 0 ) {
$combiningClass[$source] = intval( $canonicalCombiningClass );
}
-
+
if( $decompositionMapping === '' ) continue;
if( preg_match( '/^<(.+)> (.*)$/', $decompositionMapping, $matches ) ) {
# Compatibility decomposition
}
$total++;
$dest = hexSequenceToUtf8( $decompositionMapping );
-
+
$compatibilityDecomp[$source] = $dest;
if( $canonical ) {
$canonicalDecomp[$source] = $dest;
return preg_replace( '/([\x00-\xff])/e',
'sprintf("%02X", ord("$1"))',
$string );
- }
+ }
} else {
/**
* @ignore
return trim( preg_replace( '/(.)/use',
'sprintf("%04X ", utf8ToCodepoint("$1"))',
$string ) );
- }
+ }
}
if( isset( $_SERVER['argv'] ) && in_array( '--icu', $_SERVER['argv'] ) ) {
print "Part {$matches[1]}: $comment";
continue;
}
-
+
$columns = array_map( "hexSequenceToUtf8", explode( ";", $data ) );
array_unshift( $columns, '' );
-
+
$testedChars[$columns[1]] = true;
$total++;
if( testNormals( $normalizer, $columns, $comment ) ) {
$result = testNFKC( $u, $c, $comment, $reportFailure ) && $result;
$result = testNFKD( $u, $c, $comment, $reportFailure ) && $result;
$result = testCleanUp( $u, $c, $comment, $reportFailure ) && $result;
-
+
global $verbose;
if( $verbose && !$result && !$reportFailure ) {
print $comment;
<?php } ?>
</table>
<?php
-
+
if( $this->data['useemail'] ) {
echo '<div id="login-emailforlost">';
$this->msgHtml( 'emailforlost' );
if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
$datePreference = $this->dateFormat( $format );
-
+
$sep = ($datePreference == MW_DATE_ISO)
? ':'
: $this->timeSeparator( $format );
-
+
$t = substr( $ts, 8, 2 ) . $sep . substr( $ts, 10, 2 );
if ( $datePreference == MW_DATE_ISO ) {
}
return $t;
}
-
+
/**
* Default separator character between hours, minutes, and seconds.
* Will be used by Language::time() for non-ISO formats.
function timeSeparator( $format ) {
return ':';
}
-
+
/**
* String to insert between the time and the date in a combined
* string. Should include any relevant whitespace.
function timeDateSeparator( $format ) {
return ', ';
}
-
+
/**
* Return true if the time should display before the date.
* @return bool
function formatMonth( $month, $format ) {
return $this->getMonthName( $month );
}
-
+
function formatDay( $day, $format ) {
return $this->formatNum( 0 + $day );
}
$raw = $this->getMagicWords();
wfRunHooks( 'LanguageGetMagic', array( &$raw ) );
-
+
if( !isset( $raw[$mw->mId] ) ) {
# Fall back to English if local list is incomplete
$raw =& Language::getMagicWords();
global $wgMagicWordsBe;
return $wgMagicWordsBe;
}
-
+
function getDateFormats() {
return $wgDateFormatsBe = array(
MW_DATE_DEFAULT => MW_DATE_DEFAULT,
<input type="hidden" name="domains" value="{{SERVER}}" />
<input type="hidden" name="num" value="50" />
<input type="hidden" name="ie" value="$2" />
-
+
<input type="hidden" name="oe" value="$2" />
<input type="text" name="q" size="31" maxlength="255" value="$1" />
<input type="submit" name="btnG" value="Google Search" />
global $wgBookstoreListBg;
return $wgBookstoreListBg;
}
-
+
/**
* Exports $wgNamespaceNamesBg
* @return array
global $wgMagicWordsBg;
return $wgMagicWordsBg;
}
-
+
/**
* Translation table for numbers
'filename' => 'Anv ',
'filedesc' => 'Deskrivadur ',
'filestatus' => 'Statud ar gwirioù aozer',
-'filesource' => 'Mammenn',
+'filesource' => 'Mammenn',
'copyrightpage' => "{{ns:4}}:Gwirioù aozer (Copyright)",
'copyrightpagename' => "aotre {{SITENAME}}",
'uploadedfiles' => "Restroù eilet",
',' => "\xc2\xa0", // @bug 2749
'.' => ','
);
-
+
function formatNum( $number, $year = false ) {
return $year ? $number : strtr($this->commafy($number), $this->digitTransTable );
}
return parent::getMessage( $key );
}
}
-
+
}
?>
function formatMonth( $month, $format ) {
return intval( $month ) . '.';
}
-
+
function formatDay( $day, $format ) {
return intval( $day ) . '.';
}
global $wgSkinNamesDe;
return $wgSkinNamesDe;
}
-
+
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
-
+
function formatDay( $day, $format ) {
return parent::formatDay( $day, $format ) . '.';
}
global $wgNamespaceNamesEl;
return $wgNamespaceNamesEl;
}
-
+
function getMessage( $key ) {
global $wgAllMessagesEl;
return isset( $wgAllMessagesEl[$key] ) ? $wgAllMessagesEl[$key] : parent::getMessage( $key );
}
-
+
function fallback8bitEncoding() {
return 'iso-8859-7';
}
-
+
function formatNum( $number, $year = false ) {
return $year ? $number : strtr($this->commafy( $number ), '.,', ',.' );
}
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
-
+
function formatDay( $day, $format ) {
return parent::formatDay( $day, $format ) . '.';
}
global $wgSkinNamesEs;
return $wgSkinNamesEs;
}
-
+
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
-
+
function timeDateSeparator( $format ) {
return ' ';
}
-
+
function getMessage( $key ) {
global $wgAllMessagesEs;
global $wgSkinNamesFr;
return $wgSkinNamesFr;
}
-
+
function timeBeforeDate( $format ) {
return false;
}
-
+
function timeDateSeparator( $format ) {
return " à ";
}
} else {
$sep = '.';
}
-
+
$t = substr( $ts, 8, 2 ) . $sep . substr( $ts, 10, 2 );
if ( $datePreference == MW_DATE_ISO ) {
}
return $t;
}
-
+
function getMessage( $key ) {
global $wgAllMessagesFy;
if( isset( $wgAllMessagesFy[$key] ) ) {
#--------------------------------------------------------------------------
class LanguageHr extends LanguageUtf8 {
-
+
function getNamespaces() {
global $wgNamespaceNamesHr;
return $wgNamespaceNamesHr;
global $wgSkinNamesHr;
return $wgSkinNamesHr;
}
-
+
function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
global $wgQuickbarSettingsIt;
return $wgQuickbarSettingsIt;
}
-
+
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
global $wgDateFormatsJa;
return $wgDateFormatsJa;
}
-
+
function date( $ts, $adj = false, $format = true, $tc = false ) {
global $wgWeekdayAbbreviationsJa;
-
+
if ( $adj ) { $ts = $this->userAdjust( $ts, $tc ); }
$datePreference = $this->dateFormat( $format );
-
+
if( $datePreference == MW_DATE_ISO ) {
$d = substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .
substr($ts, 6, 2);
return $d;
}
-
+
$year = (int)substr( $ts, 0, 4 );
$month = (int)substr( $ts, 4, 2 );
$mday = (int)substr( $ts, 6, 2 );
$hour = (int)substr( $ts, 8, 2 );
$minute = (int)substr( $ts, 10, 2 );
$second = (int)substr( $ts, 12, 2 );
-
+
$time = mktime( $hour, $minute, $second, $month, $mday, $year );
$date = getdate( $time );
-
+
$d = $year . "年" .
$this->getMonthAbbreviation( $month ) .
$mday . "日 (" .
function time( $ts, $adj = false, $format = true, $tc = false ) {
if ( $adj ) { $ts = $this->userAdjust( $ts, $tc ); }
$datePreference = $this->dateFormat( $format );
-
+
$t = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 );
if ( $datePreference == MW_DATE_ISO ) {
$t .= ':' . substr( $ts, 12, 2 );
}
-
+
return $t;
}
global $wgSkinNamesKo;
return $wgSkinNamesKo;
}
-
+
function getDateFormats() {
return false;
}
global $wgSkinNamesLi;
return $wgSkinNamesLi;
}
-
+
function timeBeforeDate( $format ) {
return false;
}
-
+
function timeDateSeparator( $format ) {
return ' ';
}
-
+
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
-
+
function getMessage( $key ) {
global $wgAllMessagesLi;
if( isset( $wgAllMessagesLi[$key] ) ) {
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
-
+
function formatDay( $day, $format ) {
return parent::formatDay( $day, $format ) . '.';
}
function timeBeforeDate( $format ) {
return false;
}
-
+
function timeDateSeparator( $format ) {
return ' ';
}
-
+
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
-
+
function getMessage( $key ) {
global $wgAllMessagesNl;
if( isset( $wgAllMessagesNl[$key] ) ) {
global $wgSkinNamesNo;
return $wgSkinNamesNo;
}
-
+
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
-
+
function formatDay( $day, $format ) {
return parent::formatDay( $day, $format ) . '.';
}
-
+
function timeanddate( $ts, $adj = false, $format = false, $timecorrection = false ) {
$format = $this->dateFormat( $format );
if( $format == MW_DATE_ISO ) {
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
-
+
function timeBeforeDate( $format ) {
return false;
}
-
+
function timeDateSeparator( $format ) {
return " à ";
}
global $wgMonthNamesGenEn;
return wfMsg( $wgMonthNamesGenEn[$key-1] );
}
-
+
function formatMonth( $month, $format ) {
return $this->getMonthAbbreviation( $month );
}
global $wgNamespaceNamesPt;
return $wgNamespaceNamesPt;
}
-
+
/**
* Exports $wgQuickbarSettingsPt
* @return array
global $wgMagicWordsSr;
return $wgMagicWordsSr;
}
-
+
function formatNum( $number, $year = false ) {
return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
}
# or compiled and character mapping arrays otherwise.
# In case of language-specific character mismatch
# it should be dealt with in Language classes.
-
+
function ucfirst( $str ) {
return $this->uc( $str, true );
}
$1<br />
$2 gồm cả trang đổi hướng Tìm $3 $9",
'searchdisabled' => "<p>Công cụ tìm kiếm hiện bị khóa. Chức năng này sẽ được mở lại khi có điều kiện lắp thêm máy chủ. Hiện tại có thể tìm với Google:</p>",
-"blanknamespace" => "(Chính)",
+"blanknamespace" => "(Chính)",
# Preferences page
#
*Thông tin tải lên và xóa bỏ được ghi trong [[{{ns:4}}:Nhật trình tải lên|nhật trình tải lên]].
*Để cho hình vào bài, xem [[{{ns:4}}:Cú pháp hình ảnh|cú pháp hình ảnh]].
*Người khác có thể sửa hoặc xóa những thông tin bạn tải lên, và bạn có thể bị cấm tải lên nếu lạm dụng hệ thống.",
-"uploadlog" => "Nhật trình tải lên",
-"uploadlogpage" => "Nhật_trình_tải_lên",
+"uploadlog" => "Nhật trình tải lên",
+"uploadlogpage" => "Nhật_trình_tải_lên",
"uploadlogpagetext" => "Danh sách các tệp tin đã tải lên, theo giờ máy chủ (UTC).
<ul>
</ul>",
global $wgSkinNamesZh_cn;
return $wgSkinNamesZh_cn;
}
-
+
function getDateFormats() {
return false;
}
'sa' => 'संस्कृत', # Sanskrit
'sc' => 'Sardu', # Sardinian
'scn' => 'Sicilianu', # Sicilian
- 'sco' => 'Scots', # Scots
+ 'sco' => 'Scots', # Scots
'sd' => 'सिनधि', # Sindhi
'se' => 'Sámegiella', # Northern Sami
'sg' => 'Sängö', # Sango, possible alternative is Sangho
function FiveUpgrade() {
global $wgDatabase;
$this->conversionTables = $this->prepareWindows1252();
-
+
$this->dbw =& $this->newConnection();
$this->dbr =& $this->streamConnection();
-
+
$this->cleanupSwaps = array();
$this->emailAuth = false; # don't preauthenticate emails
$this->maxLag = 10; # if slaves are lagged more than 10 secs, wait
}
-
+
function doing( $step ) {
return is_null( $this->step ) || $step == $this->step;
}
-
+
function upgrade( $step ) {
$this->step = $step;
-
+
$tables = array(
'page',
'links',
$this->$method();
}
}
-
+
if( $this->doing( 'cleanup' ) ) {
$this->upgradeCleanup();
}
}
-
-
+
+
/**
* Open a connection to the master server with the admin rights.
* @return Database
$db =& new Database( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
return $db;
}
-
+
/**
* Open a second connection to the master server, with buffering off.
* This will let us stream large datasets in and write in chunks on the
$db->query( "SET net_write_timeout=$timeout" );
return $db;
}
-
+
/**
* Prepare a conversion array for converting Windows Code Page 1252 to
* UTF-8. This should provide proper conversion of text that was miscoded
}
return $pairs;
}
-
+
/**
* Convert from 8-bit Windows-1252 to UTF-8 if necessary.
* @param string $text
? strtr( $text, $this->conversionTables )
: $text );
}
-
+
/**
* Dump timestamp and message to output
* @param string $message
echo $wgDBname . ' ' . wfTimestamp( TS_DB ) . ': ' . $message . "\n";
flush();
}
-
+
/**
* Initialize the chunked-insert system.
* Rows will be inserted in chunks of the given number, rather
$this->chunkTable = $table;
$this->chunkFunction = $fname;
}
-
+
/**
* Chunked inserts: perform an insert if we've reached the chunk limit.
* Prints a progress report with estimated completion time.
function addChunk( &$chunk, $key = null ) {
if( count( $chunk ) >= $this->chunkSize ) {
$this->insertChunk( $chunk );
-
+
$this->chunkCount += count( $chunk );
$now = wfTime();
$delta = $now - $this->chunkStartTime;
$rate = $this->chunkCount / $delta;
-
+
if( is_null( $key ) ) {
$completed = $this->chunkCount;
} else {
$completed = $key;
}
$portion = $completed / $this->chunkFinal;
-
+
$estimatedTotalTime = $delta / $portion;
$eta = $this->chunkStartTime + $estimatedTotalTime;
-
+
printf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec\n",
wfTimestamp( TS_DB, intval( $now ) ),
$portion * 100.0,
$this->chunkFinal,
$rate );
flush();
-
+
$chunk = array();
}
}
-
+
/**
* Chunked inserts: perform an insert unconditionally, at the end, and log.
* @param array &$chunk -- This will be emptied if an insert is done.
}
$this->log( "100.00% done on $this->chunkTable (last chunk $n rows)." );
}
-
+
/**
* Chunked inserts: perform an insert.
* @param array &$chunk -- This will be emptied if an insert is done.
wfWaitForSlaves( $this->maxLag );
$this->dbw->insert( $this->chunkTable, $chunk, $this->chunkFunction, $this->chunkOptions );
}
-
-
+
+
/**
* Copy and transcode a table to table_temp.
* @param string $name Base name of the source table
*/
function copyTable( $name, $tabledef, $fields, $callback = null ) {
$fname = 'FiveUpgrade::copyTable';
-
+
$name_temp = $name . '_temp';
$this->log( "Migrating $name table to $name_temp..." );
$table = $this->dbw->tableName( $name );
$table_temp = $this->dbw->tableName( $name_temp );
-
+
// Create temporary table; we're going to copy everything in there,
// then at the end rename the final tables into place.
$def = str_replace( '$1', $table_temp, $tabledef );
$this->dbw->query( $def, $fname );
-
+
$numRecords = $this->dbw->selectField( $name, 'COUNT(*)', '', $fname );
$this->setChunkScale( 100, $numRecords, $name_temp, $fname );
-
+
// Pull all records from the second, streaming database connection.
$sourceFields = array_keys( array_filter( $fields,
create_function( '$x', 'return $x !== MW_UPGRADE_NULL;' ) ) );
$sourceFields,
'',
$fname );
-
+
$add = array();
while( $row = $this->dbr->fetchObject( $result ) ) {
$copy = array();
}
$this->lastChunk( $add );
$this->dbr->freeResult( $result );
-
+
$this->log( "Done converting $name." );
$this->cleanupSwaps[] = $name;
}
-
+
function upgradePage() {
$fname = "FiveUpgrade::upgradePage";
$chunksize = 100;
-
+
if( $this->dbw->tableExists( 'page' ) ) {
$this->log( 'Page table already exists; aborting.' );
die( -1 );
}
-
+
$this->log( "Checking cur table for unique title index and applying if necessary" );
checkDupes( true );
$this->log( "...converting from cur/old to page/revision/text DB structure." );
-
+
extract( $this->dbw->tableNames( 'cur', 'old', 'page', 'revision', 'text' ) );
$this->log( "Creating page and revision tables..." );
$maxcur = $this->dbw->selectField( 'cur', 'max(cur_id)', '', $fname );
$this->log( "Last cur entry is $maxcur" );
-
+
/**
* Copy placeholder records for each page's current version into old
* Don't do any conversion here; text records are converted at runtime
}
$this->lastChunk( $add );
$this->dbr->freeResult( $result );
-
+
/**
* Copy revision metadata from old into revision.
* We'll also do UTF-8 conversion of usernames and comments.
#$countold = $this->dbw->selectField( 'old', 'count(old_id)', '', $fname );
$countold = $this->dbw->selectField( 'old', 'max(old_id)', '', $fname );
$this->setChunkScale( $chunksize, $countold, 'revision', $fname );
-
+
$this->log( "......Setting up revision table." );
$result = $this->dbr->query(
"SELECT old_id, cur_id, old_comment, old_user, old_user_text,
}
$this->lastChunk( $add );
$this->dbr->freeResult( $result );
-
+
/**
* Copy page metadata from cur into page.
}
$this->lastChunk( $add );
$this->dbr->freeResult( $result );
-
+
$this->log( "...done with cur/old -> page/revision." );
}
-
+
function upgradeLinks() {
$fname = 'FiveUpgrade::upgradeLinks';
$chunksize = 200;
extract( $this->dbw->tableNames( 'links', 'brokenlinks', 'pagelinks', 'cur' ) );
-
+
$this->log( 'Checking for interwiki table change in case of bogus items...' );
if( $this->dbw->fieldExists( 'interwiki', 'iw_trans' ) ) {
$this->log( 'interwiki has iw_trans.' );
dbsource( 'maintenance/archives/patch-interwiki-trans.sql', $this->dbw );
$this->log( 'added iw_trans.' );
}
-
+
$this->log( 'Creating pagelinks table...' );
$this->dbw->query( "
CREATE TABLE $pagelinks (
} else {
$this->log( 'no links!' );
}
-
+
$this->log( 'Importing brokenlinks -> pagelinks' );
$nbrokenlinks = $this->dbw->selectField( 'brokenlinks', 'count(*)', '', $fname );
if( $nbrokenlinks ) {
} else {
$this->log( 'no brokenlinks!' );
}
-
+
$this->log( 'Done with links.' );
}
-
+
function upgradeUser() {
// Apply unique index, if necessary:
$duper = new UserDupes( $this->dbw );
$this->log( "WARNING: Duplicate user accounts, may explode!" );
}
}
-
+
$tabledef = <<<END
CREATE TABLE $1 (
user_id int(5) unsigned NOT NULL auto_increment,
$this->copyTable( 'user', $tabledef, $fields,
array( &$this, 'userCallback' ) );
}
-
+
function userCallback( $row, $copy ) {
$now = $this->dbw->timestamp();
$copy['user_touched'] = $now;
$copy['user_email_authenticated'] = $this->emailAuth ? $now : null;
return $copy;
}
-
+
function upgradeImage() {
$tabledef = <<<END
CREATE TABLE $1 (
$this->copyTable( 'image', $tabledef, $fields,
array( &$this, 'imageCallback' ) );
}
-
+
function imageCallback( $row, $copy ) {
global $options;
if( !isset( $options['noimage'] ) ) {
// Fill in the new image info fields
$info = $this->imageInfo( $row->img_name );
-
+
$copy['img_width' ] = $info['width'];
$copy['img_height' ] = $info['height'];
$copy['img_metadata' ] = ""; // loaded on-demand
$copy['img_major_mime'] = $info['major'];
$copy['img_minor_mime'] = $info['minor'];
}
-
+
// If doing UTF8 conversion the file must be renamed
$this->renameFile( $row->img_name, 'wfImageDir' );
-
+
return $copy;
}
-
+
function imageInfo( $name, $subdirCallback='wfImageDir', $basename = null ) {
if( is_null( $basename ) ) $basename = $name;
$dir = call_user_func( $subdirCallback, $basename );
'media' => '',
'major' => '',
'minor' => '' );
-
+
$magic =& wfGetMimeMagic();
$mime = $magic->guessMimeType( $filename, true );
list( $info['major'], $info['minor'] ) = explode( '/', $mime );
-
+
$info['media'] = $magic->getMediaType( $filename, $mime );
-
+
# Height and width
$gis = false;
if( $mime == 'image/svg' ) {
if( isset( $gis['bits'] ) ) {
$info['bits'] = $gis['bits'];
}
-
+
return $info;
}
-
+
/**
* Truncate a table.
$tableName = $this->db->tableName( $table );
$this->db->query( 'TRUNCATE $tableName' );
}
-
+
/**
* Rename a given image or archived image file to the converted filename,
* leaving a symlink for URL compatibility.
// No need to rename; another field triggered this row.
return false;
}
-
+
if( is_null( $basename ) ) $basename = $oldname;
$ubasename = $this->conv( $basename );
$oldpath = call_user_func( $subdirCallback, $basename ) . '/' . $oldname;
$newpath = call_user_func( $subdirCallback, $ubasename ) . '/' . $newname;
-
+
$this->log( "$oldpath -> $newpath" );
if( rename( $oldpath, $newpath ) ) {
$relpath = $this->relativize( $newpath, dirname( $oldpath ) );
return false;
}
}
-
+
/**
* Generate a relative path name to the given file.
* Assumes Unix-style paths, separators, and semantics.
function relativize( $path, $from ) {
$pieces = explode( '/', dirname( $path ) );
$against = explode( '/', $from );
-
+
// Trim off common prefix
while( count( $pieces ) && count( $against )
&& $pieces[0] == $against[0] ) {
array_shift( $pieces );
array_shift( $against );
}
-
+
// relative dots to bump us to the parent
while( count( $against ) ) {
array_unshift( $pieces, '..' );
array_shift( $against );
}
-
+
array_push( $pieces, basename( $path ) );
-
+
return implode( '/', $pieces );
}
-
+
function upgradeOldImage() {
$tabledef = <<<END
CREATE TABLE $1 (
$this->copyTable( 'oldimage', $tabledef, $fields,
array( &$this, 'oldimageCallback' ) );
}
-
+
function oldimageCallback( $row, $copy ) {
global $options;
if( !isset( $options['noimage'] ) ) {
$copy['oi_height'] = $info['height'];
$copy['oi_bits' ] = $info['bits' ];
}
-
+
// If doing UTF8 conversion the file must be renamed
$this->renameFile( $row->oi_archive_name, 'wfImageArchiveDir', $row->oi_name );
-
+
return $copy;
}
-
+
function upgradeWatchlist() {
$fname = 'FiveUpgrade::upgradeWatchlist';
$chunksize = 100;
-
+
extract( $this->dbw->tableNames( 'watchlist', 'watchlist_temp' ) );
-
+
$this->log( 'Migrating watchlist table to watchlist_temp...' );
$this->dbw->query(
"CREATE TABLE $watchlist_temp (
// Fix encoding for Latin-1 upgrades, add some fields,
// and double article to article+talk pairs
$numwatched = $this->dbw->selectField( 'watchlist', 'count(*)', '', $fname );
-
+
$this->setChunkScale( $chunksize, $numwatched * 2, 'watchlist_temp', $fname );
$result = $this->dbr->select( 'watchlist',
array(
'wl_title' ),
'',
$fname );
-
+
$add = array();
while( $row = $this->dbr->fetchObject( $result ) ) {
$now = $this->dbw->timestamp();
'wl_title' => $this->conv( $row->wl_title ),
'wl_notificationtimestamp' => '0' );
$this->addChunk( $add );
-
+
$add[] = array(
'wl_user' => $row->wl_user,
'wl_namespace' => Namespace::getTalk( $row->wl_namespace ),
}
$this->lastChunk( $add );
$this->dbr->freeResult( $result );
-
+
$this->log( 'Done converting watchlist.' );
$this->cleanupSwaps[] = 'watchlist';
}
'ar_text_id' => MW_UPGRADE_NULL );
$this->copyTable( 'archive', $tabledef, $fields );
}
-
+
function upgradeImagelinks() {
global $wgUseLatin1;
if( $wgUseLatin1 ) {
$this->copyTable( 'categorylinks', $tabledef, $fields );
}
}
-
+
function upgradeIpblocks() {
global $wgUseLatin1;
if( $wgUseLatin1 ) {
$this->copyTable( 'ipblocks', $tabledef, $fields );
}
}
-
+
function upgradeRecentchanges() {
// There's a format change in the namespace field
$tabledef = <<<END
'rc_ip' => MW_UPGRADE_COPY );
$this->copyTable( 'recentchanges', $tabledef, $fields );
}
-
+
function upgradeQuerycache() {
// There's a format change in the namespace field
$tabledef = <<<END
'qc_title' => MW_UPGRADE_ENCODE );
$this->copyTable( 'querycache', $tabledef, $fields );
}
-
+
/**
* Rename all our temporary tables into final place.
* We've left things in place so a read-only wiki can continue running
*/
function upgradeCleanup() {
$this->renameTable( 'old', 'text' );
-
+
foreach( $this->cleanupSwaps as $table ) {
$this->swap( $table );
}
}
-
+
function renameTable( $from, $to ) {
$this->log( "Renaming $from to $to..." );
$totable = $this->dbw->tableName( $to );
$this->dbw->query( "ALTER TABLE $fromtable RENAME TO $totable" );
}
-
+
function swap( $base ) {
$this->renameTable( $base, "{$base}_old" );
$this->renameTable( "{$base}_temp", $base );
}
-
+
}
?>
\ No newline at end of file
} else {
$sortedArray = $wgAllMessagesEn;
}
-
+
ksort( $sortedArray );
$messages=array();
$wgUser = new User;
$wgUser->setLoaded( true ); # Don't load from DB
$wgUser->setName( 'MediaWiki default' );
-
+
# Don't try to draw messages from the database we're initialising
$wgMessageCache->disable();
$wgMessageCache->disableTransform();
# default messages won't be overwritte
$username = 'MediaWiki default';
-
+
print "Initialising \"MediaWiki\" namespace...\n";
-
+
$dbr =& wfGetDB( DB_SLAVE );
$dbw =& wfGetDB( DB_MASTER );
$page = $dbr->tableName( 'page' );
} else {
$sortedArray = $wgAllMessagesEn;
}
-
+
ksort( $sortedArray );
# SELECT all existing messages
while ($row = $dbr->fetchObject($res))
$rows[] = $row;
}
-
+
# Read the results into an array
# Decide whether or not each one needs to be overwritten
$existingTitles = array();
$arr = array();
$talk = $wgContLang->getNsText( NS_TALK );
$mwtalk = $wgContLang->getNsText( NS_MEDIAWIKI_TALK );
-
+
# Merge these into a single transaction for speed
$dbw->begin();
<?php
-$wgNoDBParam = true;
-
+$wgNoDBParam = true;
+
require_once( "commandLine.inc" );
require_once( "rebuildInterwiki.inc" );
require_once( "languages/Names.php" );
$dbw->query( "SET table_type=Innodb" );
$dbw->query( "CREATE DATABASE $dbName" );
$dbw->selectDB( $dbName );
-
+
print "Initialising tables\n";
dbsource( "$maintenance/tables.sql", $dbw );
dbsource( "$IP/extensions/OAI/update_table.sql", $dbw );
[[zh:]]
[[zu:]]
", '', false, false );
-
+
print "Adding to dblists\n";
# Add to dblist
$file = fopen( "$common/all.dblist", "a" );
fwrite( $file, "$dbName\n" );
fclose( $file );
-
+
# Update the sublists
system("cd $common && ./refresh-dblist");
echo "$wgDBname $pageId [[$name]] can't find latest rev time?!\n";
continue;
}
-
+
$revision = Revision::loadFromTimestamp( $dbw, $title, $latestTime );
if( is_null( $revision ) ) {
echo "$wgDBname $pageId [[$name]] latest time $latestTime, can't find revision id\n";
*/
fwrite( $logfile, "**Revision IDs: " );
fwrite( $sqlfile, "UPDATE $revision SET rev_user=$uid, rev_user_text='$eDest' WHERE rev_id IN (\n" );
-
+
for ( $first=true; $row; $row = $dbr->fetchObject( $res ) ) {
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
$fullTitle = $title->getPrefixedDbKey();
print "$fullTitle\n";
$url = $title->getFullUrl( "oldid={$row->rev_id}" );
-
+
# Output
fwrite( $sqlfile, " " );
if ( $first ) {
var $endId = 0;
var $sink = null; // Output filters
var $stubText = false; // include rev_text_id instead of text; for 2-pass dump
-
+
function BackupDumper( $args ) {
$this->stderr = fopen( "php://stderr", "wt" );
-
+
// Built-in output and filter plugins
$this->registerOutput( 'file', 'DumpFileOutput' );
$this->registerOutput( 'gzip', 'DumpGZipOutput' );
$this->registerOutput( 'bzip2', 'DumpBZip2Output' );
$this->registerOutput( '7zip', 'Dump7ZipOutput' );
-
+
$this->registerFilter( 'latest', 'DumpLatestFilter' );
$this->registerFilter( 'notalk', 'DumpNotalkFilter' );
$this->registerFilter( 'namespace', 'DumpNamespaceFilter' );
-
+
$this->sink = $this->processArgs( $args );
}
-
+
/**
* @param string $name
* @param string $class name of output filter plugin class
function registerOutput( $name, $class ) {
$this->outputTypes[$name] = $class;
}
-
+
/**
* @param string $name
* @param string $class name of filter plugin class
function registerFilter( $name, $class ) {
$this->filterTypes[$name] = $class;
}
-
+
/**
* Load a plugin and register it
* @param string $class Name of plugin class; must have a static 'register'
$register = array( $class, 'register' );
call_user_func_array( $register, array( &$this ) );
}
-
+
/**
* @param array $args
* @return array
}
$type = $this->filterTypes[$val];
$filter = new $type( $sink, $param );
-
+
// references are lame in php...
unset( $sink );
$sink = $filter;
-
+
break;
default:
$this->processOption( $opt, $val, $param );
}
}
}
-
+
if( is_null( $sink ) ) {
$sink = new DumpOutput();
}
$sinks[] = $sink;
-
+
if( count( $sinks ) > 1 ) {
return new DumpMultiWriter( $sinks );
} else {
return $sink;
}
}
-
+
function processOption( $opt, $val, $param ) {
// extension point for subclasses to add options
}
-
+
function dump( $history, $text = MW_EXPORT_TEXT ) {
# This shouldn't happen if on console... ;)
header( 'Content-type: text/html; charset=UTF-8' );
-
+
# Notice messages will foul up your XML output even if they're
# relatively harmless.
ini_set( 'display_errors', false );
-
+
$this->startTime = wfTime();
-
+
$dbr =& wfGetDB( DB_SLAVE );
$this->maxCount = $dbr->selectField( 'page', 'MAX(page_id)', '', 'BackupDumper::dump' );
$this->startTime = wfTime();
-
+
$db =& $this->backupDb();
$exporter = new WikiExporter( $db, $history, MW_EXPORT_STREAM, $text );
-
+
$wrapper = new ExportProgressFilter( $this->sink, $this );
$exporter->setOutputSink( $wrapper );
-
+
if( !$this->skipHeader )
$exporter->openStream();
if( !$this->skipFooter )
$exporter->closeStream();
-
+
$this->report( true );
}
-
+
function &backupDb() {
global $wgDBadminuser, $wgDBadminpassword;
global $wgDBname;
$db->query( "SET net_write_timeout=$timeout" );
return $db;
}
-
+
function backupServer() {
global $wgDBserver;
return $this->server
$this->pageCount++;
$this->report();
}
-
+
function revCount() {
$this->revCount++;
}
-
+
function report( $final = false ) {
if( $final xor ( $this->pageCount % $this->reportingInterval == 0 ) ) {
$this->showReport();
}
}
-
+
function showReport() {
if( $this->reporting ) {
$delta = wfTime() - $this->startTime;
$this->progress( "$now: $wgDBname $this->pageCount, ETA $etats ($rate pages/sec $revrate revs/sec)" );
}
}
-
+
function progress( $string ) {
fwrite( $this->stderr, $string . "\n" );
}
parent::writeClosePage( $string );
$this->progress->reportPage();
}
-
+
function writeRevision( $rev, $string ) {
parent::writeRevision( $rev, $string );
$this->progress->revCount();
var $atPageEnd = false;
var $lastPage = 0;
var $lastRev = 0;
-
+
function BaseDump( $infile ) {
$this->reader = new XMLReader();
$this->reader->open( $infile );
}
-
+
/**
* Attempts to fetch the text of a particular page revision
* from the dump stream. May return null if the page is
return null;
}
}
-
+
function debug( $str ) {
wfDebug( $str . "\n" );
//global $dumper;
//$dumper->progress( $str );
}
-
+
/**
* @access private
*/
$this->atEnd = true;
}
}
-
+
/**
* @access private
*/
$this->atPageEnd = true;
}
}
-
+
/**
* @access private
*/
$this->skipTo( 'text' );
return strval( $this->nodeContents() );
}
-
+
/**
* @access private
*/
}
return $this->close();
}
-
+
/**
* Shouldn't something like this be built-in to XMLReader?
* Fetches text contents of the current element, assuming
}
return $this->close();
}
-
+
/**
* @access private
*/
class ChangePassword {
var $dbw;
var $user, $password;
-
+
function ChangePassword( $user, $password ) {
$this->user = User::newFromName( $user );
$this->password = $password;
-
+
$this->dbw =& wfGetDB( DB_MASTER );
}
function main() {
$fname = 'ChangePassword::main';
-
+
$this->dbw->update( 'user',
array(
'user_password' => wfEncryptPassword( $this->user->getID(), $this->password )
function main() {
global $wgDBname;
$fname = 'checkUsernames::main';
-
+
$dbr =& wfGetDB( DB_SLAVE );
-
+
$res = $dbr->select( 'user',
array( 'user_id', 'user_name' ),
null,
class CapsCleanup extends FiveUpgrade {
function CapsCleanup( $dryrun = false, $namespace=0 ) {
parent::FiveUpgrade();
-
+
$this->maxLag = 10; # if slaves are lagged more than 10 secs, wait
$this->dryrun = $dryrun;
$this->namespace = intval( $namespace );
}
-
+
function cleanup() {
global $wgCapitalLinks;
if( $wgCapitalLinks ) {
echo "\$wgCapitalLinks is on -- no need for caps links cleanup.\n";
return false;
}
-
+
$this->runTable( 'page', 'WHERE page_namespace=' . $this->namespace,
array( &$this, 'processPage' ) );
}
-
+
function init( $count, $table ) {
$this->processed = 0;
$this->updated = 0;
$this->startTime = wfTime();
$this->table = $table;
}
-
+
function progress( $updated ) {
$this->updated += $updated;
$this->processed++;
}
$portion = $this->processed / $this->count;
$updateRate = $this->updated / $this->processed;
-
+
$now = wfTime();
$delta = $now - $this->startTime;
$estimatedTotalTime = $delta / $portion;
$eta = $this->startTime + $estimatedTotalTime;
-
+
printf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n",
wfTimestamp( TS_DB, intval( $now ) ),
$portion * 100.0,
$updateRate * 100.0 );
flush();
}
-
+
function runTable( $table, $where, $callback ) {
$fname = 'CapsCleanup::buildTable';
-
+
$count = $this->dbw->selectField( $table, 'count(*)', '', $fname );
$this->init( $count, 'page' );
$this->log( "Processing $table..." );
-
+
$tableName = $this->dbr->tableName( $table );
$sql = "SELECT * FROM $tableName $where";
$result = $this->dbr->query( $sql, $fname );
-
+
while( $row = $this->dbr->fetchObject( $result ) ) {
$updated = call_user_func( $callback, $row );
}
$this->log( "Finished $table... $this->updated of $this->processed rows updated" );
$this->dbr->freeResult( $result );
}
-
+
function processPage( $row ) {
global $wgContLang;
-
+
$current = Title::makeTitle( $row->page_namespace, $row->page_title );
$display = $current->getPrefixedText();
$upper = $row->page_title;
$this->log( "\"$display\" already lowercase." );
return $this->progress( 0 );
}
-
+
$target = Title::makeTitle( $row->page_namespace, $lower );
$targetDisplay = $target->getPrefixedText();
if( $target->exists() ) {
$this->log( "\"$display\" skipped; \"$targetDisplay\" already exists" );
return $this->progress( 0 );
}
-
+
if( $this->dryrun ) {
$this->log( "\"$display\" -> \"$targetDisplay\": DRY RUN, NOT MOVED" );
$ok = true;
}
if( $ok === true ) {
$this->progress( 1 );
-
+
if( $row->page_namespace == $this->namespace ) {
$talk = $target->getTalkPage();
$xrow = $row;
while( $row = $dbw->fetchObject( $res ) ) {
$ns = intval( $row->cur_namespace );
$title = $dbw->addQuotes( $row->cur_title );
-
+
# Get the first responding ID; that'll be the one we keep.
$id = $dbw->selectField( 'cur', 'cur_id', array(
'cur_namespace' => $row->cur_namespace,
'cur_title' => $row->cur_title ) );
-
+
echo "$ns:$row->cur_title (canonical ID $id)\n";
if( $id != $row->id ) {
echo " ** minimum ID $row->id; ";
}
}
}
-
+
if( $fixthem ) {
$dbw->query( <<<END
INSERT
class TitleCleanup extends FiveUpgrade {
function TitleCleanup( $dryrun = false ) {
parent::FiveUpgrade();
-
+
$this->maxLag = 10; # if slaves are lagged more than 10 secs, wait
$this->dryrun = $dryrun;
}
-
+
function cleanup() {
$this->runTable( 'page',
'', //'WHERE page_namespace=0',
array( &$this, 'processPage' ) );
}
-
+
function init( $count, $table ) {
$this->processed = 0;
$this->updated = 0;
$this->startTime = wfTime();
$this->table = $table;
}
-
+
function progress( $updated ) {
$this->updated += $updated;
$this->processed++;
}
$portion = $this->processed / $this->count;
$updateRate = $this->updated / $this->processed;
-
+
$now = wfTime();
$delta = $now - $this->startTime;
$estimatedTotalTime = $delta / $portion;
$eta = $this->startTime + $estimatedTotalTime;
-
+
global $wgDBname;
printf( "%s %s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n",
$wgDBname,
$updateRate * 100.0 );
flush();
}
-
+
function runTable( $table, $where, $callback ) {
$fname = 'CapsCleanup::buildTable';
-
+
$count = $this->dbw->selectField( $table, 'count(*)', '', $fname );
$this->init( $count, 'page' );
$this->log( "Processing $table..." );
-
+
$tableName = $this->dbr->tableName( $table );
$sql = "SELECT * FROM $tableName $where";
$result = $this->dbr->query( $sql, $fname );
-
+
while( $row = $this->dbr->fetchObject( $result ) ) {
$updated = call_user_func( $callback, $row );
}
$this->log( "Finished $table... $this->updated of $this->processed rows updated" );
$this->dbr->freeResult( $result );
}
-
+
function processPage( $row ) {
global $wgContLang;
-
+
$current = Title::makeTitle( $row->page_namespace, $row->page_title );
$display = $current->getPrefixedText();
-
+
$verified = UtfNormal::cleanUp( $display );
-
+
$title = Title::newFromText( $verified );
-
+
if( is_null( $title ) ) {
$this->log( "page $row->page_id ($display) is illegal." );
$this->moveIllegalPage( $row );
return $this->progress( 1 );
}
-
+
if( !$title->equals( $current ) ) {
$this->log( "page $row->page_id ($display) doesn't match self." );
$this->moveInconsistentPage( $row, $title );
return $this->progress( 1 );
}
-
+
$this->progress( 0 );
}
-
+
function moveIllegalPage( $row ) {
$legal = 'A-Za-z0-9_/\\\\-';
$legalized = preg_replace_callback( "!([^$legal])!",
if( $legalized == '.' ) $legalized = '(dot)';
if( $legalized == '_' ) $legalized = '(space)';
$legalized = 'Broken/' . $legalized;
-
+
$title = Title::newFromText( $legalized );
if( is_null( $title ) ) {
$clean = 'Broken/id:' . $row->page_id;
$this->log( "Legalized for '$legalized' exists; using '$clean'" );
$title = Title::newFromText( $clean );
}
-
+
$dest = $title->getDbKey();
if( $this->dryrun ) {
$this->log( "DRY RUN: would rename $row->page_id ($row->page_namespace,'$row->page_title') to ($row->page_namespace,'$dest')" );
'cleanupTitles::moveInconsistentPage' );
}
}
-
+
function moveInconsistentPage( $row, $title ) {
if( $title->exists() || $title->getInterwiki() ) {
if( $title->getInterwiki() ) {
$linkCache->clear();
}
}
-
+
function hexChar( $matches ) {
return sprintf( "\\x%02x", ord( $matches[1] ) );
}
# If not, work out the language and site the old way
if ( is_null( $site ) || is_null( $lang ) ) {
- if ( !$db ) {
+ if ( !$db ) {
$lang = 'aa';
} else {
$lang = $db;
require_once( $IP.'/includes/Defines.php' );
require_once( $settingsFile );
ini_set( 'include_path', ".$sep$IP$sep$IP/includes$sep$IP/languages$sep$IP/maintenance" );
-
+
if ( is_readable( $IP.'/AdminSettings.php' ) ) {
require_once( $IP.'/AdminSettings.php' );
}
print "Links table already ok on PostgreSQL.\n";
return;
}
-
+
print "Converting links table to ID-ID...\n";
-
+
global $wgLang, $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname;
global $noKeys, $logPerformance, $fh;
-
+
$numRows = $tuplesAdded = $numBadLinks = $curRowsRead = 0; #counters etc
$totalTuplesInserted = 0; # total tuples INSERTed into links_temp
$logPerformance = false; # output performance data to a file
$perfLogFilename = "convLinksPerf.txt";
#--------------------------------------------------------------------
-
+
$dbw =& wfGetDB( DB_MASTER );
extract( $dbw->tableNames( 'cur', 'links', 'links_temp', 'links_backup' ) );
print "Schema already converted\n";
return;
}
-
+
$res = $dbw->query( "SELECT COUNT(*) AS count FROM $links" );
$row = $dbw->fetchObject($res);
$numRows = $row->count;
print "Loading IDs from $cur table...\n";
performanceLog ( "Reading $numRows rows from cur table...\n" );
performanceLog ( "rows read vs seconds elapsed:\n" );
-
+
$dbw->bufferResults( false );
$res = $dbw->query( "SELECT cur_namespace,cur_title,cur_id FROM $cur" );
$ids = array();
if ($reportCurReadProgress) {
if (($curRowsRead % $curReadReportInterval) == 0) {
performanceLog( $curRowsRead . " " . (getMicroTime() - $baseTime) . "\n" );
- print "\t$curRowsRead rows of $cur table read.\n";
+ print "\t$curRowsRead rows of $cur table read.\n";
}
}
}
print "Processing $numRows rows from $links table...\n";
performanceLog( "Processing $numRows rows from $links table...\n" );
performanceLog( "rows inserted vs seconds elapsed:\n" );
-
+
for ($rowOffset = $initialRowOffset; $rowOffset < $numRows; $rowOffset += $linksConvInsertInterval) {
$sqlRead = "SELECT * FROM $links ";
$sqlRead = $dbw->limitResult($sqlRead, $linksConvInsertInterval,$rowOffset);
} else {
$sqlWrite = array("INSERT IGNORE INTO $links_temp (l_from,l_to) VALUES ");
}
-
+
$tuplesAdded = 0; # no tuples added to INSERT yet
while ( $row = $dbw->fetchObject($res) ) {
$fromTitle = $row->l_from;
$sqlWrite[] = ",";
}
$sqlWrite[] = "($from,$to)";
- $tuplesAdded++;
+ $tuplesAdded++;
} else { # invalid title
$numBadLinks++;
}
print "Dropping backup links table if it exists...";
$dbConn->query( "DROP TABLE IF EXISTS $links_backup", DB_MASTER);
print " 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'...";
$dbConn->query( "RENAME TABLE links TO $links_backup, $links_temp TO $links", DB_MASTER );
print " done.\n\n";
-
+
$dbConn->close();
print "Conversion complete. The old table remains at $links_backup;\n";
print "delete at your leisure.\n";
global $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname;
global $noKeys;
$dbConn = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
-
+
if (!($dbConn->isOpen())) {
print "Opening connection to database failed.\n";
return;
}
$links_temp = $dbConn->tableName( 'links_temp' );
-
+
print "Dropping temporary links table if it exists...";
$dbConn->query( "DROP TABLE IF EXISTS $links_temp");
print " done.\n";
-
+
print "Creating temporary links table...";
if ( $noKeys ) {
$dbConn->query( "CREATE TABLE $links_temp ( " .
/**
* @param string $string A string to be converted to UTF-8
- */
+ */
function toUtf8( $string ) {
if( function_exists( 'iconv' ) ) {
# There are likely to be Windows code page 1252 chars in there.
$tableName = $this->db->tableName( $table );
$this->db->query( 'TRUNCATE $tableName' );
}
-
+
/**
* @param string $table Table to be converted
* @param string $key Primary key, to identify fields in the UPDATE. If NULL, all fields will be used to match.
$keyCond,
$fname );
if( ++$n % 100 == 0 ) echo "$n\n";
-
+
if( is_callable( $callback ) ) {
call_user_func( $callback, $s );
}
echo "$n done.\n";
$this->db->freeResult( $res );
}
-
+
/**
* @param object $row
* @access private
function imageRenameCallback( $row ) {
$this->renameFile( $row->img_name, 'wfImageDir' );
}
-
+
/**
* @param object $row
* @access private
function oldimageRenameCallback( $row ) {
$this->renameFile( $row->oi_archive_name, 'wfImageArchiveDir' );
}
-
+
/**
* Rename a given image or archived image file to the converted filename,
* leaving a symlink for URL compatibility.
// No need to rename; another field triggered this row.
return;
}
-
+
$oldpath = call_user_func( $subdirCallback, $oldname ) . '/' . $oldname;
$newpath = call_user_func( $subdirCallback, $newname ) . '/' . $newname;
-
+
echo "Renaming $oldpath to $newpath... ";
if( rename( $oldpath, $newpath ) ) {
echo "ok\n";
echo " rename failed!\n";
}
}
-
+
/**
* Lock tables.
* @param array $tables An array of table to be locked.
/**
* @todo document
- */
+ */
function updateAll() {
$this->lockTables( array(
'objectcache', 'searchindex', 'querycache',
'ipblocks', 'user', 'page', 'revision', 'recentchanges',
'brokenlinks', 'categorylinks', 'imagelinks', 'watchlist',
'image', 'oldimage', 'archive' ) );
-
+
# These are safe to clear out:
$this->clearTable( 'objectcache' );
array( 'page_title' ), 'page_touched' );
$this->convertTable( 'revision', 'rev_id',
array( 'rev_user_text', 'rev_comment' ) );
-
+
$this->convertTable( 'recentchanges', 'rc_id',
array( 'rc_user_text', 'rc_title', 'rc_comment' ) );
-
+
$this->convertTable( 'pagelinks', 'pl_title' );
$this->convertTable( 'categorylinks', 'cl_to' );
$this->convertTable( 'imagelinks', 'il_to' );
$this->convertTable( 'watchlist', 'wl_title' );
-
+
# We'll also need to change the files.
$this->convertTable( 'image', 'img_name',
array( 'img_name', 'img_description', 'img_user_text' ),
array( 'oi_name', 'oi_archive_name', 'oi_description', 'oi_user_text' ),
null,
array( &$this, 'oldimageRenameCallback' ) );
-
+
# Don't change the ar_text entries; use $wgLegacyEncoding to read them at runtime
$this->convertTable( 'archive', null,
array( 'ar_title', 'ar_comment', 'ar_user_text' ) );
echo "Not converting text table: be sure to set \$wgLegacyEncoding!\n";
-
+
$this->db->query( 'UNLOCK TABLES' );
}
-
+
}
?>
$this->sleep = $sleep;
$this->report = $report;
}
-
+
function main() {
global $wgMemc, $wgDBname;
$fname = 'DeleteImageCache::main';
ini_set( 'display_errors', false );
-
+
$dbr =& wfGetDB( DB_SLAVE );
-
+
$res = $dbr->select( 'image',
array( 'img_name' ),
array( "img_timestamp < {$this->until}" ),
printf("%s: %13s done (%s)\n", $wgDBname, "$i/$total", wfPercent( $i / $total * 100 ));
$md5 = md5( $row->img_name );
$wgMemc->delete( "$wgDBname:Image:$md5" );
-
+
if ($this->sleep != 0)
usleep( $this->sleep );
++$i;
}
}
-
+
function getImageCount() {
$fname = 'DeleteImageCache::getImageCount';
// Load datas from MediaWiki
$testMessages = getMediawikiMessages($lang);
- $testLanguage = $lang;
+ $testLanguage = $lang;
} else {
usage();
die();
# Show interlanguage links?
var $interwiki = true;
-
+
# Depth of HTML directory tree
var $depth = 3;
# Directory that commons images are copied into
var $sharedStaticPath;
-
+
# Relative path to image directory
var $imageRel = 'upload';
# List of raw pages used in the current article
var $rawPages;
-
+
function DumpHTML( $settings ) {
foreach ( $settings as $var => $value ) {
$this->$var = $value;
*/
function doArticles( $start, $end = false ) {
$fname = 'DumpHTML::doArticles';
-
+
$this->setupGlobals();
-
+
if ( $end === false ) {
$dbr =& wfGetDB( DB_SLAVE );
$end = $dbr->selectField( 'page', 'max(page_id)', false, $fname );
$mainPageObj = Title::newMainPage();
$mainPage = $mainPageObj->getPrefixedDBkey();
-
+
for ($id = $start; $id <= $end; $id++) {
wfWaitForSlaves( 20 );
if ( !($id % REPORTING_INTERVAL) ) {
}
}
print "\n";
- }
+ }
function doSpecials() {
$this->doMainPage();
function doImageDescriptions() {
global $wgSharedUploadDirectory;
-
+
$fname = 'DumpHTML::doImageDescriptions';
-
+
$this->setupGlobals();
/**
*/
print "Writing description pages for commons images\n";
$i = 0;
- for ( $hash = 0; $hash < 256; $hash++ ) {
+ for ( $hash = 0; $hash < 256; $hash++ ) {
$dir = sprintf( "%01x/%02x", intval( $hash / 16 ), $hash );
$paths = array_merge( glob( "{$this->sharedStaticPath}/$dir/*" ),
glob( "{$this->sharedStaticPath}/thumb/$dir/*" ) );
print("Can't open file $fullName for writing\n");
return;
}
-
+
fwrite( $file, $text );
fclose( $file );
}
global $wgRightsUrl, $wgRightsText, $wgCopyrightIcon;
static $oldLogo = NULL;
-
+
if ( !$this->setupDone ) {
$wgHooks['GetLocalURL'][] =& $this;
$wgHooks['GetFullURL'][] =& $this;
if ( is_null( $currentDepth ) ) {
$currentDepth = $this->depth;
}
-
+
if ( $this->alternateScriptPath ) {
if ( $currentDepth == 0 ) {
$wgScriptPath = '.';
$wgThumbnailScriptPath = $wgSharedThumbnailScriptPath = false;
$wgEnableParserCache = false;
$wgMathPath = "$wgScriptPath/math";
-
+
if ( !empty( $wgRightsText ) ) {
$wgRightsUrl = "$wgScriptPath/COPYING.html";
}
/** Reads the content of a title object, executes the skin and captures the result */
function getArticleHTML( &$title ) {
global $wgOut, $wgTitle, $wgArticle, $wgUser;
-
+
$linkCache =& LinkCache::singleton();
$linkCache->clear();
$wgTitle = $title;
if ( is_null( $wgTitle ) ) {
return false;
}
-
+
$ns = $wgTitle->getNamespace();
if ( $ns == NS_SPECIAL ) {
$wgOut = new OutputPage;
} else {
$wgOut = new OutputPage;
$wgOut->setParserOptions( new ParserOptions );
-
+
$wgArticle->view();
}
}
global $wgOutputEncoding, $wgDumpImages;
$parser = xml_parser_create( $wgOutputEncoding );
xml_set_element_handler( $parser, 'wfDumpStartTagHandler', 'wfDumpEndTagHandler' );
-
+
$wgDumpImages = array();
xml_parse( $parser, $text );
xml_parser_free( $parser );
return true;
}
}
-
+
function onGetLocalURL( &$title, &$url, $query ) {
global $wgArticlePath;
if ( $url === false ) {
$url = str_replace( '$1', wfUrlencode( $this->getHashedFilename( $title ) ), $wgArticlePath );
}
-
+
return false;
}
return $friendlyName;
}
-
+
/**
* Get a relative directory for putting a title into
*/
$end = $options['e'];
} else {
$dbr =& wfGetDB( DB_SLAVE );
- $end = $dbr->selectField( 'page', 'max(page_id)', false );
+ $end = $dbr->selectField( 'page', 'max(page_id)', false );
}
if ( !empty( $options['d'] ) ) {
$wgHTMLDump->doCategories();
$wgHTMLDump->doSpecials();
}
-
+
/*
if ( $end - $start > CHUNK_SIZE * 2 ) {
// Split the problem into smaller chunks, run them in different PHP instances
$recentchanges = $dbw->tableName( 'recentchanges' );
$result =& $dbw->safeQuery( "SELECT * FROM $recentchanges WHERE rc_timestamp >= "
. $dbw->timestamp( $start ) . ' ORDER BY rc_timestamp');
-
+
global $wgInputEncoding;
echo '<' . '?xml version="1.0" encoding="' . $wgInputEncoding . '" ?' . ">\n";
echo "<wikilog version='experimental'>\n";
case RC_NEW:
# Edit
$dbr =& wfGetDB( DB_MASTER );
-
+
$out = " <edit>\n";
$out .= " <title>" . xmlsafe( $title->getPrefixedText() ) . "</title>\n";
-
+
# Get previous edit timestamp
if( $row->rc_last_oldid ) {
$s = $dbr->selectRow( 'old',
} else {
$out .= " <newpage/>\n";
}
-
+
if( $row->rc_this_oldid ) {
$s = $dbr->selectRow( 'old', array( 'old_id as id','old_timestamp as timestamp',
'old_user as user', 'old_user_text as user_text', 'old_comment as comment',
class TextPassDumper extends BackupDumper {
var $prefetch = null;
-
+
function dump() {
# This shouldn't happen if on console... ;)
header( 'Content-type: text/html; charset=UTF-8' );
-
+
# Notice messages will foul up your XML output even if they're
# relatively harmless.
// ini_set( 'display_errors', false );
-
+
$this->startTime = wfTime();
-
+
$this->db =& $this->backupDb();
$this->maxCount = $this->db->selectField( 'page', 'MAX(page_id)', '', 'BackupDumper::dump' );
$this->startTime = wfTime();
-
+
$this->egress = new ExportProgressFilter( $this->sink, $this );
$input = fopen( "php://stdin", "rt" );
$result = $this->readDump( $input );
-
+
if( WikiError::isError( $result ) ) {
$this->progress( $result->getMessage() );
}
-
+
$this->report( true );
}
-
+
function processOption( $opt, $val, $param ) {
if( $opt == 'prefetch' ) {
require_once 'maintenance/backupPrefetch.inc';
$this->prefetch = new BaseDump( $filename );
}
}
-
+
function readDump( $input ) {
$this->buffer = "";
$this->openElement = false;
$this->lastName = "";
$this->thisPage = 0;
$this->thisRev = 0;
-
+
$parser = xml_parser_create( "UTF-8" );
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
-
+
xml_set_element_handler( $parser, array( &$this, 'startElement' ), array( &$this, 'endElement' ) );
xml_set_character_data_handler( $parser, array( &$this, 'characterData' ) );
-
+
$offset = 0; // for context extraction on error reporting
$bufferSize = 512 * 1024;
do {
} while( $chunk !== false && !feof( $input ) );
xml_parser_free( $parser );
}
-
+
function getText( $id ) {
if( isset( $this->prefetch ) ) {
$text = $this->prefetch->prefetch( $this->thisPage, $this->thisRev );
$normalized = UtfNormal::cleanUp( $stripped );
return $normalized;
}
-
+
function startElement( $parser, $name, $attribs ) {
$this->clearOpenElement( null );
$this->lastName = $name;
-
+
if( $name == 'revision' ) {
$this->state = $name;
$this->egress->writeOpenPage( null, $this->buffer );
$this->atStart = false;
}
}
-
+
if( $name == "text" && isset( $attribs['id'] ) ) {
$text = $this->getText( $attribs['id'] );
$this->openElement = array( $name, array( 'xml:space' => 'preserve' ) );
$this->openElement = array( $name, $attribs );
}
}
-
+
function endElement( $parser, $name ) {
if( $this->openElement ) {
$this->clearOpenElement( "" );
} else {
$this->buffer .= "</$name>";
}
-
+
if( $name == 'revision' ) {
$this->egress->writeRevision( null, $this->buffer );
$this->buffer = "";
$this->buffer = "";
}
}
-
+
function characterData( $parser, $data ) {
$this->clearOpenElement( null );
if( $this->lastName == "id" ) {
}
$this->buffer .= htmlspecialchars( $data );
}
-
+
function clearOpenElement( $style ) {
if( $this->openElement ) {
$this->buffer .= wfElement( $this->openElement[0], $this->openElement[1], $style );
function desyncFixPage( $pageID ) {
global $numServers;
$fname = 'desyncFixPage';
-
+
# Check for a corrupted page_latest
$dbw =& wfGetDB( DB_MASTER );
$realLatest = $dbw->selectField( 'page', 'page_latest', array( 'page_id' => $pageID ), $fname );
if ( $i == $numServers ) {
return;
}
-
+
# Find the missing revision
$res = $dbw->select( 'revision', array( 'rev_id' ), array( 'rev_page' => $pageID ), $fname );
$masterIDs = array();
$masterIDs[] = $row->rev_id;
}
$dbw->freeResult( $res );
-
+
$res = $db->select( 'revision', array( 'rev_id' ), array( 'rev_page' => $pageID ), $fname );
$slaveIDs = array();
while ( $row = $db->fetchObject( $res ) ) {
* @var int
*/
var $size_limit;
-
+
/**
* The path to prepend to the filename
*
* @var string
*/
var $path;
-
+
/**
* Whether or not to use compression
*
* @var bool
*/
var $compress;
-
+
/**
* The number of entries to save in each sitemap file
*
* @var object
*/
var $dbr;
-
+
/**
* A resource pointing to the sitemap index file
*
* @var resource
*/
var $findex;
-
+
/**
* A resource pointing to a sitemap file
*/
function GenerateSitemap( $fspath, $path, $compress ) {
global $wgDBname, $wgScriptPath;
-
+
$this->url_limit = 50000;
$this->size_limit = pow( 2, 20 ) * 10;
$this->fspath = isset( $fspath ) ? $fspath : '';
*/
function generateNamespaces() {
$fname = 'GenerateSitemap::generateNamespaces';
-
+
$res = $this->dbr->select( 'page',
array( 'page_namespace' ),
array(),
global $wgDBname, $wgContLang;
fwrite( $this->findex, $this->openIndex() );
-
+
foreach ( $this->namespaces as $namespace ) {
$res = $this->getPageRes( $namespace );
$this->file = false;
$this->generateLimit( $namespace );
$length = $this->limit[0];
$i = $smcount = 0;
-
+
$fns = $wgContLang->getFormattedNsText( $namespace );
$this->debug( "$namespace ($fns)" );
while ( $row = $this->dbr->fetchObject( $res ) ) {
function open( $file, $flags ) {
return $this->compress ? gzopen( $file, $flags ) : fopen( $file, $flags );
}
-
+
/**
* gzwrite() / fwrite() wrapper
*/
*/
function sitemapFilename( $namespace, $count ) {
global $wgDBname;
-
+
$ext = $this->compress ? '.gz' : '';
-
+
return "sitemap-$wgDBname-NS_$namespace-$count.xml$ext";
}
*/
function generateLimit( $namespace ) {
$title = Title::makeTitle( $namespace, str_repeat( "\xf0\xa8\xae\x81", 63 ) . "\xe5\x96\x83" );
-
+
$this->limit = array(
strlen( $this->openFile() ),
strlen( $this->fileEntry( $title->getFullUrl(), wfTimestamp( TS_ISO_8601, wfTimestamp() ), $this->priority( $namespace ) ) ),
*/
class LogImporter {
var $dummy = false;
-
+
function LogImporter( $type ) {
$this->type = $type;
$this->db =& wfGetDB( DB_MASTER );
$this->actions = $this->setupActions();
}
-
+
function setupActions() {
$actions = array();
foreach( LogPage::validActions( $this->type ) as $action ) {
}
return $actions;
}
-
+
function makeLineRegexp( $type, $action ) {
$linkRegexp = '(?:\[\[)?([^|\]]+?)(?:\|[^\]]+?)?(?:\]\])?';
$linkRegexp2 = '\[\[([^|\]]+?)(?:\|[^\]]+?)?\]\]';
-
+
$text = LogPage::actionText( $type, $action );
$text = preg_quote( $text, '/' );
$text = str_replace( '\$1', $linkRegexp, $text );
$text = "/$text/";
return $text;
}
-
+
function importText( $text ) {
if( $this->dummy ) {
print $text;
}
}
}
-
+
function fixDate( $date ) {
# Yuck! Parsing multilingual date formats??!!!!???!!??!
# 01:55, 23 Aug 2004 - won't take in strtotimr
$timestamp = wfTimestamp( TS_MW, $n );
return $timestamp;
}
-
+
function importLine( $line ) {
foreach( $this->actions as $action => $regexp ) {
if( preg_match( $regexp, $line, $matches ) ) {
} else {
$comment = '';
}
-
+
$insert = array(
'log_type' => $this->type,
'log_action' => preg_replace( '!^.*/!', '', $action ),
foreach( LogPage::validTypes() as $type ) {
if( $type == '' ) continue;
-
+
$page = LogPage::logName( $type );
$log = new Article( Title::makeTitleSafe( NS_PROJECT, $page ) );
$text = $log->getContentWithoutUsingSoManyDamnGlobals();
*/
class Phase2Importer {
var $olddb, $titleCache;
-
+
function Phase2Importer( $database ) {
$this->olddb = $database;
$this->titleCache = new TitleCache;
}
-
+
function importAll() {
$this->importCurData();
$this->fixCurTitles();
-
+
$this->importOldData();
$this->fixOldTitles();
-
+
$this->importUserData();
$this->fixUserOptions();
-
+
$this->importWatchlists();
-
+
$this->importLinkData();
/*
rebuildRecentChangesTablePass1();
rebuildRecentChangesTablePass2();
*/
-
+
print "Rebuilding search index:\n";
dropTextIndex();
rebuildTextIndex();
createTextIndex();
-
+
initialiseMessages();
}
-
+
# Simple import functions; for the most part these are pretty straightforward.
# MySQL copies everything over to the new database and tweaks a few things.
function importCurData() {
print "Clearing pages from default install, if any...\n";
wfQuery( "DELETE FROM cur", DB_MASTER );
-
+
print "Importing current revision data...\n";
wfQuery( "INSERT INTO cur (cur_id,cur_namespace,cur_title,cur_text,cur_comment,
cur_user,cur_user_text,cur_timestamp,cur_restrictions,cur_counter,
$total = wfNumRows( $res );
$n = 0;
print " ($total total)\n";
-
+
while( $row = wfFetchObject( $res ) ) {
$id = intval( $row->user_id );
$list = explode( "\n", $row->user_watch );
}
wfFreeResult( $res );
}
-
+
function importLinkData() {
# MUST BE CALLED BEFORE! fixCurTitles()
print "Clearing links from default install, if any...\n";
WHERE linked_to=cur_title", DB_MASTER );
$n = mysql_affected_rows();
print "$n rows imported.\n";
-
+
print "Importing broken links...";
wfQuery( "INSERT INTO brokenlinks (bl_from, bl_to)
SELECT DISTINCT cur_id,unlinked_to
function fixCurTitles() {
$this->fixTitles( "cur" );
}
-
+
function fixOldTitles() {
$this->fixTitles( "old" );
}
-
+
function fixTitles( $table ) {
print "Fixing titles in $table...";
$res = wfQuery( "SELECT DISTINCT {$table}_title AS title FROM $table", DB_MASTER );
$total = wfNumRows( $res );
$n = 0;
print " ($total total)\n";
-
+
while( $row = wfFetchObject( $res ) ) {
$xt = wfStrencode( $row->title );
$title = $this->titleCache->fetch( $row->title );
{
$s = urldecode( $in );
$a = explode( "\n", $s );
-
+
foreach ( $a as $l ) {
if ( preg_match( "/^([A-Za-z0-9_]+)=(.*)/", $l, $m ) ) {
$ops[$m[1]] = $m[2];
}
}
$nops = array();
-
+
$q = strtolower( $ops["quickBar"] );
if ( $q == "none" ) { $q = 0; }
else { $q = 1; } # Default to left
$nops["quickbar"] = $q;
-
+
if ( $ops["markupNewTopics"] == "inverse" ) {
$nops["highlightbroken"] = 1;
}
else if ( "colo" == $sk ) { $sk = 2; }
else { $sk = 0; }
$nops["skin"] = $sk;
-
+
$u = strtolower( $ops["underlineLinks"] );
if ( "yes" == $u || "on" == $u ) { $nops["underline"] = 1; }
else { $nops["underline"] = 0; }
-
+
$t = ( (int) ($ops["hourDiff"]) );
if ( $t < -23 || $t > 23 ) { $t = 0; }
if ( 0 != $t ) { $nops["timecorrection"] = $t; }
-
+
$j = strtolower( $ops["justify"] );
if ( "yes" == $j || "on" == $j ) { $nops["justify"] = 1; }
$n = strtolower( $ops["numberHeadings"] );
if ( "yes" == $r || "on" == $r ) { $nops["rememberpassword"] = 1; }
$s = strtolower( $ops["showHover"] );
if ( "yes" == $s || "on" == $s ) { $nops["hover"] = 1; }
-
+
$c = $ops["cols"];
if ( $c < 20 || $c > 200 ) { $nops["cols"] = 80; }
else { $nops["cols"] = $c; }
if ( $r < 10 || $r > 1000 ) { $nops["rclimit"] = 50; }
else { $nops["rclimit"] = $r; }
$nops["rcdays"] = 3;
-
+
$a = array();
foreach ( $nops as $oname => $oval ) {
array_push( $a, "$oname=$oval" );
$total = wfNumRows( $res );
$n = 0;
print " ($total total)\n";
-
+
while( $row = wfFetchObject( $res ) ) {
$id = intval( $row->user_id );
$option = wfStrencode( $this->rewriteUserOptions( $row->user_options ) );
}
wfFreeResult( $res );
}
-
+
}
/**
*/
class TitleCache {
var $hash = array();
-
+
function &fetch( $dbkey ) {
if( !isset( $hash[$dbkey] ) ) {
$hash[$dbkey] = Title::newFromDBkey( $dbkey );
}
return $hash[$dbkey];
}
-
+
}
#
function importPages()
{
global $wgRootDirectory;
-
+
$gt = '>';
echo <<<END
<?xml version="1.0" encoding="UTF-8" ?$gt
function fetchPage( $title )
{
global $FS,$FS1,$FS2,$FS3, $wgRootDirectory;
-
+
$fname = $wgRootDirectory . "/page/" . useModFilename( $title ) . ".db";
if( !file_exists( $fname ) ) {
die( "Couldn't open file '$fname' for page '$title'.\n" );
}
-
+
$page = splitHash( $FS1, file_get_contents( $fname ) );
$section = splitHash( $FS2, $page["text_default"] );
$text = splitHash( $FS3, $section["data"] );
-
+
return array2object( array( "text" => $text["text"] , "summary" => $text["summary"] ,
"minor" => $text["minor"] , "ts" => $section["ts"] ,
"username" => $section["username"] , "host" => $section["host"] ) );
function fetchKeptPages( $title )
{
global $FS,$FS1,$FS2,$FS3, $wgRootDirectory, $wgTimezoneCorrection;
-
+
$fname = $wgRootDirectory . "/keep/" . useModFilename( $title ) . ".kp";
if( !file_exists( $fname ) ) return array();
-
+
$keptlist = explode( $FS1, file_get_contents( $fname ) );
array_shift( $keptlist ); # Drop the junk at beginning of file
-
+
$revisions = array();
foreach( $keptlist as $rev ) {
$section = splitHash( $FS2, $rev );
function importPage( $title )
{
global $usercache;
-
+
echo "\n<!-- Importing page " . xmlCommentSafe( $title ) . " -->\n";
$page = fetchPage( $title );
$newtitle = xmlsafe( str_replace( '_', ' ', recodeText( $title ) ) );
-
+
$munged = mungeFormat( $page->text );
if( $munged != $page->text ) {
/**
if(count( $revisions ) == 0 ) {
return $sql;
}
-
+
foreach( $revisions as $rev ) {
$text = xmlsafe( recodeText( $rev->text ) );
$minor = ($rev->minor ? '<minor/>' : '');
$username = xmlsafe( recodeText( $username ) );
$timestamp = xmlsafe( timestamp2ISO8601( $rev->ts ) );
$comment = xmlsafe( recodeText( $rev->summary ) );
-
+
$xml .= <<<END
<revision>
<timestamp>$timestamp</timestamp>
* XML output invalid, so be sure to strip them out.
*/
$string = UtfNormal::cleanUp( $string );
-
+
$string = htmlspecialchars( $string );
return $string;
}
$staged = preg_replace_callback(
'/(<nowiki>.*?<\\/nowiki>|(?:http|https|ftp):\\S+|\[\[[^]\\n]+]])/s',
'nowikiPlaceholder', $text );
-
+
# This is probably not 100% correct, I'm just
# glancing at the UseModWiki code.
$upper = "[A-Z]";
$camel = "(?:$upper+$lower+$upper+$any*)";
$subpage = "(?:\\/$any+)";
$substart = "(?:\\/$upper$any*)";
-
+
$munged = preg_replace( "/(?!\\[\\[)($camel$subpage*|$substart$subpage*)\\b(?!\\]\\]|>)/",
'[[$1]]', $staged );
-
+
$final = preg_replace( '/' . preg_quote( placeholder() ) . '/es',
'array_shift( $nowiki )', $munged );
return $final;
$pot = LOCALE_OUTPUT_DIR.'/wfMsg.pot';
$dest = $langdir.'/messages.po';
- // Merge template and generate file to get final .po
+ // Merge template and generate file to get final .po
exec(MSGMERGE_BIN.MSGMERGE_OPTIONS." $from $pot -o $dest ");
// delete no more needed file
// unlink($from);
}
}
- function getList() { return $this->list; }
+ function getList() { return $this->list; }
}
?>
$line = readconsole( '> ' );
if ($line === false) exit;
-
+
$args = explode( ' ', $line );
$command = array_shift( $args );
function NamespaceConflictChecker( &$db ) {
$this->db =& $db;
}
-
+
function checkAll( $fix, $suffix = '' ) {
global $wgContLang;
$spaces = $wgContLang->getNamespaces();
}
return $ok;
}
-
+
function checkNamespace( $ns, $name, $fix, $suffix = '' ) {
echo "Checking namespace $ns: \"$name\"\n";
if( $name == '' ) {
echo "... skipping article namespace\n";
return true;
}
-
+
$conflicts = $this->getConflicts( $ns, $name );
$count = count( $conflicts );
if( $count == 0 ) {
echo "... no conflicts detected!\n";
return true;
}
-
+
echo "... $count conflicts detected:\n";
$ok = true;
foreach( $conflicts as $row ) {
}
return $ok;
}
-
+
function getConflicts( $ns, $name ) {
$page = $this->newSchema() ? 'page' : 'cur';
$table = $this->db->tableName( $page );
-
+
$prefix = $this->db->strencode( $name );
$likeprefix = str_replace( '_', '\\_', $prefix);
-
+
$sql = "SELECT {$page}_id AS id,
{$page}_title AS oldtitle,
$ns AS namespace,
FROM {$table}
WHERE {$page}_namespace=0
AND {$page}_title LIKE '$likeprefix:%'";
-
+
$result = $this->db->query( $sql, 'NamespaceConflictChecker::getConflicts' );
-
+
$set = array();
while( $row = $this->db->fetchObject( $result ) ) {
$set[] = $row;
}
$this->db->freeResult( $result );
-
+
return $set;
}
-
+
function reportConflict( $row, $suffix ) {
$newTitle = Title::makeTitle( $row->namespace, $row->title );
printf( "... %d (0,\"%s\") -> (%d,\"%s\") [[%s]]\n",
$row->namespace,
$row->title,
$newTitle->getPrefixedText() );
-
+
$id = $newTitle->getArticleId();
if( $id ) {
echo "... *** cannot resolve automatically; page exists with ID $id ***\n";
return true;
}
}
-
+
function resolveConflict( $row, $resolvable, $suffix ) {
if( !$resolvable ) {
$row->title .= $suffix;
}
return true;
}
-
+
function resolveConflictOn( $row, $table ) {
$fname = 'NamespaceConflictChecker::resolveConflictOn';
echo "... resolving on $table... ";
echo "ok.\n";
return true;
}
-
+
function newSchema() {
return class_exists( 'Revision' );
}
$dbw =& wfGetDB( DB_MASTER );
$page = $dbw->tableName( 'page' );
$revision = $dbw->tableName( 'revision' );
-
+
if( $fix ) {
$dbw->query( "LOCK TABLES $page WRITE, $revision WRITE" );
}
-
+
echo "Checking for orphan revision table entries... (this may take a while on a large wiki)\n";
$result = $dbw->query( "
SELECT *
} else {
echo "No orphans! Yay!\n";
}
-
+
if( $fix ) {
$dbw->query( "UNLOCK TABLES" );
}
$dbw =& wfGetDB( DB_MASTER );
$page = $dbw->tableName( 'page' );
$revision = $dbw->tableName( 'revision' );
-
+
if( $fix ) {
$dbw->query( "LOCK TABLES $page WRITE, $revision WRITE" );
}
-
+
echo "\nChecking for childless page table entries... (this may take a while on a large wiki)\n";
$result = $dbw->query( "
SELECT *
} else {
echo "No childless pages! Yay!\n";
}
-
+
if( $fix ) {
$dbw->query( "UNLOCK TABLES" );
}
$page = $dbw->tableName( 'page' );
$revision = $dbw->tableName( 'revision' );
$text = $dbw->tableName( 'text' );
-
+
if( $fix ) {
$dbw->query( "LOCK TABLES $page WRITE, $revision WRITE, $text WRITE" );
}
-
+
echo "\nChecking for pages whose page_latest links are incorrect... (this may take a while on a large wiki)\n";
$result = $dbw->query( "
SELECT *
echo "wtf\n";
}
}
-
+
if( $found ) {
echo "Found $found pages with incorrect latest revision.\n";
} else {
if( !$fix && $found > 0 ) {
echo "Run again with --fix to remove these entries automatically.\n";
}
-
+
if( $fix ) {
$dbw->query( "UNLOCK TABLES" );
}
foreach( $databases as $db ) {
print "GRANT SELECT, INSERT, UPDATE, DELETE ON `$db`.* TO 'wikiuser'@'$host' IDENTIFIED BY '$wikiuser_pass';\n";
}
-
+
/*
print "\n-- wikisql\n\n";
foreach ( $databases as $db ) {
EOS;
}*/
-
+
print "\n-- wikiadmin\n\n";
print "GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'wikiadmin'@'$host' IDENTIFIED BY '$wikiadmin_pass';\n";
print "GRANT ALL PRIVILEGES ON `boardvote`.* TO wikiadmin@'$host' IDENTIFIED BY '$wikiadmin_pass';\n";
*/
function ParserTest() {
global $options;
-
+
# Only colorize output if stdout is a terminal.
$this->lightcolor = false;
$this->color = !wfIsWindows() && posix_isatty(1);
-
+
if( isset( $options['color'] ) ) {
switch( $options['color'] ) {
case 'no':
break;
}
}
-
+
$this->showDiffs = !isset( $options['quick'] );
-
+
$this->quiet = isset( $options['quiet'] );
if (isset($options['regex'])) {
return $s;
}
}
-
+
/**
* Run a series of tests listed in the given text file.
* Each test consists of a brief description, wikitext input,
if( !$infile ) {
die( "Couldn't open parserTests.txt\n" );
}
-
+
$data = array();
$section = null;
$success = 0;
$result = $this->tidy($result);
}
-
+
$this->teardownGlobals();
-
+
if( $result === $out && $this->wellFormed( $out ) ) {
return $this->showSuccess( $desc );
} else {
return $this->showFailure( $desc, $result, $out );
}
}
-
+
/**
* Set up the global variables for a consistent environment for each test.
* Ideally this should replace the global configuration entirely.
if( !isset( $this->uploadDir ) ) {
$this->uploadDir = $this->setupUploadDir();
}
-
+
$settings = array(
'wgServer' => 'http://localhost',
'wgScript' => '/index.php',
'wgContLanguageCode' => 'en',
'wgDBprefix' => 'parsertest',
'wgDefaultUserOptions' => array(),
-
+
'wgLang' => new LanguageUtf8(),
'wgContLang' => new LanguageUtf8(),
'wgNamespacesWithSubpages' => array( 0 => preg_match('/\\bsubpage\\b/i', $opts)),
$GLOBALS['wgLoadBalancer']->loadMasterPos();
$GLOBALS['wgMessageCache']->initialise( new BagOStuff(), false, 0, $GLOBALS['wgDBname'] );
$this->setupDatabase();
-
+
global $wgUser;
$wgUser = new User();
}
-
+
# List of temporary tables to create, without prefix
# Some of these probably aren't necessary
function listTables() {
'objectcache'
);
}
-
+
/**
* Set up a temporary set of wiki tables to work with for the tests.
* Currently this will only be done once per run, and any changes to
'img_major_mime' => "image",
'img_minor_mime' => "jpeg",
) );
-
+
$setupDB = true;
}
}
-
+
/**
* Create a dummy uploads directory which will contain a couple
* of files in order to pass existence tests.
*/
function setupUploadDir() {
global $IP;
-
+
$dir = wfTempDir() . "/mwParser-" . mt_rand() . "-images";
mkdir( $dir );
mkdir( $dir . '/3' );
mkdir( $dir . '/3/3a' );
-
+
$img = "$IP/skins/monobook/headbg.jpg";
$h = fopen($img, 'r');
$c = fread($h, filesize($img));
fclose($h);
-
+
$f = fopen( $dir . '/3/3a/Foobar.jpg', 'wb' );
fwrite( $f, $c );
fclose( $f );
return $dir;
}
-
+
/**
* Restore default values and perform any necessary clean-up
* after each test runs.
unset( $this->uploadDir );
}
}
-
+
/**
* Remove the dummy uploads directory
* @access private
@rmdir( "$dir/thumb" );
rmdir( "$dir" );
}
-
+
/**
* "Running test $desc..."
* @access private
function showTesting( $desc ) {
print "Running test $desc... ";
}
-
+
/**
* Print a happy success message.
*
}
return true;
}
-
+
/**
* Print a failure message and provide some explanatory output
* about what went wrong if so configured.
}
return false;
}
-
+
/**
* Run given strings through a diff and return the (colorized) output.
* Requires writable /tmp directory and a 'diff' command in the PATH.
*/
function quickDiff( $input, $output, $inFileTail='expected', $outFileTail='actual' ) {
$prefix = wfTempDir() . "/mwParser-" . mt_rand();
-
+
$infile = "$prefix-$inFileTail";
$this->dumpToFile( $input, $infile );
-
+
$outfile = "$prefix-$outFileTail";
$this->dumpToFile( $output, $outfile );
-
+
$diff = `diff -au $infile $outfile`;
unlink( $infile );
unlink( $outfile );
-
+
return $this->colorDiff( $diff );
}
-
+
/**
* Write the given string to a file, adding a final newline.
*
fwrite( $file, $data . "\n" );
fclose( $file );
}
-
+
/**
* Return ANSI terminal escape code for changing text attribs/color,
* or empty string if color output is disabled.
return $this->color ? "\x1b[{$color}m" : '';
}
}
-
+
/**
* Return ANSI terminal escape code for restoring default text attributes,
* or empty string if color output is disabled.
function termReset() {
return $this->color ? "\x1b[0m" : '';
}
-
+
/**
* Colorize unified diff output if set for ANSI color output.
* Subtractions are colored blue, additions red.
}
return $text;
}
-
+
/**
* Hack up a private DOCTYPE with HTML's standard entity declarations.
* PHP 4 seemed to know these if you gave it an HTML doctype, but
$out .= "]>\n";
return $out;
}
-
+
function wellFormed( $text ) {
$html =
$this->hackDocType() .
'<html>' .
$text .
'</html>';
-
+
$parser = xml_parser_create( "UTF-8" );
-
+
# case folding violates XML standard, turn it off
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
-
+
if( !xml_parse( $parser, $html, true ) ) {
$err = xml_error_string( xml_get_error_code( $parser ) );
$position = xml_get_current_byte_index( $parser );
xml_parser_free( $parser );
return true;
}
-
+
function extractFragment( $text, $position ) {
$start = max( 0, $position - 10 );
$before = $position - $start;
$this->termColor( 0 );
return "$display\n$caret";
}
-
+
}
?>
function wfParserTestSetup( &$parser ) {
$parser->setHook( 'tag', 'wfParserTestHook' );
}
-
+
function wfParserTestHook( $in, $argv ) {
if ( count( $argv ) )
return "<pre>\n" . print_r( $argv, true ) . '</pre>';
}
return $r ;
}
-
+
/** Make shades for pref. language(s) */
function getshades ( $l )
{
$y = explode ( ";" , $x ) ;
if ( count ( $y ) == 2 ) $weight = array_pop ( explode ( "=" , $y[1] ) ) ;
else $weight = "1.0" ;
-
+
$lang = array_shift ( $y ) ;
$lang = explode ( "-" , $lang ) ;
$lang = trim ( strtolower ( array_shift ( $lang ) ) ) ;
}
if ( $count != 0 ) $l .= "</tr>" ;
$l .= "</table>" ;
-
+
print "<html><head></head><body>" ;
print $l ;
print "</body></html>" ;
class ImageBuilder extends FiveUpgrade {
function ImageBuilder( $dryrun = false ) {
parent::FiveUpgrade();
-
+
$this->maxLag = 10; # if slaves are lagged more than 10 secs, wait
$this->dryrun = $dryrun;
}
-
+
function build() {
$this->buildImage();
$this->buildOldImage();
}
-
+
function init( $count, $table ) {
$this->processed = 0;
$this->updated = 0;
$this->startTime = wfTime();
$this->table = $table;
}
-
+
function progress( $updated ) {
$this->updated += $updated;
$this->processed++;
}
$portion = $this->processed / $this->count;
$updateRate = $this->updated / $this->processed;
-
+
$now = wfTime();
$delta = $now - $this->startTime;
$estimatedTotalTime = $delta / $portion;
$eta = $this->startTime + $estimatedTotalTime;
-
+
printf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n",
wfTimestamp( TS_DB, intval( $now ) ),
$portion * 100.0,
$updateRate * 100.0 );
flush();
}
-
+
function buildTable( $table, $key, $callback ) {
$fname = 'ImageBuilder::buildTable';
-
+
$count = $this->dbw->selectField( $table, 'count(*)', '', $fname );
$this->init( $count, $table );
$this->log( "Processing $table..." );
-
+
$tableName = $this->dbr->tableName( $table );
$sql = "SELECT * FROM $tableName";
$result = $this->dbr->query( $sql, $fname );
-
+
while( $row = $this->dbr->fetchObject( $result ) ) {
$update = call_user_func( $callback, $row );
if( is_array( $update ) ) {
$this->log( "Finished $table... $this->updated of $this->processed rows updated" );
$this->dbr->freeResult( $result );
}
-
+
function buildImage() {
$callback = array( &$this, 'imageCallback' );
$this->buildTable( 'image', 'img_name', $callback );
}
-
+
function imageCallback( $row ) {
if( $row->img_width ) {
// Already processed
return null;
}
-
+
// Fill in the new image info fields
$info = $this->imageInfo( $row->img_name );
'img_major_mime' => $info['major'],
'img_minor_mime' => $info['minor'] );
}
-
-
+
+
function buildOldImage() {
$this->buildTable( 'oldimage', 'oi_archive_name',
array( &$this, 'oldimageCallback' ) );
}
-
+
function oldimageCallback( $row ) {
if( $row->oi_width ) {
return null;
}
-
+
// Fill in the new image info fields
$info = $this->imageInfo( $row->oi_archive_name, 'wfImageArchiveDir', $row->oi_name );
return array(
'oi_height' => $info['height'],
'oi_bits' => $info['bits' ] );
}
-
+
function crawlMissing() {
global $wgUploadDirectory, $wgHashedUploadDirectory;
if( $wgHashedUploadDirectory ) {
$this->crawlDirectory( $wgUploadDirectory );
}
}
-
+
function crawlDirectory( $dir ) {
if( !file_exists( $dir ) ) {
return $this->log( "no directory, skipping $dir" );
if( $source === false ) {
return $this->log( "couldn't open dir, skipping $dir" );
}
-
+
$this->log( "crawling $dir" );
while( false !== ( $filename = readdir( $source ) ) ) {
$fullpath = $dir . DIRECTORY_SEPARATOR . $filename;
}
closedir( $source );
}
-
+
function checkMissingImage( $filename, $fullpath ) {
$fname = 'ImageBuilder::checkMissingImage';
$row = $this->dbw->selectRow( 'image',
array( 'img_name' ),
array( 'img_name' => $filename ),
$fname );
-
+
if( $row ) {
// already known, move on
return;
$this->addMissingImage( $filename, $fullpath );
}
}
-
+
function addMissingImage( $filename, $fullpath ) {
$fname = 'ImageBuilder::addMissingImage';
-
+
$size = filesize( $fullpath );
$info = $this->imageInfo( $filename );
$timestamp = $this->dbw->timestamp( filemtime( $fullpath ) );
-
+
global $wgContLang;
$altname = $wgContLang->checkTitleEncoding( $filename );
if( $altname != $filename ) {
$filename = $this->renameFile( $filename );
}
}
-
+
if( $filename == '' ) {
$this->log( "Empty filename for $fullpath" );
return;
}
-
+
$fields = array(
'img_name' => $filename,
'img_size' => $size,
# List of all database names
$dblist = array_map( "trim", file( "/home/wikipedia/common/all.dblist" ) );
-
+
# Special-case hostnames
$specials = array(
'sourceswiki' => 'sources.wikipedia.org',
} else {
$local = 0;
}
-
+
if ( empty( $reserved[$prefix] ) ) {
$iwArray[$prefix] = array( "iw_prefix" => $prefix, "iw_url" => $url, "iw_local" => $local );
}
}
}
-
+
$sql = "-- Generated by rebuildInterwiki.php";
if ( isset( $specials[$db] ) ) {
# Special wiki
# Has interwiki links and interlanguage links to wikipedia
-
+
$host = $specials[$db];
$sql .= "\n--$host\n\n";
$sql .= "USE $db;\n" .
"TRUNCATE TABLE interwiki;\n" .
"INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES \n";
$first = true;
-
+
# Intermap links
foreach ( $iwArray as $iwEntry ) {
$sql .= makeLink( $iwEntry, $first, $db );
foreach ( $sites as $targetSite ) {
$sql .= makeLink( array( $targetSite->lateral, $targetSite->getURL( 'en' ), 1 ), $first, $db );
}
-
+
# Interlanguage links to wikipedia
$sql .= makeLanguageLinks( $sites['wiki'], $first, $db );
foreach ( $extraLinks as $link ) {
$sql .= makeLink( $link, $first, $db );
}
-
+
$sql .= ";\n";
} else {
# Find out which site this DB belongs to
$lang = $matches[1];
$host = "$lang." . $site->url;
$sql .= "\n--$host\n\n";
-
+
$sql .= "USE $db;\n" .
"TRUNCATE TABLE interwiki;\n" .
"INSERT INTO interwiki (iw_prefix,iw_url,iw_local) VALUES\n";
if ( $site->suffix == "wiki" ) {
$sql .= makeLink( array("w", "http://en.wikipedia.org/wiki/$1", 1), $first, $db );
}
-
+
# Extra links
foreach ( $extraLinks as $link ){
$sql .= makeLink( $link, $first, $db );
$sql = getRebuildInterwikiSQL();
# Output
-if ( isset( $options['o'] ) ) {
+if ( isset( $options['o'] ) ) {
# To file specified with -o
$file = fopen( $options['o'], "w" );
fwrite( $file, $sql );
$dbw->delete( 'recentchanges', '*' );
print( "Loading from page and revision tables...\n" );
-
+
global $wgRCMaxAge;
$cutoff = time() - $wgRCMaxAge;
$dbw->insertSelect( 'recentchanges', array( 'page', 'revision' ),
$dbr =& wfGetDB( DB_SLAVE );
$dbw =& wfGetDB( DB_MASTER );
$start = intval( $start );
-
+
# Don't generate TeX PNGs (lack of a sensible current directory causes errors anyway)
$wgUser->setOption('math', MW_MATH_SOURCE);
# Don't generate extension images (e.g. Timeline)
$wgParser->mTagHooks = array();
-
+
# Don't generate thumbnail images
$wgUseImageResize = false;
);
$num = $dbr->numRows( $res );
print "$num new articles...\n";
-
+
$i = 0;
while ( $row = $dbr->fetchObject( $res ) ) {
if ( !( ++$i % REPORTING_INTERVAL ) ) {
print("Starting from page_id $start of $end.\n");
for ($id = $start; $id <= $end; $id++) {
-
+
if ( !($id % REPORTING_INTERVAL) ) {
print "$id\n";
wfWaitForSlaves( $maxLag );
}
fixLinksFromArticle( $id );
}
-
+
}
}
function fixLinksFromArticle( $id ) {
global $wgTitle, $wgArticle, $wgOut, $wgParser;
-
+
$wgTitle = Title::newFromID( $id );
$dbw =& wfGetDB( DB_MASTER );
-
+
if ( is_null( $wgTitle ) ) {
return;
}
function deleteLinksFromNonexistent( $maxLag = 0 ) {
$fname = 'deleteLinksFromNonexistent';
-
+
wfWaitForSlaves( $maxLag );
$dbw =& wfGetDB( DB_WRITE );
-
+
$linksTables = array(
'pagelinks' => 'pl_from',
'imagelinks' => 'il_from',
$pTable = $dbw->tableName( $table );
$sql = "DELETE $pTable FROM $pTable LEFT JOIN $page ON page_id=$field WHERE page_id IS NULL";
-
+
print "Deleting $table from non-existent articles...";
$dbw->query( $sql, $fname );
print " fixed " .$dbw->affectedRows() . " row(s)\n";
$sql = 'SELECT COUNT(rev_id) AS count FROM ' . $dbw->tableName( 'revision' ) . ' WHERE rev_user = ' . $user_id;
$res = $dbw->query( $sql );
$row = $dbw->fetchObject( $res );
- return( $row->count );
+ return( $row->count );
}
# Return an array containing all valid user IDs
{
$fname = 'compressWithConcat';
$loadStyle = LS_CHUNKED;
-
+
$dbr =& wfGetDB( DB_SLAVE );
$dbw =& wfGetDB( DB_MASTER );
$conds = array(
"old_flags NOT LIKE '%object%' " .
" AND (old_flags NOT LIKE '%external%' OR old_text NOT LIKE 'DB://%/%/%')");
-
+
if ( $beginDate ) {
$conds[] = "rev_timestamp>'" . $beginDate . "'";
}
$fields = array( 'rev_id', 'rev_text_id' );
$revLoadOptions = array();
}
-
+
# Don't work with current revisions
$tables[] = 'page';
$conds[] = 'page_id=rev_page AND rev_id != page_latest';
while ( $revRow = $dbw->fetchObject( $revRes ) ) {
$revs[] = $revRow;
}
-
+
if ( count( $revs ) < 2) {
# No revisions matching, no further processing
print "\n";
$dbw->begin();
$usedChunk = false;
$primaryOldid = $revs[$i]->rev_text_id;
-
+
# Get the text of each revision and add it to the object
for ( $j = 0; $j < $thisChunkSize && $chunk->isHappy( $maxChunkFactor, $factorThreshold ); $j++ ) {
$oldid = $revs[$i + $j]->rev_text_id;
-
+
# Get text
if ( $loadStyle == LS_INDIVIDUAL ) {
$textRow = $dbw->selectRow( 'text',
}
}
$thisChunkSize = $j;
-
+
# If we couldn't actually use any stubs because the pages were too small, do nothing
if ( $usedChunk ) {
if ( $extdb != "" ) {
$dbr =& wfGetDB( DB_SLAVE );
$dbw =& wfGetDB( DB_MASTER );
-
+
if ( get_class( $stub ) !== 'historyblobstub' ) {
print "Error, invalid stub object\n";
return;
function redundant(&$arr) {
global $wgAllMessagesEn;
-
+
$redundant = 0;
foreach(array_keys($arr) as $key) {
if ( @$wgAllMessagesEn[$key] === null )
$dbw =& wfGetDB( DB_MASTER );
$recentchanges = $dbw->tableName( 'recentchanges' );
-
+
output( "Updating searchindex between $start and $end\n" );
# Select entries from recentchanges which are on top and between the specified times
}
}
}
-
+
# Unlock searchindex
if ( $maxLockTime ) {
unlockSearchindex();
function do_image_index_update() {
global $wgDatabase;
-
+
$meta = $wgDatabase->fieldInfo( "image", "img_major_mime" );
if( $meta->multiple_key == 0 ) {
echo "Updating indexes to 20050912: ";
# and update old broken items.
global $wgDatabase;
$info = $wgDatabase->fieldInfo( 'watchlist', 'wl_notificationtimestamp' );
-
+
if( $info->not_null ) {
echo "Making wl_notificationtimestamp nullable... ";
dbsource( 'maintenance/archives/patch-watchlist-null.sql', $wgDatabase );
$page = $wgDatabase->tableName( 'page' );
$wgDatabase->query( "UPDATE $page SET page_random = RAND() WHERE page_random = 0", 'do_page_random_update' );
$rows = $wgDatabase->affectedRows();
-
+
echo "changed $rows rows\n";
}
function do_templatelinks_update() {
global $wgDatabase, $wgLoadBalancer;
$fname = 'do_templatelinks_update';
-
+
if ( $wgDatabase->tableExists( 'templatelinks' ) ) {
echo "...templatelinks table already exists\n";
return;
'tl_title' => $row->pl_title,
), $fname
);
-
+
}
$wgDatabase->freeResult( $res );
} else {
do_pagelinks_update(); flush();
do_templatelinks_update(); flush(); // after pagelinks
-
+
do_drop_img_type(); flush();
do_user_unique_update(); flush();
do_user_groups_update(); flush();
-
+
do_watchlist_null(); flush();
//do_image_index_update(); flush();
var $reassigned;
var $trimmed;
var $failed;
-
+
function UserDupes( &$database ) {
$this->db =& $database;
}
-
+
/**
* Check if this database's user table has already had a unique
* user_name index applied.
echo "WARNING: doesn't seem to have user_name index at all!\n";
return false;
}
-
+
# Confusingly, 'Non_unique' is 0 for *unique* indexes,
# and 1 for *non-unique* indexes. Pass the crack, MySQL,
# it's obviously some good stuff!
return ( $info->Non_unique == 0 );
}
-
+
/**
* Checks the database for duplicate user account records
* and remove them in preparation for application of a unique
function clearDupes() {
return $this->checkDupes( true );
}
-
+
/**
* Checks the database for duplicate user account records
* in preparation for application of a unique index on the
*/
function checkDupes( $doDelete = false ) {
global $wgDBname;
-
+
if( $this->hasUniqueIndex() ) {
echo "$wgDBname already has a unique index on its user table.\n";
return true;
}
-
+
$this->lock();
-
+
echo "Checking for duplicate accounts...\n";
$dupes = $this->getDupes();
$count = count( $dupes );
-
+
echo "Found $count accounts with duplicate records on $wgDBname.\n";
$this->trimmed = 0;
$this->reassigned = 0;
foreach( $dupes as $name ) {
$this->examine( $name, $doDelete );
}
-
+
$this->unlock();
-
+
echo "\n";
-
+
if( $this->reassigned > 0 ) {
if( $doDelete ) {
echo "$this->reassigned duplicate accounts had edits reassigned to a canonical record id.\n";
echo "$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 $wgDBname.\n";
echo "$this->trimmed duplicate user accounts were found on $wgDBname which can be removed safely.\n";
}
}
-
+
if( $this->failed > 0 ) {
echo "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";
return true;
return false;
}
}
-
+
/**
* We don't want anybody to mess with our stuff...
* @access private
}
$names = array_map( array( $this, 'lockTable' ), $set );
$tables = implode( ',', $names );
-
+
$result = $this->db->query( "LOCK TABLES $tables", $fname );
}
-
+
function lockTable( $table ) {
return $this->db->tableName( $table ) . ' WRITE';
}
-
+
/**
* @return bool
* @access private
function newSchema() {
return class_exists( 'Revision' );
}
-
+
/**
* @access private
*/
$fname = 'UserDupes::unlock';
$result = $this->db->query( "UNLOCK TABLES", $fname );
}
-
+
/**
* Grab usernames for which multiple records are present in the database.
* @return array
FROM $user
GROUP BY user_name
HAVING n > 1", $fname );
-
+
$list = array();
while( $row = $this->db->fetchObject( $result ) ) {
$list[] = $row->user_name;
}
$this->db->freeResult( $result );
-
+
return $list;
}
-
+
/**
* Examine user records for the given name. Try to see which record
* will be the one that actually gets used, then check remaining records
array( 'user_id' ),
array( 'user_name' => $name ),
$fname );
-
+
$firstRow = $this->db->fetchObject( $result );
$firstId = $firstRow->user_id;
echo "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: ";
}
$this->db->freeResult( $result );
}
-
+
/**
* Count the number of edits attributed to this user.
* Does not currently check log table or other things
$this->editCountOn( 'old', 'old_user', $userid );
}
}
-
+
/**
* Count the number of hits on a given table for this account.
* @param string $table
array( $field => $userid ),
$fname ) );
}
-
+
/**
* @param int $from
* @param int $to
$this->reassignEditsOn( $table, $field, $from, $to );
}
}
-
+
/**
* @param string $table
* @param string $field
$fname );
echo "ok. ";
}
-
+
/**
* Remove a user account line.
* @param int $userid
$this->db->delete( 'user', array( 'user_id' => $userid ), $fname );
echo " ok";
}
-
+
}
$s = "";
$qb = $this->qbSetting();
$mainPageObj = Title::newMainPage();
-
+
$s .= "\n<div id='content'>\n<div id='topbar'>" .
"<table width='100%' border='0' cellspacing='0' cellpadding='8'><tr>";
if ( 0 != $qb ) { $s .= $this->quickBar(); }
return $s;
}
-
+
function doGetUserStyles() {
global $wgOut, $wgStyleSheetPath;
$s = parent::doGetUserStyles();
}
return $s;
}
-
+
function sysLinks() {
global $wgUser, $wgContLang, $wgTitle;
$li = $wgContLang->specialPage("Userlogin");
} else {
$q = "returnto={$rt}";
}
-
+
$s = "" .
$this->makeKnownLink( wfMsgForContent( "mainpage" ), wfMsg( "mainpage" ) )
. " | " .
htmlspecialchars( $link['text'] ) . '</a>' . $sep;
}
}
-
+
if ( $wgOut->isArticle() ) {
$s .= $this->menuHead( "qbedit" );
$s .= "<strong>" . $this->editThisPage() . "</strong>";
. $this->historyLink()
. $sep . $this->whatLinksHere()
. $sep . $this->watchPageLinksLink();
-
+
if( $tns == NS_USER || $tns == NS_USER_TALK ) {
$id=User::idFromName($wgTitle->getText());
if ($id != 0) {
. $sep . $tl
. $sep . $this->specialLink( "watchlist" )
. $sep . $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, "Contributions" ),
- wfMsg( "mycontris" ), "target=" . wfUrlencode($wgUser->getName() ) )
+ wfMsg( "mycontris" ), "target=" . wfUrlencode($wgUser->getName() ) )
. $sep . $this->specialLink( "preferences" )
. $sep . $this->specialLink( "userlogout" );
} else {
$s .= $sep."<a href=\"".htmlspecialchars($wgSiteSupportPage)."\" class =\"internal\">"
.wfMsg( "sitesupport" )."</a>";
}
-
+
$s .= $sep . $this->makeKnownLinkObj(
Title::makeTitle( NS_SPECIAL, 'Specialpages' ),
wfMsg( 'moredotdotdot' ) );
$ol = $this->otherLanguages();
if($ol) $s .= "<br />" . $ol;
-
+
$cat = $this->getCategoryLinks();
if($cat) $s .= "<br />" . $cat;
if ( 3 == $this->qbSetting() ) { # Floating left
$s .= "<style type='text/css'>\n" .
"@import '{$wgStylePath}/common/quickbar.css';\n</style>\n";
- } else if ( 4 == $this->qbSetting() ) { # Floating right
+ } else if ( 4 == $this->qbSetting() ) { # Floating right
$s .= "<style type='text/css'>\n" .
"@import '{$wgStylePath}/common/quickbar-right.css';\n</style>\n";
}
} else if ( 4 == $qb) {
$s .= "#quickbar { border-right: 1px solid gray; }\n" .
"#article { margin-right: 152px; margin-left: 4px; }\n";
- }
+ }
return $s;
}
$s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
$sep = "\n<br />";
-
+
# Use the first heading from the Monobook sidebar as the "browse" section
$bar = $this->buildSidebar();
$browseLinks = reset( $bar );
$this->mTitle->getSubjectPage(),
$nskey,
!$this->mTitle->isTalkPage() );
-
+
$content_actions['talk'] = $this->tabAction(
$this->mTitle->getTalkPage(),
'talk',
if ( !isset( $nt ) ) {
return "<!-- ERROR -->{$prefix}{$text}{$trail}";
}
-
+
if ( $nt->getNamespace() == NS_CATEGORY ) {
return $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
}
-
+
if ( $text == '' ) {
$text = $nt->getPrefixedText();
}
class ArticleTest extends PHPUnit_TestCase {
var $saveGlobals = array();
-
+
function ArticleTest( $name ) {
$this->PHPUnit_TestCase( $name );
}
-
+
function setUp() {
$globalSet = array(
'wgLegacyEncoding' => false,
$GLOBALS[$var] = $data;
}
}
-
+
function tearDown() {
foreach( $this->saveGlobals as $var => $data ) {
$GLOBALS[$var] = $data;
}
}
-
+
function testGetRevisionText() {
$row = new stdClass;
$row->old_flags = '';
'This is a bunch of revision text.',
Revision::getRevisionText( $row ) );
}
-
+
function testGetRevisionTextGzip() {
$row = new stdClass;
$row->old_flags = 'gzip';
'This is a bunch of revision text.',
Revision::getRevisionText( $row ) );
}
-
+
function testGetRevisionTextUtf8Native() {
$row = new stdClass;
$row->old_flags = 'utf-8';
"Wiki est l'\xc3\xa9cole superieur !",
Revision::getRevisionText( $row ) );
}
-
+
function testGetRevisionTextUtf8Legacy() {
$row = new stdClass;
$row->old_flags = '';
"Wiki est l'\xc3\xa9cole superieur !",
Revision::getRevisionText( $row ) );
}
-
+
function testGetRevisionTextUtf8NativeGzip() {
$row = new stdClass;
$row->old_flags = 'gzip,utf-8';
"Wiki est l'\xc3\xa9cole superieur !",
Revision::getRevisionText( $row ) );
}
-
+
function testGetRevisionTextUtf8LegacyGzip() {
$row = new stdClass;
$row->old_flags = 'gzip';
"Wiki est l'\xc3\xa9cole superieur !",
Revision::getRevisionText( $row ) );
}
-
+
function testCompressRevisionTextUtf8() {
$row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
$row->old_flags = Revision::compressRevisionText( $row->old_text );
$this->assertEquals( "Wiki est l'\xe9cole superieur !",
Revision::getRevisionText( $row ), "getRevisionText" );
}
-
+
function testCompressRevisionTextUtf8Gzip() {
$GLOBALS['wgCompressRevisions'] = true;
$row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
class DatabaseTest extends PHPUnit_TestCase {
var $db;
-
+
function DatabaseTest( $name ) {
$this->PHPUnit_TestCase( $name );
}
-
+
function setUp() {
$this->db =& new Database();
}
-
+
function tearDown() {
unset( $this->db );
}
-
+
function testAddQuotesNull() {
$this->assertEquals(
'NULL',
$this->db->addQuotes( NULL ) );
}
-
+
function testAddQuotesInt() {
# returning just "1234" should be ok too, though...
# maybe
"'1234'",
$this->db->addQuotes( 1234 ) );
}
-
+
function testAddQuotesFloat() {
# returning just "1234.5678" would be ok too, though
$this->assertEquals(
"'string'",
$this->db->addQuotes( 'string' ) );
}
-
+
function testAddQuotesStringQuote() {
$this->assertEquals(
"'string\'s cause trouble'",
"SELECT * FROM interwiki",
$sql);
}
-
+
function testFillPreparedQuestion() {
$sql = $this->db->fillPrepared(
'SELECT * FROM cur WHERE cur_namespace=? AND cur_title=?',
"SELECT * FROM cur WHERE cur_namespace='4' AND cur_title='Snicker\'s_paradox'",
$sql);
}
-
+
function testFillPreparedBang() {
$sql = $this->db->fillPrepared(
'SELECT user_id FROM ! WHERE user_name=?',
function GlobalTest( $name ) {
$this->PHPUnit_TestCase( $name );
}
-
+
function setUp() {
$this->save = array();
$saveVars = array( 'wgReadOnlyFile' );
}
$GLOBALS['wgReadOnlyFile'] = wfTempDir() . '/testReadOnly-' . mt_rand();
}
-
+
function tearDown() {
foreach( $this->save as $var => $data ) {
$GLOBALS[$var] = $data;
}
}
-
+
function testRandom() {
# This could hypothetically fail, but it shouldn't ;)
$this->assertFalse(
wfRandom() == wfRandom() );
}
-
+
function testUrlencode() {
$this->assertEquals(
"%E7%89%B9%E5%88%A5:Contributions/Foobar",
wfUrlencode( "\xE7\x89\xB9\xE5\x88\xA5:Contributions/Foobar" ) );
}
-
+
function testReadOnlyEmpty() {
$this->assertFalse( wfReadOnly() );
}
-
+
function testReadOnlySet() {
$f = fopen( $GLOBALS['wgReadOnlyFile'], "wt" );
fwrite( $f, 'Message' );
fclose( $f );
$this->assertTrue( wfReadOnly() );
-
+
unlink( $GLOBALS['wgReadOnlyFile'] );
$this->assertFalse( wfReadOnly() );
}
-
+
function testQuotedPrintable() {
$this->assertEquals(
"=?UTF-8?Q?=C4=88u=20legebla=3F?=",
wfQuotedPrintable( "\xc4\x88u legebla?", "UTF-8" ) );
}
-
+
function testTime() {
$start = wfTime();
$this->assertType( 'double', $start );
$end = wfTime();
$this->assertTrue( $end > $start, "Time is running backwards!" );
}
-
+
function testArrayToCGI() {
$this->assertEquals(
"baz=AT%26T&foo=bar",
array( 'baz' => 'AT&T', 'ignore' => '' ),
array( 'foo' => 'bar', 'baz' => 'overridden value' ) ) );
}
-
+
function testMimeTypeMatch() {
$this->assertEquals(
'text/html',
array( 'image/png' => 1.0,
'image/svg+xml' => 0.5 ) ) );
}
-
+
function testNegotiateType() {
$this->assertEquals(
'text/html',
array( 'text/*' => 1.0 ),
array( 'application/xhtml+xml' => 1.0 ) ) );
}
-
+
function testTimestamp() {
$t = gmmktime( 12, 34, 56, 1, 15, 2001 );
$this->assertEquals(
'2001-01-15 12:34:56',
wfTimestamp( TS_DB, $t ),
'TS_UNIX to TS_DB' );
-
+
$this->assertEquals(
'20010115123456',
wfTimestamp( TS_MW, '20010115123456' ),
'2001-01-15 12:34:56',
wfTimestamp( TS_DB, '20010115123456' ),
'TS_MW to TS_DB' );
-
+
$this->assertEquals(
'20010115123456',
wfTimestamp( TS_MW, '2001-01-15 12:34:56' ),
wfTimestamp( TS_DB, '2001-01-15 12:34:56' ),
'TS_DB to TS_DB' );
}
-
+
/* TODO: many more! */
}
function SanitizerTest( $name ) {
$this->PHPUnit_TestCase( $name );
}
-
+
function setUp() {
}
-
+
function tearDown() {
}
"\xc4\x88io bonas dans l'\xc3\xa9cole!",
Sanitizer::decodeCharReferences( "Ĉio bonas dans l'école!" ) );
}
-
+
function testDecodeMixed() {
$this->assertEquals(
"\xc4\x88io bonas dans l'\xc3\xa9cole!",
Sanitizer::decodeCharReferences( "Ĉio bonas dans l'école!" ) );
}
-
+
function testDecodeMixedComplex() {
$this->assertEquals(
"\xc4\x88io bonas dans l'\xc3\xa9cole! (mais pas Ĉio dans l'école)",
"a & b",
Sanitizer::decodeCharReferences( "a & b" ) );
}
-
+
function testDecodeInvalidNamed() {
$this->assertEquals(
"&foo;",
Sanitizer::decodeCharReferences( "&foo;" ) );
}
-
+
function testDecodeInvalidNumbered() {
$this->assertEquals(
UTF8_REPLACEMENT,
Sanitizer::decodeCharReferences( "�" ) );
}
-
+
/* TODO: many more! */
}
/** @todo document */
class SearchEngine_TestCase extends PHPUnit_TestCase {
var $db, $search;
-
+
function insertSearchData() {
$this->db->safeQuery( <<<END
INSERT INTO ! (page_id,page_namespace,page_title,page_latest)
END
, $this->db->tableName( 'searchindex' ) );
}
-
+
function fetchIds( &$results ) {
$matches = array();
while( $row = $results->fetchObject() ) {
sort( $matches );
return $matches;
}
-
+
function testTextSearch() {
$this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
if( !is_null( $this->db ) ) {
"Plain search failed" );
}
}
-
+
function testTextPowerSearch() {
$this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
if( !is_null( $this->db ) ) {
"Power search failed" );
}
}
-
+
function testTitleSearch() {
$this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
if( !is_null( $this->db ) ) {
"Title search failed" );
}
}
-
+
function testTextTitlePowerSearch() {
$this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
if( !is_null( $this->db ) ) {
"Title power search failed" );
}
}
-
+
}
class SearchMySQL4Test extends SearchEngine_TestCase {
var $db;
-
+
function SearchMySQL4Test( $name ) {
$this->PHPUnit_TestCase( $name );
}
-
+
function setUp() {
$GLOBALS['wgContLang'] = new LanguageUtf8;
$this->db =& buildTestDatabase(
}
$this->search =& new SearchMySQL4( $this->db );
}
-
+
function tearDown() {
if( !is_null( $this->db ) ) {
$this->db->close();