aboutsummaryrefslogtreecommitdiffstats
path: root/includes
diff options
context:
space:
mode:
Diffstat (limited to 'includes')
-rw-r--r--includes/Article.php65
-rw-r--r--includes/ChangesList.php17
-rw-r--r--includes/Credits.php5
-rw-r--r--includes/Database.php55
-rw-r--r--includes/DefaultSettings.php72
-rw-r--r--includes/Defines.php11
-rw-r--r--includes/DifferenceEngine.php8
-rw-r--r--includes/EditPage.php15
-rw-r--r--includes/ExternalStoreDB.php59
-rw-r--r--includes/Feed.php2
-rw-r--r--includes/GlobalFunctions.php98
-rw-r--r--includes/HistoryBlob.php16
-rw-r--r--includes/Hooks.php12
-rw-r--r--includes/Image.php66
-rw-r--r--includes/ImagePage.php73
-rw-r--r--includes/Linker.php11
-rw-r--r--includes/LoadBalancer.php18
-rw-r--r--includes/MimeMagic.php42
-rw-r--r--includes/OutputPage.php11
-rw-r--r--includes/Parser.php99
-rwxr-xr-xincludes/Profiling.php10
-rw-r--r--includes/QueryPage.php1
-rw-r--r--includes/Sanitizer.php40
-rw-r--r--includes/SearchMySQL.php4
-rw-r--r--includes/SearchMySQL4.php2
-rw-r--r--includes/Setup.php10
-rw-r--r--includes/Skin.php28
-rw-r--r--includes/SkinTemplate.php30
-rw-r--r--includes/SpecialAllmessages.php46
-rw-r--r--includes/SpecialAllpages.php19
-rw-r--r--includes/SpecialBlockip.php2
-rw-r--r--includes/SpecialBrokenRedirects.php2
-rw-r--r--includes/SpecialContributions.php25
-rw-r--r--includes/SpecialImport.php34
-rw-r--r--includes/SpecialIpblocklist.php29
-rw-r--r--includes/SpecialMostlinked.php69
-rw-r--r--includes/SpecialMovepage.php12
-rw-r--r--includes/SpecialNewpages.php10
-rw-r--r--includes/SpecialPage.php18
-rw-r--r--includes/SpecialPreferences.php67
-rw-r--r--includes/SpecialRandompage.php2
-rw-r--r--includes/SpecialRecentchanges.php73
-rw-r--r--includes/SpecialRecentchangeslinked.php2
-rw-r--r--includes/SpecialSearch.php7
-rw-r--r--includes/SpecialUndelete.php18
-rw-r--r--includes/SpecialUpload.php48
-rw-r--r--includes/SpecialUserlogin.php2
-rw-r--r--includes/SpecialVersion.php164
-rw-r--r--includes/SpecialWatchlist.php163
-rw-r--r--includes/SpecialWhatlinkshere.php2
-rw-r--r--includes/StreamFile.php3
-rw-r--r--includes/Title.php107
-rw-r--r--includes/User.php14
-rw-r--r--includes/UserTalkUpdate.php4
-rw-r--r--includes/WatchedItem.php23
-rw-r--r--includes/WikiError.php25
56 files changed, 1268 insertions, 602 deletions
diff --git a/includes/Article.php b/includes/Article.php
index e0bd2016f242..23ae0bd21ff8 100644
--- a/includes/Article.php
+++ b/includes/Article.php
@@ -173,6 +173,7 @@ class Article {
$striparray=array();
$parser=new Parser();
$parser->mOutputType=OT_WIKI;
+ $parser->mOptions = new ParserOptions();
$striptext=$parser->strip($text, $striparray, true);
# now that we can be sure that no pseudo-sections are in the source,
@@ -428,15 +429,17 @@ class Article {
return false;
}
}
- $redirData = $this->pageDataFromTitle( $dbr, $rt );
- if( $redirData ) {
- $redirRev = Revision::newFromId( $redirData->page_latest );
- if( !is_null( $redirRev ) ) {
- $this->mRedirectedFrom = $this->mTitle->getPrefixedText();
- $this->mTitle = $rt;
- $data = $redirData;
- $this->loadPageData( $data );
- $revision = $redirRev;
+ if( $rt->getInterwiki() == '' ) {
+ $redirData = $this->pageDataFromTitle( $dbr, $rt );
+ if( $redirData ) {
+ $redirRev = Revision::newFromId( $redirData->page_latest );
+ if( !is_null( $redirRev ) ) {
+ $this->mRedirectedFrom = $this->mTitle->getPrefixedText();
+ $this->mTitle = $rt;
+ $data = $redirData;
+ $this->loadPageData( $data );
+ $revision = $redirRev;
+ }
}
}
}
@@ -755,14 +758,14 @@ class Article {
$wgOut->setRobotpolicy( 'noindex,follow' );
}
if ( '' != $this->mRedirectedFrom ) {
- $sk = $wgUser->getSkin();
- $redir = $sk->makeKnownLink( $this->mRedirectedFrom, '',
- 'redirect=no' );
- $s = wfMsg( 'redirectedfrom', $redir );
- $wgOut->setSubtitle( $s );
-
- # Can't cache redirects
- $pcache = false;
+ if ( wfRunHooks( 'ArticleViewRedirect', array( &$this ) ) ) {
+ $sk = $wgUser->getSkin();
+ $redir = $sk->makeKnownLink( $this->mRedirectedFrom, '', 'redirect=no' );
+ $s = wfMsg( 'redirectedfrom', $redir );
+ $wgOut->setSubtitle( $s );
+ # Can't cache redirects
+ $pcache = false;
+ }
} elseif ( !empty( $rdfrom ) ) {
global $wgRedirectSources;
if( $wgRedirectSources && preg_match( $wgRedirectSources, $rdfrom ) ) {
@@ -864,7 +867,7 @@ class Article {
$tbtext = "";
while ($o = $dbr->fetchObject($tbs)) {
- $rmvtext = "";
+ $rmvtxt = "";
if ($wgUser->isSysop()) {
$delurl = $this->mTitle->getFullURL("action=deletetrackback&tbid="
. $o->tb_id . "&token=" . $wgUser->editToken());
@@ -939,6 +942,7 @@ class Article {
'page_random' => wfRandom(),
'page_touched' => $dbw->timestamp(),
'page_latest' => 0, # Fill this in shortly...
+ 'page_len' => 0, # Fill this in shortly...
), $fname );
$newid = $dbw->insertId();
@@ -970,13 +974,14 @@ class Article {
# An extra check against threads stepping on each other
$conditions['page_latest'] = $lastRevision;
}
+
$text = $revision->getText();
$dbw->update( 'page',
array( /* SET */
'page_latest' => $revision->getId(),
'page_touched' => $dbw->timestamp(),
'page_is_new' => ($lastRevision === 0) ? 1 : 0,
- 'page_is_redirect' => Article::isRedirect( $text ),
+ 'page_is_redirect' => Article::isRedirect( $text ) ? 1 : 0,
'page_len' => strlen( $text ),
),
$conditions,
@@ -1118,6 +1123,7 @@ class Article {
$striparray=array();
$parser=new Parser();
$parser->mOutputType=OT_WIKI;
+ $parser->mOptions = new ParserOptions();
$oldtext=$parser->strip($oldtext, $striparray, true);
# now that we can be sure that no pseudo-sections are in the source,
@@ -1582,7 +1588,7 @@ class Article {
wfDebug( "Article::confirmProtect\n" );
- $sub = $this->mTitle->getPrefixedText();
+ $sub = htmlspecialchars( $this->mTitle->getPrefixedText() );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$check = '';
@@ -1599,7 +1605,7 @@ class Article {
$wgOut->setPageTitle( wfMsg( 'confirmprotect' ) );
$wgOut->setSubtitle( wfMsg( 'protectsub', $sub ) );
$wgOut->addWikiText( wfMsg( 'confirmprotecttext' ) );
- $moveonly = htmlspecialchars( wfMsg( 'protectmoveonly' ) );
+ $moveonly = wfMsg( 'protectmoveonly' ) ; // add it using addWikiText to prevent xss. bug:3991
$protcom = htmlspecialchars( wfMsg( 'protectcomment' ) );
$formaction = $this->mTitle->escapeLocalURL( 'action=protect' . $par );
}
@@ -1625,7 +1631,10 @@ class Article {
<input type='checkbox' name='wpMoveOnly' value='1' id='wpMoveOnly' />
</td>
<td align='left'>
- <label for='wpMoveOnly'>{$moveonly}</label>
+ <label for='wpMoveOnly'> ");
+ $wgOut->addWikiText( $moveonly ); // bug 3991
+ $wgOut->addHTML( "
+ </label>
</td>
</tr> " );
}
@@ -1706,7 +1715,7 @@ class Article {
}
# Fetch cur_text
- $rev =& Revision::newFromTitle( $this->mTitle );
+ $rev = Revision::newFromTitle( $this->mTitle );
# Fetch name(s) of contributors
$rev_name = '';
@@ -2354,8 +2363,14 @@ class Article {
}
}
- function onArticleDelete($title_obj) {
- $title_obj->touchLinks();
+ function onArticleDelete( $title ) {
+ global $wgMessageCache;
+
+ $title->touchLinks();
+
+ if( $title->getNamespace() == NS_MEDIAWIKI) {
+ $wgMessageCache->replace( $title->getDBkey(), false );
+ }
}
function onArticleEdit($title_obj) {
diff --git a/includes/ChangesList.php b/includes/ChangesList.php
index b224c0a68105..3578d2720137 100644
--- a/includes/ChangesList.php
+++ b/includes/ChangesList.php
@@ -205,8 +205,8 @@ class ChangesList {
$r .= '&nbsp;</tt>' ;
$o = '' ;
- if ( $rc_last_oldid != 0 ) {
- $o = 'oldid='.$rc_last_oldid ;
+ if ( $rc_this_oldid != 0 ) {
+ $o = 'oldid='.$rc_this_oldid ;
}
if ( $rc_type == RC_LOG ) {
$link = $rcObj->timestamp ;
@@ -365,7 +365,7 @@ class ChangesList {
$rc_user_text, 'target=' . $rc_user_text );
} else {
$userPage =& Title::makeTitle( NS_USER, $rc_user_text );
- $userLink = $this->skin->makeLinkObj( $userPage, $rc_user_text );
+ $userLink = $this->skin->makeLinkObj( $userPage, htmlspecialchars( $rc_user_text ) );
}
$s .= $userLink;
@@ -376,14 +376,14 @@ class ChangesList {
$userTalkLink = '';
} else {
$userTalkPage =& Title::makeTitle( NS_USER_TALK, $rc_user_text );
- $userTalkLink= $this->skin->makeLinkObj( $userTalkPage, $talkname );
+ $userTalkLink= $this->skin->makeLinkObj( $userTalkPage, htmlspecialchars( $talkname ) );
}
# Block link
$blockLink='';
if ( ( $wgSysopUserBans || 0 == $rc_user ) && $wgUser->isAllowed('block') ) {
$blockLinkPage = Title::makeTitle( NS_SPECIAL, 'Blockip' );
$blockLink = $this->skin->makeKnownLinkObj( $blockLinkPage,
- $message['blocklink'], 'ip='.$rc_user_text );
+ htmlspecialchars( $message['blocklink'] ), 'ip=' . urlencode( $rc_user_text ) );
}
if($blockLink) {
@@ -475,16 +475,17 @@ class ChangesList {
} else {
$rcIdQuery = '';
}
- $query = $curIdEq."&diff=$rc_this_oldid&oldid=$rc_last_oldid";
+ $querycur = $curIdEq."&diff=0&oldid=$rc_this_oldid";
+ $querydiff = $curIdEq."&diff=$rc_this_oldid&oldid=$rc_last_oldid";
$aprops = ' tabindex="'.$baseRC->counter.'"';
- $curLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $message['cur'], $query, '' ,'' , $aprops );
+ $curLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $message['cur'], $querycur, '' ,'' , $aprops );
if( $rc_type == RC_NEW || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
if( $rc_type != RC_NEW ) {
$curLink = $message['cur'];
}
$diffLink = $message['diff'];
} else {
- $diffLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $message['diff'], $query . $rcIdQuery, '' ,'' , $aprops );
+ $diffLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $message['diff'], $querydiff . $rcIdQuery, '' ,'' , $aprops );
}
# Make "last" link
diff --git a/includes/Credits.php b/includes/Credits.php
index 8699c79f768f..7131789b0cd4 100644
--- a/includes/Credits.php
+++ b/includes/Credits.php
@@ -68,15 +68,14 @@ function getCredits($article, $cnt, $showIfMax=true) {
*
*/
function getAuthorCredits($article) {
- global $wgLang;
+ global $wgLang, $wgAllowRealName;
$last_author = $article->getUser();
if ($last_author == 0) {
$author_credit = wfMsg('anonymous');
} else {
-
- $real_name = User::whoIsReal($last_author);
+ if($wgAllowRealName) { $real_name = User::whoIsReal($last_author); }
$user_name = User::whoIs($last_author);
if (!empty($real_name)) {
diff --git a/includes/Database.php b/includes/Database.php
index b66e7178dc8c..724a6e98d8c4 100644
--- a/includes/Database.php
+++ b/includes/Database.php
@@ -37,7 +37,7 @@ class Database {
*/
var $mLastQuery = '';
- var $mServer, $mUser, $mPassword, $mConn, $mDBname;
+ var $mServer, $mUser, $mPassword, $mConn = null, $mDBname;
var $mOut, $mOpened = false;
var $mFailFunction;
@@ -215,7 +215,14 @@ class Database {
@/**/$this->mConn = mysql_pconnect( $server, $user, $password );
} else {
# Create a new connection...
- @/**/$this->mConn = mysql_connect( $server, $user, $password, true );
+ if( version_compare( PHP_VERSION, '4.2.0', 'ge' ) ) {
+ @/**/$this->mConn = mysql_connect( $server, $user, $password, true );
+ } else {
+ # On PHP 4.1 the new_link parameter is not available. We cannot
+ # guarantee that we'll actually get a new connection, and this
+ # may cause some operations to fail possibly.
+ @/**/$this->mConn = mysql_connect( $server, $user, $password );
+ }
}
if ( $dbName != '' ) {
@@ -237,8 +244,15 @@ class Database {
if ( !$success ) {
$this->reportConnectionError();
- $this->close();
}
+
+ 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;
}
@@ -266,16 +280,15 @@ class Database {
/**
* @access private
* @param string $msg error message ?
- * @todo parameter $msg is not used
*/
- function reportConnectionError( $msg = '') {
+ function reportConnectionError() {
if ( $this->mFailFunction ) {
if ( !is_int( $this->mFailFunction ) ) {
$ff = $this->mFailFunction;
$ff( $this, mysql_error() );
}
} else {
- wfEmergencyAbort( $this, mysql_error() );
+ wfEmergencyAbort( $this, $this->lastError() );
}
}
@@ -591,7 +604,13 @@ class Database {
*/
function lastError() {
if ( $this->mConn ) {
- $error = mysql_error( $this->mConn );
+ # Even if it's non-zero, it can still be invalid
+ wfSuppressWarnings();
+ $error = mysql_error( $this->mConn );
+ if ( !$error ) {
+ $error = mysql_error();
+ }
+ wfRestoreWarnings();
} else {
$error = mysql_error();
}
@@ -1120,7 +1139,10 @@ class Database {
* PostgreSQL doesn't have them and returns ""
*/
function useIndexClause( $index ) {
- return "FORCE INDEX ($index)";
+ global $wgDBmysql4;
+ return $wgDBmysql4
+ ? "FORCE INDEX ($index)"
+ : "USE INDEX ($index)";
}
/**
@@ -1458,7 +1480,7 @@ class Database {
/**
* @todo document
*/
- function resultObject( &$result ) {
+ function resultObject( $result ) {
if( empty( $result ) ) {
return NULL;
} else {
@@ -1606,13 +1628,12 @@ class ResultWrapper {
*/
function wfEmergencyAbort( &$conn, $error ) {
global $wgTitle, $wgUseFileCache, $title, $wgInputEncoding, $wgOutputEncoding;
- global $wgSitename, $wgServer;
-
+ global $wgSitename, $wgServer, $wgMessageCache, $wgLogo;
+
# I give up, Brion is right. Getting the message cache to work when there is no DB is tricky.
# Hard coding strings instead.
- $noconnect = 'Sorry! The wiki is experiencing some technical difficulties, and cannot contact the database server. <br />
-$1';
+ $noconnect = "<h1><img src='$wgLogo' style='float:left;margin-right:1em' alt=''>$wgSitename has a problem</h1><p><strong>Sorry! This site is experiencing technical difficulties.</strong></p><p>Try waiting a few minutes and reloading.</p><p><small>(Can't contact the database server: $1)</small></p>";
$mainpage = 'Main Page';
$searchdisabled = <<<EOT
<p style="margin: 1.5em 2em 1em">$wgSitename search is disabled for performance reasons. You can search via Google in the meantime.
@@ -1648,9 +1669,15 @@ border=\"0\" ALT=\"Google\"></A>
header( 'Cache-control: none' );
header( 'Pragma: nocache' );
}
+
+ # No database access
+ if ( is_object( $wgMessageCache ) ) {
+ $wgMessageCache->disable();
+ }
+
$msg = wfGetSiteNotice();
if($msg == '') {
- $msg = str_replace( '$1', $error, $noconnect );
+ $msg = str_replace( '$1', htmlspecialchars( $error ), $noconnect );
}
$text = $msg;
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 7690ddc86abe..190cd4918eb9 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -1,8 +1,11 @@
<?php
/**
- * DO NOT EDIT THIS FILE!
*
- * To customize your installation, edit "LocalSettings.php".
+ * DO NOT EVER EDIT THIS FILE!
+ *
+ *
+ * To customize your installation, edit "LocalSettings.php". If you make
+ * changes here, they will be lost on next upgrade of MediaWiki!
*
* Note that since all these string interpolations are expanded
* before LocalSettings is included, if you localize something
@@ -28,7 +31,7 @@ require_once( 'includes/SiteConfiguration.php' );
$wgConf = new SiteConfiguration;
/** MediaWiki version number */
-$wgVersion = '1.5beta4';
+$wgVersion = '1.5.5';
/** Name of the site. It must be changed in LocalSettings.php */
$wgSitename = 'MediaWiki';
@@ -451,6 +454,24 @@ $wgDBtransactions = false;
$wgDBmysql4 = false;
/**
+ * Set to true to engage MySQL 4.1/5.0 charset-related features;
+ * for now will just cause sending of 'SET NAMES=utf8' on connect.
+ *
+ * WARNING: THIS IS EXPERIMENTAL!
+ *
+ * May break if you're not using the table defs from mysql5/tables.sql.
+ * May break if you're upgrading an existing wiki if set differently.
+ * Broken symptoms likely to include incorrect behavior with page titles,
+ * usernames, comments etc containing non-ASCII characters.
+ * Might also cause failures on the object cache and other things.
+ *
+ * Even correct usage may cause failures with Unicode supplementary
+ * characters (those not in the Basic Multilingual Plane) unless MySQL
+ * has enhanced their Unicode support.
+ */
+$wgDBmysql5 = false;
+
+/**
* Other wikis on this site, can be administered from a single developer
* account.
* Array, interwiki prefix => database name
@@ -616,6 +637,14 @@ $wgLogQueries = false;
$wgDebugDumpSql = false;
/**
+ * Set to an array of log group keys to filenames.
+ * If set, wfDebugLog() output for that group will go to that file instead
+ * of the regular $wgDebugLogFile. Useful for enabling selective logging
+ * in production.
+ */
+$wgDebugLogGroups = array();
+
+/**
* Whether to show "we're sorry, but there has been a database error" pages.
* Displaying errors aids in debugging, but may display information useful
* to an attacker.
@@ -1009,7 +1038,9 @@ $wgMimeTypeBlacklist= array(
# PHP scripts may execute arbitrary code on the server
'application/x-php', 'text/x-php',
# Other types that may be interpreted by some servers
- 'text/x-python', 'text/x-perl', 'text/x-bash', 'text/x-sh', 'text/x-csh'
+ 'text/x-python', 'text/x-perl', 'text/x-bash', 'text/x-sh', 'text/x-csh',
+ # Windows metafile, client-side vulnerability on some systems
+ 'application/x-msmetafile'
);
/** This is a flag to determine whether or not to check file extensions on upload. */
@@ -1078,11 +1109,14 @@ $wgSVGConverters = array(
'sodipodi' => '$path/sodipodi -z -w $width -f $input -e $output',
'inkscape' => '$path/inkscape -z -w $width -f $input -e $output',
'batik' => 'java -Djava.awt.headless=true -jar $path/batik-rasterizer.jar -w $width -d $output $input',
+ 'rsvg' => '$path/rsvg -w$width -h$height $input $output',
);
/** Pick one of the above */
$wgSVGConverter = 'ImageMagick';
/** If not in the executable PATH, specify */
$wgSVGConverterPath = '';
+/** Don't scale a SVG larger than this unless its native size is larger */
+$wgSVGMaxSize = 1024;
/** Set $wgCommandLineMode if it's not set already, to avoid notices */
if( !isset( $wgCommandLineMode ) ) {
@@ -1378,6 +1412,9 @@ $wgBrowserBlackList = array(
* Fake out the timezone that the server thinks it's in. This will be used for
* date display and not for what's stored in the DB. Leave to null to retain
* your server's OS-based timezone value. This is the same as the timezone.
+ *
+ * This variable is currently used ONLY for signature formatting, not for
+ * anything else.
*/
# $wgLocaltimezone = 'GMT';
# $wgLocaltimezone = 'PST8PDT';
@@ -1385,6 +1422,27 @@ $wgBrowserBlackList = array(
# $wgLocaltimezone = 'CET';
$wgLocaltimezone = null;
+/**
+ * Set an offset from UTC in hours to use for the default timezone setting
+ * for anonymous users and new user accounts.
+ *
+ * This setting is used for most date/time displays in the software, and is
+ * overrideable in user preferences. It is *not* used for signature timestamps.
+ *
+ * You can set it to match the configured server timezone like this:
+ * $wgLocalTZoffset = date("Z") / 3600;
+ *
+ * If your server is not configured for the timezone you want, you can set
+ * this in conjunction with the signature timezone and override the TZ
+ * environment variable like so:
+ * $wgLocaltimezone="Europe/Berlin";
+ * putenv("TZ=$wgLocaltimezone");
+ * $wgLocalTZoffset = date("Z") / 3600;
+ *
+ * Leave at NULL to show times in universal time (UTC/GMT).
+ */
+$wgLocalTZoffset = null;
+
/**
* When translating messages with wfMsg(), it is not always clear what should be
@@ -1557,6 +1615,12 @@ $wgCountCategorizedImagesAsUsed = false;
$wgExternalStores = false;
/**
+ * An array of external mysql servers, e.g.
+ * $wgExternalServers = array( 'cluster1' => array( 'srv28', 'srv29', 'srv30' ) );
+ */
+$wgExternalServers = array();
+
+/**
* list of trusted media-types and mime types.
* Use the MEDIATYPE_xxx constants to represent media types.
* This list is used by Image::isSafeFile
diff --git a/includes/Defines.php b/includes/Defines.php
index 67789ec96636..e17dc2b7809e 100644
--- a/includes/Defines.php
+++ b/includes/Defines.php
@@ -129,4 +129,15 @@ define( 'ALF_NO_LINK_LOCK', 4 );
define( 'ALF_NO_BLOCK_LOCK', 8 );
/**#@-*/
+/**#@+
+ * Date format selectors; used in user preference storage and by
+ * Language::date() and co.
+ */
+define( 'MW_DATE_DEFAULT', '0' );
+define( 'MW_DATE_MDY', '1' );
+define( 'MW_DATE_DMY', '2' );
+define( 'MW_DATE_YMD', '3' );
+define( 'MW_DATE_ISO', 'ISO 8601' );
+/**#@-*/
+
?>
diff --git a/includes/DifferenceEngine.php b/includes/DifferenceEngine.php
index e78fb878388c..e056eee1fd67 100644
--- a/includes/DifferenceEngine.php
+++ b/includes/DifferenceEngine.php
@@ -169,11 +169,13 @@ CONTROL;
$patrol = '';
}
- $prevlink = $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'previousdiff' ), 'diff=prev&oldid='.$this->mOldid );
+ $prevlink = $sk->makeKnownLinkObj( $wgTitle, wfMsgHtml( 'previousdiff' ),
+ 'diff=prev&oldid='.$this->mOldid, '', '', 'id="differences-prevlink"' );
if ( $this->newRev->isCurrent() ) {
$nextlink = '';
} else {
- $nextlink = $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'nextdiff' ), 'diff=next&oldid='.$this->mNewid );
+ $nextlink = $sk->makeKnownLinkObj( $wgTitle, wfMsgHtml( 'nextdiff' ),
+ 'diff=next&oldid='.$this->mNewid, '', '', 'id="differences-nextlink"' );
}
$oldHeader = "<strong>{$this->mOldtitle}</strong><br />$oldUserLink " .
@@ -240,7 +242,7 @@ CONTROL;
$userLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mOldUser ), $this->mOldUser );
$contribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ), wfMsg( 'contribslink' ),
'target=' . urlencode($this->mOldUser) );
- $nextlink = $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'nextdiff' ), 'diff=next&oldid='.$this->mNewid );
+ $nextlink = $sk->makeKnownLinkObj( $wgTitle, wfMsgHtml( 'nextdiff' ), 'diff=next&oldid='.$this->mNewid, '', '', 'id="differences-nextlink"' );
$header = "<div class=\"firstrevisionheader\" style=\"text-align: center\"><strong>{$this->mOldtitle}</strong><br />$userLink " .
"($uTLink | $contribs)<br />" . $this->mOldComment .
'<br />' . $nextlink. "</div>\n";
diff --git a/includes/EditPage.php b/includes/EditPage.php
index 1bf5650be9ed..09468a2b9f5a 100644
--- a/includes/EditPage.php
+++ b/includes/EditPage.php
@@ -526,13 +526,12 @@ class EditPage {
}
$wgOut->setPageTitle( $s );
if ( !$this->checkUnicodeCompliantBrowser() ) {
- $this->mArticle->setOldSubtitle();
$wgOut->addWikiText( wfMsg( 'nonunicodebrowser') );
}
if ( isset( $this->mArticle )
&& isset( $this->mArticle->mRevision )
&& !$this->mArticle->mRevision->isCurrent() ) {
- $this->mArticle->setOldSubtitle();
+ $this->mArticle->setOldSubtitle( $this->mArticle->mRevision->getId() );
$wgOut->addWikiText( wfMsg( 'editingold' ) );
}
}
@@ -960,9 +959,19 @@ END
}
}
-
+ /**
+ * Check if the browser is on a blacklist of user-agents known to
+ * mangle UTF-8 data on form submission. Returns true if Unicode
+ * should make it through, false if it's known to be a problem.
+ * @return bool
+ * @access private
+ */
function checkUnicodeCompliantBrowser() {
global $wgBrowserBlackList;
+ if( empty( $_SERVER["HTTP_USER_AGENT"] ) ) {
+ // No User-Agent header sent? Trust it by default...
+ return true;
+ }
$currentbrowser = $_SERVER["HTTP_USER_AGENT"];
foreach ( $wgBrowserBlackList as $browser ) {
if ( preg_match($browser, $currentbrowser) ) {
diff --git a/includes/ExternalStoreDB.php b/includes/ExternalStoreDB.php
index 00f8c481ea89..3c61726523fb 100644
--- a/includes/ExternalStoreDB.php
+++ b/includes/ExternalStoreDB.php
@@ -10,31 +10,74 @@ require_once( 'LoadBalancer.php' );
/** @package MediaWiki */
+
class ExternalStoreDB {
+ var $loadBalancers = array();
+
/**
* Fetch data from given URL
* @param string $url An url
*/
+
+ function &getLoadBalancer( $cluster ) {
+ global $wgExternalServers;
+ if ( !array_key_exists( $cluster, $this->loadBalancers ) ) {
+ $this->loadBalancers[$cluster] = LoadBalancer::newFromParams( $wgExternalServers[$cluster] );
+ }
+ return $this->loadBalancers[$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 fetchFromURL($url) {
global $wgExternalServers;
#
- # URLs have the form DB://cluster/id, e.g.
- # DB://cluster1/3298247
+ # URLs have the form DB://cluster/id or DB://cluster/id/itemid for concatenated storage
#
$path = explode( '/', $url );
$cluster = $path[2];
$id = $path[3];
+ if ( isset( $path[4] ) ) {
+ $itemID = $path[4];
+ } else {
+ $itemID = false;
+ }
- $lb = LoadBalancer::NewFromParams( $wgExternalServers[$cluster] );
- $db = $lb->getConnection( DB_SLAVE );
+ $dbr =& $this->getSlave( $cluster );
+ $ret = $dbr->selectField( 'blobs', 'blob_text', array( 'blob_id' => $id ) );
- $ret = $db->selectField( 'blobs', 'blob_text', array( 'blob_id' => $id ) );
-
+ if ( $itemID !== false ) {
+ # Unserialise object and get item
+ $obj = unserialize( $ret );
+ $ret = $obj->getItem( $itemID );
+ }
return $ret;
}
- /* @fixme XXX: may require other methods, for store, delete,
- * whatever, for initial ext storage
+ /**
+ * Insert a data item into a given cluster
+ *
+ * @param string $cluster The cluster name
+ * @param string $data The data item
+ * @return string URL
*/
+ function store( $cluster, $data ) {
+ global $wgExternalServers;
+ $fname = 'ExternalStoreDB::store';
+
+ $dbw =& $this->getMaster( $cluster );
+
+ $id = $dbw->nextSequenceValue( 'blob_blob_id_seq' );
+ $dbw->insert( 'blobs', array( 'blob_id' => $id, 'blob_text' => $data ), $fname );
+ return "DB://$cluster/" . $dbw->insertId();
+ }
}
?>
diff --git a/includes/Feed.php b/includes/Feed.php
index a798ce44ec7c..6a2862762104 100644
--- a/includes/Feed.php
+++ b/includes/Feed.php
@@ -240,7 +240,7 @@ class AtomFeed extends ChannelFeed {
global $wgVersion, $wgOut;
$this->outXmlHeader();
- ?><feed version="0.3" xml:lang="<?php print $this->getLanguage() ?>">
+ ?><feed version="0.3" xmlns="http://purl.org/atom/ns#" xml:lang="<?php print $this->getLanguage() ?>">
<title><?php print $this->getTitle() ?></title>
<link rel="alternate" type="text/html" href="<?php print $this->getUrl() ?>"/>
<modified><?php print $this->formatTime( wfTimestampNow() ) ?>Z</modified>
diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php
index a694c96cfefc..afb7fc026086 100644
--- a/includes/GlobalFunctions.php
+++ b/includes/GlobalFunctions.php
@@ -176,6 +176,22 @@ function wfDebug( $text, $logonly = false ) {
}
/**
+ * Send a line to a supplementary debug log file, if configured, or main debug log if not.
+ * $wgDebugLogGroups[$logGroup] should be set to a filename to send to a separate log.
+ * @param string $logGroup
+ * @param string $text
+ */
+function wfDebugLog( $logGroup, $text ) {
+ global $wgDebugLogGroups, $wgDBname;
+ if( $text{strlen( $text ) - 1} != "\n" ) $text .= "\n";
+ if( isset( $wgDebugLogGroups[$logGroup] ) ) {
+ @error_log( "$wgDBname: $text", 3, $wgDebugLogGroups[$logGroup] );
+ } else {
+ wfDebug( $text, true );
+ }
+}
+
+/**
* Log for database errors
* @param string $text Database error message.
*/
@@ -238,7 +254,7 @@ function wfReadOnly() {
// Set $wgReadOnly and unset $wgReadOnlyFile, for faster access next time
if ( is_file( $wgReadOnlyFile ) ) {
- $wgReadOnly = true;
+ $wgReadOnly = file_get_contents( $wgReadOnlyFile );
} else {
$wgReadOnly = false;
}
@@ -402,8 +418,8 @@ function wfAbruptExit( $error = false ){
if( function_exists( 'debug_backtrace' ) ){ // PHP >= 4.3
$bt = debug_backtrace();
for($i = 0; $i < count($bt) ; $i++){
- $file = $bt[$i]['file'];
- $line = $bt[$i]['line'];
+ $file = isset($bt[$i]['file']) ? $bt[$i]['file'] : "unknown";
+ $line = isset($bt[$i]['line']) ? $bt[$i]['line'] : "unknown";
wfDebug("WARNING: Abrupt exit in $file at line $line\n");
}
} else {
@@ -523,7 +539,7 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) {
if( is_object( $link ) ) {
$title =& $link;
} else {
- $title =& Title::newFromText( $link );
+ $title = Title::newFromText( $link );
if( is_null( $title ) ) {
return false;
}
@@ -774,6 +790,7 @@ function wfMerge( $old, $mine, $yours, &$result ){
# This check may also protect against code injection in
# case of broken installations.
if(! file_exists( $wgDiff3 ) ){
+ wfDebug( "diff3 not found\n" );
return false;
}
@@ -788,7 +805,7 @@ function wfMerge( $old, $mine, $yours, &$result ){
fwrite( $yourtextFile, $yours ); fclose( $yourtextFile );
# Check for a conflict
- $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a --overlap-only ' .
+ $cmd = $wgDiff3 . ' -a --overlap-only ' .
wfEscapeShellArg( $mytextName ) . ' ' .
wfEscapeShellArg( $oldtextName ) . ' ' .
wfEscapeShellArg( $yourtextName );
@@ -802,7 +819,7 @@ function wfMerge( $old, $mine, $yours, &$result ){
pclose( $handle );
# Merge differences
- $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' .
+ $cmd = $wgDiff3 . ' -a -e --merge ' .
wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName );
$handle = popen( $cmd, 'r' );
$result = '';
@@ -815,6 +832,11 @@ function wfMerge( $old, $mine, $yours, &$result ){
} while ( true );
pclose( $handle );
unlink( $mytextName ); unlink( $oldtextName ); unlink( $yourtextName );
+
+ if ( $result === '' && $old !== '' && $conflict == false ) {
+ wfDebug( "Unexpected null result from diff3. Command: $cmd\n" );
+ $conflict = true;
+ }
return ! $conflict;
}
@@ -1042,8 +1064,9 @@ define('TS_EXIF', 4);
* @return string Time in the format specified in $outputtype
*/
function wfTimestamp($outputtype=TS_UNIX,$ts=0) {
- if ($ts==0) {
- $uts=time();
+ $uts = 0;
+ if ($ts==0) {
+ $uts=time();
} elseif (preg_match("/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/",$ts,$da)) {
# TS_DB
$uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6],
@@ -1151,7 +1174,7 @@ function wfGetSiteNotice() {
*
* @param string $element
* @param array $attribs Name=>value pairs. Values will be escaped.
- * @param bool $contents NULL to make an open tag only; '' for a contentless closed tag (default)
+ * @param string $contents NULL to make an open tag only; '' for a contentless closed tag (default)
* @return string
*/
function wfElement( $element, $attribs = null, $contents = '') {
@@ -1182,7 +1205,7 @@ function wfElement( $element, $attribs = null, $contents = '') {
*
* @param string $element
* @param array $attribs Name=>value pairs. Values will be escaped.
- * @param bool $contents NULL to make an open tag only; '' for a contentless closed tag (default)
+ * @param string $contents NULL to make an open tag only; '' for a contentless closed tag (default)
* @return string
*/
function wfElementClean( $element, $attribs = array(), $contents = '') {
@@ -1195,6 +1218,37 @@ function wfElementClean( $element, $attribs = array(), $contents = '') {
return wfElement( $element, $attribs, $contents );
}
+/**
+ * Create a namespace selector
+ *
+ * @param mixed $selected The namespace which should be selected, default ''
+ * @param string $allnamespaces Value of a special item denoting all namespaces. Null to not include (default)
+ * @return Html string containing the namespace selector
+ */
+function &HTMLnamespaceselector($selected = '', $allnamespaces = null) {
+ global $wgContLang;
+ $s = "<select name='namespace' class='namespaceselector'>\n";
+ $arr = $wgContLang->getFormattedNamespaces();
+ if( !is_null($allnamespaces) ) {
+ $arr = array($allnamespaces => wfMsgHtml('namespacesall')) + $arr;
+ }
+ foreach ($arr as $index => $name) {
+ if ($index < NS_MAIN) continue;
+
+ $name = $index !== 0 ? $name : wfMsgHtml('blanknamespace');
+
+ if ($index === $selected) {
+ $s .= wfElement("option",
+ array("value" => $index, "selected" => "selected"),
+ $name);
+ } else {
+ $s .= wfElement("option", array("value" => $index), $name);
+ }
+ }
+ $s .= "</select>\n";
+ return $s;
+}
+
/** Global singleton instance of MimeMagic. This is initialized on demand,
* please always use the wfGetMimeMagic() function to get the instance.
*
@@ -1304,4 +1358,28 @@ function wfEncryptPassword( $userid, $password ) {
return $p;
}
+/**
+ * Appends to second array if $value differs from that in $default
+ */
+function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) {
+ if ( is_null( $changed ) ) {
+ wfDebugDieBacktrace('GlobalFunctions::wfAppendToArrayIfNotDefault got null');
+ }
+ if ( $default[$key] !== $value ) {
+ $changed[$key] = $value;
+ }
+}
+
+/**
+ * Since wfMsg() and co suck, they don't return false if the message key they
+ * looked up didn't exist but a XHTML string, this function checks for the
+ * nonexistance of messages by looking at wfMsg() output
+ *
+ * @param $msg The message key looked up
+ * @param $wfMsgOut The output of wfMsg*()
+ * @return bool
+ */
+function wfNoMsg( $msg, $wfMsgOut ) {
+ return $wfMsgOut === "&lt;$msg&gt;";
+}
?>
diff --git a/includes/HistoryBlob.php b/includes/HistoryBlob.php
index f7fa77afd304..3eb2b6f5335e 100644
--- a/includes/HistoryBlob.php
+++ b/includes/HistoryBlob.php
@@ -182,7 +182,7 @@ $wgBlobCache = array();
* @package MediaWiki
*/
class HistoryBlobStub {
- var $mOldId, $mHash;
+ var $mOldId, $mHash,$mRef;
/** @todo document */
function HistoryBlobStub( $hash = '', $oldid = 0 ) {
@@ -197,6 +197,20 @@ class HistoryBlobStub {
$this->mOldId = $id;
}
+ /**
+ * Sets the location (old_id) of the referring object
+ */
+ function setReferrer( $id ) {
+ $this->mRef = $id;
+ }
+
+ /**
+ * Gets the location of the referring object
+ */
+ function getReferrer() {
+ return $this->mRef;
+ }
+
/** @todo document */
function getText() {
global $wgBlobCache;
diff --git a/includes/Hooks.php b/includes/Hooks.php
index 021d799cf066..3e337f80959c 100644
--- a/includes/Hooks.php
+++ b/includes/Hooks.php
@@ -30,12 +30,12 @@ if (defined('MEDIAWIKI')) {
* in here than would normally be necessary.
*/
- function wfRunHooks($event, $args) {
+ function wfRunHooks($event, $args = null) {
global $wgHooks;
if (!is_array($wgHooks)) {
- wfDieDebugBacktrace("Global hooks array is not an array!\n");
+ wfDebugDieBacktrace("Global hooks array is not an array!\n");
return false;
}
@@ -44,7 +44,7 @@ if (defined('MEDIAWIKI')) {
}
if (!is_array($wgHooks[$event])) {
- wfDieDebugBacktrace("Hooks array for event '$event' is not an array!\n");
+ wfDebugDieBacktrace("Hooks array for event '$event' is not an array!\n");
return false;
}
@@ -63,7 +63,7 @@ if (defined('MEDIAWIKI')) {
if (is_array($hook)) {
if (count($hook) < 1) {
- wfDieDebugBacktrace("Empty array in hooks for " . $event . "\n");
+ wfDebugDieBacktrace("Empty array in hooks for " . $event . "\n");
} else if (is_object($hook[0])) {
$object = $hook[0];
if (count($hook) < 2) {
@@ -82,7 +82,7 @@ if (defined('MEDIAWIKI')) {
$have_data = true;
}
} else {
- wfDieDebugBacktrace("Unknown datatype in hooks for " . $event . "\n");
+ wfDebugDieBacktrace("Unknown datatype in hooks for " . $event . "\n");
}
} else if (is_string($hook)) { # functions look like strings, too
$func = $hook;
@@ -90,7 +90,7 @@ if (defined('MEDIAWIKI')) {
$object = $hook;
$method = "on" . $event;
} else {
- wfDieDebugBacktrace("Unknown datatype in hooks for " . $event . "\n");
+ wfDebugDieBacktrace("Unknown datatype in hooks for " . $event . "\n");
}
/* We put the first data element on, if needed. */
diff --git a/includes/Image.php b/includes/Image.php
index 3e7362132438..15e45937ef25 100644
--- a/includes/Image.php
+++ b/includes/Image.php
@@ -582,7 +582,7 @@ class Image
if (!$mime || $mime==='unknown' || $mime==='unknown/unknown') return false;
- #if it's SVG, check if ther's a converter enabled
+ #if it's SVG, check if there's a converter enabled
if ($mime === 'image/svg') {
global $wgSVGConverters, $wgSVGConverter;
@@ -854,7 +854,7 @@ class Image
* @return ThumbnailImage
* @access public
*/
- function &getThumbnail( $width, $height=-1 ) {
+ function getThumbnail( $width, $height=-1 ) {
if ( $height == -1 ) {
return $this->renderThumb( $width );
}
@@ -915,6 +915,9 @@ class Image
function renderThumb( $width, $useScript = true ) {
global $wgUseSquid, $wgInternalServer;
global $wgThumbnailScriptPath, $wgSharedThumbnailScriptPath;
+
+ $fname = 'Image::renderThumb';
+ wfProfileIn( $fname );
$width = IntVal( $width );
@@ -922,18 +925,26 @@ class Image
if ( ! $this->exists() )
{
# If there is no image, there will be no thumbnail
+ wfProfileOut( $fname );
return null;
}
# Sanity check $width
if( $width <= 0 || $this->width <= 0) {
# BZZZT
+ wfProfileOut( $fname );
return null;
}
- if( $width >= $this->width && !$this->mustRender() ) {
+ global $wgSVGMaxSize;
+ $maxsize = $this->mustRender()
+ ? max( $this->width, $wgSVGMaxSize )
+ : $this->width - 1;
+ if( $width > $maxsize ) {
# Don't make an image bigger than the source
- return new ThumbnailImage( $this->getViewURL(), $this->getWidth(), $this->getHeight() );
+ $thumb = new ThumbnailImage( $this->getViewURL(), $this->getWidth(), $this->getHeight() );
+ wfProfileOut( $fname );
+ return $thumb;
}
$height = floor( $this->height * ( $width/$this->width ) );
@@ -941,7 +952,9 @@ class Image
list( $isScriptUrl, $url ) = $this->thumbUrl( $width );
if ( $isScriptUrl && $useScript ) {
// Use thumb.php to render the image
- return new ThumbnailImage( $url, $width, $height );
+ $thumb = new ThumbnailImage( $url, $width, $height );
+ wfProfileOut( $fname );
+ return $thumb;
}
$thumbName = $this->thumbName( $width, $this->fromSharedDirectory );
@@ -976,7 +989,9 @@ class Image
}
}
- return new ThumbnailImage( $url, $width, $height, $thumbPath );
+ $thumb = new ThumbnailImage( $url, $width, $height, $thumbPath );
+ wfProfileOut( $fname );
+ return $thumb;
} // END OF function renderThumb
/**
@@ -998,12 +1013,14 @@ class Image
if( isset( $wgSVGConverters[$wgSVGConverter] ) ) {
global $wgSVGConverterPath;
$cmd = str_replace(
- array( '$path/', '$width', '$input', '$output' ),
- array( $wgSVGConverterPath,
- $width,
+ array( '$path/', '$width', '$height', '$input', '$output' ),
+ array( $wgSVGConverterPath ? "$wgSVGConverterPath/" : "",
+ intval( $width ),
+ intval( $height ),
wfEscapeShellArg( $this->imagePath ),
wfEscapeShellArg( $thumbPath ) ),
$wgSVGConverters[$wgSVGConverter] );
+ wfDebug( "reallyRenderThumb SVG: $cmd\n" );
$conv = shell_exec( $cmd );
} else {
$conv = false;
@@ -1016,7 +1033,7 @@ class Image
" -quality 85 -background white -geometry {$width} ".
wfEscapeShellArg($this->imagePath) . " " .
wfEscapeShellArg($thumbPath);
- wfDebug("reallyRenderThumb: running ImageMagick: $cmd");
+ wfDebug("reallyRenderThumb: running ImageMagick: $cmd\n");
$conv = shell_exec( $cmd );
} else {
# Use PHP's builtin GD library functions.
@@ -1244,7 +1261,7 @@ class Image
/**
* Record an image upload in the upload log and the image table
*/
- function recordUpload( $oldver, $desc, $copyStatus = '', $source = '' ) {
+ function recordUpload( $oldver, $desc, $copyStatus = '', $source = '', $watch = false ) {
global $wgUser, $wgLang, $wgTitle, $wgDeferredUpdateList;
global $wgUseCopyrightUpload, $wgUseSquid, $wgPostCommitUpdateList;
@@ -1304,15 +1321,7 @@ class Image
$descTitle = $this->getTitle();
$purgeURLs = array();
- if ( $dbw->affectedRows() ) {
- # Successfully inserted, this is a new image
- $id = $descTitle->getArticleID();
-
- if ( $id == 0 ) {
- $article = new Article( $descTitle );
- $article->insertNewArticle( $textdesc, $desc, false, false, true );
- }
- } else {
+ if( $dbw->affectedRows() == 0 ) {
# Collision, this is an update of an image
# Insert previous contents into oldimage
$dbw->insertSelect( 'oldimage', 'image',
@@ -1349,12 +1358,27 @@ class Image
'img_name' => $this->name
), $fname
);
+ }
+
+ $article = new Article( $descTitle );
+ $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();
+ } else {
+ // New image; create the description page.
+ $article->insertNewArticle( $textdesc, $desc, $minor, $watch, $suppressRC );
}
-
+
# Invalidate cache for all pages using this image
$linksTo = $this->getLinksTo();
diff --git a/includes/ImagePage.php b/includes/ImagePage.php
index 58085809521e..b6524e191107 100644
--- a/includes/ImagePage.php
+++ b/includes/ImagePage.php
@@ -132,7 +132,7 @@ class ImagePage extends Article {
global $wgOut, $wgUser, $wgImageLimits, $wgRequest,
$wgUseImageResize, $wgRepositoryBaseUrl,
$wgUseExternalEditor, $wgServer, $wgFetchCommonsDescriptions;
- $full_url = $this->img->getViewURL();
+ $full_url = $this->img->getURL();
$anchoropen = '';
$anchorclose = '';
@@ -168,25 +168,29 @@ class ImagePage extends Article {
$width = floor( $width * $maxHeight / $height );
$height = $maxHeight;
}
- if ( !$this->img->mustRender()
- && ( $width != $this->img->getWidth() || $height != $this->img->getHeight() ) ) {
+ if ( $width != $this->img->getWidth() || $height != $this->img->getHeight() ) {
if( $wgUseImageResize ) {
$thumbnail = $this->img->getThumbnail( $width );
if ( $thumbnail == null ) {
- $url = $full_url;
+ $url = $this->img->getViewURL();
} else {
- $url = $thumbnail->getUrl();
+ $url = $thumbnail->getURL();
}
} else {
# No resize ability? Show the full image, but scale
# it down in the browser so it fits on the page.
- $url = $full_url;
+ $url = $this->img->getViewURL();
}
$anchoropen = "<a href=\"{$full_url}\">";
- $anchorclose = "</a><br />\n$anchoropen{$msg}</a>";
+ $anchorclose = "</a><br />";
+ if( $this->img->mustRender() ) {
+ $showLink = true;
+ } else {
+ $anchorclose .= "\n$anchoropen{$msg}</a>";
+ }
} else {
- $url = $full_url;
- $showLink = $this->img->mustRender();
+ $url = $this->img->getViewURL();
+ $showLink = true;
}
$wgOut->addHTML( '<div class="fullImageLink" id="file">' . $anchoropen .
"<img border=\"0\" src=\"{$url}\" width=\"{$width}\" height=\"{$height}\" alt=\"" .
@@ -200,40 +204,35 @@ class ImagePage extends Article {
$icon->toHtml() .
'</a></div>' );
}
-
+
$showLink = true;
}
if ($showLink) {
- $s= $sk->makeMediaLink( $this->img->getName(), '', '', true );
- $info= wfMsg( 'fileinfo', ceil($this->img->getSize()/1024.0), $this->img->getMimeType() );
-
+ $filename = wfEscapeWikiText( $this->img->getName() );
+ $info = wfMsg( 'fileinfo',
+ ceil($this->img->getSize()/1024.0),
+ $this->img->getMimeType() );
+
if (!$this->img->isSafeFile()) {
- $wgOut->addHTML("<div class=\"fullMedia\">");
- $wgOut->addHTML("<span class=\"dangerousLink\">");
- $wgOut->addHTML($s);
- $wgOut->addHTML("</span>");
-
- $wgOut->addHTML("<span class=\"fileInfo\"> (");
- $wgOut->addWikiText( $info, false );
- $wgOut->addHTML(")</span>");
- $wgOut->addHTML("</div>");
-
- #this should be formated a little nicer. Is CSS sufficient?
- $wgOut->addHTML("<div class=\"mediaWarning\">");
- $wgOut->addWikiText( wfMsg( 'mediawarning' ) );
- $wgOut->addHTML('</div>');
-
+ $warning = wfMsg( 'mediawarning' );
+ $wgOut->addWikiText( <<<END
+<div class="fullMedia">
+<span class="dangerousLink">[[Media:$filename|$filename]]</span>
+<span class="fileInfo"> ($info)</span>
+</div>
+
+<div class="mediaWarning">$warning</div>
+END
+ );
} else {
- $wgOut->addHTML("<div class=\"fullMedia\">");
- $wgOut->addHTML($s);
-
- $wgOut->addHTML("<span class=\"fileInfo\"> (");
- $wgOut->addWikiText( $info, false );
- $wgOut->addHTML(")</span>");
-
- $wgOut->addHTML("</div>");
+ $wgOut->addWikiText( <<<END
+<div class="fullMedia">
+[[Media:$filename|$filename]] <span class="fileInfo"> ($info)</span>
+</div>
+END
+ );
}
}
@@ -367,7 +366,7 @@ class ImagePage extends Article {
{
global $wgUser, $wgOut, $wgRequest;
- $confirm = $wgRequest->getBool( 'wpConfirmB' );
+ $confirm = $wgRequest->wasPosted();
$image = $wgRequest->getVal( 'image' );
$oldimage = $wgRequest->getVal( 'oldimage' );
diff --git a/includes/Linker.php b/includes/Linker.php
index 81e31e56ce0c..d37e8148e7b4 100644
--- a/includes/Linker.php
+++ b/includes/Linker.php
@@ -373,6 +373,10 @@ class Linker {
global $wgContLang, $wgUser, $wgThumbLimits;
$img = new Image( $nt );
+ if ( !$img->allowInlineDisplay() ) {
+ return $this->makeKnownLinkObj( $nt );
+ }
+
$url = $img->getViewURL();
$prefix = $postfix = '';
@@ -406,7 +410,7 @@ class Linker {
$wopt = User::getDefaultOption( 'thumbsize' );
}
- $width = $wgThumbLimits[$wopt];
+ $width = min( $img->getWidth(), $wgThumbLimits[$wopt] );
}
return $prefix.$this->makeThumbLinkObj( $img, $label, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
@@ -591,7 +595,7 @@ class Linker {
* @access public
* @todo Handle invalid or missing images better.
*/
- function makeMediaLinkObj( $title, $text = '', $nourl=false ) {
+ function makeMediaLinkObj( $title, $text = '' ) {
if( is_null( $title ) ) {
### HOTFIX. Instead of breaking, return empty string.
return $text;
@@ -600,9 +604,6 @@ class Linker {
$img = new Image( $title );
if( $img->exists() ) {
$url = $img->getURL();
- if( $nourl ) {
- $url = str_replace( "http://", "http-noparse://", $url );
- }
$class = 'internal';
} else {
$upload = Title::makeTitle( NS_SPECIAL, 'Upload' );
diff --git a/includes/LoadBalancer.php b/includes/LoadBalancer.php
index ee402d68e587..c4c780576b4e 100644
--- a/includes/LoadBalancer.php
+++ b/includes/LoadBalancer.php
@@ -27,7 +27,7 @@ define( 'DB_WRITE', -2 );
*/
class LoadBalancer {
/* private */ var $mServers, $mConnections, $mLoads, $mGroupLoads;
- /* private */ var $mFailFunction;
+ /* private */ var $mFailFunction, $mErrorConnection;
/* private */ var $mForce, $mReadIndex, $mLastIndex;
/* private */ var $mWaitForFile, $mWaitForPos, $mWaitTimeout;
/* private */ var $mLaggedSlaveMode;
@@ -40,6 +40,7 @@ class LoadBalancer {
$this->mReadIndex = -1;
$this->mForce = -1;
$this->mLastIndex = -1;
+ $this->mErrorConnection = false;
}
function newFromParams( $servers, $failFunction = false, $waitTimeout = 10 )
@@ -139,7 +140,7 @@ class LoadBalancer {
return false;
}
- #wfDebug( var_export( $loads, true ) );
+ #wfDebugLog( 'connect', var_export( $loads, true ) );
# Return a random representative of the remainder
return $this->pickRandom( $loads );
@@ -182,8 +183,9 @@ class LoadBalancer {
$i = $this->pickRandom( $loads );
}
}
+ $serverIndex = $i;
if ( $i !== false ) {
- wfDebug( "Using reader #$i: {$this->mServers[$i]['host']}...\n" );
+ wfDebugLog( 'connect', "Using reader #$i: {$this->mServers[$i]['host']}...\n" );
$this->openConnection( $i );
if ( !$this->isOpen( $i ) ) {
@@ -210,7 +212,10 @@ class LoadBalancer {
}
if ( $sleepTime ) {
$totalElapsed += $sleepTime;
+ $x = "{$this->mServers[$serverIndex]['host']} $sleepTime [$serverIndex]";
+ wfProfileIn( "$fname-sleep $x" );
usleep( $sleepTime );
+ wfProfileOut( "$fname-sleep $x" );
}
} while ( count( $loads ) && !$done && $totalElapsed / 1e6 < $wgDBClusterTimeout );
@@ -348,6 +353,10 @@ class LoadBalancer {
$i = $this->getWriterIndex();
}
}
+ # Couldn't find a working server in getReaderIndex()?
+ if ( $i === false ) {
+ $this->reportConnectionError( $this->mErrorConnection );
+ }
# Now we have an explicit index into the servers array
$this->openConnection( $i, $fail );
@@ -374,6 +383,7 @@ class LoadBalancer {
if ( $fail ) {
$this->reportConnectionError( $this->mConnections[$i] );
}
+ $this->mErrorConnection = $this->mConnections[$i];
$this->mConnections[$i] = false;
$success = false;
}
@@ -434,7 +444,7 @@ class LoadBalancer {
if ( $this->mFailFunction ) {
$conn->failFunction( $this->mFailFunction );
} else {
- $conn->failFunction( 'wfEmergencyAbort' );
+ $conn->failFunction( false );
}
$conn->reportConnectionError();
$reporting = false;
diff --git a/includes/MimeMagic.php b/includes/MimeMagic.php
index 5be0ee602954..31f57d0e7d11 100644
--- a/includes/MimeMagic.php
+++ b/includes/MimeMagic.php
@@ -304,6 +304,27 @@ class MimeMagic {
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
+ * whether strict content checks should be applied to reject
+ * invalid uploads; if we can't identify the type we won't
+ * be able to say if it's invalid.
+ *
+ * @todo Be more accurate when using fancy mime detector plugins;
+ * right now this is the bare minimum getimagesize() list.
+ * @return bool
+ */
+ function isRecognizableExtension( $extension ) {
+ static $types = array(
+ 'gif', 'jpeg', 'jpg', 'png', 'swf', 'psd',
+ 'bmp', 'tiff', 'tif', 'jpc', 'jp2',
+ 'jpx', 'jb2', 'swc', 'iff', 'wbmp',
+ 'xbm'
+ );
+ 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
@@ -318,14 +339,21 @@ class MimeMagic {
$fname = 'MimeMagic::guessMimeType';
$mime= $this->detectMimeType($file,$useExt);
- if (strpos($mime,"text/")===0 ||
- $mime==="application/xml") {
+ // 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
+ // Note that WMF may have a bare header, no magic number.
+ // The former of the above two checks is theoretically prone to false positives
+ $mime = "application/x-msmetafile";
+ }
- // Read a chunk of the file
- $f = fopen( $file, "rt" );
- if( !$f ) return "unknown/unknown";
- $head = fread( $f, 1024 );
- fclose( $f );
+ if (strpos($mime,"text/")===0 || $mime==="application/xml") {
$xml_type= NULL;
$script_type= NULL;
diff --git a/includes/OutputPage.php b/includes/OutputPage.php
index ae4694bc4812..e2e63fc4e826 100644
--- a/includes/OutputPage.php
+++ b/includes/OutputPage.php
@@ -174,7 +174,8 @@ class OutputPage {
$name .= ' - '.$taction;
}
}
- $this->setHTMLTitle( $name . ' - ' . wfMsg( 'wikititlesuffix' ) );
+
+ $this->setHTMLTitle( wfMsg( 'pagetitle', $name ) );
}
function getHTMLTitle() { return $this->mHTMLtitle; }
function getPageTitle() { return $this->mPagetitle; }
@@ -809,13 +810,13 @@ class OutputPage {
$ret .= "<!DOCTYPE html PUBLIC \"$wgDocType\"\n \"$wgDTD\">\n";
- if ( "" == $this->mHTMLtitle ) {
- $this->mHTMLtitle = wfMsg( "pagetitle", $this->mPagetitle );
+ if ( '' == $this->getHTMLTitle() ) {
+ $this->setHTMLTitle( wfMsg( 'pagetitle', $this->getPageTitle() ));
}
$rtl = $wgContLang->isRTL() ? " dir='RTL'" : '';
$ret .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"$wgContLanguageCode\" lang=\"$wgContLanguageCode\" $rtl>\n";
- $ret .= "<head>\n<title>" . htmlspecialchars( $this->mHTMLtitle ) . "</title>\n";
+ $ret .= "<head>\n<title>" . htmlspecialchars( $this->getHTMLTitle() ) . "</title>\n";
array_push( $this->mMetatags, array( "http:Content-type", "$wgMimeType; charset={$wgOutputEncoding}" ) );
$ret .= $this->getHeadLinks();
@@ -876,7 +877,7 @@ class OutputPage {
$link = $wgRequest->escapeAppendQuery( 'feed=rss' );
$ret .= "<link rel='alternate' type='application/rss+xml' title='RSS 2.0' href='$link' />\n";
$link = $wgRequest->escapeAppendQuery( 'feed=atom' );
- $ret .= "<link rel='alternate' type='application/rss+atom' title='Atom 0.3' href='$link' />\n";
+ $ret .= "<link rel='alternate' type='application/atom+xml' title='Atom 0.3' href='$link' />\n";
}
return $ret;
diff --git a/includes/Parser.php b/includes/Parser.php
index f7d32f5590a3..53f11493580c 100644
--- a/includes/Parser.php
+++ b/includes/Parser.php
@@ -43,9 +43,6 @@ define( 'OT_MSG' , 3 );
# may want to use in wikisyntax
define( 'STRIP_COMMENTS', 'HTMLCommentStrip' );
-# prefix for escaping, used in two functions at least
-define( 'UNIQ_PREFIX', 'NaodW29');
-
# Constants needed for external link processing
define( 'HTTP_PROTOCOLS', 'http:\/\/|https:\/\/' );
# Everything except bracket, space, or control characters
@@ -101,7 +98,7 @@ class Parser
# Cleared with clearState():
var $mOutput, $mAutonumber, $mDTopen, $mStripState = array();
var $mVariables, $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
- var $mInterwikiLinkHolders, $mLinkHolders;
+ var $mInterwikiLinkHolders, $mLinkHolders, $mUniqPrefix;
# Temporary:
var $mOptions, $mTitle, $mOutputType,
@@ -153,6 +150,7 @@ class Parser
'texts' => array(),
'titles' => array()
);
+ $this->mUniqPrefix = 'UNIQ' . Parser::getRandomString();
}
/**
@@ -349,7 +347,7 @@ class Parser
$gallery_content = array();
# Replace any instances of the placeholders
- $uniq_prefix = UNIQ_PREFIX;
+ $uniq_prefix = $this->mUniqPrefix;
#$text = str_replace( $uniq_prefix, wfHtmlEscapeFirst( $uniq_prefix ), $text );
# html
@@ -377,16 +375,14 @@ class Parser
}
# math
- $text = Parser::extractTags('math', $text, $math_content, $uniq_prefix);
- foreach( $math_content as $marker => $content ){
- if( $render ) {
- if( $this->mOptions->getUseTeX() ) {
+ if( $this->mOptions->getUseTeX() ) {
+ $text = Parser::extractTags('math', $text, $math_content, $uniq_prefix);
+ foreach( $math_content as $marker => $content ){
+ if( $render ) {
$math_content[$marker] = renderMath( $content );
} else {
- $math_content[$marker] = '&lt;math&gt;'.$content.'&lt;math&gt;';
+ $math_content[$marker] = '<math>'.$content.'</math>';
}
- } else {
- $math_content[$marker] = '<math>'.$content.'</math>';
}
}
@@ -470,11 +466,10 @@ class Parser
*/
function unstrip( $text, &$state ) {
# Must expand in reverse order, otherwise nested tags will be corrupted
- $contentDict = end( $state );
- for ( $contentDict = end( $state ); $contentDict !== false; $contentDict = prev( $state ) ) {
- if( key($state) != 'nowiki' && key($state) != 'html') {
- for ( $content = end( $contentDict ); $content !== false; $content = prev( $contentDict ) ) {
- $text = str_replace( key( $contentDict ), $content, $text );
+ foreach( array_reverse( $state, true ) as $tag => $contentDict ) {
+ if( $tag != 'nowiki' && $tag != 'html' ) {
+ foreach( array_reverse( $contentDict, true ) as $uniq => $content ) {
+ $text = str_replace( $uniq, $content, $text );
}
}
}
@@ -511,7 +506,7 @@ class Parser
* @access private
*/
function insertStripItem( $text, &$state ) {
- $rnd = UNIQ_PREFIX . '-item' . Parser::getRandomString();
+ $rnd = $this->mUniqPrefix . '-item' . Parser::getRandomString();
if ( !$state ) {
$state = array(
'html' => array(),
@@ -650,8 +645,11 @@ class Parser
$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 ) .
- '<table' . Sanitizer::fixTagAttributes ( $matches[2], 'table' ) . '>' ;
+ '<table' . Sanitizer::fixTagAttributes ( $attributes, 'table' ) . '>' ;
array_push ( $td , false ) ;
array_push ( $ltd , '' ) ;
array_push ( $tr , false ) ;
@@ -678,7 +676,8 @@ class Parser
array_push ( $tr , false ) ;
array_push ( $td , false ) ;
array_push ( $ltd , '' ) ;
- array_push ( $ltr , Sanitizer::fixTagAttributes ( $x, 'tr' ) ) ;
+ $attributes = $this->unstripForHTML( $x );
+ array_push ( $ltr , Sanitizer::fixTagAttributes ( $attributes, 'tr' ) ) ;
}
else if ( '|' == $fc || '!' == $fc || '|+' == substr ( $x , 0 , 2 ) ) { # Caption
# $x is a table row
@@ -720,7 +719,10 @@ class Parser
}
if ( count ( $y ) == 1 )
$y = "{$z}<{$l}>{$y[0]}" ;
- else $y = $y = "{$z}<{$l}".Sanitizer::fixTagAttributes($y[0], $l).">{$y[1]}" ;
+ else {
+ $attributes = $this->unstripForHTML( $y[0] );
+ $y = "{$z}<{$l}".Sanitizer::fixTagAttributes($attributes, $l).">{$y[1]}" ;
+ }
$t[$k] .= $y ;
array_push ( $td , true ) ;
}
@@ -753,7 +755,11 @@ class Parser
$fname = 'Parser::internalParse';
wfProfileIn( $fname );
- $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'replaceVariables' ) );
+ # Remove <noinclude> tags and <includeonly> sections
+ $text = strtr( $text, array( '<noinclude>' => '', '</noinclude>' => '') );
+ $text = preg_replace( '/<includeonly>.*?<\/includeonly>/s', '', $text );
+
+ $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ) );
$text = $this->replaceVariables( $text, $args );
$text = preg_replace( '/(^|\n)-----*/', '\\1<hr />', $text );
@@ -769,7 +775,7 @@ class Parser
# replaceInternalLinks may sometimes leave behind
# absolute URLs, which have to be masked to hide them from replaceExternalLinks
- $text = str_replace("http-noparse://","http://",$text);
+ $text = str_replace($this->mUniqPrefix."NOPARSE", "", $text);
$text = $this->doMagicLinks( $text );
$text = $this->doTableStuff( $text );
@@ -1225,7 +1231,6 @@ class Parser
if ( $useLinkPrefixExtension ) {
if ( preg_match( $e2, $s, $m ) ) {
$first_prefix = $m[2];
- $s = $m[1];
} else {
$first_prefix = false;
}
@@ -1308,7 +1313,7 @@ class Parser
$link = substr($link, 1);
}
- $nt =& Title::newFromText( $this->unstripNoWiki($link, $this->mStripState) );
+ $nt = Title::newFromText( $this->unstripNoWiki($link, $this->mStripState) );
if( !$nt ) {
$s .= $prefix . '[[' . $line;
continue;
@@ -1329,7 +1334,8 @@ class Parser
$found = false;
while (isset ($a[$k+1]) ) {
#look at the next 'line' to see if we can close it there
- $next_line = array_shift(array_splice( $a, $k + 1, 1) );
+ $spliced = array_splice( $a, $k + 1, 1 );
+ $next_line = array_shift( $spliced );
if( preg_match("/^(.*?]].*?)]](.*)$/sD", $next_line, $m) ) {
# the first ]] closes the inner link, the second the image
$found = true;
@@ -1385,7 +1391,7 @@ class Parser
$text = $this->replaceInternalLinks($text);
# cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them
- $s .= $prefix . str_replace('http://', 'http-noparse://', $this->makeImage( $nt, $text ) ) . $trail;
+ $s .= $prefix . preg_replace( "/\b($wgUrlProtocols)/", "{$this->mUniqPrefix}NOPARSE$1", $this->makeImage( $nt, $text) ) . $trail;
$wgLinkCache->addImageLinkObj( $nt );
wfProfileOut( "$fname-image" );
@@ -1437,7 +1443,9 @@ class Parser
# Special and Media are pseudo-namespaces; no pages actually exist in them
if( $ns == NS_MEDIA ) {
- $s .= $prefix . $sk->makeMediaLinkObj( $nt, $text, true ) . $trail;
+ $link = $sk->makeMediaLinkObj( $nt, $text );
+ # Cloak with NOPARSE to avoid replacement in replaceExternalLinks
+ $s .= $prefix . str_replace( 'http://', "http{$this->mUniqPrefix}NOPARSE://", $link ) . $trail;
$wgLinkCache->addImageLinkObj( $nt );
continue;
} elseif( $ns == NS_SPECIAL ) {
@@ -1743,12 +1751,11 @@ class Parser
if( 0 == $prefixLength ) {
wfProfileIn( "$fname-paragraph" );
# No prefix (not in list)--go to paragraph mode
- $uniq_prefix = UNIQ_PREFIX;
// XXX: use a stack for nestable elements like span, table and div
$openmatch = preg_match('/(<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
$closematch = preg_match(
'/(<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'.
- '<td|<th|<div|<\\/div|<hr|<\\/pre|<\\/p|'.$uniq_prefix.'-pre|<\\/li|<\\/ul)/iS', $t );
+ '<td|<th|<div|<\\/div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul)/iS', $t );
if ( $openmatch or $closematch ) {
$paragraphStack = false;
$output .= $this->closeParagraph();
@@ -2279,6 +2286,10 @@ class Parser
$this->mTemplatePath[$part1] = 1;
if( $this->mOutputType == OT_HTML ) {
+ # Remove <noinclude> sections and <includeonly> tags
+ $text = preg_replace( '/<noinclude>.*?<\/noinclude>/s', '', $text );
+ $text = strtr( $text, array( '<includeonly>' => '' , '</includeonly>' => '' ) );
+ # Strip <nowiki>, <pre>, etc.
$text = $this->strip( $text, $this->mStripState );
$text = Sanitizer::removeHTMLtags( $text, array( &$this, 'replaceVariables' ), $assocArgs );
}
@@ -3289,6 +3300,34 @@ class Parser
$sk =& $this->mOptions->getSkin();
return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $width, $height, $framed, $thumb, $manual_thumb );
}
+
+ /**
+ * Set a flag in the output object indicating that the content is dynamic and
+ * shouldn't be cached.
+ */
+ 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.
+ * @param string $text
+ * @param array $args
+ * @return string
+ * @access private
+ */
+ function attributeStripCallback( &$text, $args ) {
+ $text = $this->replaceVariables( $text, $args );
+ $text = $this->unstripForHTML( $text );
+ return $text;
+ }
+
+ function unstripForHTML( $text ) {
+ $text = $this->unstrip( $text, $this->mStripState );
+ $text = $this->unstripNoWiki( $text, $this->mStripState );
+ return $text;
+ }
}
/**
diff --git a/includes/Profiling.php b/includes/Profiling.php
index 770f39fedd3b..2fe5adab3b75 100755
--- a/includes/Profiling.php
+++ b/includes/Profiling.php
@@ -245,10 +245,12 @@ class Profiler {
$subcalls = $this->calltreeCount($this->mStack, $index);
if (!preg_match('/^-overhead/', $fname)) {
- # Adjust for profiling overhead
- $elapsed -= $overheadInternal;
- $elapsed -= ($subcalls * $overheadTotal);
- $memory -= ($subcalls * $overheadMemory);
+ # Adjust for profiling overhead (except special values with elapsed=0
+ if ( $elapsed ) {
+ $elapsed -= $overheadInternal;
+ $elapsed -= ($subcalls * $overheadTotal);
+ $memory -= ($subcalls * $overheadMemory);
+ }
}
if (!array_key_exists($fname, $this->mCollated)) {
diff --git a/includes/QueryPage.php b/includes/QueryPage.php
index 8c6e110364dd..6ed0de439dcf 100644
--- a/includes/QueryPage.php
+++ b/includes/QueryPage.php
@@ -29,6 +29,7 @@ $wgQueryPages = array(
array( 'UncategorizedPagesPage', 'Uncategorizedpages'),
array( 'UnusedimagesPage', 'Unusedimages' ),
array( 'WantedPagesPage', 'Wantedpages' ),
+ array( 'MostlinkedPage', 'Mostlinked' ),
);
global $wgDisableCounters;
diff --git a/includes/Sanitizer.php b/includes/Sanitizer.php
index b9b3b50212ac..3816b9de03c7 100644
--- a/includes/Sanitizer.php
+++ b/includes/Sanitizer.php
@@ -554,11 +554,22 @@ class Sanitizer {
# Strip javascript "expression" from stylesheets.
# http://msdn.microsoft.com/workshop/author/dhtml/overview/recalc.asp
- if( $attribute == 'style' && preg_match(
- '/(expression|tps*:\/\/|url\\s*\().*/is',
- Sanitizer::decodeCharReferences( $value ) ) ) {
- # haxx0r
- continue;
+ 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 );
+ $stripped = str_replace( '\\', '', $stripped );
+ if( preg_match( '/(expression|tps*:\/\/|url\\s*\().*/is',
+ $stripped ) ) {
+ # haxx0r
+ continue;
+ }
}
# Templates and links may be expanded in later parsing,
@@ -571,9 +582,12 @@ class Sanitizer {
'RFC' => '&#82;FC',
'PMID' => '&#80;MID',
) );
- $value = preg_replace(
- '/(' . $wgUrlProtocols . '):/',
- '\\1&#58;', $value );
+
+ # Stupid hack
+ $value = preg_replace_callback(
+ '/(' . $wgUrlProtocols . ')/',
+ array( 'Sanitizer', 'armorLinksCallback' ),
+ $value );
// If this attribute was previously set, override it.
// Output should only have one attribute of each name.
@@ -587,6 +601,16 @@ class Sanitizer {
}
/**
+ * Regex replace callback for armoring links against further processing.
+ * @param array $matches
+ * @return string
+ * @access private
+ */
+ function armorLinksCallback( $matches ) {
+ return str_replace( ':', '&#58;', $matches[1] );
+ }
+
+ /**
* Return an associative array of attribute names and values from
* a partial tag string. Attribute names are forces to lowercase,
* character references are decoded to UTF-8 text.
diff --git a/includes/SearchMySQL.php b/includes/SearchMySQL.php
index 304c714050e3..bf90fdb721e0 100644
--- a/includes/SearchMySQL.php
+++ b/includes/SearchMySQL.php
@@ -61,9 +61,9 @@ class SearchMySQL extends SearchEngine {
*/
function queryRedirect() {
if( $this->showRedirects ) {
- return 'AND cur_is_redirect=0';
- } else {
return '';
+ } else {
+ return 'AND page_is_redirect=0';
}
}
diff --git a/includes/SearchMySQL4.php b/includes/SearchMySQL4.php
index 76025c4c6a6b..256579f1c283 100644
--- a/includes/SearchMySQL4.php
+++ b/includes/SearchMySQL4.php
@@ -64,7 +64,7 @@ class SearchMySQL4 extends SearchMySQL {
wfDebug( "Would search with '$searchon'\n" );
wfDebug( "Match with /\b" . implode( '\b|\b', $this->searchTerms ) . "\b/\n" );
} else {
- wfDebug( "Can't understand search query '{$this->filteredText}'\n" );
+ wfDebug( "Can't understand search query '{$filteredText}'\n" );
}
$searchon = $this->db->strencode( $searchon );
diff --git a/includes/Setup.php b/includes/Setup.php
index 1a580c163d8b..1904c3af3055 100644
--- a/includes/Setup.php
+++ b/includes/Setup.php
@@ -152,7 +152,7 @@ wfProfileIn( $fname.'-language1' );
require_once( "$IP/languages/Language.php" );
-function setupLangObj(&$langclass) {
+function setupLangObj($langclass) {
global $IP;
if( ! class_exists( $langclass ) ) {
@@ -206,7 +206,11 @@ if( $wgCommandLineMode ) {
# Prevent loading User settings from the DB.
$wgUser->setLoaded( true );
} else {
- $wgUser = User::loadFromSession();
+ $wgUser = null;
+ wfRunHooks('AutoAuthenticate',array(&$wgUser));
+ if ($wgUser === null) {
+ $wgUser = User::loadFromSession();
+ }
}
wfProfileOut( $fname.'-User' );
@@ -217,7 +221,7 @@ $wgLanguageCode = $wgRequest->getText('uselang', '');
if ($wgLanguageCode == '')
$wgLanguageCode = $wgUser->getOption('language');
# Validate $wgLanguageCode, which will soon be sent to an eval()
-if( empty( $wgLanguageCode ) || preg_match( '/^[^a-z-]*$/', $wgLanguageCode ) ) {
+if( empty( $wgLanguageCode ) || !preg_match( '/^[a-z]+(-[a-z]+)?$/', $wgLanguageCode ) ) {
$wgLanguageCode = $wgContLanguageCode;
}
diff --git a/includes/Skin.php b/includes/Skin.php
index dc1fa4a6bcc4..a84b3f3c6962 100644
--- a/includes/Skin.php
+++ b/includes/Skin.php
@@ -436,22 +436,30 @@ END;
# get a big array of the parents tree
$parenttree = $wgTitle->getParentCategoryTree();
-
# Skin object passed by reference cause it can not be
- # accessed under the method subfunction walkThrough.
- $s .= Skin::drawCategoryBrowser($parenttree, $this);
+ # accessed under the method subfunction drawCategoryBrowser
+ $tempout = explode("\n", Skin::drawCategoryBrowser($parenttree, $this) );
+ # Clean out bogus first entry and sort them
+ unset($tempout[0]);
+ asort($tempout);
+ # Output one per line
+ $s .= implode("<br />\n", $tempout);
}
return $s;
}
- # Render the array as a serie of links
- function drawCategoryBrowser ($tree, &$skin) {
+ /** Render the array as a serie of links.
+ * @param array $tree Categories tree returned by Title::getParentCategoryTree
+ * @param object &skin Skin passed by reference
+ * @return string separated by &gt;, terminate with "\n"
+ */
+ function drawCategoryBrowser($tree, &$skin) {
$return = '';
foreach ($tree as $element => $parent) {
if (empty($parent)) {
# element start a new list
- $return .= '<br />';
+ $return .= "\n";
} else {
# grab the others elements
$return .= Skin::drawCategoryBrowser($parent, $skin) . ' &gt; ';
@@ -555,7 +563,7 @@ END;
return wfMsg( 'thisisdeleted',
$this->makeKnownLink(
$wgContLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
- wfMsg( 'restorelink', $n ) ) );
+ wfMsg( 'restorelink' . ($n == 1 ? '1' : ''), $n ) ) );
}
return '';
}
@@ -1316,8 +1324,12 @@ END;
$link = wfMsgForContent( $line[0] );
if ($link == '-')
continue;
+ if (wfNoMsg($line[1], $text = wfMsg($line[1])))
+ $text = $line[1];
+ if (wfNoMsg($line[0], $link))
+ $link = $line[0];
$bar[$heading][] = array(
- 'text' => wfMsg( $line[1] ),
+ 'text' => $text,
'href' => $this->makeInternalOrExternalUrl( $link ),
'id' => 'n-' . strtr($line[1], ' ', '-'),
);
diff --git a/includes/SkinTemplate.php b/includes/SkinTemplate.php
index 0cd2963658cf..752ea26d4b0c 100644
--- a/includes/SkinTemplate.php
+++ b/includes/SkinTemplate.php
@@ -225,6 +225,7 @@ class SkinTemplate extends Skin {
$tpl->setRef( 'jsmimetype', $wgJsMimeType );
$tpl->setRef( 'charset', $wgOutputEncoding );
$tpl->set( 'headlinks', $out->getHeadLinks() );
+ $tpl->set('headscripts', $out->getScript() );
$tpl->setRef( 'wgScript', $wgScript );
$tpl->setRef( 'skinname', $this->skinname );
$tpl->setRef( 'stylename', $this->stylename );
@@ -362,10 +363,15 @@ class SkinTemplate extends Skin {
if ( !$wgHideInterlanguageLinks ) {
foreach( $wgOut->getLanguageLinks() as $l ) {
+ $tmp = explode( ':', $l, 2 );
+ $class = 'interwiki-' . $tmp[0];
+ unset($tmp);
$nt = Title::newFromText( $l );
- $language_urls[] = array('href' => $nt->getFullURL(),
- 'text' => ($wgContLang->getLanguageName( $nt->getInterwiki()) != ''?$wgContLang->getLanguageName( $nt->getInterwiki()) : $l),
- 'class' => $wgContLang->isRTL() ? 'rtl' : 'ltr');
+ $language_urls[] = array(
+ 'href' => $nt->getFullURL(),
+ 'text' => ($wgContLang->getLanguageName( $nt->getInterwiki()) != ''?$wgContLang->getLanguageName( $nt->getInterwiki()) : $l),
+ 'class' => $class
+ );
}
}
if(count($language_urls)) {
@@ -615,14 +621,12 @@ class SkinTemplate extends Skin {
'href' => $this->mTitle->getLocalUrl( 'action=delete' )
);
}
- if ( $wgUser->isLoggedIn() ) {
- if ( $this->mTitle->userCanMove()) {
- $content_actions['move'] = array(
- 'class' => ($this->mTitle->getDbKey() == 'Movepage' and $this->mTitle->getNamespace == NS_SPECIAL) ? 'selected' : false,
- 'text' => wfMsg('move'),
- 'href' => $this->makeSpecialUrl("Movepage/$this->thispage" )
- );
- }
+ if ( $this->mTitle->userCanMove()) {
+ $content_actions['move'] = array(
+ 'class' => ($this->mTitle->getDbKey() == 'Movepage' and $this->mTitle->getNamespace == NS_SPECIAL) ? 'selected' : false,
+ 'text' => wfMsg('move'),
+ 'href' => $this->makeSpecialUrl("Movepage/$this->thispage" )
+ );
}
} else {
//article doesn't exist or is deleted
@@ -638,7 +642,7 @@ class SkinTemplate extends Skin {
}
wfProfileOut( "$fname-live" );
- if( $wgUser->isLoggedIn() and $action != 'submit' ) {
+ if( $this->loggedin ) {
if( !$this->mTitle->userIsWatching()) {
$content_actions['watch'] = array(
'class' => ($action == 'watch' or $action == 'unwatch') ? 'selected' : false,
@@ -711,6 +715,8 @@ class SkinTemplate extends Skin {
}
}
+ wfRunHooks( 'SkinTemplateContentActions', array(&$content_actions) );
+
wfProfileOut( $fname );
return $content_actions;
}
diff --git a/includes/SpecialAllmessages.php b/includes/SpecialAllmessages.php
index 56e128f37a87..91975a8c891b 100644
--- a/includes/SpecialAllmessages.php
+++ b/includes/SpecialAllmessages.php
@@ -96,12 +96,13 @@ function makeHTMLText( $messages ) {
$mwnspace = $wgLang->getNsText( NS_MEDIAWIKI );
$mwtalk = $wgLang->getNsText( NS_MEDIAWIKI_TALK );
$txt = "
-
- <table border='1' cellspacing='0' width='100%'>
- <tr bgcolor='#b2b2ff'>
- <th>" . wfMsg('allmessagesname') . "</th>
- <th>" . wfMsg('allmessagesdefault') . "</th>
- <th>" . wfMsg('allmessagescurrent') . "</th>
+<table border='1' cellspacing='0' width='100%' id='allmessagestable'>
+ <tr >
+ <th rowspan='2'>" . wfMsgHtml('allmessagesname') . "</th>
+ <th>" . wfMsgHtml('allmessagesdefault') . "</th>
+ </tr>
+ <tr>
+ <th>" . wfMsgHtml('allmessagescurrent') . "</th>
</tr>";
wfProfileIn( "$fname-check" );
@@ -132,7 +133,7 @@ function makeHTMLText( $messages ) {
$titleObj =& Title::makeTitle( NS_MEDIAWIKI, $title );
$talkPage =& Title::makeTitle( NS_MEDIAWIKI_TALK, $title );
- $colorIt = ($m['statmsg'] == $m['msg']) ? " bgcolor=\"#f0f0ff\"" : " bgcolor=\"#ffe2e2\"";
+ $changed = ($m['statmsg'] != $m['msg']);
$message = htmlspecialchars( $m['statmsg'] );
$mw = htmlspecialchars( $m['msg'] );
@@ -149,15 +150,32 @@ function makeHTMLText( $messages ) {
$talkLink = $sk->makeBrokenLinkObj( $talkPage, htmlspecialchars( $talk ) );
}
- $txt .=
- "<tr$colorIt><td>
- $pageLink<br />
- $talkLink
+ if($changed) {
+
+ $txt .=
+ "<tr class='orig'>
+ <td rowspan='2'>
+ $pageLink<br />$talkLink
</td><td>
- $message
+$message
+ </td>
+ </tr><tr class='new'>
+ <td>
+$mw
+ </td>
+ </tr>";
+ } else {
+
+ $txt .=
+ "<tr class='def'>
+ <td>
+ $pageLink<br />$talkLink
</td><td>
- $mw
- </td></tr>";
+$mw
+ </td>
+ </tr>";
+
+ }
}
$txt .= "</table>";
wfProfileOut( "$fname-output" );
diff --git a/includes/SpecialAllpages.php b/includes/SpecialAllpages.php
index 26e7434abaed..5ba83c7e90b7 100644
--- a/includes/SpecialAllpages.php
+++ b/includes/SpecialAllpages.php
@@ -45,31 +45,22 @@ function indexNamespaceForm ( $namespace = NS_MAIN, $from = '' ) {
global $wgContLang, $wgScript;
$t = Title::makeTitle( NS_SPECIAL, "Allpages" );
- $namespaceselect = "<select name='namespace' id='nsselectbox'>";
- $arr = $wgContLang->getFormattedNamespaces();
- foreach ( $arr as $ns => $name ) {
- if ($ns < NS_MAIN)
- continue;
- $n = $ns == 0 ? wfMsg ( 'blanknamespace' ) : $name;
- $sel = $ns == $namespace ? ' selected="selected"' : '';
- $namespaceselect .= "<option value='$ns'$sel>$n</option>";
- }
- $namespaceselect .= '</select>';
+ $namespaceselect = HTMLnamespaceselector($namespace, null);
$frombox = "<input type='text' size='20' name='from' id='nsfrom' value=\""
. htmlspecialchars ( $from ) . '"/>';
- $submitbutton = '<input type="submit" value="' . wfMsg( 'allpagessubmit' ) . '" />';
+ $submitbutton = '<input type="submit" value="' . wfMsgHtml( 'allpagessubmit' ) . '" />';
- $out = "<div class='namespaceselector'><form method='get' action='{$wgScript}'>";
+ $out = "<div class='namespaceoptions'><form method='get' action='{$wgScript}'>";
$out .= '<input type="hidden" name="title" value="'.$t->getPrefixedText().'" />';
$out .= "
<table id='nsselect' class='allpages'>
<tr>
- <td align='right'>" . wfMsg('allpagesfrom') . "</td>
+ <td align='right'>" . wfMsgHtml('allpagesfrom') . "</td>
<td align='left'><label for='nsfrom'>$frombox</label></td>
</tr>
<tr>
- <td align='right'><label for='nsselectbox'>" . wfMsg('namespace') . "</label></td>
+ <td align='right'><label for='namespace'>" . wfMsgHtml('namespace') . "</label></td>
<td align='left'>
$namespaceselect $submitbutton
</td>
diff --git a/includes/SpecialBlockip.php b/includes/SpecialBlockip.php
index 8d7c3bb61713..28ef283d581a 100644
--- a/includes/SpecialBlockip.php
+++ b/includes/SpecialBlockip.php
@@ -67,7 +67,7 @@ class IPBlockForm {
$action = $titleObj->escapeLocalURL( "action=submit" );
if ( "" != $err ) {
- $wgOut->setSubtitle( wfMsg( 'formerror' ) );
+ $wgOut->setSubtitle( wfMsgHtml( 'formerror' ) );
$wgOut->addHTML( "<p class='error'>{$err}</p>\n" );
}
diff --git a/includes/SpecialBrokenRedirects.php b/includes/SpecialBrokenRedirects.php
index 41011209dab1..4c3a8ed0c12f 100644
--- a/includes/SpecialBrokenRedirects.php
+++ b/includes/SpecialBrokenRedirects.php
@@ -38,7 +38,7 @@ class BrokenRedirectsPage extends PageQueryPage {
p1.page_title AS title,
pl_namespace,
pl_title
- FROM $pagelinks, $page AS p1
+ FROM ($pagelinks, $page AS p1)
LEFT JOIN $page AS p2
ON pl_namespace=p2.page_namespace AND pl_title=p2.page_title
WHERE p1.page_is_redirect=1
diff --git a/includes/SpecialContributions.php b/includes/SpecialContributions.php
index 35afe173eca5..ffbfe91c733c 100644
--- a/includes/SpecialContributions.php
+++ b/includes/SpecialContributions.php
@@ -169,7 +169,7 @@ function wfSpecialContributions( $par = null ) {
}
$nt =& Title::makeTitle(NS_USER, $nt->getDBkey());
- $limit = min($wgRequest->getInt('limit', 50), 500);
+ list( $limit, $offset) = wfCheckLimits();
$offset = $wgRequest->getVal('offset');
/* Offset must be an integral. */
if (!strlen($offset) || !preg_match("/^[0-9]+$/", $offset))
@@ -226,6 +226,8 @@ function wfSpecialContributions( $par = null ) {
$wgOut->setSubtitle( wfMsgHtml( 'contribsub', $ul ) );
+ wfRunHooks('SpecialContributionsBeforeMainOutput', $id );
+
$arr = $wgContLang->getFormattedNamespaces();
$nsform = "<form method='get' action=\"$wgScript\">\n";
$nsform .= wfElement("input", array(
@@ -245,19 +247,10 @@ function wfSpecialContributions( $par = null ) {
"type" => "hidden",
"value" => $target));
$nsform .= "<p>";
- $nsform .= htmlspecialchars(wfMsg('namespace')) . " <select name='namespace'>\n";
- foreach (array("" => wfMsg('contributionsall')) + $arr as $nsn => $name) {
- if ($nsn < 0)
- continue;
- $name = $nsn!==0 ? $name : wfMsg('blanknamespace');
- $nsform .= ("$nsn" == "$ns") ?
- wfElement("option",
- array("value" => $nsn, "selected" => "selected"),
- $name)
- :
- wfElement("option", array("value" => $nsn), $name);
- }
- $nsform .= "</select>\n";
+ $nsform .= wfMsgHtml('namespace');
+
+ $nsform .= HTMLnamespaceselector($ns, '');
+
$nsform .= wfElement("input", array(
"type" => "submit",
"value" => wfMsg('allpagessubmit')));
@@ -355,7 +348,7 @@ function ucListEdit( $sk, $row ) {
if( $row->rev_id == $row->page_latest ) {
$topmarktext .= '<strong>' . $messages['uctop'] . '</strong>';
if( !$row->page_is_new ) {
- $difftext .= $sk->makeKnownLinkObj( $page, '(' . $messages['diff'] . ')', 'diff=0' );
+ $difftext .= '(' . $sk->makeKnownLinkObj( $page, $messages['diff'], 'diff=0' ) . ')';
} else {
$difftext .= $messages['newarticle'];
}
@@ -373,7 +366,7 @@ function ucListEdit( $sk, $row ) {
if( $row->rev_deleted && !$wgUser->isAllowed( 'undelete' ) ) {
$difftext = '(' . $messages['diff'] . ')';
} else {
- $difftext = $sk->makeKnownLinkObj( $page, '(' . $messages['diff'].')', 'diff=prev&oldid='.$row->rev_id );
+ $difftext = '(' . $sk->makeKnownLinkObj( $page, $messages['diff'], 'diff=prev&oldid='.$row->rev_id ) . ')';
}
$histlink='('.$sk->makeKnownLinkObj( $page, $messages['hist'], 'action=history' ) . ')';
diff --git a/includes/SpecialImport.php b/includes/SpecialImport.php
index 07b2df54afa6..728f80c16774 100644
--- a/includes/SpecialImport.php
+++ b/includes/SpecialImport.php
@@ -128,6 +128,7 @@ class WikiRevision {
var $user_text = "";
var $text = "";
var $comment = "";
+ var $minor = false;
function setTitle( $text ) {
$this->title = Title::newFromText( $text );
@@ -154,6 +155,10 @@ class WikiRevision {
$this->comment = $text;
}
+ function setMinor( $minor ) {
+ $this->minor = (bool)$minor;
+ }
+
function getTitle() {
return $this->title;
}
@@ -173,6 +178,10 @@ class WikiRevision {
function getComment() {
return $this->comment;
}
+
+ function getMinor() {
+ return $this->minor;
+ }
function importOldRevision() {
$fname = "WikiImporter::importOldRevision";
@@ -188,6 +197,10 @@ class WikiRevision {
$userText = $this->getUser();
}
+ // avoid memory leak...?
+ global $wgLinkCache;
+ $wgLinkCache->clear();
+
$article = new Article( $this->title );
$pageId = $article->getId();
if( $pageId == 0 ) {
@@ -211,7 +224,7 @@ class WikiRevision {
'user' => $userId,
'user_text' => $userText,
'timestamp' => $this->timestamp,
- 'minor_edit' => 0
+ 'minor_edit' => $this->minor,
) );
$revId = $revision->insertOn( $dbw );
$article->updateIfNewerOn( $dbw, $revision );
@@ -239,6 +252,7 @@ class WikiImporter {
function throwXmlError( $err ) {
$this->debug( "FAILURE: $err" );
+ wfDebug( "WikiImporter XML error: $err\n" );
}
# --------------
@@ -253,14 +267,17 @@ class WikiImporter {
# 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_object( $parser, $this );
xml_set_element_handler( $parser, "in_start", "" );
+ $offset = 0; // for context extraction on error reporting
do {
$chunk = $this->mSource->readChunk();
if( !xml_parse( $parser, $chunk, $this->mSource->atEnd() ) ) {
- return new WikiXmlError( $parser );
+ wfDebug( "WikiImporter::doImport encountered XML parsing error\n" );
+ return new WikiXmlError( $parser, 'XML import parse failure', $chunk, $offset );
}
+ $offset += strlen( $chunk );
} while( $chunk !== false && !$this->mSource->atEnd() );
xml_parser_free( $parser );
@@ -380,6 +397,7 @@ class WikiImporter {
$this->debug( "in_siteinfo $name" );
switch( $name ) {
case "sitename":
+ case "base":
case "generator":
case "case":
case "namespaces":
@@ -466,6 +484,9 @@ class WikiImporter {
case "comment":
$this->workRevision->setComment( $this->appenddata );
break;
+ case "minor":
+ $this->workRevision->setMinor( true );
+ break;
default:
$this->debug( "Bad append: {$this->appendfield}" );
}
@@ -479,6 +500,7 @@ class WikiImporter {
case "id":
case "timestamp":
case "comment":
+ case "minor":
case "text":
$this->parenttag = "revision";
$this->appendfield = $name;
@@ -500,9 +522,8 @@ class WikiImporter {
}
xml_set_element_handler( $parser, "in_page", "out_page" );
- $out = call_user_func( $this->mRevisionCallback,
- &$this->workRevision,
- &$this );
+ $out = call_user_func_array( $this->mRevisionCallback,
+ array( &$this->workRevision, &$this ) );
if( !empty( $out ) ) {
global $wgOut;
$wgOut->addHTML( "<li>" . $out . "</li>\n" );
@@ -514,6 +535,7 @@ class WikiImporter {
switch( $name ) {
case "username":
case "ip":
+ case "id":
$this->parenttag = "contributor";
$this->appendfield = $name;
xml_set_element_handler( $parser, "in_nothing", "out_append" );
diff --git a/includes/SpecialIpblocklist.php b/includes/SpecialIpblocklist.php
index 492f78db26c9..609bda25631e 100644
--- a/includes/SpecialIpblocklist.php
+++ b/includes/SpecialIpblocklist.php
@@ -49,20 +49,20 @@ class IPUnblockForm {
function showForm( $err )
{
- global $wgOut, $wgUser, $wgLang;
+ global $wgOut, $wgUser, $wgLang, $wgSysopUserBans;
$wgOut->setPagetitle( wfMsg( "unblockip" ) );
$wgOut->addWikiText( wfMsg( "unblockiptext" ) );
- $ipa = wfMsg( "ipaddress" );
- $ipr = wfMsg( "ipbreason" );
- $ipus = htmlspecialchars( wfMsg( "ipusubmit" ) );
+ $ipa = wfMsgHtml( $wgSysopUserBans ? 'ipadressorusername' : 'ipaddress' );
+ $ipr = wfMsgHtml( 'ipbreason' );
+ $ipus = wfMsgHtml( 'ipusubmit' );
$titleObj = Title::makeTitle( NS_SPECIAL, "Ipblocklist" );
$action = $titleObj->escapeLocalURL( "action=submit" );
if ( "" != $err ) {
$wgOut->setSubtitle( wfMsg( "formerror" ) );
- $wgOut->addHTML( "<p class='error'>{$err}</p>\n" );
+ $wgOut->addWikitext( "<span class='error'>{$err}</span>\n" );
}
$token = htmlspecialchars( $wgUser->editToken() );
@@ -104,7 +104,7 @@ class IPUnblockForm {
} else {
$block->mAddress = $this->ip;
}
-
+
# Delete block (if it exists)
# We should probably check for errors rather than just declaring success
$block->delete();
@@ -127,7 +127,9 @@ class IPUnblockForm {
$wgOut->setSubtitle( $msg );
}
$wgOut->addHTML( "<ul>" );
- Block::enumBlocks( "wfAddRow", 0 );
+ // FIXME hack to solve #bug 1487
+ if(!Block::enumBlocks( "wfAddRow", 0 ))
+ $wgOut->addHTML( '<li>'.wfMsg( 'ipblocklistempty' ).'</li>' );
$wgOut->addHTML( "</ul>\n" );
}
}
@@ -148,9 +150,9 @@ function wfAddRow( $block, $tag ) {
$formattedTime = $wgLang->timeanddate( $block->mTimestamp, true );
if ( $block->mExpiry === "" ) {
- $formattedExpiry = "indefinite";
+ $formattedExpiry = wfMsgHtml('infiniteblock');
} else {
- $formattedExpiry = $wgLang->timeanddate( $block->mExpiry, true );
+ $formattedExpiry = wfMsgHtml('expiringblock', $wgLang->timeanddate( $block->mExpiry, true ) );
}
$line = wfMsg( "blocklistline", $formattedTime, $ulink, $addr, $formattedExpiry );
@@ -159,17 +161,12 @@ function wfAddRow( $block, $tag ) {
if ( !$block->mAuto ) {
$titleObj = Title::makeTitle( NS_SPECIAL, "Contributions" );
- $clink = "<a href=\"" . $titleObj->escapeLocalURL( "target={$block->mAddress}" ) . "\">" .
- wfMsg( "contribslink" ) . "</a>";
- $wgOut->addHTML( " ({$clink})" );
+ $wgOut->addHTML( ' (' . $sk->makeKnownLinkObj($titleObj, wfMsgHtml( 'contribslink' ), "target={$block->mAddress}") . ')' );
}
if ( $wgUser->isAllowed('block') ) {
$titleObj = Title::makeTitle( NS_SPECIAL, "Ipblocklist" );
- $ublink = "<a href=\"" .
- $titleObj->escapeLocalURL( "action=unblock&ip=" . urlencode( $addr ) ) . "\">" .
- wfMsg( "unblocklink" ) . "</a>";
- $wgOut->addHTML( " ({$ublink})" );
+ $wgOut->addHTML( ' (' . $sk->makeKnownLinkObj($titleObj, wfMsgHtml( 'unblocklink' ), 'action=unblock&ip=' . urlencode( $addr ) ) . ')' );
}
$wgOut->addHTML( $sk->commentBlock( $block->mReason ) );
$wgOut->addHTML( "</li>\n" );
diff --git a/includes/SpecialMostlinked.php b/includes/SpecialMostlinked.php
new file mode 100644
index 000000000000..008a2d4123be
--- /dev/null
+++ b/includes/SpecialMostlinked.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+require_once ( 'QueryPage.php' ) ;
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class MostlinkedPage extends QueryPage {
+
+ function getName() {
+ return 'Mostlinked';
+ }
+
+ function isExpensive() {
+ return true;
+ }
+ function isSyndicated() { return false; }
+
+ function getSQL() {
+ $dbr =& wfGetDB( DB_SLAVE );
+ extract( $dbr->tableNames( 'pagelinks', 'page' ) );
+ return
+ "SELECT 'Mostlinked' AS type,
+ 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
+ GROUP BY pl_namespace,pl_title
+ HAVING COUNT(*) > 1";
+ }
+
+ function formatResult( $skin, $result ) {
+ global $wgContLang;
+
+ $nt = Title::makeTitle( $result->namespace, $result->title );
+ $text = $wgContLang->convert( $nt->getPrefixedText() );
+ if ( is_null( $result->page_namespace ) )
+ $plink = $skin->makeBrokenLink( $nt->getPrefixedText(), $text );
+ else
+ $plink = $skin->makeKnownLink( $nt->getPrefixedText(), $text );
+
+ $nl = wfMsg( "nlinks", $result->value );
+ $nlink = $skin->makeKnownLink( $wgContLang->specialPage( "Whatlinkshere" ), $nl, "target=" . $nt->getPrefixedURL() );
+
+ return "{$plink} ({$nlink})";
+ }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialMostlinked() {
+ list( $limit, $offset ) = wfCheckLimits();
+
+ $wpp = new MostlinkedPage();
+
+ $wpp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialMovepage.php b/includes/SpecialMovepage.php
index 70c8a4feda13..b07274079b48 100644
--- a/includes/SpecialMovepage.php
+++ b/includes/SpecialMovepage.php
@@ -17,7 +17,7 @@ function wfSpecialMovepage( $par = null ) {
global $wgUser, $wgOut, $wgRequest, $action, $wgOnlySysopMayMove;
# check rights. We don't want newbies to move pages to prevents possible attack
- if ( $wgUser->isAnon() or $wgUser->isBlocked() or ($wgOnlySysopMayMove and $wgUser->isNewbie())) {
+ if ( !$wgUser->isAllowed( 'move' ) or $wgUser->isBlocked() or ($wgOnlySysopMayMove and $wgUser->isNewbie())) {
$wgOut->errorpage( "movenologin", "movenologintext" );
return;
}
@@ -138,9 +138,9 @@ class MovePageForm {
</td>
</tr>
<tr>
- <td align='right'>{$movereason}:</td>
- <td align='left'>
- <input type='text' size='40' name=\"wpReason\" value=\"{$encReason}\" />
+ <td align='right' valign='top'><br />{$movereason}:</td>
+ <td align='left' valign='top'><br />
+ <textarea cols='60' rows='2' name='wpReason' id='wpReason'>{$encReason}</textarea>
</td>
</tr>" );
@@ -148,9 +148,9 @@ class MovePageForm {
$wgOut->addHTML( "
<tr>
<td align='right'>
- <input type='checkbox' name=\"wpMovetalk\"{$moveTalkChecked} value=\"1\" />
+ <input type='checkbox' id=\"wpMovetalk\" name=\"wpMovetalk\"{$moveTalkChecked} value=\"1\" />
</td>
- <td>{$movetalk}</td>
+ <td><label for=\"wpMovetalk\">{$movetalk}</label></td>
</tr>" );
}
$wgOut->addHTML( "
diff --git a/includes/SpecialNewpages.php b/includes/SpecialNewpages.php
index feb4c54105e1..3b24cc2a1df2 100644
--- a/includes/SpecialNewpages.php
+++ b/includes/SpecialNewpages.php
@@ -62,11 +62,13 @@ class NewPagesPage extends QueryPage {
$length = wfMsg( 'nbytes', $wgLang->formatNum( $result->length ) );
if ( $u == 0 ) { # not by a logged-in user
- $ul = $ut;
- }
- else {
- $ul = $skin->makeLink( $wgContLang->getNsText(NS_USER) . ":{$ut}", $ut );
+ $userPage = Title::makeTitle( NS_SPECIAL, 'Contributions' );
+ $linkParams = 'target=' . urlencode( $ut );
+ } else {
+ $userPage = Title::makeTitle( NS_USER, $ut );
+ $linkParams = '';
}
+ $ul = $skin->makeLinkObj( $userPage, htmlspecialchars( $ut ), $linkParams );
$d = $wgLang->timeanddate( $result->timestamp, true );
diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php
index 869ccafe1af2..4fbd7b9f5b1d 100644
--- a/includes/SpecialPage.php
+++ b/includes/SpecialPage.php
@@ -17,11 +17,6 @@
/**
- *
- */
-global $wgSpecialPages, $wgUser;
-
-/**
* @access private
*/
$wgSpecialPages = array(
@@ -47,6 +42,7 @@ $wgSpecialPages = array(
'Unusedcategories' => new SpecialPage( 'Unusedcategories' ),
'Unusedimages' => new SpecialPage( 'Unusedimages' ),
'Wantedpages' => new SpecialPage( 'Wantedpages' ),
+ 'Mostlinked' => new SpecialPage( 'Mostlinked' ),
'Shortpages' => new SpecialPage( 'Shortpages' ),
'Longpages' => new SpecialPage( 'Longpages' ),
'Newpages' => new IncludableSpecialPage( 'Newpages' ),
@@ -75,21 +71,17 @@ $wgSpecialPages = array(
'Userrights' => new SpecialPage( 'Userrights', 'userrights' ),
);
-global $wgUseValidation ;
if ( $wgUseValidation )
$wgSpecialPages['Validate'] = new SpecialPage( 'Validate' );
-global $wgDisableCounters;
if( !$wgDisableCounters ) {
$wgSpecialPages['Popularpages'] = new SpecialPage( 'Popularpages' );
}
-global $wgDisableInternalSearch;
if( !$wgDisableInternalSearch ) {
$wgSpecialPages['Search'] = new UnlistedSpecialPage( 'Search' );
}
-global $wgEmailAuthentication;
if( $wgEmailAuthentication ) {
$wgSpecialPages['Confirmemail'] = new UnlistedSpecialPage( 'Confirmemail' );
}
@@ -165,7 +157,7 @@ class SpecialPage
* @static
* @param string $name
*/
- function &getPage( $name ) {
+ function getPage( $name ) {
global $wgSpecialPages;
if ( array_key_exists( $name, $wgSpecialPages ) ) {
return $wgSpecialPages[$name];
@@ -179,7 +171,7 @@ class SpecialPage
* @param string $name
* @return mixed Title object if the redirect exists, otherwise NULL
*/
- function &getRedirect( $name ) {
+ function getRedirect( $name ) {
global $wgUser;
switch ( $name ) {
case 'Mypage':
@@ -240,12 +232,12 @@ class SpecialPage
$par = $bits[1];
}
- $page =& SpecialPage::getPage( $name );
+ $page = SpecialPage::getPage( $name );
if ( is_null( $page ) ) {
if ( $including ) {
return false;
} else {
- $redir =& SpecialPage::getRedirect( $name );
+ $redir = SpecialPage::getRedirect( $name );
if ( isset( $redir ) ) {
if ( isset( $par ) )
$wgOut->redirect( $redir->getFullURL() . '/' . $par );
diff --git a/includes/SpecialPreferences.php b/includes/SpecialPreferences.php
index 6e99b3f03fe6..bdf9e1e45c98 100644
--- a/includes/SpecialPreferences.php
+++ b/includes/SpecialPreferences.php
@@ -66,6 +66,7 @@ class PreferencesForm {
$this->mAction = $request->getVal( 'action' );
$this->mReset = $request->getCheck( 'wpReset' );
$this->mPosted = $request->wasPosted();
+ $this->mSuccess = $request->getCheck( 'success' );
$this->mSaveprefs = $request->getCheck( 'wpSaveprefs' ) &&
$this->mPosted &&
@@ -113,7 +114,7 @@ class PreferencesForm {
}
if ( $this->mReset ) {
$this->resetPrefs();
- $this->mainPrefsForm( wfMsg( 'prefsreset' ) );
+ $this->mainPrefsForm( 'reset', wfMsg( 'prefsreset' ) );
} else if ( $this->mSaveprefs ) {
$this->savePreferences();
} else {
@@ -197,26 +198,33 @@ class PreferencesForm {
if ( '' != $this->mNewpass ) {
if ( $this->mNewpass != $this->mRetypePass ) {
- $this->mainPrefsForm( wfMsg( 'badretype' ) );
+ $this->mainPrefsForm( 'error', wfMsg( 'badretype' ) );
return;
}
if ( strlen( $this->mNewpass ) < $wgMinimalPasswordLength ) {
- $this->mainPrefsForm( wfMsg( 'passwordtooshort', $wgMinimalPasswordLength ) );
+ $this->mainPrefsForm( 'error', wfMsg( 'passwordtooshort', $wgMinimalPasswordLength ) );
return;
}
if (!$wgUser->checkPassword( $this->mOldpass )) {
- $this->mainPrefsForm( wfMsg( 'wrongpassword' ) );
+ $this->mainPrefsForm( 'error', wfMsg( 'wrongpassword' ) );
return;
}
if (!$wgAuth->setPassword( $wgUser, $this->mNewpass )) {
- $this->mainPrefsForm( wfMsg( 'externaldberror' ) );
+ $this->mainPrefsForm( 'error', wfMsg( 'externaldberror' ) );
return;
}
$wgUser->setPassword( $this->mNewpass );
}
$wgUser->setRealName( $this->mRealName );
+
+ if( $wgUser->getOption( 'language' ) !== $this->mUserLanguage ) {
+ $needRedirect = true;
+ } else {
+ $needRedirect = false;
+ }
+
$wgUser->setOption( 'language', $this->mUserLanguage );
$wgUser->setOption( 'variant', $this->mUserVariant );
$wgUser->setOption( 'nickname', $this->mNick );
@@ -226,7 +234,7 @@ class PreferencesForm {
if( $wgUseTeX ) {
$wgUser->setOption( 'math', $this->mMath );
}
- $wgUser->setOption( 'date', $this->validateDate( $this->mDate, 0, 10 ) );
+ $wgUser->setOption( 'date', $this->validateDate( $this->mDate, 0, 20 ) );
$wgUser->setOption( 'searchlimit', $this->validateIntOrNull( $this->mSearch ) );
$wgUser->setOption( 'contextlines', $this->validateIntOrNull( $this->mSearchLines ) );
$wgUser->setOption( 'contextchars', $this->validateIntOrNull( $this->mSearchChars ) );
@@ -259,7 +267,7 @@ class PreferencesForm {
$wgUser->setCookies();
$wgUser->saveSettings();
- $error = wfMsg( 'savedprefs' );
+ $error = false;
if( $wgEnableEmail ) {
$newadr = $this->mUserEmail;
$oldadr = $wgUser->getEmail();
@@ -274,7 +282,7 @@ class PreferencesForm {
# User can come back through the confirmation URL to re-enable email.
$result = $wgUser->sendConfirmationMail();
if( WikiError::isError( $result ) ) {
- $error = wfMsg( 'mailerror', $result->getMessage() );
+ $error = wfMsg( 'mailerror', htmlspecialchars( $result->getMessage() ) );
} else {
$error = wfMsg( 'eauthentsent', $wgUser->getName() );
}
@@ -289,9 +297,15 @@ class PreferencesForm {
}
}
+ if( $needRedirect && $error === false ) {
+ $title =& Title::makeTitle( NS_SPECIAL, "Preferences" );
+ $wgOut->redirect($title->getFullURL('success'));
+ return;
+ }
+
$wgOut->setParserOptions( ParserOptions::newFromUser( $wgUser ) );
$po = ParserOptions::newFromUser( $wgUser );
- $this->mainPrefsForm( $error );
+ $this->mainPrefsForm( $error === false ? 'success' : 'error', $error);
}
/**
@@ -378,7 +392,7 @@ class PreferencesForm {
$checked = $wgUser->getOption( $tname ) == 1 ? ' checked="checked"' : '';
$trailer = $trailer ? $trailer : '';
return "<div class='toggle'><input type='checkbox' value='1' id=\"$tname\" name=\"wpOp$tname\"$checked />" .
- " <span class='toggletext'><label for=\"$tname\">$ttext</label>$trailer</span></div>";
+ " <span class='toggletext'><label for=\"$tname\">$ttext</label>$trailer</span></div>\n";
}
function getToggles( $items ) {
@@ -404,7 +418,7 @@ class PreferencesForm {
/**
* @access private
*/
- function mainPrefsForm( $err ) {
+ function mainPrefsForm( $status , $message = '' ) {
global $wgUser, $wgOut, $wgLang, $wgContLang, $wgValidSkinNames;
global $wgAllowRealName, $wgImageLimits, $wgThumbLimits;
global $wgDisableLangConversion;
@@ -417,8 +431,12 @@ class PreferencesForm {
$wgOut->setArticleRelated( false );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
- if ( '' != $err ) {
- $wgOut->addHTML( "<p class='error'>" . htmlspecialchars( $err ) . "</p>\n" );
+ if ( $this->mSuccess || 'success' == $status ) {
+ $wgOut->addWikitext( '<span class="preferences-save-success">'. wfMsg( 'savedprefs' ) . "</span>\n----" );
+ } else if ( 'error' == $status ) {
+ $wgOut->addWikitext( "<span class='error'>" . $message . "</span>\n----" );
+ } else if ( '' != $status ) {
+ $wgOut->addWikitext( $message . "\n----" );
}
$uname = $wgUser->getName();
$uid = $wgUser->getID();
@@ -661,7 +679,7 @@ class PreferencesForm {
$imageLimitOptions = null;
foreach ( $wgImageLimits as $index => $limits ) {
$selected = ($index == $this->mImageSize) ? 'selected="selected"' : '';
- $imageLimitOptions .= "<option value=\"{$index}\" {$selected}>{$limits[0]}x{$limits[1]}</option>\n";
+ $imageLimitOptions .= "<option value=\"{$index}\" {$selected}>{$limits[0]}×{$limits[1]}". wfMsgHtml('unit-pixel') ."</option>\n";
}
$imageThumbOptions = null;
@@ -669,7 +687,7 @@ class PreferencesForm {
<div><label>" . wfMsg('thumbsize') . "<select name=\"wpThumbSize\">");
foreach ( $wgThumbLimits as $index => $size ) {
$selected = ($index == $this->mThumbSize) ? 'selected="selected"' : '';
- $imageThumbOptions .= "<option value=\"{$index}\" {$selected}>{$size}px</option>\n";
+ $imageThumbOptions .= "<option value=\"{$index}\" {$selected}>{$size}". wfMsgHtml('unit-pixel') ."</option>\n";
}
$wgOut->addHTML( "{$imageThumbOptions}</select></label></div></fieldset>\n\n");
@@ -754,14 +772,14 @@ class PreferencesForm {
#
$wgOut->addHTML('<fieldset><legend>' . wfMsg('prefs-misc') . '</legend>');
- $msgUnderline = htmlspecialchars(wfMsg("tog-underline"));
- $msgUnderlinenever = htmlspecialchars(wfMsg("underline-never"));
- $msgUnderlinealways = htmlspecialchars(wfMsg("underline-always"));
- $msgUnderlinedefault = htmlspecialchars(wfMsg("underline-default"));
- $uopt = $wgUser->getOption("underline");
- $s0 = $uopt == 0 ? " selected=\"selected\"" : "";
- $s1 = $uopt == 1 ? " selected=\"selected\"" : "";
- $s2 = $uopt == 2 ? " selected=\"selected\"" : "";
+ $msgUnderline = htmlspecialchars(wfMsg('tog-underline'));
+ $msgUnderlinenever = htmlspecialchars(wfMsg('underline-never'));
+ $msgUnderlinealways = htmlspecialchars(wfMsg('underline-always'));
+ $msgUnderlinedefault = htmlspecialchars(wfMsg('underline-default'));
+ $uopt = $wgUser->getOption('underline');
+ $s0 = $uopt == 0 ? ' selected="selected"' : '';
+ $s1 = $uopt == 1 ? ' selected="selected"' : '';
+ $s2 = $uopt == 2 ? ' selected="selected"' : '';
$wgOut->addHTML("
<div class='toggle'><label>$msgUnderline
<select name=\"wpOpunderline\">
@@ -769,7 +787,8 @@ class PreferencesForm {
<option value=\"1\"$s1>$msgUnderlinealways</option>
<option value=\"2\"$s2>$msgUnderlinedefault</option>
</select>
-</label></div>
+</label>
+</div>
");
foreach ( $togs as $tname ) {
if( !array_key_exists( $tname, $this->mUsedToggles ) ) {
diff --git a/includes/SpecialRandompage.php b/includes/SpecialRandompage.php
index 59836c9fedfe..82d580cb6a6b 100644
--- a/includes/SpecialRandompage.php
+++ b/includes/SpecialRandompage.php
@@ -51,7 +51,7 @@ function wfSpecialRandompage( $par = NS_MAIN ) {
}
if( is_null( $title ) ) {
# That's not supposed to happen :)
- $title =& Title::newFromText( wfMsg( 'mainpage' ) );
+ $title = Title::newFromText( wfMsg( 'mainpage' ) );
}
$wgOut->reportTime(); # for logfile
$wgOut->redirect( $title->getFullUrl() );
diff --git a/includes/SpecialRecentchanges.php b/includes/SpecialRecentchanges.php
index 8ad4899d7e4c..75bcda521b46 100644
--- a/includes/SpecialRecentchanges.php
+++ b/includes/SpecialRecentchanges.php
@@ -131,14 +131,15 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
$hidem .= $hidebots ? ' AND rc_bot=0' : '';
$hidem .= $hideliu ? ' AND rc_user=0' : '';
$hidem .= $hidepatrolled ? ' AND rc_patrolled=0' : '';
- $hidem .= is_null( $namespace ) ? '' : ' AND rc_namespace' . ($invert ? '!=' : '=') . $namespace;
+ $hidem .= is_null( $namespace ) ? '' : ' AND rc_namespace' . ($invert ? '!=' : '=') . $namespace;
// This is the big thing!
$uid = $wgUser->getID();
+ $notifts = ($wgShowUpdatedMarker?",wl_notificationtimestamp":"");
// Perform query
- $sql2 = "SELECT *" . ($uid ? ",wl_user,wl_notificationtimestamp" : "") . " FROM $recentchanges " .
+ $sql2 = "SELECT $recentchanges.*" . ($uid ? ",wl_user".$notifts : "") . " FROM $recentchanges " .
($uid ? "LEFT OUTER JOIN $watchlist ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") .
"WHERE rc_timestamp > '{$cutoff}' {$hidem} " .
"ORDER BY rc_timestamp DESC LIMIT {$limit}";
@@ -176,15 +177,15 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
// Dump everything here
$nondefaults = array();
- appendToArrayIfNotDefault( 'days', $days, $defaults, $nondefaults);
- appendToArrayIfNotDefault( 'limit', $limit , $defaults, $nondefaults);
- appendToArrayIfNotDefault( 'hideminor', $hideminor, $defaults, $nondefaults);
- appendToArrayIfNotDefault( 'hidebots', $hidebots, $defaults, $nondefaults);
- appendToArrayIfNotDefault( 'hideliu', $hideliu, $defaults, $nondefaults);
- appendToArrayIfNotDefault( 'hidepatrolled', $hidepatrolled, $defaults, $nondefaults);
- appendToArrayIfNotDefault( 'from', $from, $defaults, $nondefaults);
- appendToArrayIfNotDefault( 'namespace', $namespace, $defaults, $nondefaults);
- appendToArrayIfNotDefault( 'invert', $invert, $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'days', $days, $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'limit', $limit , $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'hideminor', $hideminor, $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'hidebots', $hidebots, $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'hideliu', $hideliu, $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'hidepatrolled', $hidepatrolled, $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'from', $from, $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'namespace', $namespace, $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'invert', $invert, $defaults, $nondefaults);
// Add end of the texts
$wgOut->addHTML( '<div class="rcoptions">' . rcOptionsPanel( $defaults, $nondefaults ) );
@@ -458,34 +459,22 @@ function rcNamespaceForm ( $namespace, $invert, $nondefaults ) {
global $wgContLang, $wgScript;
$t = Title::makeTitle( NS_SPECIAL, 'Recentchanges' );
- $namespaceselect = "<select name='namespace' id='nsselectbox'>";
- $namespaceselect .= '<option value="" ' . ($namespace === '' ? ' selected="selected"' : '') . '>' . wfMsg( 'contributionsall' ) . '</option>';
- $arr = $wgContLang->getFormattedNamespaces();
- foreach ( $arr as $ns => $name ) {
- if( $ns < NS_MAIN )
- continue;
- $n = $ns === NS_MAIN ? wfMsg ( 'blanknamespace' ) : $name;
- $sel = $namespace === (string) $ns ? ' selected="selected"' : '';
- $namespaceselect .= "<option value='$ns'$sel>$n</option>";
- }
- $namespaceselect .= '</select>';
+ $namespaceselect = HTMLnamespaceselector($namespace, '');
+ $submitbutton = '<input type="submit" value="' . wfMsgHtml( 'allpagessubmit' ) . '" />';
+ $invertbox = "<input type='checkbox' name='invert' value='1' id='nsinvert'" . ( $invert ? ' checked="checked"' : '' ) . ' />';
+
+ $out = "<div class='namespacesettings'><form method='get' action='{$wgScript}'>\n";
- $out = '';
- $out .= "<div class='namespaceselector'><form method='get' action='{$wgScript}'>\n";
foreach ( $nondefaults as $key => $value ) {
if ($key != 'namespace' && $key != 'invert')
- $out .= "<input type='hidden' name='$key' value='$value' />";
+ $out .= wfElement('input', array( 'type' => 'hidden', 'name' => $key, 'value' => $value));
}
- $submitbutton = '<input type="submit" value="' . wfMsg( 'allpagessubmit' ) . '" />';
- $invertbox = "<input type='checkbox' name='invert' value='1' id='nsinvert'" . ( $invert ? ' checked="checked"' : '' ) . ' />';
-
-
$out .= '<input type="hidden" name="title" value="'.$t->getPrefixedText().'" />';
$out .= "
<div id='nsselect' class='recentchanges'>
- <label for='nsselectbox'>" . wfMsg('namespace') . "</label>
- $namespaceselect $submitbutton $invertbox <label for='nsinvert'>" . wfMsg('invert') . "</label>
+ <label for='namespace'>" . wfMsgHtml('namespace') . "</label>
+ $namespaceselect $submitbutton $invertbox <label for='nsinvert'>" . wfMsgHtml('invert') . "</label>
</div>";
$out .= '</form></div>';
return $out;
@@ -551,7 +540,13 @@ function rcFormatDiff( $row ) {
}
wfProfileOut( "$fname-dodiff" );
} else {
- $diffText = '<p><b>' . wfMsg( 'newpage' ) . '</b></p>' .
+ $rev = Revision::newFromId( $row->rc_this_oldid );
+ if( is_null( $rev ) ) {
+ $newtext = '';
+ } else {
+ $newtext = $rev->getText();
+ }
+ $diffText = '<p><b>' . wfMsg( 'newpage' ) . '</b></p>' .
'<div>' . nl2br( htmlspecialchars( $newtext ) ) . '</div>';
}
@@ -563,18 +558,4 @@ function rcFormatDiff( $row ) {
return $comment;
}
-
-/**
- * Appends to second array if $value differs from that in $default
- */
-function appendToArrayIfNotDefault( $key, $value, $default, &$changed )
-{
- if ( is_null( $changed ) ) {
- die();
- }
- if ( $default[$key] !== $value ) {
- $changed[$key] = $value;
- }
-}
-
?>
diff --git a/includes/SpecialRecentchangeslinked.php b/includes/SpecialRecentchangeslinked.php
index 938a1609024e..5aaa49032947 100644
--- a/includes/SpecialRecentchangeslinked.php
+++ b/includes/SpecialRecentchangeslinked.php
@@ -36,7 +36,7 @@ function wfSpecialRecentchangeslinked( $par = NULL ) {
}
$id = $nt->getArticleId();
- $wgOut->setSubtitle( wfMsg( 'rclsub', $nt->getPrefixedText() ) );
+ $wgOut->setSubtitle( htmlspecialchars( wfMsg( 'rclsub', $nt->getPrefixedText() ) ) );
if ( ! $days ) {
$days = $wgUser->getOption( 'rcdays' );
diff --git a/includes/SpecialSearch.php b/includes/SpecialSearch.php
index 20948b96aed3..fe883874d2b4 100644
--- a/includes/SpecialSearch.php
+++ b/includes/SpecialSearch.php
@@ -70,7 +70,7 @@ class SpecialSearch {
$this->namespaces = $this->userNamespaces( $user );
}
- $this->searchRedirects = false;
+ $this->searchRedirects = $request->getcheck( 'redirs' ) ? true : false;
}
/**
@@ -161,9 +161,10 @@ class SpecialSearch {
return;
}
- $search =& SearchEngine::create();
+ $search = SearchEngine::create();
$search->setLimitOffset( $this->limit, $this->offset );
$search->setNamespaces( $this->namespaces );
+ $search->showRedirects = $this->searchRedirects;
$titleMatches = $search->searchTitle( $term );
$textMatches = $search->searchText( $term );
@@ -223,7 +224,7 @@ class SpecialSearch {
function setupPage( $term ) {
global $wgOut;
$wgOut->setPageTitle( wfMsg( 'searchresults' ) );
- $wgOut->setSubtitle( wfMsg( 'searchquery', $term ) );
+ $wgOut->setSubtitle( htmlspecialchars( wfMsg( 'searchquery', $term ) ) );
$wgOut->setArticleRelated( false );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
}
diff --git a/includes/SpecialUndelete.php b/includes/SpecialUndelete.php
index 51b8083f7a4a..5613b283f8b7 100644
--- a/includes/SpecialUndelete.php
+++ b/includes/SpecialUndelete.php
@@ -40,7 +40,7 @@ class PageArchive {
*
* @return ResultWrapper
*/
- /* static */ function &listAllPages() {
+ /* static */ function listAllPages() {
$dbr =& wfGetDB( DB_SLAVE );
$archive = $dbr->tableName( 'archive' );
@@ -56,7 +56,7 @@ class PageArchive {
*
* @return ResultWrapper
*/
- function &listRevisions() {
+ function listRevisions() {
$dbr =& wfGetDB( DB_SLAVE );
return $dbr->resultObject( $dbr->select( 'archive',
array( 'ar_minor_edit', 'ar_timestamp', 'ar_user', 'ar_user_text', 'ar_comment' ),
@@ -214,10 +214,22 @@ class PageArchive {
);
$revision = null;
while( $row = $dbw->fetchObject( $result ) ) {
+ if( $row->ar_text_id ) {
+ // Revision was deleted in 1.5+; text is in
+ // the regular text table, use the reference.
+ // Specify null here so the so the text is
+ // dereferenced for page length info if needed.
+ $revText = null;
+ } else {
+ // Revision was deleted in 1.4 or earlier.
+ // Text is squashed into the archive row, and
+ // a new text table entry will be created for it.
+ $revText = Revision::getRevisionText( $row, 'ar_' );
+ }
$revision = new Revision( array(
'page' => $pageId,
'id' => $row->ar_rev_id,
- 'text' => Revision::getRevisionText( $row, 'ar_' ),
+ 'text' => $revText,
'comment' => $row->ar_comment,
'user' => $row->ar_user,
'user_text' => $row->ar_user_text,
diff --git a/includes/SpecialUpload.php b/includes/SpecialUpload.php
index a10b2aa85ef8..52d145b88e2e 100644
--- a/includes/SpecialUpload.php
+++ b/includes/SpecialUpload.php
@@ -53,8 +53,10 @@ class UploadForm {
$this->mUploadDescription = $request->getText( 'wpUploadDescription' );
$this->mUploadCopyStatus = $request->getText( 'wpUploadCopyStatus' );
- $this->mUploadSource = $request->getText( 'wpUploadSource');
-
+ $this->mUploadSource = $request->getText( 'wpUploadSource' );
+ $this->mWatchthis = $request->getBool( 'wpWatchthis' );
+ wfDebug( "UploadForm: watchthis is: '$this->mWatchthis'\n" );
+
$this->mAction = $request->getVal( 'action' );
$this->mSessionKey = $request->getInt( 'wpSessionKey' );
@@ -213,7 +215,12 @@ class UploadForm {
*/
if ( ! $this->mIgnoreWarning ) {
$warning = '';
- if( $this->mUploadSaveName != ucfirst( $filtered ) ) {
+
+ global $wgCapitalLinks;
+ if( $wgCapitalLinks ) {
+ $filtered = ucfirst( $filtered );
+ }
+ if( $this->mUploadSaveName != $filtered ) {
$warning .= '<li>'.wfMsg( 'badfilename', htmlspecialchars( $this->mUploadSaveName ) ).'</li>';
}
@@ -265,7 +272,8 @@ class UploadForm {
$success = $img->recordUpload( $this->mUploadOldVersion,
$this->mUploadDescription,
$this->mUploadCopyStatus,
- $this->mUploadSource );
+ $this->mUploadSource,
+ $this->mWatchthis );
if ( $success ) {
$this->showSuccess();
@@ -482,6 +490,7 @@ class UploadForm {
<input type='hidden' name='wpSessionKey' value=\"" . htmlspecialchars( $this->mSessionKey ) . "\" />
<input type='hidden' name='wpUploadDescription' value=\"" . htmlspecialchars( $this->mUploadDescription ) . "\" />
<input type='hidden' name='wpDestFile' value=\"" . htmlspecialchars( $this->mDestFile ) . "\" />
+ <input type='hidden' name='wpWatchthis' value=\"" . htmlspecialchars( intval( $this->mWatchthis ) ) . "\" />
{$copyright}
<table border='0'>
<tr>
@@ -553,12 +562,16 @@ class UploadForm {
" ;
}
+ $watchChecked = $wgUser->getOption( 'watchdefault' )
+ ? 'checked="checked"'
+ : '';
+
$wgOut->addHTML( "
<form id='upload' method='post' enctype='multipart/form-data' action=\"$action\">
<table border='0'><tr>
<td align='right'>{$sourcefilename}:</td><td align='left'>
- <input tabindex='1' type='file' name='wpUploadFile' id='wpUploadFile' onchange='fillDestFilename()' size='40' />
+ <input tabindex='1' type='file' name='wpUploadFile' id='wpUploadFile' " . ($this->mDestFile?"":"onchange='fillDestFilename()' ") . "size='40' />
</td></tr><tr>
<td align='right'>{$destfilename}:</td><td align='left'>
@@ -570,6 +583,11 @@ class UploadForm {
. htmlspecialchars( $this->mUploadDescription ) .
"</textarea>
</td></tr><tr>
+
+ <td></td><td align='left'>
+ <input type='checkbox' name='wpWatchthis' id='wpWatchthis' $watchChecked value='true' />
+ <label for='wpWatchthis'>" . wfMsgHtml( 'watchthis' ) . "</label>
+ </td></tr><tr>
{$source}
</tr>
<tr><td></td><td align='left'>
@@ -679,14 +697,18 @@ class UploadForm {
*/
function verifyExtension( $mime, $extension ) {
$fname = 'SpecialUpload::verifyExtension';
-
- if (!$mime || $mime=="unknown" || $mime=="unknown/unknown") {
- wfDebug( "$fname: passing file with unknown mime type\n" );
- return true;
- }
-
- $magic=& wfGetMimeMagic();
-
+
+ $magic =& wfGetMimeMagic();
+
+ if ( ! $mime || $mime == 'unknown' || $mime == 'unknown/unknown' )
+ if ( ! $magic->isRecognizableExtension( $extension ) ) {
+ wfDebug( "$fname: passing file with unknown detected mime type; unrecognized extension '$extension', can't verify\n" );
+ return true;
+ } else {
+ wfDebug( "$fname: rejecting file with unknown detected mime type; recognized extension '$extension', so probably invalid file\n" );
+ return false;
+ }
+
$match= $magic->isMatchingExtension($extension,$mime);
if ($match===NULL) {
diff --git a/includes/SpecialUserlogin.php b/includes/SpecialUserlogin.php
index 84b36ccdb15a..57859a4ca34d 100644
--- a/includes/SpecialUserlogin.php
+++ b/includes/SpecialUserlogin.php
@@ -147,6 +147,8 @@ class LoginForm {
$wgUser->sendConfirmationMail();
}
+ wfRunHooks( 'AddNewAccount' );
+
if( $this->hasSessionCookie() ) {
return $this->successfulLogin( wfMsg( 'welcomecreation', $wgUser->getName() ) );
} else {
diff --git a/includes/SpecialVersion.php b/includes/SpecialVersion.php
index a525d35ef0c9..8e8112907dae 100644
--- a/includes/SpecialVersion.php
+++ b/includes/SpecialVersion.php
@@ -1,77 +1,147 @@
<?php
/**
- * Give information about the version MediaWiki, PHP, and the database
+ * Give information about the version of MediaWiki, PHP, the DB and extensions
*
* @package MediaWiki
* @subpackage SpecialPage
+ *
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
/**
* constructor
*/
function wfSpecialVersion() {
- global $wgOut, $wgVersion, $wgExtensionCredits;
+ $version = new SpecialVersion;
+ $version->execute();
+}
+
+class SpecialVersion {
+ /**
+ * @var object
+ */
+ var $langObj;
- $dbr =& wfGetDB( DB_SLAVE );
+ /**
+ * Constructor
+ */
+ function SpecialVersion() {
+ // English motherfucker, do you speak it?
+ $this->langObj = setupLangObj( 'LanguageEn' );
+ $this->langObj->initEncoding();
+ }
- $out = "
-<div dir='ltr'>
-This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''',
-copyright (C) 2001-2005 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.
+ function execute() {
+ global $wgOut;
+
+ $wgOut->addWikiText( $this->MediaWikiCredits() . $this->extensionCredits() );
+ $wgOut->addHTML( $this->IPInfo() );
+ }
-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]
+ 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-2005 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() . "
+ </div>";
+
+ return str_replace( "\t\t", '', $ret );
+ }
+
+ function extensionCredits() {
+ global $wgExtensionCredits, $wgExtensionFunctions, $wgSkinExtensionFunction;
+
+ if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunction ) )
+ return '';
-* [http://www.mediawiki.org/ MediaWiki]: $wgVersion
-* [http://www.php.net/ PHP]: " . phpversion() . " (" . php_sapi_name() . ")
-* " . $dbr->getSoftwareLink() . ": " . $dbr->getServerVersion() . "
-</div>
-";
- if ( count( $wgExtensionCredits ) > 0 ) {
$extensionTypes = array(
'specialpage' => 'Special pages',
'parserhook' => 'Parser hooks',
- 'other' => 'Other'
+ 'other' => 'Other',
);
- $out .= "== Extensions ==\n";
-
+ $out = "\n* Extensions:\n";
foreach ( $extensionTypes as $type => $text ) {
- if ( count( @$wgExtensionCredits[$type] ) > 0 ) {
- $out .= "=== $text ===\n";
+ if ( count( @$wgExtensionCredits[$type] ) ) {
+ $out .= "** $text:\n";
foreach ( $wgExtensionCredits[$type] as $extension ) {
- $out .= formatExtensionCredits( $extension['name'], $extension['author'], @$extension['url'], @$extension['version'] );
+ wfSuppressWarnings();
+ $out .= $this->formatCredits(
+ $extension['name'],
+ $extension['version'],
+ $extension['author'],
+ $extension['url'],
+ $extension['description']
+ );
+ wfRestoreWarnings();
}
}
+ }
+ if ( count( $wgExtensionFunctions ) ) {
+ $out .= "** Extension functions:\n";
+ $out .= '***' . $this->langObj->listToText( $wgExtensionFunctions ) . "\n";
}
+
+ if ( count( $wgSkinExtensionFunction ) ) {
+ $out .= "** Skin extension functions:\n";
+ $out .= '***' . $this->langObj->listToText( $wgSkinExtensionFunction ) . "\n";
+ }
+
+ return $out;
+ }
+
+ function formatCredits( $name, $version = null, $author = null, $url = null, $description = null) {
+ $ret = '*** ';
+ if ( isset( $url ) )
+ $ret .= "[$url ";
+ $ret .= "''$name";
+ if ( isset( $version ) )
+ $ret .= " (version $version)";
+ $ret .= "''";
+ if ( isset( $url ) )
+ $ret .= ']';
+ if ( isset( $description ) )
+ $ret .= ', ' . $description;
+ if ( isset( $description ) && isset( $author ) )
+ $ret .= ', ';
+ if ( isset( $author ) )
+ $ret .= ' by ' . $this->langObj->listToText( (array)$author );
+
+ return "$ret\n";
}
- $wgOut->addWikiText( $out );
-}
-function formatExtensionCredits( $name, $author, $url = null, $version = null ) {
- $ret = '* ';
- if ( isset( $url ) )
- $ret .= "[$url ";
- $ret .= $name;
- if ( isset( $url ) )
- $ret .= ']';
- if ( isset( $version ) )
- $ret .= " $version";
- $ret .= " by $author\n";
- return $ret;
+ function IPInfo() {
+ global $wgIP;
+
+ $ip = str_replace( '--', ' - - ', htmlspecialchars( $wgIP ) );
+ return "<!-- visited from $ip -->\n";
+ }
}
?>
diff --git a/includes/SpecialWatchlist.php b/includes/SpecialWatchlist.php
index e6fabf80fa26..c0accdaaae37 100644
--- a/includes/SpecialWatchlist.php
+++ b/includes/SpecialWatchlist.php
@@ -22,7 +22,7 @@ function wfSpecialWatchlist( $par ) {
$fname = 'wfSpecialWatchlist';
$wgOut->setPagetitle( wfMsg( 'watchlist' ) );
- $sub = wfMsg( 'watchlistsub', $wgUser->getName() );
+ $sub = htmlspecialchars( wfMsg( 'watchlistsub', $wgUser->getName() ) );
$wgOut->setSubtitle( $sub );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
@@ -33,11 +33,20 @@ function wfSpecialWatchlist( $par ) {
return;
}
+ $defaults = array(
+ /* float */ 'days' => 3.0, /* or 0.5, watch further below */
+ /* bool */ 'hideOwn' => false,
+ );
+
+ extract($defaults);
+
# Get query variables
$days = $wgRequest->getVal( 'days' );
+ $hideOwn = $wgRequest->getBool( 'hideOwn' );
+
+ # Watchlist editing
$action = $wgRequest->getVal( 'action' );
$remove = $wgRequest->getVal( 'remove' );
- $hideOwn = $wgRequest->getBool( 'hideOwn' );
$id = $wgRequest->getArray( 'id' );
$uid = $wgUser->getID();
@@ -45,7 +54,7 @@ function wfSpecialWatchlist( $par ) {
$wgUser->clearAllNotifications( $uid );
}
-
+ # Deleting items from watchlist
if(($action == 'submit') && isset($remove) && is_array($id)) {
$wgOut->addWikiText( wfMsg( 'removingchecked' ) );
$wgOut->addHTML( '<p>' );
@@ -78,32 +87,38 @@ function wfSpecialWatchlist( $par ) {
$dbr =& wfGetDB( DB_SLAVE );
extract( $dbr->tableNames( 'page', 'revision', 'watchlist', 'recentchanges' ) );
- $sql = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_user=$uid";
- $res = $dbr->query( $sql, $fname );
- $s = $dbr->fetchObject( $res );
+ $sql = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_user=$uid";
+ $res = $dbr->query( $sql, $fname );
+ $s = $dbr->fetchObject( $res );
-# Patch *** A1 *** (see A2 below)
+ # Patch *** A1 *** (see A2 below)
# adjust for page X, talk:page X, which are both stored separately, but treated together
-# $nitems = $s->n / 2;
- $nitems = $s->n;
+ $nitems = floor($s->n / 2);
+# $nitems = $s->n;
if($nitems == 0) {
$wgOut->addWikiText( wfMsg( 'nowatchlist' ) );
return;
}
- if ( is_null( $days ) ) {
- $big = 1000;
+ if( is_null($days) || !is_numeric($days) ) {
+ $big = 1000; /* The magical big */
if($nitems > $big) {
# Set default cutoff shorter
- $days = (12.0 / 24.0); # 12 hours...
+ $days = $defaults['days'] = (12.0 / 24.0); # 12 hours...
} else {
- $days = 3; # longer cutoff for shortlisters
+ $days = $defaults['days']; # default cutoff for shortlisters
}
} else {
$days = floatval($days);
}
+ // Dump everything here
+ $nondefaults = array();
+
+ wfAppendToArrayIfNotDefault( 'days', $days, $defaults, $nondefaults);
+ wfAppendToArrayIfNotDefault( 'hideOwn', $hideOwn, $defaults, $nondefaults);
+
if ( $days <= 0 ) {
$docutoff = '';
$cutoff = false;
@@ -112,13 +127,17 @@ function wfSpecialWatchlist( $par ) {
$docutoff = "AND rev_timestamp > '" .
( $cutoff = $dbr->timestamp( time() - intval( $days * 86400 ) ) )
. "'";
- $sql = "SELECT COUNT(*) AS n FROM $page, $revision WHERE rev_timestamp>'$cutoff' AND page_id=rev_page";
- $res = $dbr->query( $sql, $fname );
- $s = $dbr->fetchObject( $res );
- $npages = $s->n;
+ /*
+ $sql = "SELECT COUNT(*) AS n FROM $page, $revision WHERE rev_timestamp>'$cutoff' AND page_id=rev_page";
+ $res = $dbr->query( $sql, $fname );
+ $s = $dbr->fetchObject( $res );
+ $npages = $s->n;
+ */
+ $npages = 40000 * $days;
}
+ /* Edit watchlist form */
if($wgRequest->getBool('edit') || $par == 'edit' ) {
$wgOut->addWikiText( wfMsg( 'watchlistcontains', $wgLang->formatNum( $nitems ) ) .
"\n\n" . wfMsg( 'watcheditlist' ) );
@@ -139,12 +158,12 @@ function wfSpecialWatchlist( $par ) {
while( $s = $dbr->fetchObject( $res ) ) {
$list[$s->wl_namespace][] = $s->wl_title;
}
-
+
// TODO: Display a TOC
foreach($list as $ns => $titles) {
if (Namespace::isTalk($ns))
continue;
- if ($ns != NS_MAIN)
+ if ($ns != NS_MAIN)
$wgOut->addHTML( '<h2>' . $wgContLang->getFormattedNsText( $ns ) . '</h2>' );
$wgOut->addHTML( '<ul>' );
foreach($titles as $title) {
@@ -181,23 +200,8 @@ function wfSpecialWatchlist( $par ) {
# through the time-sorted page list checking for watched items.
# Up estimate of watched items by 15% to compensate for talk pages...
- if( $cutoff && ( $nitems*1.15 > $npages ) ) {
- $x = 'rev_timestamp';
- $y = wfMsg( 'watchmethod-recent' );
- # TG patch: here we do not consider pages and their talk pages equivalent - why should we ?
- # The change results in talk-pages not automatically included in watchlists, when their parent page is included
- # $z = "wl_namespace=cur_namespace & ~1";
- $z = 'wl_namespace=page_namespace';
- } else {
- $x = 'page_timestamp';
- $y = wfMsg( 'watchmethod-list' );
- # TG patch: here we do not consider pages and their talk pages equivalent - why should we ?
- # The change results in talk-pages not automatically included in watchlists, when their parent page is included
- # $z = "(wl_namespace=cur_namespace OR wl_namespace+1=cur_namespace)";
- $z = 'wl_namespace=page_namespace';
- }
- $andHideOwn = $hideOwn ? "AND (rev_user <> $uid)" : '';
+ $andHideOwn = $hideOwn ? "AND (rc_user <> $uid)" : '';
# Show watchlist header
$header = '';
@@ -208,8 +212,9 @@ function wfSpecialWatchlist( $par ) {
$header .= wfMsg( 'wlheader-showupdated' ) . "\n";
}
- $header .= wfMsg( 'watchdetails', $wgLang->formatNum( $nitems / 2 ),
- $wgLang->formatNum( $npages ), $y,
+ # TODO: Consider removing the third parameter
+ $header .= wfMsg( 'watchdetails', $wgLang->formatNum( $nitems ),
+ $wgLang->formatNum( $npages ), '',
$specialTitle->getFullUrl( 'edit=yes' ) );
$wgOut->addWikiText( $header );
@@ -222,53 +227,63 @@ function wfSpecialWatchlist( $par ) {
"\n\n" );
}
- $use_index = $dbr->useIndexClause( $x );
- $sql = "SELECT
- page_namespace,page_title,rev_comment, page_id,
- rev_user,rev_user_text,rev_timestamp,rev_minor_edit,rev_id,page_is_new,wl_notificationtimestamp
- FROM $watchlist,$page,$revision $use_index
- WHERE wl_user=$uid
- $andHideOwn
- AND $z
- AND wl_title=page_title
- AND page_latest=rev_id
- $docutoff
- ORDER BY rev_timestamp DESC";
-
+ $sql = "SELECT
+ rc_namespace page_namespace,rc_title page_title,
+ rc_comment rev_comment, rc_cur_id page_id,
+ rc_user rev_user,rc_user_text rev_user_text,
+ rc_timestamp rev_timestamp,rc_minor rev_minor_edit,
+ rc_this_oldid rev_id,
+ rc_last_oldid,
+ rc_new page_is_new,wl_notificationtimestamp
+ FROM $watchlist,$recentchanges,$page
+ WHERE wl_user=$uid
+ AND wl_namespace=rc_namespace
+ AND wl_title=rc_title
+ AND rc_timestamp > '$cutoff'
+ AND rc_cur_id=page_id
+ AND rc_this_oldid=page_latest
+ $andHideOwn
+ ORDER BY rc_timestamp DESC";
$res = $dbr->query( $sql, $fname );
$numRows = $dbr->numRows( $res );
+
+ /* Start bottom header */
+ $wgOut->addHTML( "<hr />\n<p>" );
+
if($days >= 1)
- $note = wfMsg( 'rcnote', $wgLang->formatNum( $numRows ), $wgLang->formatNum( $days ) );
+ $wgOut->addWikiText( wfMsg( 'rcnote', $wgLang->formatNum( $numRows ),
+ $wgLang->formatNum( $days ) ) . '<br />' , false );
elseif($days > 0)
- $note = wfMsg( 'wlnote', $wgLang->formatNum( $numRows ), $wgLang->formatNum( round($days*24) ) );
- else
- $note = '';
- $wgOut->addHTML( "\n<hr />\n{$note}\n<br />" );
- $note = wlCutoffLinks( $days );
- $wgOut->addHTML( "{$note}\n" );
+ $wgOut->addWikiText( wfMsg( 'wlnote', $wgLang->formatNum( $numRows ),
+ $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' ),
- (0 == $hideOwn) ? wfMsg( 'wlhide' ) : wfMsg( 'wlshow' ),
- 'hideOwn=' . $wgLang->formatNum( 1-$hideOwn ) );
-
- $note = wfMsg( "wlhideshowown", $s );
- $wgOut->addHTML( "\n<br />{$note}\n<br />" );
+ (0 == $hideOwn) ? wfMsgHtml( 'wlhide' ) : wfMsgHtml( 'wlshow' ),
+ wfArrayToCGI( array('hideOwn' => 1-$hideOwn ), $nondefaults ) );
+
+ $wgOut->addHTML( wfMsgHtml( "wlhideshowown", $s ) );
if ( $numRows == 0 ) {
- $wgOut->addHTML( '<p><i>' . wfMsg( 'watchnochange' ) . '</i></p>' );
+ $wgOut->addWikitext( "<br />" . wfMsg( 'watchnochange' ), false );
+ $wgOut->addHTML( "</p>\n" );
return;
}
+ $wgOut->addHTML( "</p>\n" );
+ /* End bottom header */
+
$sk = $wgUser->getSkin();
$list =& new ChangesList( $sk );
$s = $list->beginRecentChangesList();
$counter = 1;
while ( $obj = $dbr->fetchObject( $res ) ) {
# Make fake RC entry
- $rc = RecentChange::newFromCurRow( $obj );
+ $rc = RecentChange::newFromCurRow( $obj, $obj->rc_last_oldid );
$rc->counter = $counter++;
if ( $wgShowUpdatedMarker ) {
@@ -300,44 +315,42 @@ function wfSpecialWatchlist( $par ) {
}
-
-function wlHoursLink( $h, $page ) {
+function wlHoursLink( $h, $page, $options = array() ) {
global $wgUser, $wgLang, $wgContLang;
$sk = $wgUser->getSkin();
$s = $sk->makeKnownLink(
$wgContLang->specialPage( $page ),
$wgLang->formatNum( $h ),
- 'days=' . ($h / 24.0) );
+ wfArrayToCGI( array('days' => ($h / 24.0)), $options ) );
return $s;
}
-
-function wlDaysLink( $d, $page ) {
+function wlDaysLink( $d, $page, $options = array() ) {
global $wgUser, $wgLang, $wgContLang;
$sk = $wgUser->getSkin();
$s = $sk->makeKnownLink(
$wgContLang->specialPage( $page ),
- ($d ? $wgLang->formatNum( $d ) : wfMsg( 'watchlistall2' ) ), "days=$d" );
+ ($d ? $wgLang->formatNum( $d ) : wfMsgHtml( 'watchlistall2' ) ),
+ wfArrayToCGI( array('days' => $d), $options ) );
return $s;
}
-function wlCutoffLinks( $days, $page = 'Watchlist' )
-{
+function wlCutoffLinks( $days, $page = 'Watchlist', $options = array() ) {
$hours = array( 1, 2, 6, 12 );
$days = array( 1, 3, 7 );
$cl = '';
$i = 0;
foreach( $hours as $h ) {
- $hours[$i++] = wlHoursLink( $h, $page );
+ $hours[$i++] = wlHoursLink( $h, $page, $options );
}
$i = 0;
foreach( $days as $d ) {
- $days[$i++] = wlDaysLink( $d, $page );
+ $days[$i++] = wlDaysLink( $d, $page, $options );
}
return wfMsg ('wlshowlast',
implode(' | ', $hours),
implode(' | ', $days),
- wlDaysLink( 0, $page ) );
+ wlDaysLink( 0, $page, $options ) );
}
?>
diff --git a/includes/SpecialWhatlinkshere.php b/includes/SpecialWhatlinkshere.php
index 4d5bfa0564d7..087b517cebb8 100644
--- a/includes/SpecialWhatlinkshere.php
+++ b/includes/SpecialWhatlinkshere.php
@@ -32,7 +32,7 @@ function wfSpecialWhatlinkshere($par = NULL) {
$sk = $wgUser->getSkin();
$isredir = ' (' . wfMsg( 'isredirect' ) . ")\n";
- $wgOut->addHTML('&lt; '.$sk->makeKnownLinkObj($nt, '', 'redirect=no' )."<br />\n");
+ $wgOut->addHTML('&lt; '.$sk->makeLinkObj($nt, '', 'redirect=no' )."<br />\n");
wfShowIndirectLinks( 0, $nt, $limit, $offset );
}
diff --git a/includes/StreamFile.php b/includes/StreamFile.php
index 3098ea876cdd..0c44bb9228a0 100644
--- a/includes/StreamFile.php
+++ b/includes/StreamFile.php
@@ -4,7 +4,7 @@
/** */
function wfStreamFile( $fname ) {
global $wgSquidMaxage;
- $stat = stat( $fname );
+ $stat = @stat( $fname );
if ( !$stat ) {
header( 'HTTP/1.0 404 Not Found' );
echo "<html><body>
@@ -15,7 +15,6 @@ does not.</p>
return;
}
- header( "Cache-Control: s-maxage=$wgSquidMaxage, must-revalidate, max-age=0" );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $stat['mtime'] ) . ' GMT' );
if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) {
diff --git a/includes/Title.php b/includes/Title.php
index 33f728b780aa..e147b28e1299 100644
--- a/includes/Title.php
+++ b/includes/Title.php
@@ -102,7 +102,7 @@ class Title {
* @static
* @access public
*/
- function &newFromText( $text, $defaultNamespace = NS_MAIN ) {
+ function newFromText( $text, $defaultNamespace = NS_MAIN ) {
$fname = 'Title::newFromText';
wfProfileIn( $fname );
@@ -667,7 +667,7 @@ class Title {
$namespace = $wgContLang->getNsText( $this->mNamespace );
if ( '' != $namespace ) {
# Can this actually happen? Interwikis shouldn't be parsed.
- $namepace .= ':';
+ $namespace .= ':';
}
$url = str_replace( '$1', $namespace . $this->mUrlform, $baseUrl );
if( $query != '' ) {
@@ -950,7 +950,8 @@ class Title {
}
}
- if( $action == 'move' && !$this->isMovable() ) {
+ if( $action == 'move' &&
+ !( $this->isMovable() && $wgUser->isAllowed( 'move' ) ) ) {
wfProfileOut( $fname );
return false;
}
@@ -1280,57 +1281,58 @@ class Title {
$this->mDbkeyform = $t;
- # Initial colon indicating main namespace
+ # Initial colon indicates main namespace rather than specified default
+ # but should not create invalid {ns,title} pairs such as {0,Project:Foo}
if ( ':' == $t{0} ) {
- $r = substr( $t, 1 );
$this->mNamespace = NS_MAIN;
- } else {
- # Namespace or interwiki prefix
- $firstPass = true;
- do {
- if ( preg_match( "/^(.+?)_*:_*(.*)$/S", $t, $m ) ) {
- $p = $m[1];
- $lowerNs = strtolower( $p );
- if ( $ns = Namespace::getCanonicalIndex( $lowerNs ) ) {
- # Canonical namespace
- $t = $m[2];
- $this->mNamespace = $ns;
- } elseif ( $ns = $wgContLang->getNsIndex( $lowerNs )) {
- # Ordinary namespace
- $t = $m[2];
- $this->mNamespace = $ns;
- } elseif( $this->getInterwikiLink( $p ) ) {
- if( !$firstPass ) {
- # Can't make a local interwiki link to an interwiki link.
- # That's just crazy!
+ $t = substr( $t, 1 ); # remove the colon but continue processing
+ }
+
+ # Namespace or interwiki prefix
+ $firstPass = true;
+ do {
+ if ( preg_match( "/^(.+?)_*:_*(.*)$/S", $t, $m ) ) {
+ $p = $m[1];
+ $lowerNs = strtolower( $p );
+ if ( $ns = Namespace::getCanonicalIndex( $lowerNs ) ) {
+ # Canonical namespace
+ $t = $m[2];
+ $this->mNamespace = $ns;
+ } elseif ( $ns = $wgContLang->getNsIndex( $lowerNs )) {
+ # Ordinary namespace
+ $t = $m[2];
+ $this->mNamespace = $ns;
+ } elseif( $this->getInterwikiLink( $p ) ) {
+ if( !$firstPass ) {
+ # Can't make a local interwiki link to an interwiki link.
+ # That's just crazy!
+ wfProfileOut( $fname );
+ return false;
+ }
+
+ # Interwiki link
+ $t = $m[2];
+ $this->mInterwiki = $p;
+
+ # Redundant interwiki prefix to the local wiki
+ if ( 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) ) {
+ if( $t == '' ) {
+ # Can't have an empty self-link
wfProfileOut( $fname );
return false;
}
-
- # Interwiki link
- $t = $m[2];
- $this->mInterwiki = $p;
-
- # Redundant interwiki prefix to the local wiki
- if ( 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) ) {
- if( $t == '' ) {
- # Can't have an empty self-link
- wfProfileOut( $fname );
- return false;
- }
- $this->mInterwiki = '';
- $firstPass = false;
- # Do another namespace split...
- continue;
- }
+ $this->mInterwiki = '';
+ $firstPass = false;
+ # Do another namespace split...
+ continue;
}
- # If there's no recognized interwiki or namespace,
- # then let the colon expression be part of the title.
}
- break;
- } while( true );
- $r = $t;
- }
+ # If there's no recognized interwiki or namespace,
+ # then let the colon expression be part of the title.
+ }
+ break;
+ } while( true );
+ $r = $t;
# We already know that some pages won't be in the database!
#
@@ -1657,6 +1659,7 @@ class Title {
$u->doUpdate();
}
+ global $wgUser;
wfRunHooks( 'TitleMoveComplete', array( &$this, &$nt, &$wgUser, $pageid, $redirid ) );
return true;
}
@@ -1845,7 +1848,7 @@ class Title {
# Is it a redirect?
$id = $nt->getArticleID();
$obj = $dbw->selectRow( array( 'page', 'revision', 'text'),
- array( 'page_is_redirect','old_text' ),
+ array( 'page_is_redirect','old_text','old_flags' ),
array( 'page_id' => $id, 'page_latest=rev_id', 'rev_text_id=old_id' ),
$fname, 'FOR UPDATE' );
@@ -1853,14 +1856,18 @@ class Title {
# Not a redirect
return false;
}
+ $text = Revision::getRevisionText( $obj );
# Does the redirect point to the source?
- if ( preg_match( "/\\[\\[\\s*([^\\]\\|]*)]]/", $obj->old_text, $m ) ) {
+ if ( preg_match( "/\\[\\[\\s*([^\\]\\|]*)]]/", $text, $m ) ) {
$redirTitle = Title::newFromText( $m[1] );
if( !is_object( $redirTitle ) ||
$redirTitle->getPrefixedDBkey() != $this->getPrefixedDBkey() ) {
return false;
}
+ } else {
+ # Fail safe
+ return false;
}
# Does the article have a history?
@@ -2036,7 +2043,7 @@ class Title {
* @param Title $title
* @return bool
*/
- function equals( &$title ) {
+ function equals( $title ) {
return $this->getInterwiki() == $title->getInterwiki()
&& $this->getNamespace() == $title->getNamespace()
&& $this->getDbkey() == $title->getDbkey();
diff --git a/includes/User.php b/includes/User.php
index 902283182495..8b0f577a8dbb 100644
--- a/includes/User.php
+++ b/includes/User.php
@@ -50,8 +50,6 @@ class User {
* @static
*/
function newFromName( $name ) {
- $u = new User();
-
# Force usernames to capital
global $wgContLang;
$name = $wgContLang->ucfirst( $name );
@@ -71,6 +69,7 @@ class User {
return null;
}
+ $u = new User();
$u->setName( $canonicalName );
$u->setId( $u->idFromName( $canonicalName ) );
return $u;
@@ -252,13 +251,16 @@ class User {
* @todo Check what is doing really [AV]
*/
function randomPassword() {
+ global $wgMinimalPasswordLength;
$pwchars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz';
$l = strlen( $pwchars ) - 1;
- $np = $pwchars{mt_rand( 0, $l )} . $pwchars{mt_rand( 0, $l )} .
- $pwchars{mt_rand( 0, $l )} . chr( mt_rand(48, 57) ) .
- $pwchars{mt_rand( 0, $l )} . $pwchars{mt_rand( 0, $l )} .
- $pwchars{mt_rand( 0, $l )};
+ $pwlength = max( 7, $wgMinimalPasswordLength );
+ $digit = mt_rand(0, $pwlength - 1);
+ $np = '';
+ for ( $i = 0; $i < $pwlength; $i++ ) {
+ $np .= $i == $digit ? chr( mt_rand(48, 57) ) : $pwchars{ mt_rand(0, $l)};
+ }
return $np;
}
diff --git a/includes/UserTalkUpdate.php b/includes/UserTalkUpdate.php
index 7c61406026e6..10bf9158f891 100644
--- a/includes/UserTalkUpdate.php
+++ b/includes/UserTalkUpdate.php
@@ -50,7 +50,7 @@ class UserTalkUpdate {
$this->mAction = $action;
$this->mNamespace = $ns;
- $this->mTitle = $title; # str_replace( '_', ' ', $title ); # I do not know, why this was needed . T. Gries 23.11.2004
+ $this->mTitle = $title;
$this->mSummary = $summary;
$this->mMinorEdit = $minoredit;
$this->mTimestamp = $timestamp;
@@ -62,7 +62,7 @@ class UserTalkUpdate {
# If the user talk page is our own, clear the flag
# when we are reading it or writing it.
- if ( 0 == strcmp( $this->mTitle, $wgUser->getName() ) ) {
+ if ( 0 == strcmp( str_replace( '_', ' ', $this->mTitle ), $wgUser->getName() ) ) {
$wgUser->setNewtalk( 0 );
$wgUser->saveSettings();
} else {
diff --git a/includes/WatchedItem.php b/includes/WatchedItem.php
index b27c53faf95c..1912f5400b6c 100644
--- a/includes/WatchedItem.php
+++ b/includes/WatchedItem.php
@@ -133,13 +133,27 @@ class WatchedItem {
}
/**
+ * Check if the given title already is watched by the user, and if so
+ * add watches on a new title. To be used for page renames and such.
+ *
+ * @param Title $ot Page title to duplicate entries from, if present
+ * @param Title $nt Page title to add watches on
* @static
*/
function duplicateEntries( $ot, $nt ) {
+ WatchedItem::doDuplicateEntries( $ot->getSubjectPage(), $nt->getSubjectPage() );
+ WatchedItem::doDuplicateEntries( $ot->getTalkPage(), $nt->getTalkPage() );
+ }
+
+ /**
+ * @static
+ * @access private
+ */
+ function doDuplicateEntries( $ot, $nt ) {
$fname = "WatchedItem::duplicateEntries";
global $wgMemc, $wgDBname;
- $oldnamespace = $ot->getNamespace() & ~1;
- $newnamespace = $nt->getNamespace() & ~1;
+ $oldnamespace = $ot->getNamespace();
+ $newnamespace = $nt->getNamespace();
$oldtitle = $ot->getDBkey();
$newtitle = $nt->getDBkey();
@@ -160,6 +174,11 @@ class WatchedItem {
);
}
$dbw->freeResult( $res );
+
+ if( empty( $values ) ) {
+ // Nothing to do
+ return true;
+ }
# Perform replace
# Note that multi-row replace is very efficient for MySQL but may be inefficient for
diff --git a/includes/WikiError.php b/includes/WikiError.php
index f693003a5ffa..46738fccf5b9 100644
--- a/includes/WikiError.php
+++ b/includes/WikiError.php
@@ -89,15 +89,36 @@ class WikiXmlError extends WikiError {
* @param resource $parser
* @param string $message
*/
- function WikiXmlError( $parser, $message = '' ) {
+ function WikiXmlError( $parser, $message = 'XML parsing error', $context = null, $offset = 0 ) {
$this->mXmlError = xml_get_error_code( $parser );
+ $this->mColumn = xml_get_current_column_number( $parser );
+ $this->mLine = xml_get_current_line_number( $parser );
+ $this->mByte = xml_get_current_byte_index( $parser );
+ $this->mContext = $this->_extractContext( $context, $offset );
$this->mMessage = $message;
xml_parser_free( $parser );
+ wfDebug( "WikiXmlError: " . $this->getMessage() . "\n" );
}
/** @return string */
function getMessage() {
- return $this->mMessage . ': ' . xml_error_string( $this->mXmlError );
+ return sprintf( '%s at line %d, col %d (byte %d%s): %s',
+ $this->mMessage,
+ $this->mLine,
+ $this->mColumn,
+ $this->mByte,
+ $this->mContext,
+ xml_error_string( $this->mXmlError ) );
+ }
+
+ function _extractContext( $context, $offset ) {
+ if( is_null( $context ) ) {
+ return null;
+ } else {
+ // Hopefully integer overflow will be handled transparently here
+ $inlineOffset = $this->mByte - $offset;
+ return '; "' . substr( $context, $inlineOffset, 16 ) . '"';
+ }
}
}