2003-04-14 23:10:40 +00:00
|
|
|
<?
|
|
|
|
|
# See design.doc
|
|
|
|
|
|
2003-08-30 10:04:59 +00:00
|
|
|
if($wgUseTeX) include_once( "Math.php" );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
class OutputPage {
|
|
|
|
|
var $mHeaders, $mCookies, $mMetatags, $mKeywords;
|
|
|
|
|
var $mLinktags, $mPagetitle, $mBodytext, $mDebugtext;
|
|
|
|
|
var $mHTMLtitle, $mRobotpolicy, $mIsarticle, $mPrintable;
|
|
|
|
|
var $mSubtitle, $mRedirect, $mAutonumber, $mHeadtext;
|
2003-07-11 07:02:22 +00:00
|
|
|
var $mLastModified, $mCategoryLinks;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
var $mDTopen, $mLastSection; # Used for processing DL, PRE
|
|
|
|
|
var $mLanguageLinks, $mSupressQuickbar;
|
2003-12-10 10:30:14 +00:00
|
|
|
var $mOnloadHandler;
|
2003-12-11 20:16:34 +00:00
|
|
|
var $mDoNothing;
|
2004-01-07 02:51:47 +00:00
|
|
|
var $mContainsOldMagic, $mContainsNewMagic;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
function OutputPage()
|
|
|
|
|
{
|
|
|
|
|
$this->mHeaders = $this->mCookies = $this->mMetatags =
|
|
|
|
|
$this->mKeywords = $this->mLinktags = array();
|
|
|
|
|
$this->mHTMLtitle = $this->mPagetitle = $this->mBodytext =
|
|
|
|
|
$this->mLastSection = $this->mRedirect = $this->mLastModified =
|
2003-12-10 10:30:14 +00:00
|
|
|
$this->mSubtitle = $this->mDebugtext = $this->mRobotpolicy =
|
|
|
|
|
$this->mOnloadHandler = "";
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->mIsarticle = $this->mPrintable = true;
|
|
|
|
|
$this->mSupressQuickbar = $this->mDTopen = $this->mPrintable = false;
|
|
|
|
|
$this->mLanguageLinks = array();
|
2003-07-11 07:02:22 +00:00
|
|
|
$this->mCategoryLinks = array() ;
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->mAutonumber = 0;
|
2003-12-11 20:16:34 +00:00
|
|
|
$this->mDoNothing = false;
|
2004-01-07 02:51:47 +00:00
|
|
|
$this->mContainsOldMagic = $this->mContainsNewMagic = 0;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addHeader( $name, $val ) { array_push( $this->mHeaders, "$name: $val" ) ; }
|
|
|
|
|
function addCookie( $name, $val ) { array_push( $this->mCookies, array( $name, $val ) ); }
|
|
|
|
|
function redirect( $url ) { $this->mRedirect = $url; }
|
|
|
|
|
|
|
|
|
|
# To add an http-equiv meta tag, precede the name with "http:"
|
|
|
|
|
function addMeta( $name, $val ) { array_push( $this->mMetatags, array( $name, $val ) ); }
|
|
|
|
|
function addKeyword( $text ) { array_push( $this->mKeywords, $text ); }
|
|
|
|
|
function addLink( $rel, $rev, $target ) { array_push( $this->mLinktags, array( $rel, $rev, $target ) ); }
|
|
|
|
|
|
2003-12-11 20:16:34 +00:00
|
|
|
# checkLastModified tells the client to use the client-cached page if
|
|
|
|
|
# possible. If sucessful, the OutputPage is disabled so that
|
|
|
|
|
# any future call to OutputPage->output() have no effect. The method
|
|
|
|
|
# returns true iff cache-ok headers was sent.
|
2003-04-14 23:10:40 +00:00
|
|
|
function checkLastModified ( $timestamp )
|
|
|
|
|
{
|
|
|
|
|
global $wgLang, $wgCachePages, $wgUser;
|
2003-07-10 04:55:41 +00:00
|
|
|
if( !$wgCachePages ) {
|
|
|
|
|
wfDebug( "CACHE DISABLED\n", false );
|
|
|
|
|
return;
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
if( preg_match( '/MSIE ([1-4]|5\.0)/', $_SERVER["HTTP_USER_AGENT"] ) ) {
|
|
|
|
|
# IE 5.0 has probs with our caching
|
2003-07-10 04:55:41 +00:00
|
|
|
wfDebug( "-- bad client, not caching\n", false );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if( $wgUser->getOption( "nocache" ) ) {
|
|
|
|
|
wfDebug( "USER DISABLED CACHE\n", false );
|
2003-04-14 23:10:40 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-10 04:55:41 +00:00
|
|
|
$lastmod = gmdate( "D, j M Y H:i:s", wfTimestamp2Unix(
|
|
|
|
|
max( $timestamp, $wgUser->mTouched ) ) ) . " GMT";
|
|
|
|
|
|
2003-11-15 23:06:59 +00:00
|
|
|
if( !empty( $_SERVER["HTTP_IF_MODIFIED_SINCE"] ) ) {
|
2003-11-09 11:45:12 +00:00
|
|
|
# IE sends sizes after the date like this:
|
2003-08-20 07:45:18 +00:00
|
|
|
# Wed, 20 Aug 2003 06:51:19 GMT; length=5202
|
|
|
|
|
# this breaks strtotime().
|
|
|
|
|
$modsince = preg_replace( '/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"] );
|
|
|
|
|
$ismodsince = wfUnix2Timestamp( strtotime( $modsince ) );
|
|
|
|
|
wfDebug( "-- client send If-Modified-Since: " . $modsince . "\n", false );
|
2003-07-10 04:55:41 +00:00
|
|
|
wfDebug( "-- we might send Last-Modified : $lastmod\n", false );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
if( ($ismodsince >= $timestamp ) and $wgUser->validateCache( $ismodsince ) ) {
|
|
|
|
|
# Make sure you're in a place you can leave when you call us!
|
|
|
|
|
header( "HTTP/1.0 304 Not Modified" );
|
|
|
|
|
header( "Expires: Mon, 15 Jan 2001 00:00:00 GMT" ); # Cachers always validate the page!
|
|
|
|
|
header( "Cache-Control: private, must-revalidate, max-age=0" );
|
|
|
|
|
header( "Last-Modified: {$lastmod}" );
|
2003-07-10 04:55:41 +00:00
|
|
|
wfDebug( "CACHED client: $ismodsince ; user: $wgUser->mTouched ; page: $timestamp\n", false );
|
2003-12-11 20:16:34 +00:00
|
|
|
$this->disable();
|
|
|
|
|
return true;
|
2003-04-14 23:10:40 +00:00
|
|
|
} else {
|
2003-07-10 04:55:41 +00:00
|
|
|
wfDebug( "READY client: $ismodsince ; user: $wgUser->mTouched ; page: $timestamp\n", false );
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->mLastModified = $lastmod;
|
|
|
|
|
}
|
2003-07-10 04:55:41 +00:00
|
|
|
} else {
|
|
|
|
|
wfDebug( "We're confused.\n", false );
|
|
|
|
|
$this->mLastModified = $lastmod;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setRobotpolicy( $str ) { $this->mRobotpolicy = $str; }
|
|
|
|
|
function setHTMLtitle( $name ) { $this->mHTMLtitle = $name; }
|
|
|
|
|
function setPageTitle( $name ) { $this->mPagetitle = $name; }
|
|
|
|
|
function getPageTitle() { return $this->mPagetitle; }
|
|
|
|
|
function setSubtitle( $str ) { $this->mSubtitle = $str; }
|
|
|
|
|
function getSubtitle() { return $this->mSubtitle; }
|
|
|
|
|
function setArticleFlag( $v ) { $this->mIsarticle = $v; }
|
|
|
|
|
function isArticle() { return $this->mIsarticle; }
|
|
|
|
|
function setPrintable() { $this->mPrintable = true; }
|
|
|
|
|
function isPrintable() { return $this->mPrintable; }
|
2003-12-10 10:30:14 +00:00
|
|
|
function setOnloadHandler( $js ) { $this->mOnloadHandler = $js; }
|
|
|
|
|
function getOnloadHandler() { return $this->mOnloadHandler; }
|
2003-12-11 20:16:34 +00:00
|
|
|
function disable() { $this->mDoNothing = true; }
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
function getLanguageLinks() {
|
2003-11-09 11:45:12 +00:00
|
|
|
global $wgTitle, $wgLanguageCode;
|
|
|
|
|
global $wgDBconnection, $wgDBname;
|
|
|
|
|
return $this->mLanguageLinks;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
function supressQuickbar() { $this->mSupressQuickbar = true; }
|
|
|
|
|
function isQuickbarSupressed() { return $this->mSupressQuickbar; }
|
|
|
|
|
|
|
|
|
|
function addHTML( $text ) { $this->mBodytext .= $text; }
|
|
|
|
|
function addHeadtext( $text ) { $this->mHeadtext .= $text; }
|
|
|
|
|
function debug( $text ) { $this->mDebugtext .= $text; }
|
|
|
|
|
|
|
|
|
|
# First pass--just handle <nowiki> sections, pass the rest off
|
|
|
|
|
# to doWikiPass2() which does all the real work.
|
|
|
|
|
#
|
|
|
|
|
function addWikiText( $text, $linestart = true )
|
|
|
|
|
{
|
2004-01-07 02:51:47 +00:00
|
|
|
global $wgUseTeX, $wgArticle, $wgUser, $action;
|
2003-10-16 13:30:45 +00:00
|
|
|
$fname = "OutputPage::addWikiText";
|
|
|
|
|
wfProfileIn( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
$unique = "3iyZiyA7iMwg5rhxP0Dcc9oTnj8qD1jm1Sfv4";
|
|
|
|
|
$unique2 = "4LIQ9nXtiYFPCSfitVwDw7EYwQlL4GeeQ7qSO";
|
|
|
|
|
$unique3 = "fPaA8gDfdLBqzj68Yjg9Hil3qEF8JGO0uszIp";
|
|
|
|
|
$nwlist = array();
|
|
|
|
|
$nwsecs = 0;
|
|
|
|
|
$mathlist = array();
|
|
|
|
|
$mathsecs = 0;
|
|
|
|
|
$prelist = array ();
|
|
|
|
|
$presecs = 0;
|
|
|
|
|
$stripped = "";
|
|
|
|
|
$stripped2 = "";
|
|
|
|
|
$stripped3 = "";
|
2004-01-07 08:17:19 +00:00
|
|
|
|
|
|
|
|
# Replace any instances of the placeholders
|
2004-01-07 09:02:36 +00:00
|
|
|
$text = str_replace( $unique, wfHtmlEscapeFirst( $unique ), $text );
|
|
|
|
|
$text = str_replace( $unique2, wfHtmlEscapeFirst( $unique2 ), $text );
|
|
|
|
|
$text = str_replace( $unique3, wfHtmlEscapeFirst( $unique3 ), $text );
|
2004-01-07 08:17:19 +00:00
|
|
|
|
2004-01-07 02:51:47 +00:00
|
|
|
global $wgEnableParserCache;
|
|
|
|
|
$use_parser_cache =
|
|
|
|
|
$wgEnableParserCache && $action == "view" &&
|
|
|
|
|
intval($wgUser->getOption( "stubthreshold" )) == 0 &&
|
|
|
|
|
isset($wgArticle) && $wgArticle->getID() > 0;
|
|
|
|
|
|
|
|
|
|
if( $use_parser_cache ){
|
|
|
|
|
if( $this->fillFromParserCache() ){
|
|
|
|
|
wfProfileOut( $fname );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-01-07 08:17:19 +00:00
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
while ( "" != $text ) {
|
|
|
|
|
$p = preg_split( "/<\\s*nowiki\\s*>/i", $text, 2 );
|
|
|
|
|
$stripped .= $p[0];
|
|
|
|
|
if ( ( count( $p ) < 2 ) || ( "" == $p[1] ) ) { $text = ""; }
|
|
|
|
|
else {
|
|
|
|
|
$q = preg_split( "/<\\/\\s*nowiki\\s*>/i", $p[1], 2 );
|
|
|
|
|
++$nwsecs;
|
|
|
|
|
$nwlist[$nwsecs] = wfEscapeHTMLTagsOnly($q[0]);
|
2003-12-08 04:28:10 +00:00
|
|
|
$stripped .= $unique . $nwsecs . "s";
|
2003-04-14 23:10:40 +00:00
|
|
|
$text = $q[1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( $wgUseTeX ) {
|
|
|
|
|
while ( "" != $stripped ) {
|
|
|
|
|
$p = preg_split( "/<\\s*math\\s*>/i", $stripped, 2 );
|
|
|
|
|
$stripped2 .= $p[0];
|
|
|
|
|
if ( ( count( $p ) < 2 ) || ( "" == $p[1] ) ) { $stripped = ""; }
|
|
|
|
|
else {
|
|
|
|
|
$q = preg_split( "/<\\/\\s*math\\s*>/i", $p[1], 2 );
|
|
|
|
|
++$mathsecs;
|
|
|
|
|
$mathlist[$mathsecs] = renderMath($q[0]);
|
2003-12-08 04:28:10 +00:00
|
|
|
$stripped2 .= $unique2 . $mathsecs . "s";
|
2003-04-14 23:10:40 +00:00
|
|
|
$stripped = $q[1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$stripped2 = $stripped;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while ( "" != $stripped2 ) {
|
|
|
|
|
$p = preg_split( "/<\\s*pre\\s*>/i", $stripped2, 2 );
|
|
|
|
|
$stripped3 .= $p[0];
|
|
|
|
|
if ( ( count( $p ) < 2 ) || ( "" == $p[1] ) ) { $stripped2 = ""; }
|
|
|
|
|
else {
|
|
|
|
|
$q = preg_split( "/<\\/\\s*pre\\s*>/i", $p[1], 2 );
|
|
|
|
|
++$presecs;
|
2004-01-06 19:44:04 +00:00
|
|
|
$prelist[$presecs] = "<pre>". wfEscapeHTMLTagsOnly($q[0]). "</pre>\n";
|
2003-12-08 04:28:10 +00:00
|
|
|
$stripped3 .= $unique3 . $presecs . "s";
|
2003-04-14 23:10:40 +00:00
|
|
|
$stripped2 = $q[1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$text = $this->doWikiPass2( $stripped3, $linestart );
|
2003-07-05 01:12:22 +00:00
|
|
|
|
|
|
|
|
$specialChars = array("\\", "$");
|
|
|
|
|
$escapedChars = array("\\\\", "\\$");
|
2003-04-14 23:10:40 +00:00
|
|
|
for ( $i = 1; $i <= $presecs; ++$i ) {
|
2003-12-08 04:28:10 +00:00
|
|
|
$text = preg_replace( "/{$unique3}{$i}s/", str_replace( $specialChars,
|
|
|
|
|
$escapedChars, $prelist[$i] ), $text );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( $i = 1; $i <= $mathsecs; ++$i ) {
|
2003-12-08 04:28:10 +00:00
|
|
|
$text = preg_replace( "/{$unique2}{$i}s/", str_replace( $specialChars,
|
|
|
|
|
$escapedChars, $mathlist[$i] ), $text );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( $i = 1; $i <= $nwsecs; ++$i ) {
|
2003-12-08 04:28:10 +00:00
|
|
|
$text = preg_replace( "/{$unique}{$i}s/", str_replace( $specialChars,
|
|
|
|
|
$escapedChars, $nwlist[$i] ), $text );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
$this->addHTML( $text );
|
2004-01-07 02:51:47 +00:00
|
|
|
|
|
|
|
|
if($use_parser_cache ){
|
|
|
|
|
$this->saveParserCache( $text );
|
|
|
|
|
}
|
2003-10-16 13:30:45 +00:00
|
|
|
wfProfileOut( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2003-07-03 10:18:07 +00:00
|
|
|
function sendCacheControl() {
|
2003-08-20 07:45:18 +00:00
|
|
|
global $wgUseGzip;
|
2003-07-03 10:18:07 +00:00
|
|
|
if( $this->mLastModified != "" ) {
|
2003-07-10 04:55:41 +00:00
|
|
|
wfDebug( "** private caching; {$this->mLastModified} **\n", false );
|
2003-07-03 10:18:07 +00:00
|
|
|
header( "Cache-Control: private, must-revalidate, max-age=0" );
|
|
|
|
|
header( "Last-modified: {$this->mLastModified}" );
|
2003-08-20 07:45:18 +00:00
|
|
|
if( $wgUseGzip ) {
|
|
|
|
|
# We should put in Accept-Encoding, but IE chokes on anything but
|
|
|
|
|
# User-Agent in a Vary: header (at least through 6.0)
|
|
|
|
|
header( "Vary: User-Agent" );
|
|
|
|
|
}
|
2003-07-03 10:18:07 +00:00
|
|
|
} else {
|
2003-07-10 04:55:41 +00:00
|
|
|
wfDebug( "** no caching **\n", false );
|
2003-07-03 10:18:07 +00:00
|
|
|
header( "Cache-Control: no-cache" ); # Experimental - see below
|
|
|
|
|
header( "Pragma: no-cache" );
|
|
|
|
|
header( "Last-modified: " . gmdate( "D, j M Y H:i:s" ) . " GMT" );
|
|
|
|
|
}
|
|
|
|
|
header( "Expires: Mon, 15 Jan 2001 00:00:00 GMT" ); # Cachers always validate the page!
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
# Finally, all the text has been munged and accumulated into
|
|
|
|
|
# the object, let's actually output it:
|
|
|
|
|
#
|
|
|
|
|
function output()
|
|
|
|
|
{
|
|
|
|
|
global $wgUser, $wgLang, $wgDebugComments, $wgCookieExpiration;
|
|
|
|
|
global $wgInputEncoding, $wgOutputEncoding, $wgLanguageCode;
|
2003-12-11 20:16:34 +00:00
|
|
|
if( $this->mDoNothing ){
|
|
|
|
|
return;
|
|
|
|
|
}
|
2003-10-25 08:01:33 +00:00
|
|
|
$fname = "OutputPage::output";
|
|
|
|
|
wfProfileIn( $fname );
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
|
|
2003-07-03 10:18:07 +00:00
|
|
|
$this->sendCacheControl();
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
header( "Content-type: text/html; charset={$wgOutputEncoding}" );
|
|
|
|
|
header( "Content-language: {$wgLanguageCode}" );
|
|
|
|
|
|
|
|
|
|
if ( "" != $this->mRedirect ) {
|
2003-12-22 10:21:18 +00:00
|
|
|
if( substr( $this->mRedirect, 0, 4 ) != "http" ) {
|
|
|
|
|
# Standards require redirect URLs to be absolute
|
|
|
|
|
global $wgServer;
|
|
|
|
|
$this->mRedirect = $wgServer . $this->mRedirect;
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
header( "Location: {$this->mRedirect}" );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$exp = time() + $wgCookieExpiration;
|
|
|
|
|
foreach( $this->mCookies as $name => $val ) {
|
|
|
|
|
setcookie( $name, $val, $exp, "/" );
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-11 12:21:03 +00:00
|
|
|
$sk->outputPage( $this );
|
2004-01-10 19:42:33 +00:00
|
|
|
# flush();
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function out( $ins )
|
|
|
|
|
{
|
|
|
|
|
global $wgInputEncoding, $wgOutputEncoding, $wgLang;
|
|
|
|
|
if ( 0 == strcmp( $wgInputEncoding, $wgOutputEncoding ) ) {
|
|
|
|
|
$outs = $ins;
|
|
|
|
|
} else {
|
|
|
|
|
$outs = $wgLang->iconv( $wgInputEncoding, $wgOutputEncoding, $ins );
|
|
|
|
|
if ( false === $outs ) { $outs = $ins; }
|
|
|
|
|
}
|
|
|
|
|
print $outs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setEncodings()
|
|
|
|
|
{
|
2003-11-18 02:39:38 +00:00
|
|
|
global $wgInputEncoding, $wgOutputEncoding;
|
2003-04-14 23:10:40 +00:00
|
|
|
global $wgUser, $wgLang;
|
|
|
|
|
|
|
|
|
|
$wgInputEncoding = strtolower( $wgInputEncoding );
|
|
|
|
|
|
|
|
|
|
if( $wgUser->getOption( 'altencoding' ) ) {
|
|
|
|
|
$wgLang->setAltEncoding();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-15 23:06:59 +00:00
|
|
|
if ( empty( $_SERVER['HTTP_ACCEPT_CHARSET'] ) ) {
|
2003-04-14 23:10:40 +00:00
|
|
|
$wgOutputEncoding = strtolower( $wgOutputEncoding );
|
|
|
|
|
return;
|
|
|
|
|
}
|
2003-11-15 23:06:59 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
# This code is unused anyway!
|
|
|
|
|
# Commenting out. --bv 2003-11-15
|
|
|
|
|
|
|
|
|
|
$a = explode( ",", $_SERVER['HTTP_ACCEPT_CHARSET'] );
|
2003-04-14 23:10:40 +00:00
|
|
|
$best = 0.0;
|
|
|
|
|
$bestset = "*";
|
|
|
|
|
|
|
|
|
|
foreach ( $a as $s ) {
|
|
|
|
|
if ( preg_match( "/(.*);q=(.*)/", $s, $m ) ) {
|
|
|
|
|
$set = $m[1];
|
|
|
|
|
$q = (float)($m[2]);
|
|
|
|
|
} else {
|
|
|
|
|
$set = $s;
|
|
|
|
|
$q = 1.0;
|
|
|
|
|
}
|
|
|
|
|
if ( $q > $best ) {
|
|
|
|
|
$bestset = $set;
|
|
|
|
|
$best = $q;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#if ( "*" == $bestset ) { $bestset = "iso-8859-1"; }
|
|
|
|
|
if ( "*" == $bestset ) { $bestset = $wgOutputEncoding; }
|
|
|
|
|
$wgOutputEncoding = strtolower( $bestset );
|
|
|
|
|
|
|
|
|
|
# Disable for now
|
|
|
|
|
#
|
2003-11-15 23:06:59 +00:00
|
|
|
*/
|
2003-04-14 23:10:40 +00:00
|
|
|
$wgOutputEncoding = $wgInputEncoding;
|
|
|
|
|
}
|
|
|
|
|
|
2003-12-11 20:16:34 +00:00
|
|
|
# Returns a HTML comment with the elapsed time since request.
|
|
|
|
|
# This method has no side effects.
|
2003-04-14 23:10:40 +00:00
|
|
|
function reportTime()
|
|
|
|
|
{
|
2003-12-11 20:16:34 +00:00
|
|
|
global $wgRequestTime;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
list( $usec, $sec ) = explode( " ", microtime() );
|
|
|
|
|
$now = (float)$sec + (float)$usec;
|
|
|
|
|
|
|
|
|
|
list( $usec, $sec ) = explode( " ", $wgRequestTime );
|
|
|
|
|
$start = (float)$sec + (float)$usec;
|
|
|
|
|
$elapsed = $now - $start;
|
|
|
|
|
$com = sprintf( "<!-- Time since request: %01.2f secs. -->",
|
|
|
|
|
$elapsed );
|
|
|
|
|
return $com;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Note: these arguments are keys into wfMsg(), not text!
|
|
|
|
|
#
|
|
|
|
|
function errorpage( $title, $msg )
|
|
|
|
|
{
|
|
|
|
|
global $wgTitle;
|
|
|
|
|
|
|
|
|
|
$this->mDebugtext .= "Original title: " .
|
|
|
|
|
$wgTitle->getPrefixedText() . "\n";
|
|
|
|
|
$this->setHTMLTitle( wfMsg( "errorpagetitle" ) );
|
|
|
|
|
$this->setPageTitle( wfMsg( $title ) );
|
|
|
|
|
$this->setRobotpolicy( "noindex,nofollow" );
|
|
|
|
|
$this->setArticleFlag( false );
|
|
|
|
|
|
|
|
|
|
$this->mBodytext = "";
|
|
|
|
|
$this->addHTML( "<p>" . wfMsg( $msg ) . "\n" );
|
|
|
|
|
$this->returnToMain( false );
|
|
|
|
|
|
|
|
|
|
$this->output();
|
2003-12-10 15:05:08 +00:00
|
|
|
wfAbruptExit();
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function sysopRequired()
|
|
|
|
|
{
|
|
|
|
|
global $wgUser;
|
|
|
|
|
|
|
|
|
|
$this->setHTMLTitle( wfMsg( "errorpagetitle" ) );
|
|
|
|
|
$this->setPageTitle( wfMsg( "sysoptitle" ) );
|
|
|
|
|
$this->setRobotpolicy( "noindex,nofollow" );
|
|
|
|
|
$this->setArticleFlag( false );
|
|
|
|
|
$this->mBodytext = "";
|
|
|
|
|
|
|
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
|
$ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
|
2003-11-15 14:32:58 +00:00
|
|
|
$this->addHTML( wfMsg( "sysoptext", $ap ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->returnToMain();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function developerRequired()
|
|
|
|
|
{
|
|
|
|
|
global $wgUser;
|
|
|
|
|
|
|
|
|
|
$this->setHTMLTitle( wfMsg( "errorpagetitle" ) );
|
|
|
|
|
$this->setPageTitle( wfMsg( "developertitle" ) );
|
|
|
|
|
$this->setRobotpolicy( "noindex,nofollow" );
|
|
|
|
|
$this->setArticleFlag( false );
|
|
|
|
|
$this->mBodytext = "";
|
|
|
|
|
|
|
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
|
$ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
|
2003-11-15 14:32:58 +00:00
|
|
|
$this->addHTML( wfMsg( "developertext", $ap ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->returnToMain();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function databaseError( $fname )
|
|
|
|
|
{
|
2003-04-16 07:30:52 +00:00
|
|
|
global $wgUser, $wgCommandLineMode;
|
2003-09-21 13:10:10 +00:00
|
|
|
|
|
|
|
|
$this->setPageTitle( wfMsgNoDB( "databaseerror" ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->setRobotpolicy( "noindex,nofollow" );
|
|
|
|
|
$this->setArticleFlag( false );
|
|
|
|
|
|
2003-04-16 07:30:52 +00:00
|
|
|
if ( $wgCommandLineMode ) {
|
2003-09-21 13:10:10 +00:00
|
|
|
$msg = wfMsgNoDB( "dberrortextcl" );
|
2003-04-16 07:30:52 +00:00
|
|
|
} else {
|
2003-11-15 14:32:58 +00:00
|
|
|
$msg = wfMsgNoDB( "dberrortext" );
|
2003-04-16 07:30:52 +00:00
|
|
|
}
|
2003-09-21 13:10:10 +00:00
|
|
|
|
2003-04-16 07:30:52 +00:00
|
|
|
$msg = str_replace( "$1", htmlspecialchars( wfLastDBquery() ), $msg );
|
2003-04-14 23:10:40 +00:00
|
|
|
$msg = str_replace( "$2", htmlspecialchars( $fname ), $msg );
|
|
|
|
|
$msg = str_replace( "$3", wfLastErrno(), $msg );
|
|
|
|
|
$msg = str_replace( "$4", htmlspecialchars( wfLastError() ), $msg );
|
2003-09-21 13:10:10 +00:00
|
|
|
|
2003-04-16 07:30:52 +00:00
|
|
|
if ( $wgCommandLineMode ) {
|
2003-09-21 13:10:10 +00:00
|
|
|
print "$msg\n";
|
2003-12-10 15:05:08 +00:00
|
|
|
wfAbruptExit();
|
2003-04-16 07:30:52 +00:00
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
$sk = $wgUser->getSkin();
|
2003-09-21 13:10:10 +00:00
|
|
|
$shlink = $sk->makeKnownLink( wfMsgNoDB( "searchhelppage" ),
|
|
|
|
|
wfMsgNoDB( "searchingwikipedia" ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
$msg = str_replace( "$5", $shlink, $msg );
|
|
|
|
|
|
|
|
|
|
$this->mBodytext = $msg;
|
|
|
|
|
$this->output();
|
2003-12-10 15:05:08 +00:00
|
|
|
wfAbruptExit();
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
function readOnlyPage( $source = "", $protected = false )
|
2003-04-14 23:10:40 +00:00
|
|
|
{
|
|
|
|
|
global $wgUser, $wgReadOnlyFile;
|
|
|
|
|
|
|
|
|
|
$this->setRobotpolicy( "noindex,nofollow" );
|
|
|
|
|
$this->setArticleFlag( false );
|
|
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
if( $protected ) {
|
|
|
|
|
$this->setPageTitle( wfMsg( "viewsource" ) );
|
|
|
|
|
$this->addWikiText( wfMsg( "protectedtext" ) );
|
|
|
|
|
} else {
|
|
|
|
|
$this->setPageTitle( wfMsg( "readonly" ) );
|
|
|
|
|
$reason = file_get_contents( $wgReadOnlyFile );
|
|
|
|
|
$this->addHTML( wfMsg( "readonlytext", $reason ) );
|
|
|
|
|
}
|
2003-09-09 05:46:22 +00:00
|
|
|
|
|
|
|
|
if($source) {
|
|
|
|
|
$rows = $wgUser->getOption( "rows" );
|
|
|
|
|
$cols = $wgUser->getOption( "cols" );
|
|
|
|
|
$text .= "</p>\n<textarea cols='$cols' rows='$rows' readonly>" .
|
|
|
|
|
htmlspecialchars( $source ) . "\n</textarea>";
|
2003-11-09 11:45:12 +00:00
|
|
|
$this->addHTML( $text );
|
2003-09-09 05:46:22 +00:00
|
|
|
}
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->returnToMain( false );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fatalError( $message )
|
|
|
|
|
{
|
|
|
|
|
$this->setPageTitle( wfMsg( "internalerror" ) );
|
|
|
|
|
$this->setRobotpolicy( "noindex,nofollow" );
|
|
|
|
|
$this->setArticleFlag( false );
|
|
|
|
|
|
|
|
|
|
$this->mBodytext = $message;
|
|
|
|
|
$this->output();
|
2003-12-10 15:05:08 +00:00
|
|
|
wfAbruptExit();
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function unexpectedValueError( $name, $val )
|
|
|
|
|
{
|
2003-11-15 14:32:58 +00:00
|
|
|
$this->fatalError( wfMsg( "unexpected", $name, $val ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fileCopyError( $old, $new )
|
|
|
|
|
{
|
2003-11-15 14:32:58 +00:00
|
|
|
$this->fatalError( wfMsg( "filecopyerror", $old, $new ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fileRenameError( $old, $new )
|
|
|
|
|
{
|
2003-11-15 14:32:58 +00:00
|
|
|
$this->fatalError( wfMsg( "filerenameerror", $old, $new ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fileDeleteError( $name )
|
|
|
|
|
{
|
2003-11-15 14:32:58 +00:00
|
|
|
$this->fatalError( wfMsg( "filedeleteerror", $name ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fileNotFoundError( $name )
|
|
|
|
|
{
|
2003-11-15 14:32:58 +00:00
|
|
|
$this->fatalError( wfMsg( "filenotfound", $name ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function returnToMain( $auto = true )
|
|
|
|
|
{
|
|
|
|
|
global $wgUser, $wgOut, $returnto;
|
|
|
|
|
|
|
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
|
if ( "" == $returnto ) {
|
|
|
|
|
$returnto = wfMsg( "mainpage" );
|
|
|
|
|
}
|
|
|
|
|
$link = $sk->makeKnownLink( $returnto, "" );
|
|
|
|
|
|
2003-11-15 14:32:58 +00:00
|
|
|
$r = wfMsg( "returnto", $link );
|
2003-04-14 23:10:40 +00:00
|
|
|
if ( $auto ) {
|
|
|
|
|
$wgOut->addMeta( "http:Refresh", "10;url=" .
|
|
|
|
|
wfLocalUrlE( wfUrlencode( $returnto ) ) );
|
|
|
|
|
}
|
|
|
|
|
$wgOut->addHTML( "\n<p>$r\n" );
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-11 07:02:22 +00:00
|
|
|
|
2003-08-31 14:30:24 +00:00
|
|
|
function categoryMagic ()
|
|
|
|
|
{
|
|
|
|
|
global $wgTitle , $wgUseCategoryMagic ;
|
|
|
|
|
if ( !isset ( $wgUseCategoryMagic ) || !$wgUseCategoryMagic ) return ;
|
|
|
|
|
$id = $wgTitle->getArticleID() ;
|
|
|
|
|
$cat = ucfirst ( wfMsg ( "category" ) ) ;
|
|
|
|
|
$ti = $wgTitle->getText() ;
|
|
|
|
|
$ti = explode ( ":" , $ti , 2 ) ;
|
|
|
|
|
if ( $cat != $ti[0] ) return "" ;
|
|
|
|
|
$r = "<br break=all>\n" ;
|
|
|
|
|
|
|
|
|
|
$articles = array() ;
|
|
|
|
|
$parents = array () ;
|
|
|
|
|
$children = array() ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
global $wgUser ;
|
|
|
|
|
$sk = $wgUser->getSkin() ;
|
|
|
|
|
$sql = "SELECT l_from FROM links WHERE l_to={$id}" ;
|
2003-09-20 01:34:06 +00:00
|
|
|
$res = wfQuery ( $sql, DB_READ ) ;
|
2003-08-31 14:30:24 +00:00
|
|
|
while ( $x = wfFetchObject ( $res ) )
|
|
|
|
|
{
|
|
|
|
|
# $t = new Title ;
|
|
|
|
|
# $t->newFromDBkey ( $x->l_from ) ;
|
|
|
|
|
# $t = $t->getText() ;
|
|
|
|
|
$t = $x->l_from ;
|
|
|
|
|
$y = explode ( ":" , $t , 2 ) ;
|
2003-10-22 23:56:49 +00:00
|
|
|
if ( count ( $y ) == 2 && $y[0] == $cat ) {
|
2003-08-31 14:30:24 +00:00
|
|
|
array_push ( $children , $sk->makeLink ( $t , $y[1] ) ) ;
|
2003-10-22 23:56:49 +00:00
|
|
|
} else {
|
|
|
|
|
array_push ( $articles , $sk->makeLink ( $t ) ) ;
|
2003-08-31 14:30:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
wfFreeResult ( $res ) ;
|
|
|
|
|
|
|
|
|
|
# Children
|
|
|
|
|
if ( count ( $children ) > 0 )
|
|
|
|
|
{
|
|
|
|
|
asort ( $children ) ;
|
|
|
|
|
$r .= "<h2>".wfMsg("subcategories")."</h2>\n" ;
|
|
|
|
|
$r .= implode ( ", " , $children ) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Articles
|
|
|
|
|
if ( count ( $articles ) > 0 )
|
|
|
|
|
{
|
|
|
|
|
asort ( $articles ) ;
|
2003-11-15 14:32:58 +00:00
|
|
|
$h = wfMsg( "category_header", $ti[1] );
|
2003-08-31 14:30:24 +00:00
|
|
|
$r .= "<h2>{$h}</h2>\n" ;
|
|
|
|
|
$r .= implode ( ", " , $articles ) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return $r ;
|
|
|
|
|
}
|
2003-07-11 07:02:22 +00:00
|
|
|
|
2003-09-17 08:38:14 +00:00
|
|
|
function getHTMLattrs ()
|
2003-09-17 08:20:16 +00:00
|
|
|
{
|
2003-09-17 08:38:14 +00:00
|
|
|
$htmlattrs = array( # Allowed attributes--no scripting, etc.
|
|
|
|
|
"title", "align", "lang", "dir", "width", "height",
|
|
|
|
|
"bgcolor", "clear", /* BR */ "noshade", /* HR */
|
|
|
|
|
"cite", /* BLOCKQUOTE, Q */ "size", "face", "color",
|
|
|
|
|
/* FONT */ "type", "start", "value", "compact",
|
|
|
|
|
/* For various lists, mostly deprecated but safe */
|
|
|
|
|
"summary", "width", "border", "frame", "rules",
|
|
|
|
|
"cellspacing", "cellpadding", "valign", "char",
|
|
|
|
|
"charoff", "colgroup", "col", "span", "abbr", "axis",
|
|
|
|
|
"headers", "scope", "rowspan", "colspan", /* Tables */
|
|
|
|
|
"id", "class", "name", "style" /* For CSS */
|
|
|
|
|
);
|
|
|
|
|
return $htmlattrs ;
|
2003-09-17 08:20:16 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-17 07:33:44 +00:00
|
|
|
function fixTagAttributes ( $t )
|
2003-09-17 08:20:16 +00:00
|
|
|
{
|
2004-01-17 07:33:44 +00:00
|
|
|
if ( trim ( $t ) == "" ) return "" ; # Saves runtime ;-)
|
|
|
|
|
$htmlattrs = $this->getHTMLattrs() ;
|
2003-09-17 08:38:14 +00:00
|
|
|
|
2004-01-17 07:33:44 +00:00
|
|
|
# Strip non-approved attributes from the tag
|
|
|
|
|
$t = preg_replace(
|
|
|
|
|
"/(\\w+)(\\s*=\\s*([^\\s\">]+|\"[^\">]*\"))?/e",
|
|
|
|
|
"(in_array(strtolower(\"\$1\"),\$htmlattrs)?(\"\$1\".((\"x\$3\" != \"x\")?\"=\$3\":'')):'')",
|
|
|
|
|
$t);
|
|
|
|
|
# Strip javascript "expression" from stylesheets. Brute force approach:
|
|
|
|
|
# If anythin offensive is found, all attributes of the HTML tag are dropped
|
|
|
|
|
|
|
|
|
|
if( preg_match(
|
|
|
|
|
"/style\\s*=.*(expression|tps*:\/\/|url\\s*\().*/is",
|
|
|
|
|
wfMungeToUtf8( $t ) ) )
|
|
|
|
|
{
|
|
|
|
|
$t="";
|
|
|
|
|
}
|
2003-09-17 08:38:14 +00:00
|
|
|
|
2004-01-17 07:33:44 +00:00
|
|
|
return trim ( $t ) ;
|
2003-09-17 08:20:16 +00:00
|
|
|
}
|
|
|
|
|
|
2003-09-08 07:52:03 +00:00
|
|
|
function doTableStuff ( $t )
|
|
|
|
|
{
|
|
|
|
|
$t = explode ( "\n" , $t ) ;
|
|
|
|
|
$td = array () ; # Is currently a td tag open?
|
2003-09-16 08:07:34 +00:00
|
|
|
$ltd = array () ; # Was it TD or TH?
|
2003-09-17 12:40:54 +00:00
|
|
|
$tr = array () ; # Is currently a tr tag open?
|
|
|
|
|
$ltr = array () ; # tr attributes
|
2003-09-08 07:52:03 +00:00
|
|
|
foreach ( $t AS $k => $x )
|
|
|
|
|
{
|
|
|
|
|
$x = rtrim ( $x ) ;
|
2003-09-16 08:07:34 +00:00
|
|
|
$fc = substr ( $x , 0 , 1 ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
if ( "{|" == substr ( $x , 0 , 2 ) )
|
|
|
|
|
{
|
2004-01-17 07:33:44 +00:00
|
|
|
$t[$k] = "<table " . $this->fixTagAttributes ( substr ( $x , 3 ) ) . ">" ;
|
2003-09-08 07:52:03 +00:00
|
|
|
array_push ( $td , false ) ;
|
2003-09-16 08:07:34 +00:00
|
|
|
array_push ( $ltd , "" ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
array_push ( $tr , false ) ;
|
2003-09-17 12:40:54 +00:00
|
|
|
array_push ( $ltr , "" ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
}
|
|
|
|
|
else if ( count ( $td ) == 0 ) { } # Don't do any of the following
|
|
|
|
|
else if ( "|}" == substr ( $x , 0 , 2 ) )
|
|
|
|
|
{
|
|
|
|
|
$z = "</table>\n" ;
|
2003-09-16 08:07:34 +00:00
|
|
|
$l = array_pop ( $ltd ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
if ( array_pop ( $tr ) ) $z = "</tr>" . $z ;
|
2003-09-16 08:07:34 +00:00
|
|
|
if ( array_pop ( $td ) ) $z = "</{$l}>" . $z ;
|
2003-09-17 12:40:54 +00:00
|
|
|
array_pop ( $ltr ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
$t[$k] = $z ;
|
|
|
|
|
}
|
2003-09-17 12:40:54 +00:00
|
|
|
/* else if ( "|_" == substr ( $x , 0 , 2 ) ) # Caption
|
2003-09-16 08:07:34 +00:00
|
|
|
{
|
|
|
|
|
$z = trim ( substr ( $x , 2 ) ) ;
|
|
|
|
|
$t[$k] = "<caption>{$z}</caption>\n" ;
|
2003-09-17 12:40:54 +00:00
|
|
|
}*/
|
2003-09-08 07:52:03 +00:00
|
|
|
else if ( "|-" == substr ( $x , 0 , 2 ) ) # Allows for |---------------
|
|
|
|
|
{
|
2003-09-17 12:40:54 +00:00
|
|
|
$x = substr ( $x , 1 ) ;
|
|
|
|
|
while ( $x != "" && substr ( $x , 0 , 1 ) == '-' ) $x = substr ( $x , 1 ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
$z = "" ;
|
2003-09-16 08:07:34 +00:00
|
|
|
$l = array_pop ( $ltd ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
if ( array_pop ( $tr ) ) $z = "</tr>" . $z ;
|
2003-09-16 08:07:34 +00:00
|
|
|
if ( array_pop ( $td ) ) $z = "</{$l}>" . $z ;
|
2003-09-17 12:40:54 +00:00
|
|
|
array_pop ( $ltr ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
$t[$k] = $z ;
|
|
|
|
|
array_push ( $tr , false ) ;
|
|
|
|
|
array_push ( $td , false ) ;
|
2003-09-16 08:07:34 +00:00
|
|
|
array_push ( $ltd , "" ) ;
|
2004-01-17 07:33:44 +00:00
|
|
|
array_push ( $ltr , $this->fixTagAttributes ( $x ) ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
}
|
2003-09-17 12:40:54 +00:00
|
|
|
else if ( "|" == $fc || "!" == $fc || "|+" == substr ( $x , 0 , 2 ) ) # Caption
|
2003-09-08 07:52:03 +00:00
|
|
|
{
|
2003-09-17 12:40:54 +00:00
|
|
|
if ( "|+" == substr ( $x , 0 , 2 ) )
|
|
|
|
|
{
|
|
|
|
|
$fc = "+" ;
|
|
|
|
|
$x = substr ( $x , 1 ) ;
|
|
|
|
|
}
|
2003-09-08 07:52:03 +00:00
|
|
|
$after = substr ( $x , 1 ) ;
|
2003-09-16 08:07:34 +00:00
|
|
|
if ( $fc == "!" ) $after = str_replace ( "!!" , "||" , $after ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
$after = explode ( "||" , $after ) ;
|
|
|
|
|
$t[$k] = "" ;
|
|
|
|
|
foreach ( $after AS $theline )
|
|
|
|
|
{
|
|
|
|
|
$z = "" ;
|
2003-09-17 12:40:54 +00:00
|
|
|
$tra = array_pop ( $ltr ) ;
|
|
|
|
|
if ( !array_pop ( $tr ) ) $z = "<tr {$tra}>\n" ;
|
2003-09-08 07:52:03 +00:00
|
|
|
array_push ( $tr , true ) ;
|
2003-09-17 12:40:54 +00:00
|
|
|
array_push ( $ltr , "" ) ;
|
2003-09-16 08:07:34 +00:00
|
|
|
|
|
|
|
|
$l = array_pop ( $ltd ) ;
|
|
|
|
|
if ( array_pop ( $td ) ) $z = "</{$l}>" . $z ;
|
|
|
|
|
if ( $fc == "|" ) $l = "TD" ;
|
|
|
|
|
else if ( $fc == "!" ) $l = "TH" ;
|
2003-09-17 12:40:54 +00:00
|
|
|
else if ( $fc == "+" ) $l = "CAPTION" ;
|
2003-09-16 08:07:34 +00:00
|
|
|
else $l = "" ;
|
|
|
|
|
array_push ( $ltd , $l ) ;
|
2003-09-08 07:52:03 +00:00
|
|
|
$y = explode ( "|" , $theline , 2 ) ;
|
2003-09-16 08:07:34 +00:00
|
|
|
if ( count ( $y ) == 1 ) $y = "{$z}<{$l}>{$y[0]}" ;
|
2004-01-17 07:33:44 +00:00
|
|
|
else $y = $y = "{$z}<{$l} ".$this->fixTagAttributes($y[0]).">{$y[1]}" ;
|
2003-09-08 07:52:03 +00:00
|
|
|
$t[$k] .= $y ;
|
|
|
|
|
array_push ( $td , true ) ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-09-12 07:13:48 +00:00
|
|
|
|
2003-09-16 13:26:09 +00:00
|
|
|
# Closing open td, tr && table
|
|
|
|
|
while ( count ( $td ) > 0 )
|
|
|
|
|
{
|
|
|
|
|
if ( array_pop ( $td ) ) $t[] = "</td>" ;
|
|
|
|
|
if ( array_pop ( $tr ) ) $t[] = "</tr>" ;
|
|
|
|
|
$t[] = "</table>" ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$t = implode ( "\n" , $t ) ;
|
2003-09-17 12:40:54 +00:00
|
|
|
# $t = $this->removeHTMLtags( $t );
|
2003-09-16 13:26:09 +00:00
|
|
|
return $t ;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
# Well, OK, it's actually about 14 passes. But since all the
|
|
|
|
|
# hard lifting is done inside PHP's regex code, it probably
|
|
|
|
|
# wouldn't speed things up much to add a real parser.
|
|
|
|
|
#
|
|
|
|
|
function doWikiPass2( $text, $linestart )
|
|
|
|
|
{
|
2003-07-06 02:48:06 +00:00
|
|
|
global $wgUser, $wgLang, $wgUseDynamicDates;
|
2003-10-16 13:30:45 +00:00
|
|
|
$fname = "OutputPage::doWikiPass2";
|
|
|
|
|
wfProfileIn( $fname );
|
2003-07-01 12:47:44 +00:00
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
$text = $this->removeHTMLtags( $text );
|
|
|
|
|
$text = $this->replaceVariables( $text );
|
|
|
|
|
|
|
|
|
|
$text = preg_replace( "/(^|\n)-----*/", "\\1<hr>", $text );
|
|
|
|
|
$text = str_replace ( "<HR>", "<hr>", $text );
|
|
|
|
|
|
2004-01-05 01:14:14 +00:00
|
|
|
$text = $this->doAllQuotes( $text );
|
|
|
|
|
$text = $this->doHeadings( $text );
|
|
|
|
|
$text = $this->doBlockLevels( $text, $linestart );
|
|
|
|
|
|
|
|
|
|
if($wgUseDynamicDates) {
|
|
|
|
|
global $wgDateFormatter;
|
|
|
|
|
$text = $wgDateFormatter->reformat( $wgUser->getOption("date"), $text );
|
|
|
|
|
}
|
2003-07-06 02:48:06 +00:00
|
|
|
|
2004-01-05 01:14:14 +00:00
|
|
|
$text = $this->replaceExternalLinks( $text );
|
|
|
|
|
$text = $this->replaceInternalLinks ( $text );
|
|
|
|
|
$text = $this->doTableStuff ( $text ) ;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
$text = $this->magicISBN( $text );
|
|
|
|
|
$text = $this->magicRFC( $text );
|
2003-06-30 00:19:35 +00:00
|
|
|
$text = $this->formatHeadings( $text );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
|
$text = $sk->transformContent( $text );
|
2003-11-15 07:14:05 +00:00
|
|
|
$text .= $this->categoryMagic () ;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2003-10-16 13:30:45 +00:00
|
|
|
wfProfileOut( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-11 02:11:08 +00:00
|
|
|
/* private */ function doAllQuotes( $text )
|
2003-04-14 23:10:40 +00:00
|
|
|
{
|
2003-07-11 02:11:08 +00:00
|
|
|
$outtext = "";
|
|
|
|
|
$lines = explode( "\r\n", $text );
|
|
|
|
|
foreach ( $lines as $line ) {
|
|
|
|
|
$outtext .= $this->doQuotes ( "", $line, "" ) . "\r\n";
|
|
|
|
|
}
|
|
|
|
|
return $outtext;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function doQuotes( $pre, $text, $mode )
|
|
|
|
|
{
|
|
|
|
|
if ( preg_match( "/^(.*)''(.*)$/sU", $text, $m ) ) {
|
|
|
|
|
$m1_strong = ($m[1] == "") ? "" : "<strong>{$m[1]}</strong>";
|
|
|
|
|
$m1_em = ($m[1] == "") ? "" : "<em>{$m[1]}</em>";
|
|
|
|
|
if ( substr ($m[2], 0, 1) == "'" ) {
|
|
|
|
|
$m[2] = substr ($m[2], 1);
|
|
|
|
|
if ($mode == "em") {
|
|
|
|
|
return $this->doQuotes ( $m[1], $m[2], ($m[1] == "") ? "both" : "emstrong" );
|
|
|
|
|
} else if ($mode == "strong") {
|
|
|
|
|
return $m1_strong . $this->doQuotes ( "", $m[2], "" );
|
|
|
|
|
} else if (($mode == "emstrong") || ($mode == "both")) {
|
|
|
|
|
return $this->doQuotes ( "", $pre.$m1_strong.$m[2], "em" );
|
|
|
|
|
} else if ($mode == "strongem") {
|
|
|
|
|
return "<strong>{$pre}{$m1_em}</strong>" . $this->doQuotes ( "", $m[2], "em" );
|
|
|
|
|
} else {
|
|
|
|
|
return $m[1] . $this->doQuotes ( "", $m[2], "strong" );
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if ($mode == "strong") {
|
|
|
|
|
return $this->doQuotes ( $m[1], $m[2], ($m[1] == "") ? "both" : "strongem" );
|
|
|
|
|
} else if ($mode == "em") {
|
|
|
|
|
return $m1_em . $this->doQuotes ( "", $m[2], "" );
|
|
|
|
|
} else if ($mode == "emstrong") {
|
|
|
|
|
return "<em>{$pre}{$m1_strong}</em>" . $this->doQuotes ( "", $m[2], "strong" );
|
|
|
|
|
} else if (($mode == "strongem") || ($mode == "both")) {
|
|
|
|
|
return $this->doQuotes ( "", $pre.$m1_em.$m[2], "strong" );
|
|
|
|
|
} else {
|
|
|
|
|
return $m[1] . $this->doQuotes ( "", $m[2], "em" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$text_strong = ($text == "") ? "" : "<strong>{$text}</strong>";
|
|
|
|
|
$text_em = ($text == "") ? "" : "<em>{$text}</em>";
|
|
|
|
|
if ($mode == "") {
|
|
|
|
|
return $pre . $text;
|
|
|
|
|
} else if ($mode == "em") {
|
|
|
|
|
return $pre . $text_em;
|
|
|
|
|
} else if ($mode == "strong") {
|
|
|
|
|
return $pre . $text_strong;
|
|
|
|
|
} else if ($mode == "strongem") {
|
|
|
|
|
return (($pre == "") && ($text == "")) ? "" : "<strong>{$pre}{$text_em}</strong>";
|
|
|
|
|
} else {
|
|
|
|
|
return (($pre == "") && ($text == "")) ? "" : "<em>{$pre}{$text_strong}</em>";
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function doHeadings( $text )
|
|
|
|
|
{
|
|
|
|
|
for ( $i = 6; $i >= 1; --$i ) {
|
|
|
|
|
$h = substr( "======", 0, $i );
|
|
|
|
|
$text = preg_replace( "/^{$h}([^=]+){$h}(\\s|$)/m",
|
|
|
|
|
"<h{$i}>\\1</h{$i}>\\2", $text );
|
|
|
|
|
}
|
|
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Note: we have to do external links before the internal ones,
|
|
|
|
|
# and otherwise take great care in the order of things here, so
|
|
|
|
|
# that we don't end up interpreting some URLs twice.
|
|
|
|
|
|
|
|
|
|
/* private */ function replaceExternalLinks( $text )
|
|
|
|
|
{
|
2003-10-16 13:30:45 +00:00
|
|
|
$fname = "OutputPage::replaceExternalLinks";
|
|
|
|
|
wfProfileIn( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
$text = $this->subReplaceExternalLinks( $text, "http", true );
|
|
|
|
|
$text = $this->subReplaceExternalLinks( $text, "https", true );
|
|
|
|
|
$text = $this->subReplaceExternalLinks( $text, "ftp", false );
|
|
|
|
|
$text = $this->subReplaceExternalLinks( $text, "gopher", false );
|
|
|
|
|
$text = $this->subReplaceExternalLinks( $text, "news", false );
|
|
|
|
|
$text = $this->subReplaceExternalLinks( $text, "mailto", false );
|
2003-10-16 13:30:45 +00:00
|
|
|
wfProfileOut( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
return $text;
|
|
|
|
|
}
|
2003-07-01 12:47:44 +00:00
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
/* private */ function subReplaceExternalLinks( $s, $protocol, $autonumber )
|
|
|
|
|
{
|
|
|
|
|
global $wgUser, $printable;
|
|
|
|
|
global $wgAllowExternalImages;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$unique = "4jzAfzB8hNvf4sqyO9Edd8pSmk9rE2in0Tgw3";
|
|
|
|
|
$uc = "A-Za-z0-9_\\/~%\\-+&*#?!=()@\\x80-\\xFF";
|
|
|
|
|
|
|
|
|
|
# this is the list of separators that should be ignored if they
|
|
|
|
|
# are the last character of an URL but that should be included
|
|
|
|
|
# if they occur within the URL, e.g. "go to www.foo.com, where .."
|
|
|
|
|
# in this case, the last comma should not become part of the URL,
|
|
|
|
|
# but in "www.foo.com/123,2342,32.htm" it should.
|
|
|
|
|
$sep = ",;\.:";
|
|
|
|
|
$fnc = "A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF";
|
|
|
|
|
$images = "gif|png|jpg|jpeg";
|
|
|
|
|
|
|
|
|
|
# PLEASE NOTE: The curly braces { } are not part of the regex,
|
|
|
|
|
# they are interpreted as part of the string (used to tell PHP
|
|
|
|
|
# that the content of the string should be inserted there).
|
|
|
|
|
$e1 = "/(^|[^\\[])({$protocol}:)([{$uc}{$sep}]+)\\/([{$fnc}]+)\\." .
|
|
|
|
|
"((?i){$images})([^{$uc}]|$)/";
|
|
|
|
|
|
|
|
|
|
$e2 = "/(^|[^\\[])({$protocol}:)(([".$uc."]|[".$sep."][".$uc."])+)([^". $uc . $sep. "]|[".$sep."]|$)/";
|
|
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
|
|
|
|
|
|
if ( $autonumber and $wgAllowExternalImages) { # Use img tags only for HTTP urls
|
|
|
|
|
$s = preg_replace( $e1, "\\1" . $sk->makeImage( "{$unique}:\\3" .
|
|
|
|
|
"/\\4.\\5", "\\4.\\5" ) . "\\6", $s );
|
|
|
|
|
}
|
|
|
|
|
$s = preg_replace( $e2, "\\1" . "<a href=\"{$unique}:\\3\"" .
|
|
|
|
|
$sk->getExternalLinkAttributes( "{$unique}:\\3", wfEscapeHTML(
|
|
|
|
|
"{$unique}:\\3" ) ) . ">" . wfEscapeHTML( "{$unique}:\\3" ) .
|
|
|
|
|
"</a>\\5", $s );
|
|
|
|
|
$s = str_replace( $unique, $protocol, $s );
|
|
|
|
|
|
|
|
|
|
$a = explode( "[{$protocol}:", " " . $s );
|
|
|
|
|
$s = array_shift( $a );
|
|
|
|
|
$s = substr( $s, 1 );
|
|
|
|
|
|
|
|
|
|
$e1 = "/^([{$uc}"."{$sep}]+)](.*)\$/sD";
|
|
|
|
|
$e2 = "/^([{$uc}"."{$sep}]+)\\s+([^\\]]+)](.*)\$/sD";
|
|
|
|
|
|
|
|
|
|
foreach ( $a as $line ) {
|
|
|
|
|
if ( preg_match( $e1, $line, $m ) ) {
|
|
|
|
|
$link = "{$protocol}:{$m[1]}";
|
|
|
|
|
$trail = $m[2];
|
|
|
|
|
if ( $autonumber ) { $text = "[" . ++$this->mAutonumber . "]"; }
|
|
|
|
|
else { $text = wfEscapeHTML( $link ); }
|
|
|
|
|
} else if ( preg_match( $e2, $line, $m ) ) {
|
|
|
|
|
$link = "{$protocol}:{$m[1]}";
|
|
|
|
|
$text = $m[2];
|
|
|
|
|
$trail = $m[3];
|
|
|
|
|
} else {
|
|
|
|
|
$s .= "[{$protocol}:" . $line;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ( $printable == "yes") $paren = " (<i>" . htmlspecialchars ( $link ) . "</i>)";
|
|
|
|
|
else $paren = "";
|
|
|
|
|
$la = $sk->getExternalLinkAttributes( $link, $text );
|
|
|
|
|
$s .= "<a href='{$link}'{$la}>{$text}</a>{$paren}{$trail}";
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return $s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function replaceInternalLinks( $s )
|
|
|
|
|
{
|
|
|
|
|
global $wgTitle, $wgUser, $wgLang;
|
2003-08-05 11:51:05 +00:00
|
|
|
global $wgLinkCache, $wgInterwikiMagic, $wgUseCategoryMagic;
|
2003-07-05 01:12:22 +00:00
|
|
|
global $wgNamespacesWithSubpages, $wgLanguageCode;
|
2003-05-17 07:17:52 +00:00
|
|
|
wfProfileIn( $fname = "OutputPage::replaceInternalLinks" );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2003-05-17 07:17:52 +00:00
|
|
|
wfProfileIn( "$fname-setup" );
|
2003-04-14 23:10:40 +00:00
|
|
|
$tc = Title::legalChars() . "#";
|
|
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
|
|
|
|
|
|
$a = explode( "[[", " " . $s );
|
|
|
|
|
$s = array_shift( $a );
|
|
|
|
|
$s = substr( $s, 1 );
|
|
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
$e1 = "/^([{$tc}]+)(?:\\|([^]]+))?]](.*)\$/sD";
|
|
|
|
|
|
|
|
|
|
# Special and Media are pseudo-namespaces; no pages actually exist in them
|
|
|
|
|
$image = Namespace::getImage();
|
|
|
|
|
$special = Namespace::getSpecial();
|
|
|
|
|
$media = Namespace::getMedia();
|
|
|
|
|
$nottalk = !Namespace::isTalk( $wgTitle->getNamespace() );
|
2003-10-16 13:30:45 +00:00
|
|
|
wfProfileOut( "$fname-setup" );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
foreach ( $a as $line ) {
|
2003-11-09 11:45:12 +00:00
|
|
|
if ( preg_match( $e1, $line, $m ) ) { # page with normal text or alt
|
2003-04-14 23:10:40 +00:00
|
|
|
$text = $m[2];
|
|
|
|
|
$trail = $m[3];
|
2003-11-09 11:45:12 +00:00
|
|
|
} else { # Invalid form; output directly
|
2003-04-14 23:10:40 +00:00
|
|
|
$s .= "[[" . $line ;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2003-11-09 11:45:12 +00:00
|
|
|
|
|
|
|
|
/* Valid link forms:
|
|
|
|
|
Foobar -- normal
|
|
|
|
|
:Foobar -- override special treatment of prefix (images, language links)
|
|
|
|
|
/Foobar -- convert to CurrentPage/Foobar
|
|
|
|
|
/Foobar/ -- convert to CurrentPage/Foobar, strip the initial / from text
|
|
|
|
|
*/
|
|
|
|
|
$c = substr($m[1],0,1);
|
|
|
|
|
$noforce = ($c != ":");
|
|
|
|
|
if( $c == "/" ) { # subpage
|
2003-04-14 23:10:40 +00:00
|
|
|
if(substr($m[1],-1,1)=="/") { # / at end means we don't want the slash to be shown
|
|
|
|
|
$m[1]=substr($m[1],1,strlen($m[1])-2);
|
|
|
|
|
$noslash=$m[1];
|
|
|
|
|
} else {
|
|
|
|
|
$noslash=substr($m[1],1);
|
|
|
|
|
}
|
|
|
|
|
if($wgNamespacesWithSubpages[$wgTitle->getNamespace()]) { # subpages allowed here
|
|
|
|
|
$link = $wgTitle->getPrefixedText(). "/" . trim($noslash);
|
2003-12-14 05:14:04 +00:00
|
|
|
if( "" == $text ) {
|
2003-04-14 23:10:40 +00:00
|
|
|
$text= $m[1];
|
|
|
|
|
} # this might be changed for ugliness reasons
|
|
|
|
|
} else {
|
|
|
|
|
$link = $noslash; # no subpage allowed, use standard link
|
|
|
|
|
}
|
2003-11-09 11:45:12 +00:00
|
|
|
} elseif( $noforce ) { # no subpage
|
|
|
|
|
$link = $m[1];
|
|
|
|
|
} else {
|
|
|
|
|
$link = substr( $m[1], 1 );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2003-12-14 05:14:04 +00:00
|
|
|
if( "" == $text )
|
2003-11-09 11:45:12 +00:00
|
|
|
$text = $link;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
$nt = Title::newFromText( $link );
|
|
|
|
|
if( !$nt ) {
|
|
|
|
|
$s .= "[[" . $line;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
$ns = $nt->getNamespace();
|
|
|
|
|
$iw = $nt->getInterWiki();
|
|
|
|
|
if( $noforce ) {
|
|
|
|
|
if( $iw && $wgInterwikiMagic && $nottalk && $wgLang->getLanguageName( $iw ) ) {
|
|
|
|
|
array_push( $this->mLanguageLinks, $nt->getPrefixedText() );
|
2003-04-14 23:10:40 +00:00
|
|
|
$s .= $trail;
|
2003-11-09 11:45:12 +00:00
|
|
|
/* CHECK MERGE @@@
|
2003-04-14 23:10:40 +00:00
|
|
|
} else if ( "media" == $pre ) {
|
|
|
|
|
$nt = Title::newFromText( $suf );
|
|
|
|
|
$name = $nt->getDBkey();
|
|
|
|
|
if ( "" == $text ) { $text = $nt->GetText(); }
|
|
|
|
|
|
|
|
|
|
$wgLinkCache->addImageLink( $name );
|
|
|
|
|
$s .= $sk->makeMediaLink( $name,
|
|
|
|
|
wfImageUrl( $name ), $text );
|
|
|
|
|
$s .= $trail;
|
2003-10-22 23:56:49 +00:00
|
|
|
} else if ( isset($wgUseCategoryMagic) && $wgUseCategoryMagic && $pre == wfMsg ( "category" ) ) {
|
|
|
|
|
$l = $sk->makeLink ( $pre.":".ucfirst( $m[2] ), ucfirst ( $m[2] ) ) ;
|
|
|
|
|
array_push ( $this->mCategoryLinks , $l ) ;
|
|
|
|
|
$s .= $trail ;
|
2003-04-14 23:10:40 +00:00
|
|
|
} else {
|
|
|
|
|
$l = $wgLang->getLanguageName( $pre );
|
2003-10-22 23:56:49 +00:00
|
|
|
if ( "" == $l or !$wgInterwikiMagic or Namespace::isTalk( $wgTitle->getNamespace() ) ) {
|
|
|
|
|
if ( "" == $text ) {
|
|
|
|
|
$text = $link;
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
$s .= $sk->makeLink( $link, $text, "", $trail );
|
2003-07-05 01:12:22 +00:00
|
|
|
} else if ( $pre != $wgLanguageCode ) {
|
2003-04-14 23:10:40 +00:00
|
|
|
array_push( $this->mLanguageLinks, "$pre:$suf" );
|
|
|
|
|
$s .= $trail;
|
|
|
|
|
}
|
2003-11-09 11:45:12 +00:00
|
|
|
*/
|
|
|
|
|
continue;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2003-11-09 11:45:12 +00:00
|
|
|
if( $ns == $image ) {
|
|
|
|
|
$s .= $sk->makeImageLinkObj( $nt, $text ) . $trail;
|
|
|
|
|
$wgLinkCache->addImageLinkObj( $nt );
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* CHECK MERGE @@@
|
2003-04-14 23:10:40 +00:00
|
|
|
# } else if ( 0 == strcmp( "##", substr( $link, 0, 2 ) ) ) {
|
|
|
|
|
# $link = substr( $link, 2 );
|
|
|
|
|
# $s .= "<a name=\"{$link}\">{$text}</a>{$trail}";
|
|
|
|
|
} else {
|
|
|
|
|
if ( "" == $text ) { $text = $link; }
|
2003-10-22 23:56:49 +00:00
|
|
|
# Hotspot:
|
2003-04-14 23:10:40 +00:00
|
|
|
$s .= $sk->makeLink( $link, $text, "", $trail );
|
2003-11-09 11:45:12 +00:00
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
if( $ns == $media ) {
|
|
|
|
|
$s .= $sk->makeMediaLinkObj( $nt, $text ) . $trail;
|
|
|
|
|
$wgLinkCache->addImageLinkObj( $nt );
|
|
|
|
|
continue;
|
|
|
|
|
} elseif( $ns == $special ) {
|
|
|
|
|
$s .= $sk->makeKnownLinkObj( $nt, $text, "", $trail );
|
|
|
|
|
continue;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2003-11-09 11:45:12 +00:00
|
|
|
$s .= $sk->makeLinkObj( $nt, $text, "", $trail );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2003-10-16 13:30:45 +00:00
|
|
|
wfProfileOut( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
return $s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Some functions here used by doBlockLevels()
|
|
|
|
|
#
|
|
|
|
|
/* private */ function closeParagraph()
|
|
|
|
|
{
|
|
|
|
|
$result = "";
|
|
|
|
|
if ( 0 != strcmp( "p", $this->mLastSection ) &&
|
|
|
|
|
0 != strcmp( "", $this->mLastSection ) ) {
|
|
|
|
|
$result = "</" . $this->mLastSection . ">";
|
|
|
|
|
}
|
|
|
|
|
$this->mLastSection = "";
|
2004-01-06 19:44:04 +00:00
|
|
|
return $result."\n";
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
# getCommon() returns the length of the longest common substring
|
|
|
|
|
# of both arguments, starting at the beginning of both.
|
|
|
|
|
#
|
|
|
|
|
/* private */ function getCommon( $st1, $st2 )
|
|
|
|
|
{
|
|
|
|
|
$fl = strlen( $st1 );
|
|
|
|
|
$shorter = strlen( $st2 );
|
|
|
|
|
if ( $fl < $shorter ) { $shorter = $fl; }
|
|
|
|
|
|
|
|
|
|
for ( $i = 0; $i < $shorter; ++$i ) {
|
|
|
|
|
if ( $st1{$i} != $st2{$i} ) { break; }
|
|
|
|
|
}
|
|
|
|
|
return $i;
|
|
|
|
|
}
|
|
|
|
|
# These next three functions open, continue, and close the list
|
|
|
|
|
# element appropriate to the prefix character passed into them.
|
|
|
|
|
#
|
|
|
|
|
/* private */ function openList( $char )
|
|
|
|
|
{
|
|
|
|
|
$result = $this->closeParagraph();
|
|
|
|
|
|
|
|
|
|
if ( "*" == $char ) { $result .= "<ul><li>"; }
|
|
|
|
|
else if ( "#" == $char ) { $result .= "<ol><li>"; }
|
|
|
|
|
else if ( ":" == $char ) { $result .= "<dl><dd>"; }
|
|
|
|
|
else if ( ";" == $char ) {
|
|
|
|
|
$result .= "<dl><dt>";
|
|
|
|
|
$this->mDTopen = true;
|
|
|
|
|
}
|
|
|
|
|
else { $result = "<!-- ERR 1 -->"; }
|
|
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function nextItem( $char )
|
|
|
|
|
{
|
|
|
|
|
if ( "*" == $char || "#" == $char ) { return "</li><li>"; }
|
|
|
|
|
else if ( ":" == $char || ";" == $char ) {
|
|
|
|
|
$close = "</dd>";
|
|
|
|
|
if ( $this->mDTopen ) { $close = "</dt>"; }
|
|
|
|
|
if ( ";" == $char ) {
|
|
|
|
|
$this->mDTopen = true;
|
|
|
|
|
return $close . "<dt>";
|
|
|
|
|
} else {
|
|
|
|
|
$this->mDTopen = false;
|
|
|
|
|
return $close . "<dd>";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "<!-- ERR 2 -->";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */function closeList( $char )
|
|
|
|
|
{
|
2004-01-06 19:44:04 +00:00
|
|
|
if ( "*" == $char ) { $text = "</li></ul>"; }
|
|
|
|
|
else if ( "#" == $char ) { $text = "</li></ol>"; }
|
2003-04-14 23:10:40 +00:00
|
|
|
else if ( ":" == $char ) {
|
|
|
|
|
if ( $this->mDTopen ) {
|
|
|
|
|
$this->mDTopen = false;
|
2004-01-06 19:44:04 +00:00
|
|
|
$text = "</dt></dl>";
|
2003-04-14 23:10:40 +00:00
|
|
|
} else {
|
2004-01-06 19:44:04 +00:00
|
|
|
$text = "</dd></dl>";
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
2004-01-06 19:44:04 +00:00
|
|
|
else { return "<!-- ERR 3 -->"; }
|
|
|
|
|
return $text."\n";
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function doBlockLevels( $text, $linestart )
|
|
|
|
|
{
|
2003-10-16 13:30:45 +00:00
|
|
|
$fname = "OutputPage::doBlockLevels";
|
|
|
|
|
wfProfileIn( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
# Parsing through the text line by line. The main thing
|
|
|
|
|
# happening here is handling of block-level elements p, pre,
|
|
|
|
|
# and making lists from lines starting with * # : etc.
|
|
|
|
|
#
|
|
|
|
|
$a = explode( "\n", $text );
|
|
|
|
|
$text = $lastPref = "";
|
|
|
|
|
$this->mDTopen = $inBlockElem = false;
|
|
|
|
|
|
|
|
|
|
if ( ! $linestart ) { $text .= array_shift( $a ); }
|
|
|
|
|
foreach ( $a as $t ) {
|
|
|
|
|
if ( "" != $text ) { $text .= "\n"; }
|
|
|
|
|
|
|
|
|
|
$oLine = $t;
|
|
|
|
|
$opl = strlen( $lastPref );
|
|
|
|
|
$npl = strspn( $t, "*#:;" );
|
|
|
|
|
$pref = substr( $t, 0, $npl );
|
|
|
|
|
$pref2 = str_replace( ";", ":", $pref );
|
|
|
|
|
$t = substr( $t, $npl );
|
|
|
|
|
|
|
|
|
|
if ( 0 != $npl && 0 == strcmp( $lastPref, $pref2 ) ) {
|
|
|
|
|
$text .= $this->nextItem( substr( $pref, -1 ) );
|
|
|
|
|
|
|
|
|
|
if ( ";" == substr( $pref, -1 ) ) {
|
|
|
|
|
$cpos = strpos( $t, ":" );
|
|
|
|
|
if ( ! ( false === $cpos ) ) {
|
|
|
|
|
$term = substr( $t, 0, $cpos );
|
|
|
|
|
$text .= $term . $this->nextItem( ":" );
|
|
|
|
|
$t = substr( $t, $cpos + 1 );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (0 != $npl || 0 != $opl) {
|
|
|
|
|
$cpl = $this->getCommon( $pref, $lastPref );
|
|
|
|
|
|
|
|
|
|
while ( $cpl < $opl ) {
|
|
|
|
|
$text .= $this->closeList( $lastPref{$opl-1} );
|
|
|
|
|
--$opl;
|
|
|
|
|
}
|
|
|
|
|
if ( $npl <= $cpl && $cpl > 0 ) {
|
|
|
|
|
$text .= $this->nextItem( $pref{$cpl-1} );
|
|
|
|
|
}
|
|
|
|
|
while ( $npl > $cpl ) {
|
|
|
|
|
$char = substr( $pref, $cpl, 1 );
|
|
|
|
|
$text .= $this->openList( $char );
|
|
|
|
|
|
|
|
|
|
if ( ";" == $char ) {
|
|
|
|
|
$cpos = strpos( $t, ":" );
|
|
|
|
|
if ( ! ( false === $cpos ) ) {
|
|
|
|
|
$term = substr( $t, 0, $cpos );
|
|
|
|
|
$text .= $term . $this->nextItem( ":" );
|
|
|
|
|
$t = substr( $t, $cpos + 1 );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++$cpl;
|
|
|
|
|
}
|
|
|
|
|
$lastPref = $pref2;
|
|
|
|
|
}
|
|
|
|
|
if ( 0 == $npl ) { # No prefix--go to paragraph mode
|
|
|
|
|
if ( preg_match(
|
|
|
|
|
"/(<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6)/i", $t ) ) {
|
|
|
|
|
$text .= $this->closeParagraph();
|
|
|
|
|
$inBlockElem = true;
|
|
|
|
|
}
|
|
|
|
|
if ( ! $inBlockElem ) {
|
|
|
|
|
if ( " " == $t{0} ) {
|
|
|
|
|
$newSection = "pre";
|
|
|
|
|
# $t = wfEscapeHTML( $t );
|
|
|
|
|
}
|
|
|
|
|
else { $newSection = "p"; }
|
|
|
|
|
|
|
|
|
|
if ( 0 == strcmp( "", trim( $oLine ) ) ) {
|
|
|
|
|
$text .= $this->closeParagraph();
|
|
|
|
|
$text .= "<" . $newSection . ">";
|
|
|
|
|
} else if ( 0 != strcmp( $this->mLastSection,
|
|
|
|
|
$newSection ) ) {
|
|
|
|
|
$text .= $this->closeParagraph();
|
|
|
|
|
if ( 0 != strcmp( "p", $newSection ) ) {
|
|
|
|
|
$text .= "<" . $newSection . ">";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$this->mLastSection = $newSection;
|
|
|
|
|
}
|
|
|
|
|
if ( $inBlockElem &&
|
|
|
|
|
preg_match( "/(<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6)/i", $t ) ) {
|
|
|
|
|
$inBlockElem = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$text .= $t;
|
|
|
|
|
}
|
|
|
|
|
while ( $npl ) {
|
|
|
|
|
$text .= $this->closeList( $pref2{$npl-1} );
|
|
|
|
|
--$npl;
|
|
|
|
|
}
|
|
|
|
|
if ( "" != $this->mLastSection ) {
|
|
|
|
|
if ( "p" != $this->mLastSection ) {
|
|
|
|
|
$text .= "</" . $this->mLastSection . ">";
|
|
|
|
|
}
|
|
|
|
|
$this->mLastSection = "";
|
|
|
|
|
}
|
2003-10-16 13:30:45 +00:00
|
|
|
wfProfileOut( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function replaceVariables( $text )
|
|
|
|
|
{
|
|
|
|
|
global $wgLang;
|
2003-10-25 08:01:33 +00:00
|
|
|
$fname = "OutputPage::replaceVariables";
|
2003-10-16 13:30:45 +00:00
|
|
|
wfProfileIn( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2004-01-10 22:49:37 +00:00
|
|
|
$magic = array();
|
|
|
|
|
|
2003-11-02 13:57:24 +00:00
|
|
|
# Basic variables
|
|
|
|
|
# See Language.php for the definition of each magic word
|
|
|
|
|
# As with sigs, this uses the server's local time -- ensure
|
|
|
|
|
# this is appropriate for your audience!
|
2004-01-10 22:49:37 +00:00
|
|
|
|
|
|
|
|
$magic[MAG_CURRENTMONTH] = date( "m" );
|
|
|
|
|
$magic[MAG_CURRENTMONTHNAME] = $wgLang->getMonthName( date("n") );
|
|
|
|
|
$magic[MAG_CURRENTMONTHNAMEGEN] = $wgLang->getMonthNameGen( date("n") );
|
|
|
|
|
$magic[MAG_CURRENTDAY] = date("j");
|
|
|
|
|
$magic[MAG_CURRENTDAYNAME] = $wgLang->getWeekdayName( date("w")+1 );
|
|
|
|
|
$magic[MAG_CURRENTYEAR] = date( "Y" );
|
|
|
|
|
$magic[MAG_CURRENTTIME] = $wgLang->time( wfTimestampNow(), false );
|
2003-08-31 09:46:37 +00:00
|
|
|
|
2004-01-10 22:49:37 +00:00
|
|
|
$this->mContainsOldMagic += MagicWord::replaceMultiple($magic, $text, $text);
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2003-08-31 09:46:37 +00:00
|
|
|
$mw =& MagicWord::get( MAG_NUMBEROFARTICLES );
|
|
|
|
|
if ( $mw->match( $text ) ) {
|
2003-04-14 23:10:40 +00:00
|
|
|
$v = wfNumberOfArticles();
|
2003-08-31 09:46:37 +00:00
|
|
|
$text = $mw->replace( $v, $text );
|
2004-01-07 02:51:47 +00:00
|
|
|
if( $mw->getWasModified() ) { $this->mContainsOldMagic++; }
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2003-09-21 13:10:10 +00:00
|
|
|
|
2003-11-02 13:57:24 +00:00
|
|
|
# "Variables" with an additional parameter e.g. {{MSG:wikipedia}}
|
|
|
|
|
# The callbacks are at the bottom of this file
|
2003-09-21 13:10:10 +00:00
|
|
|
$mw =& MagicWord::get( MAG_MSG );
|
2003-11-02 13:57:24 +00:00
|
|
|
$text = $mw->substituteCallback( $text, "wfReplaceMsgVar" );
|
2004-01-07 02:51:47 +00:00
|
|
|
if( $mw->getWasModified() ) { $this->mContainsNewMagic++; }
|
2003-09-21 13:10:10 +00:00
|
|
|
|
|
|
|
|
$mw =& MagicWord::get( MAG_MSGNW );
|
2003-11-02 13:57:24 +00:00
|
|
|
$text = $mw->substituteCallback( $text, "wfReplaceMsgnwVar" );
|
2004-01-07 02:51:47 +00:00
|
|
|
if( $mw->getWasModified() ) { $this->mContainsNewMagic++; }
|
2003-09-21 13:10:10 +00:00
|
|
|
|
2003-10-16 13:30:45 +00:00
|
|
|
wfProfileOut( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-02 13:57:24 +00:00
|
|
|
# Cleans up HTML, removes dangerous tags and attributes
|
2003-04-14 23:10:40 +00:00
|
|
|
/* private */ function removeHTMLtags( $text )
|
|
|
|
|
{
|
2003-10-16 13:30:45 +00:00
|
|
|
$fname = "OutputPage::removeHTMLtags";
|
|
|
|
|
wfProfileIn( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
$htmlpairs = array( # Tags that must be closed
|
|
|
|
|
"b", "i", "u", "font", "big", "small", "sub", "sup", "h1",
|
|
|
|
|
"h2", "h3", "h4", "h5", "h6", "cite", "code", "em", "s",
|
|
|
|
|
"strike", "strong", "tt", "var", "div", "center",
|
|
|
|
|
"blockquote", "ol", "ul", "dl", "table", "caption", "pre",
|
|
|
|
|
"ruby", "rt" , "rb" , "rp"
|
|
|
|
|
);
|
|
|
|
|
$htmlsingle = array(
|
|
|
|
|
"br", "p", "hr", "li", "dt", "dd"
|
|
|
|
|
);
|
|
|
|
|
$htmlnest = array( # Tags that can be nested--??
|
|
|
|
|
"table", "tr", "td", "th", "div", "blockquote", "ol", "ul",
|
|
|
|
|
"dl", "font", "big", "small", "sub", "sup"
|
|
|
|
|
);
|
|
|
|
|
$tabletags = array( # Can only appear inside table
|
|
|
|
|
"td", "th", "tr"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$htmlsingle = array_merge( $tabletags, $htmlsingle );
|
|
|
|
|
$htmlelements = array_merge( $htmlsingle, $htmlpairs );
|
|
|
|
|
|
2003-09-17 12:40:54 +00:00
|
|
|
$htmlattrs = $this->getHTMLattrs () ;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
# Remove HTML comments
|
|
|
|
|
$text = preg_replace( "/<!--.*-->/sU", "", $text );
|
|
|
|
|
|
|
|
|
|
$bits = explode( "<", $text );
|
|
|
|
|
$text = array_shift( $bits );
|
|
|
|
|
$tagstack = array(); $tablestack = array();
|
|
|
|
|
|
|
|
|
|
foreach ( $bits as $x ) {
|
|
|
|
|
$prev = error_reporting( E_ALL & ~( E_NOTICE | E_WARNING ) );
|
|
|
|
|
preg_match( "/^(\\/?)(\\w+)([^>]*)(\\/{0,1}>)([^<]*)$/",
|
|
|
|
|
$x, $regs );
|
|
|
|
|
list( $qbar, $slash, $t, $params, $brace, $rest ) = $regs;
|
|
|
|
|
error_reporting( $prev );
|
|
|
|
|
|
|
|
|
|
$badtag = 0 ;
|
|
|
|
|
if ( in_array( $t = strtolower( $t ), $htmlelements ) ) {
|
|
|
|
|
# Check our stack
|
|
|
|
|
if ( $slash ) {
|
|
|
|
|
# Closing a tag...
|
|
|
|
|
if ( ! in_array( $t, $htmlsingle ) &&
|
|
|
|
|
( $ot = array_pop( $tagstack ) ) != $t ) {
|
|
|
|
|
array_push( $tagstack, $ot );
|
|
|
|
|
$badtag = 1;
|
|
|
|
|
} else {
|
|
|
|
|
if ( $t == "table" ) {
|
|
|
|
|
$tagstack = array_pop( $tablestack );
|
|
|
|
|
}
|
|
|
|
|
$newparams = "";
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
# Keep track for later
|
|
|
|
|
if ( in_array( $t, $tabletags ) &&
|
|
|
|
|
! in_array( "table", $tagstack ) ) {
|
|
|
|
|
$badtag = 1;
|
|
|
|
|
} else if ( in_array( $t, $tagstack ) &&
|
|
|
|
|
! in_array ( $t , $htmlnest ) ) {
|
|
|
|
|
$badtag = 1 ;
|
|
|
|
|
} else if ( ! in_array( $t, $htmlsingle ) ) {
|
|
|
|
|
if ( $t == "table" ) {
|
|
|
|
|
array_push( $tablestack, $tagstack );
|
|
|
|
|
$tagstack = array();
|
|
|
|
|
}
|
|
|
|
|
array_push( $tagstack, $t );
|
|
|
|
|
}
|
|
|
|
|
# Strip non-approved attributes from the tag
|
2004-01-17 07:33:44 +00:00
|
|
|
$newparams = $this->fixTagAttributes($params);
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
if ( ! $badtag ) {
|
|
|
|
|
$rest = str_replace( ">", ">", $rest );
|
2004-01-17 07:33:44 +00:00
|
|
|
$text .= "<$slash$t $newparams$brace$rest";
|
2003-04-14 23:10:40 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$text .= "<" . str_replace( ">", ">", $x);
|
|
|
|
|
}
|
|
|
|
|
# Close off any remaining tags
|
|
|
|
|
while ( $t = array_pop( $tagstack ) ) {
|
|
|
|
|
$text .= "</$t>\n";
|
|
|
|
|
if ( $t == "table" ) { $tagstack = array_pop( $tablestack ); }
|
|
|
|
|
}
|
2003-10-16 13:30:45 +00:00
|
|
|
wfProfileOut( $fname );
|
2003-04-14 23:10:40 +00:00
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-30 00:19:35 +00:00
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* This function accomplishes several tasks:
|
|
|
|
|
* 1) Auto-number headings if that option is enabled
|
|
|
|
|
* 2) Add an [edit] link to sections for logged in users who have enabled the option
|
|
|
|
|
* 3) Add a Table of contents on the top for users who have enabled the option
|
|
|
|
|
* 4) Auto-anchor headings
|
|
|
|
|
*
|
|
|
|
|
* It loops through all headlines, collects the necessary data, then splits up the
|
|
|
|
|
* string and re-inserts the newly formatted headlines.
|
|
|
|
|
*
|
|
|
|
|
* */
|
|
|
|
|
/* private */ function formatHeadings( $text )
|
2003-04-14 23:10:40 +00:00
|
|
|
{
|
2003-06-30 00:19:35 +00:00
|
|
|
global $wgUser,$wgArticle,$wgTitle,$wpPreview;
|
|
|
|
|
$nh=$wgUser->getOption( "numberheadings" );
|
|
|
|
|
$st=$wgUser->getOption( "showtoc" );
|
2003-07-28 03:57:40 +00:00
|
|
|
if(!$wgTitle->userCanEdit()) {
|
|
|
|
|
$es=0;
|
|
|
|
|
$esr=0;
|
|
|
|
|
} else {
|
|
|
|
|
$es=$wgUser->getID() && $wgUser->getOption( "editsection" );
|
|
|
|
|
$esr=$wgUser->getID() && $wgUser->getOption( "editsectiononrightclick" );
|
|
|
|
|
}
|
2003-09-18 10:51:36 +00:00
|
|
|
|
2003-10-05 09:44:20 +00:00
|
|
|
# Inhibit editsection links if requested in the page
|
2004-01-06 00:47:52 +00:00
|
|
|
$esw =& MagicWord::get( MAG_NOEDITSECTION );
|
|
|
|
|
if ($esw->matchAndRemove( $text )) {
|
|
|
|
|
$es=0;
|
2003-10-05 09:44:20 +00:00
|
|
|
}
|
2003-09-18 10:51:36 +00:00
|
|
|
# if the string __NOTOC__ (not case-sensitive) occurs in the HTML,
|
|
|
|
|
# do not add TOC
|
2003-08-31 09:46:37 +00:00
|
|
|
$mw =& MagicWord::get( MAG_NOTOC );
|
2003-09-18 10:51:36 +00:00
|
|
|
if ($mw->matchAndRemove( $text ))
|
|
|
|
|
{
|
|
|
|
|
$st = 0;
|
|
|
|
|
}
|
2003-07-21 07:36:52 +00:00
|
|
|
|
|
|
|
|
# never add the TOC to the Main Page. This is an entry page that should not
|
|
|
|
|
# be more than 1-2 screens large anyway
|
2003-06-30 02:15:17 +00:00
|
|
|
if($wgTitle->getPrefixedText()==wfMsg("mainpage")) {$st=0;}
|
2003-06-30 00:19:35 +00:00
|
|
|
|
2003-07-21 07:36:52 +00:00
|
|
|
# We need this to perform operations on the HTML
|
2003-06-30 00:19:35 +00:00
|
|
|
$sk=$wgUser->getSkin();
|
|
|
|
|
|
2003-07-21 07:36:52 +00:00
|
|
|
# Get all headlines for numbering them and adding funky stuff like [edit]
|
|
|
|
|
# links
|
|
|
|
|
preg_match_all("/<H([1-6])(.*?>)(.*?)<\/H[1-6]>/i",$text,$matches);
|
|
|
|
|
|
|
|
|
|
# headline counter
|
2003-06-30 00:19:35 +00:00
|
|
|
$c=0;
|
|
|
|
|
|
2003-07-21 07:36:52 +00:00
|
|
|
# Ugh .. the TOC should have neat indentation levels which can be
|
|
|
|
|
# passed to the skin functions. These are determined here
|
2003-06-30 00:19:35 +00:00
|
|
|
foreach($matches[3] as $headline) {
|
|
|
|
|
if($level) { $prevlevel=$level;}
|
|
|
|
|
$level=$matches[1][$c];
|
2003-07-02 22:49:20 +00:00
|
|
|
if(($nh||$st) && $prevlevel && $level>$prevlevel) {
|
2003-06-30 00:19:35 +00:00
|
|
|
|
|
|
|
|
$h[$level]=0; // reset when we enter a new level
|
2003-07-02 22:49:20 +00:00
|
|
|
$toc.=$sk->tocIndent($level-$prevlevel);
|
|
|
|
|
$toclevel+=$level-$prevlevel;
|
2003-06-30 00:19:35 +00:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if(($nh||$st) && $level<$prevlevel) {
|
|
|
|
|
$h[$level+1]=0; // reset when we step back a level
|
2003-07-02 22:49:20 +00:00
|
|
|
$toc.=$sk->tocUnindent($prevlevel-$level);
|
|
|
|
|
$toclevel-=$prevlevel-$level;
|
2003-06-30 00:19:35 +00:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
$h[$level]++; // count number of headlines for each level
|
|
|
|
|
|
|
|
|
|
if($nh||$st) {
|
|
|
|
|
for($i=1;$i<=$level;$i++) {
|
|
|
|
|
if($h[$i]) {
|
|
|
|
|
if($dot) {$numbering.=".";}
|
|
|
|
|
$numbering.=$h[$i];
|
|
|
|
|
$dot=1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2003-11-09 11:45:12 +00:00
|
|
|
|
2003-11-08 12:12:50 +00:00
|
|
|
// The canonized header is a version of the header text safe to use for links
|
2003-06-30 00:19:35 +00:00
|
|
|
|
|
|
|
|
$canonized_headline=preg_replace("/<.*?>/","",$headline); // strip out HTML
|
2003-12-22 08:03:21 +00:00
|
|
|
$tocline = trim( $canonized_headline );
|
2003-06-30 02:51:50 +00:00
|
|
|
$canonized_headline=str_replace('"',"",$canonized_headline);
|
2003-06-30 00:19:35 +00:00
|
|
|
$canonized_headline=str_replace(" ","_",trim($canonized_headline));
|
|
|
|
|
$refer[$c]=$canonized_headline;
|
|
|
|
|
$refers[$canonized_headline]++; // count how many in assoc. array so we can track dupes in anchors
|
|
|
|
|
$refcount[$c]=$refers[$canonized_headline];
|
2003-11-09 11:45:12 +00:00
|
|
|
|
|
|
|
|
// Prepend the number to the heading text
|
2003-11-08 12:12:50 +00:00
|
|
|
|
2003-06-30 00:19:35 +00:00
|
|
|
if($nh||$st) {
|
|
|
|
|
$tocline=$numbering ." ". $tocline;
|
2003-11-08 12:12:50 +00:00
|
|
|
|
|
|
|
|
// Don't number the heading if it is the only one (looks silly)
|
|
|
|
|
if($nh && count($matches[3]) > 1) {
|
2003-06-30 00:19:35 +00:00
|
|
|
$headline=$numbering . " " . $headline; // the two are different if the line contains a link
|
2003-11-08 12:12:50 +00:00
|
|
|
}
|
2003-06-30 00:19:35 +00:00
|
|
|
}
|
2003-11-08 12:12:50 +00:00
|
|
|
|
|
|
|
|
// Create the anchor for linking from the TOC to the section
|
|
|
|
|
|
2003-06-30 00:19:35 +00:00
|
|
|
$anchor=$canonized_headline;
|
|
|
|
|
if($refcount[$c]>1) {$anchor.="_".$refcount[$c];}
|
|
|
|
|
if($st) {
|
2003-07-02 22:49:20 +00:00
|
|
|
$toc.=$sk->tocLine($anchor,$tocline,$toclevel);
|
2003-06-30 00:19:35 +00:00
|
|
|
}
|
2003-06-30 02:15:17 +00:00
|
|
|
if($es && !isset($wpPreview)) {
|
|
|
|
|
$head[$c].=$sk->editSectionLink($c+1);
|
|
|
|
|
}
|
2003-11-08 12:12:50 +00:00
|
|
|
|
|
|
|
|
// Put it all together
|
|
|
|
|
|
|
|
|
|
$head[$c].="<h".$level.$matches[2][$c]
|
2003-06-30 00:19:35 +00:00
|
|
|
."<a name=\"".$anchor."\">"
|
|
|
|
|
.$headline
|
|
|
|
|
."</a>"
|
2003-11-08 12:12:50 +00:00
|
|
|
."</h".$level.">";
|
|
|
|
|
|
|
|
|
|
// Add the edit section link
|
|
|
|
|
|
2003-07-21 07:36:52 +00:00
|
|
|
if($esr && !isset($wpPreview)) {
|
|
|
|
|
$head[$c]=$sk->editSectionScript($c+1,$head[$c]);
|
|
|
|
|
}
|
2003-11-08 12:12:50 +00:00
|
|
|
|
2003-06-30 00:19:35 +00:00
|
|
|
$numbering="";
|
|
|
|
|
$c++;
|
|
|
|
|
$dot=0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($st) {
|
|
|
|
|
$toclines=$c;
|
2003-07-02 22:49:20 +00:00
|
|
|
$toc.=$sk->tocUnindent($toclevel);
|
2003-06-30 00:19:35 +00:00
|
|
|
$toc=$sk->tocTable($toc);
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2003-06-30 00:19:35 +00:00
|
|
|
|
|
|
|
|
// split up and insert constructed headlines
|
|
|
|
|
|
|
|
|
|
$blocks=preg_split("/<H[1-6].*?>.*?<\/H[1-6]>/i",$text);
|
|
|
|
|
$i=0;
|
2003-06-30 02:15:17 +00:00
|
|
|
|
|
|
|
|
foreach($blocks as $block) {
|
2003-07-28 03:57:40 +00:00
|
|
|
if(($es) && !isset($wpPreview) && $c>0 && $i==0) {
|
2003-07-21 07:36:52 +00:00
|
|
|
# This is the [edit] link that appears for the top block of text when
|
|
|
|
|
# section editing is enabled
|
2003-11-08 12:12:50 +00:00
|
|
|
$full.=$sk->editSectionLink(0);
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2003-06-30 02:15:17 +00:00
|
|
|
$full.=$block;
|
2003-07-02 22:49:20 +00:00
|
|
|
if($st && $toclines>3 && !$i) {
|
2003-07-21 07:36:52 +00:00
|
|
|
# Let's add a top anchor just in case we want to link to the top of the page
|
2003-07-02 22:49:20 +00:00
|
|
|
$full="<a name=\"top\"></a>".$full.$toc;
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-30 00:19:35 +00:00
|
|
|
$full.=$head[$i];
|
|
|
|
|
$i++;
|
|
|
|
|
}
|
2003-11-08 12:12:50 +00:00
|
|
|
|
2003-06-30 00:19:35 +00:00
|
|
|
return $full;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function magicISBN( $text )
|
|
|
|
|
{
|
|
|
|
|
global $wgLang;
|
|
|
|
|
|
|
|
|
|
$a = split( "ISBN ", " $text" );
|
|
|
|
|
if ( count ( $a ) < 2 ) return $text;
|
|
|
|
|
$text = substr( array_shift( $a ), 1);
|
2003-11-08 12:12:50 +00:00
|
|
|
$valid = "0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
foreach ( $a as $x ) {
|
|
|
|
|
$isbn = $blank = "" ;
|
|
|
|
|
while ( " " == $x{0} ) {
|
2003-11-08 12:12:50 +00:00
|
|
|
$blank .= " ";
|
|
|
|
|
$x = substr( $x, 1 );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2003-11-08 12:12:50 +00:00
|
|
|
while ( strstr( $valid, $x{0} ) != false ) {
|
2003-04-14 23:10:40 +00:00
|
|
|
$isbn .= $x{0};
|
|
|
|
|
$x = substr( $x, 1 );
|
|
|
|
|
}
|
2003-11-08 12:12:50 +00:00
|
|
|
$num = str_replace( "-", "", $isbn );
|
|
|
|
|
$num = str_replace( " ", "", $num );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2003-11-08 12:12:50 +00:00
|
|
|
if ( "" == $num ) {
|
2003-04-14 23:10:40 +00:00
|
|
|
$text .= "ISBN $blank$x";
|
2003-11-08 12:12:50 +00:00
|
|
|
} else {
|
2003-04-14 23:10:40 +00:00
|
|
|
$text .= "<a href=\"" . wfLocalUrlE( $wgLang->specialPage(
|
2003-11-08 12:12:50 +00:00
|
|
|
"Booksources"), "isbn={$num}" ) . "\" class=\"internal\">ISBN $isbn</a>";
|
2003-04-14 23:10:40 +00:00
|
|
|
$text .= $x;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-11-08 12:12:50 +00:00
|
|
|
return $text;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function magicRFC( $text )
|
|
|
|
|
{
|
|
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function headElement()
|
|
|
|
|
{
|
2003-07-08 20:17:36 +00:00
|
|
|
global $wgDocType, $wgDTD, $wgUser, $wgLanguageCode, $wgOutputEncoding, $wgLang;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2003-07-02 06:22:03 +00:00
|
|
|
$ret = "<!DOCTYPE HTML PUBLIC \"$wgDocType\"\n \"$wgDTD\">\n";
|
2003-04-14 23:10:40 +00:00
|
|
|
|
|
|
|
|
if ( "" == $this->mHTMLtitle ) {
|
|
|
|
|
$this->mHTMLtitle = $this->mPagetitle;
|
|
|
|
|
}
|
2003-07-08 20:17:36 +00:00
|
|
|
$rtl = $wgLang->isRTL() ? " dir='RTL'" : "";
|
|
|
|
|
$ret .= "<html lang=\"$wgLanguageCode\"$rtl><head><title>{$this->mHTMLtitle}</title>\n";
|
2003-04-14 23:10:40 +00:00
|
|
|
array_push( $this->mMetatags, array( "http:Content-type", "text/html; charset={$wgOutputEncoding}" ) );
|
|
|
|
|
foreach ( $this->mMetatags as $tag ) {
|
|
|
|
|
if ( 0 == strcasecmp( "http:", substr( $tag[0], 0, 5 ) ) ) {
|
|
|
|
|
$a = "http-equiv";
|
|
|
|
|
$tag[0] = substr( $tag[0], 5 );
|
|
|
|
|
} else {
|
|
|
|
|
$a = "name";
|
|
|
|
|
}
|
|
|
|
|
$ret .= "<meta $a=\"{$tag[0]}\" content=\"{$tag[1]}\">\n";
|
|
|
|
|
}
|
|
|
|
|
$p = $this->mRobotpolicy;
|
|
|
|
|
if ( "" == $p ) { $p = "index,follow"; }
|
|
|
|
|
$ret .= "<meta name=\"robots\" content=\"$p\">\n";
|
|
|
|
|
|
|
|
|
|
if ( count( $this->mKeywords ) > 0 ) {
|
|
|
|
|
$ret .= "<meta name=\"keywords\" content=\"" .
|
|
|
|
|
implode( ",", $this->mKeywords ) . "\">\n";
|
|
|
|
|
}
|
|
|
|
|
foreach ( $this->mLinktags as $tag ) {
|
|
|
|
|
$ret .= "<link ";
|
|
|
|
|
if ( "" != $tag[0] ) { $ret .= "rel=\"{$tag[0]}\" "; }
|
|
|
|
|
if ( "" != $tag[1] ) { $ret .= "rev=\"{$tag[1]}\" "; }
|
|
|
|
|
$ret .= "href=\"{$tag[2]}\">\n";
|
|
|
|
|
}
|
|
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
|
$ret .= $sk->getHeadScripts();
|
|
|
|
|
$ret .= $sk->getUserStyles();
|
|
|
|
|
|
|
|
|
|
$ret .= "</head>\n";
|
|
|
|
|
return $ret;
|
|
|
|
|
}
|
2004-01-07 02:51:47 +00:00
|
|
|
|
|
|
|
|
/* private */ function fillFromParserCache(){
|
|
|
|
|
global $wgUser, $wgArticle;
|
|
|
|
|
$hash = $wgUser->getPageRenderingHash();
|
|
|
|
|
$pageid = intval( $wgArticle->getID() );
|
|
|
|
|
$res = wfQuery("SELECT pc_data FROM parsercache WHERE pc_pageid = {$pageid} ".
|
|
|
|
|
" AND pc_prefhash = '{$hash}' AND pc_expire > NOW()", DB_WRITE);
|
|
|
|
|
$row = wfFetchObject ( $res );
|
|
|
|
|
if( $row ){
|
|
|
|
|
$data = unserialize( gzuncompress($row->pc_data) );
|
|
|
|
|
$this->addHTML( $data['html'] );
|
|
|
|
|
$this->mLanguageLinks = $data['mLanguageLinks'];
|
|
|
|
|
$this->mCategoryLinks = $data['mCategoryLinks'];
|
|
|
|
|
wfProfileOut( $fname );
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* private */ function saveParserCache( $text ){
|
|
|
|
|
global $wgUser, $wgArticle;
|
|
|
|
|
$hash = $wgUser->getPageRenderingHash();
|
|
|
|
|
$pageid = intval( $wgArticle->getID() );
|
|
|
|
|
$title = wfStrencode( $wgArticle->mTitle->getPrefixedDBKey() );
|
|
|
|
|
$data = array();
|
|
|
|
|
$data['html'] = $text;
|
|
|
|
|
$data['mLanguageLinks'] = $this->mLanguageLinks;
|
|
|
|
|
$data['mCategoryLinks'] = $this->mCategoryLinks;
|
|
|
|
|
$ser = addslashes( gzcompress( serialize( $data ) ) );
|
|
|
|
|
if( $this->mContainsOldMagic ){
|
|
|
|
|
$expire = "1 HOUR";
|
|
|
|
|
} else if( $this->mContainsNewMagic ){
|
|
|
|
|
$expire = "1 DAY";
|
|
|
|
|
} else {
|
|
|
|
|
$expire = "7 DAY";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wfQuery("REPLACE INTO parsercache (pc_prefhash,pc_pageid,pc_title,pc_data, pc_expire) ".
|
|
|
|
|
"VALUES('{$hash}', {$pageid}, '{$title}', '{$ser}', ".
|
|
|
|
|
"DATE_ADD(NOW(), INTERVAL {$expire}))", DB_WRITE);
|
|
|
|
|
|
|
|
|
|
if( rand() % 50 == 0 ){ // more efficient to just do it sometimes
|
|
|
|
|
$this->purgeParserCache();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* static private */ function purgeParserCache(){
|
|
|
|
|
wfQuery("DELETE FROM parsercache WHERE pc_expire < NOW() LIMIT 250", DB_WRITE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* static */ function parsercacheClearLinksTo( $pid ){
|
|
|
|
|
$pid = intval( $pid );
|
|
|
|
|
wfQuery("DELETE parsercache FROM parsercache,links ".
|
|
|
|
|
"WHERE pc_title=links.l_from AND l_to={$pid}", DB_WRITE);
|
|
|
|
|
wfQuery("DELETE FROM parsercache WHERE pc_pageid='{$pid}'", DB_WRITE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# $title is a prefixed db title, for example like Title->getPrefixedDBkey() returns.
|
|
|
|
|
/* static */ function parsercacheClearBrokenLinksTo( $title ){
|
|
|
|
|
$title = wfStrencode( $title );
|
|
|
|
|
wfQuery("DELETE parsercache FROM parsercache,brokenlinks ".
|
|
|
|
|
"WHERE pc_pageid=bl_from AND bl_to='{$title}'", DB_WRITE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# $pid is a page id
|
|
|
|
|
/* static */ function parsercacheClearPage( $pid ){
|
|
|
|
|
$pid = intval( $pid );
|
|
|
|
|
wfQuery("DELETE FROM parsercache WHERE pc_pageid='{$pid}'", DB_WRITE);
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2003-11-02 13:57:24 +00:00
|
|
|
# Regex callbacks, used in OutputPage::replaceVariables
|
|
|
|
|
|
|
|
|
|
# Just get rid of the dangerous stuff
|
|
|
|
|
# Necessary because replaceVariables is called after removeHTMLtags,
|
|
|
|
|
# and message text can come from any user
|
|
|
|
|
function wfReplaceMsgVar( $matches ) {
|
|
|
|
|
global $wgOut;
|
|
|
|
|
$text = $wgOut->removeHTMLtags( wfMsg( $matches[1] ) );
|
|
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Effective <nowiki></nowiki>
|
|
|
|
|
# Not real <nowiki> because this is called after nowiki sections are processed
|
|
|
|
|
function wfReplaceMsgnwVar( $matches ) {
|
|
|
|
|
$text = wfEscapeWikiText( wfMsg( $matches[1] ) );
|
|
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
?>
|