<?php
+
+# This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
+if( defined( "MEDIAWIKI" ) ) {
+
# See design.doc
if($wgUseTeX) require_once( "Math.php" );
+define( 'RLH_FOR_UPDATE', 1 );
+
class OutputPage {
var $mHeaders, $mCookies, $mMetatags, $mKeywords;
var $mLinktags, $mPagetitle, $mBodytext, $mDebugtext;
var $mHTMLtitle, $mRobotpolicy, $mIsarticle, $mPrintable;
var $mSubtitle, $mRedirect;
var $mLastModified, $mCategoryLinks;
- var $mScripts;
-
+ var $mScripts, $mLinkColours;
+
var $mSuppressQuickbar;
var $mOnloadHandler;
var $mDoNothing;
- var $mContainsOldMagic, $mContainsNewMagic;
+ var $mContainsOldMagic, $mContainsNewMagic;
var $mIsArticleRelated;
var $mParserOptions;
var $mShowFeedLinks = false;
var $mEnableClientCache = true;
-
+
function OutputPage()
{
$this->mHeaders = $this->mCookies = $this->mMetatags =
$this->mKeywords = $this->mLinktags = array();
$this->mHTMLtitle = $this->mPagetitle = $this->mBodytext =
$this->mRedirect = $this->mLastModified =
- $this->mSubtitle = $this->mDebugtext = $this->mRobotpolicy =
+ $this->mSubtitle = $this->mDebugtext = $this->mRobotpolicy =
$this->mOnloadHandler = "";
$this->mIsArticleRelated = $this->mIsarticle = $this->mPrintable = true;
$this->mSuppressQuickbar = $this->mPrintable = false;
function addKeyword( $text ) { array_push( $this->mKeywords, $text ); }
function addScript( $script ) { $this->mScripts .= $script; }
function getScript() { return $this->mScripts; }
-
+
function addLink( $linkarr ) {
# $linkarr should be an associative array of attributes. We'll escape on output.
array_push( $this->mLinktags, $linkarr );
# 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.
+ # returns true iff cache-ok headers was sent.
function checkLastModified ( $timestamp )
{
global $wgLang, $wgCachePages, $wgUser;
$modsince = preg_replace( '/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"] );
$ismodsince = wfUnix2Timestamp( strtotime( $modsince ) );
wfDebug( "-- client send If-Modified-Since: " . $modsince . "\n", false );
- wfDebug( "-- we might send Last-Modified : $lastmod\n", false );
+ wfDebug( "-- we might send Last-Modified : $lastmod\n", false );
if( ($ismodsince >= $timestamp ) and $wgUser->validateCache( $ismodsince ) ) {
# Make sure you're in a place you can leave when you call us!
global $action;
switch($action) {
case 'edit':
- return wfMsg('edit');
+ return wfMsg('edit');
case 'history':
return wfMsg('history_short');
case 'protect':
- return wfMsg('unprotect');
+ return wfMsg('protect');
case 'unprotect':
return wfMsg('unprotect');
case 'delete':
return wfMsg('unwatch');
case 'submit':
return wfMsg('preview');
+ case 'info':
+ return wfMsg('info_short');
default:
return '';
}
$this->mIsarticle = false;
}
}
- function setArticleFlag( $v ) {
- $this->mIsarticle = $v;
+ function setArticleFlag( $v ) {
+ $this->mIsarticle = $v;
if ( $v ) {
$this->mIsArticleRelated = $v;
}
{
return $this->mIsArticleRelated;
}
-
+
function getLanguageLinks() {
return $this->mLanguageLinks;
}
function setLanguageLinks($newLinkArray) {
$this->mLanguageLinks = $newLinkArray;
}
+ function getCategoryLinks() {
+ return $this->mCategoryLinks;
+ }
+ function addCategoryLinks($newLinkArray) {
+ $this->mCategoryLinks += $newLinkArray;
+ }
+ function setCategoryLinks($newLinkArray) {
+ $this->mCategoryLinks += $newLinkArray;
+ }
+
function suppressQuickbar() { $this->mSuppressQuickbar = true; }
function isQuickbarSuppressed() { return $this->mSuppressQuickbar; }
function addWikiText( $text, $linestart = true, $cacheArticle = NULL )
{
global $wgParser, $wgParserCache, $wgUser, $wgTitle;
-
+
$parserOutput = $wgParser->parse( $text, $wgTitle, $this->mParserOptions, $linestart );
if ( $cacheArticle ) {
$wgParserCache->save( $parserOutput, $cacheArticle, $wgUser );
}
-
+
$this->mLanguageLinks += $parserOutput->getLanguageLinks();
$this->mCategoryLinks += $parserOutput->getCategoryLinks();
$this->addHTML( $parserOutput->getText() );
return false;
}
}
-
+
# Set the maximum cache time on the Squid in seconds
function setSquidMaxage( $maxage ) {
$this->mSquidMaxage = $maxage;
}
-
+
# Use enableClientCache(false) to force it to send nocache headers
function enableClientCache( $state ) {
return wfSetVar( $this->mEnableClientCache, $state );
}
-
+
function sendCacheControl() {
global $wgUseSquid, $wgUseESI;
# FIXME: This header may cause trouble with some versions of Internet Explorer
header( "Vary: Accept-Encoding, Cookie" );
if( $this->mEnableClientCache ) {
- if( $wgUseSquid && ! isset( $_COOKIE[ini_get( "session.name") ] ) &&
- ! $this->isPrintable() && $this->mSquidMaxage != 0 )
+ if( $wgUseSquid && ! isset( $_COOKIE[ini_get( "session.name") ] ) &&
+ ! $this->isPrintable() && $this->mSquidMaxage != 0 )
{
if ( $wgUseESI ) {
# We'll purge the proxy cache explicitly, but require end user agents
} else {
# We'll purge the proxy cache for anons explicitly, but require end user agents
# to revalidate against the proxy on each visit.
- # IMPORTANT! The Squid needs to replace the Cache-Control header with
+ # IMPORTANT! The Squid needs to replace the Cache-Control header with
# Cache-Control: s-maxage=0, must-revalidate, max-age=0
wfDebug( "** local proxy caching; {$this->mLastModified} **\n", false );
# start with a shorter timeout for initial testing
header( "Pragma: no-cache" );
}
}
-
+
# Finally, all the text has been munged and accumulated into
# the object, let's actually output it:
#
{
global $wgUser, $wgLang, $wgDebugComments, $wgCookieExpiration;
global $wgInputEncoding, $wgOutputEncoding, $wgLanguageCode;
- global $wgDebugRedirects, $wgMimeType;
+ global $wgDebugRedirects, $wgMimeType, $wgProfiler;
if( $this->mDoNothing ){
return;
}
$fname = "OutputPage::output";
wfProfileIn( $fname );
-
+
$sk = $wgUser->getSkin();
if ( "" != $this->mRedirect ) {
}
$this->mLastModified = gmdate( "D, j M Y H:i:s" ) . " GMT";
}
-
+
$this->sendCacheControl();
-
+
if( $wgDebugRedirects ) {
$url = htmlspecialchars( $this->mRedirect );
print "<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
} else {
header( "Location: {$this->mRedirect}" );
}
+ if ( isset( $wgProfiler ) ) { wfDebug( $wgProfiler->getOutput() ); }
return;
}
-
-
+
+
$this->sendCacheControl();
+ # Perform link colouring
+ $this->replaceLinkHolders();
+ # Disable temporary placeholders, so that the skin produces HTML
+ $sk->postParseLinkColour( false );
+
header( "Content-type: $wgMimeType; charset={$wgOutputEncoding}" );
header( "Content-language: {$wgLanguageCode}" );
foreach( $this->mCookies as $name => $val ) {
setcookie( $name, $val, $exp, "/" );
}
-
+
$sk->outputPage( $this );
# flush();
}
global $wgUser, $wgLang;
$wgInputEncoding = strtolower( $wgInputEncoding );
-
+
if( $wgUser->getOption( 'altencoding' ) ) {
$wgLang->setAltEncoding();
return;
$wgOutputEncoding = strtolower( $wgOutputEncoding );
return;
}
-
+
/*
# This code is unused anyway!
# Commenting out. --bv 2003-11-15
-
+
$a = explode( ",", $_SERVER['HTTP_ACCEPT_CHARSET'] );
$best = 0.0;
$bestset = "*";
$wgOutputEncoding = $wgInputEncoding;
}
- # Returns a HTML comment with the elapsed time since request.
+ # Returns a HTML comment with the elapsed time since request.
# This method has no side effects.
function reportTime()
{
list( $usec, $sec ) = explode( " ", $wgRequestTime );
$start = (float)$sec + (float)$usec;
$elapsed = $now - $start;
-
+
# Use real server name if available, so we know which machine
# in a server farm generated the current page.
if ( function_exists( "posix_uname" ) ) {
$this->setRobotpolicy( "noindex,nofollow" );
$this->setArticleRelated( false );
$this->enableClientCache( false );
+ $this->mRedirect = "";
$this->mBodytext = "";
$this->addHTML( "<p>" . wfMsg( $msg ) . "</p>\n" );
$this->returnToMain( false );
$this->output();
- wfAbruptExit();
+ wfErrorExit();
}
function sysopRequired()
$this->mBodytext = "";
$sk = $wgUser->getSkin();
- $ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
+ $ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
$this->addHTML( wfMsg( "sysoptext", $ap ) );
$this->returnToMain();
}
$this->mBodytext = "";
$sk = $wgUser->getSkin();
- $ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
+ $ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
$this->addHTML( wfMsg( "developertext", $ap ) );
$this->returnToMain();
}
# We put a comment in the .html file so a Sysop can diagnose the page the
# user can't see.
- $this->addHTML( "\n<!--" .
- $wgLang->getNsText( $wgTitle->getNamespace() ) .
- ":" .
+ $this->addHTML( "\n<!--" .
+ $wgLang->getNsText( $wgTitle->getNamespace() ) .
+ ":" .
$wgTitle->getDBkey() . "-->" );
$this->returnToMain(); # Flip back to the main page after 10 seconds.
}
$this->setRobotpolicy( "noindex,nofollow" );
$this->setArticleRelated( false );
$this->enableClientCache( false );
+ $this->mRedirect = "";
if ( $wgCommandLineMode ) {
- $msg = wfMsgNoDB( "dberrortextcl" );
+ $msg = wfMsgNoDB( "dberrortextcl", htmlspecialchars( $sql ),
+ htmlspecialchars( $fname ), $errno, htmlspecialchars( $error ) );
} else {
- $msg = wfMsgNoDB( "dberrortext" );
+ $msg = wfMsgNoDB( "dberrortext", htmlspecialchars( $sql ),
+ htmlspecialchars( $fname ), $errno, htmlspecialchars( $error ) );
}
- $msg = str_replace( "$1", htmlspecialchars( $sql ), $msg );
- $msg = str_replace( "$2", htmlspecialchars( $fname ), $msg );
- $msg = str_replace( "$3", $errno, $msg );
- $msg = str_replace( "$4", htmlspecialchars( $error ), $msg );
-
if ( $wgCommandLineMode || !is_object( $wgUser )) {
print "$msg\n";
- wfAbruptExit();
+ wfErrorExit();
}
- $sk = $wgUser->getSkin();
- $shlink = $sk->makeKnownLink( wfMsgNoDB( "searchhelppage" ),
- wfMsgNoDB( "searchingwikipedia" ) );
- $msg = str_replace( "$5", $shlink, $msg );
$this->mBodytext = $msg;
$this->output();
- wfAbruptExit();
+ wfErrorExit();
}
function readOnlyPage( $source = null, $protected = false )
$reason = file_get_contents( $wgReadOnlyFile );
$this->addWikiText( wfMsg( "readonlytext", $reason ) );
}
-
+
if( is_string( $source ) ) {
if( strcmp( $source, "" ) == 0 ) {
$source = wfMsg( "noarticletext" );
htmlspecialchars( $source ) . "\n</textarea>";
$this->addHTML( $text );
}
-
+
$this->returnToMain( false );
}
$this->setRobotpolicy( "noindex,nofollow" );
$this->setArticleRelated( false );
$this->enableClientCache( false );
+ $this->mRedirect = "";
$this->mBodytext = $message;
$this->output();
- wfAbruptExit();
+ wfErrorExit();
}
function unexpectedValueError( $name, $val )
function returnToMain( $auto = true, $returnto = NULL )
{
global $wgUser, $wgOut, $wgRequest;
-
+
if ( $returnto == NULL ) {
$returnto = $wgRequest->getText( 'returnto' );
}
$a = array_slice ( $a , 0 , 10 ) ; # 10 keywords max
$a = implode ( "," , $a ) ;
$strip = array(
- "/<.*?>/" => '',
+ "/<.*?" . ">/" => '',
"/[_]/" => ' '
);
$a = htmlspecialchars(preg_replace(array_keys($strip), array_values($strip),$a ));
-
+
$wgOut->addMeta ( "KEYWORDS" , $a ) ;
}
} else {
$ret = "";
}
-
+
$ret .= "<!DOCTYPE html PUBLIC \"$wgDocType\"\n \"$wgDTD\">\n";
if ( "" == $this->mHTMLtitle ) {
$ret .= "<html $xmlbits lang=\"$wgLanguageCode\" $rtl>\n";
$ret .= "<head>\n<title>" . htmlspecialchars( $this->mHTMLtitle ) . "</title>\n";
array_push( $this->mMetatags, array( "http:Content-type", "$wgMimeType; charset={$wgOutputEncoding}" ) );
-
+
$ret .= $this->getHeadLinks();
global $wgStylePath;
if( $this->isPrintable() ) {
$ret .= "</head>\n";
return $ret;
}
-
+
function getHeadLinks() {
global $wgRequest, $wgStylePath;
$ret = "";
if ( count( $this->mKeywords ) > 0 ) {
$strip = array(
- "/<.*?>/" => '',
+ "/<.*?" . ">/" => '',
"/[_]/" => ' '
);
$ret .= "<meta name=\"keywords\" content=\"" .
}
# FIXME: get these working
# $fix = htmlspecialchars( $wgStylePath . "/ie-png-fix.js" );
- # $ret .= "<!--[if gte IE 5.5000]><script type='text/javascript' src='$fix'></script><![endif]-->";
+ # $ret .= "<!--[if gte IE 5.5000]><script type='text/javascript' src='$fix'>< /script><![endif]-->";
return $ret;
}
+
+ # Replace <!--LINK--> link placeholders with actual links, in the buffer
+ # Placeholders created in Skin::makeLinkObj()
+ # Returns an array of links found, indexed by PDBK:
+ # 0 - broken
+ # 1 - normal link
+ # 2 - stub
+ # $options is a bit field, RLH_FOR_UPDATE to select for update
+ function replaceLinkHolders( $options = 0 )
+ {
+ global $wgUser, $wgLinkCache, $wgUseOldExistenceCheck;
+
+ if ( $wgUseOldExistenceCheck ) {
+ return array();
+ }
+
+ $fname = 'OutputPage::replaceLinkHolders';
+ wfProfileIn( $fname );
+
+ $titles = array();
+ $pdbks = array();
+ $colours = array();
+
+ # Get placeholders from body
+ wfProfileIn( "$fname-match" );
+ preg_match_all( "/<!--LINK (.*?) (.*?) (.*?) (.*?)-->/", $this->mBodytext, $tmpLinks );
+ wfProfileOut( "$fname-match" );
+
+ if ( !empty( $tmpLinks[0] ) ) {
+ wfProfileIn( "$fname-check" );
+ $dbr =& wfGetDB( DB_SLAVE );
+ $cur = $dbr->tableName( 'cur' );
+ $sk = $wgUser->getSkin();
+ $threshold = $wgUser->getOption('stubthreshold');
+
+ $namespaces =& $tmpLinks[1];
+ $dbkeys =& $tmpLinks[2];
+ $queries =& $tmpLinks[3];
+ $texts =& $tmpLinks[4];
+
+ # Sort by namespace
+ asort( $namespaces );
+
+ # Generate query
+ $query = false;
+ foreach ( $namespaces as $key => $val ) {
+ # Make title object
+ $dbk = $dbkeys[$key];
+ $title = $titles[$key] = Title::makeTitle( $val, $dbk );
+
+ # Skip invalid entries.
+ # Result will be ugly, but prevents crash.
+ if ( is_null( $title ) ) {
+ continue;
+ }
+ $pdbk = $pdbks[$key] = $title->getPrefixedDBkey();
+
+ # Check if it's in the link cache already
+ if ( $wgLinkCache->getGoodLinkID( $pdbk ) ) {
+ $colours[$pdbk] = 1;
+ } elseif ( $wgLinkCache->isBadLink( $pdbk ) ) {
+ $colours[$pdbk] = 0;
+ } else {
+ # Not in the link cache, add it to the query
+ if ( !isset( $current ) ) {
+ $current = $val;
+ $query = "SELECT cur_id, cur_namespace, cur_title";
+ if ( $threshold > 0 ) {
+ $query .= ", LENGTH(cur_text) AS cur_len, cur_is_redirect";
+ }
+ $query .= " FROM $cur WHERE (cur_namespace=$val AND cur_title IN(";
+ } elseif ( $current != $val ) {
+ $current = $val;
+ $query .= ")) OR (cur_namespace=$val AND cur_title IN(";
+ } else {
+ $query .= ", ";
+ }
+
+ $query .= $dbr->addQuotes( $dbkeys[$key] );
+ }
+ }
+ if ( $query ) {
+ $query .= "))";
+ if ( $options & RLH_FOR_UPDATE ) {
+ $query .= " FOR UPDATE";
+ }
+
+ $res = $dbr->query( $query, $fname );
+
+ # Fetch data and form into an associative array
+ # non-existent = broken
+ # 1 = known
+ # 2 = stub
+ while ( $s = $dbr->fetchObject($res) ) {
+ $title = Title::makeTitle( $s->cur_namespace, $s->cur_title );
+ $pdbk = $title->getPrefixedDBkey();
+ $wgLinkCache->addGoodLink( $s->cur_id, $pdbk );
+
+ if ( $threshold > 0 ) {
+ $size = $s->cur_len;
+ if ( $s->cur_is_redirect || $s->cur_namespace != 0 || $length < $threshold ) {
+ $colours[$pdbk] = 1;
+ } else {
+ $colours[$pdbk] = 2;
+ }
+ } else {
+ $colours[$pdbk] = 1;
+ }
+ }
+ }
+ wfProfileOut( "$fname-check" );
+
+ # Construct search and replace arrays
+ wfProfileIn( "$fname-construct" );
+ $search = $replace = array();
+ foreach ( $namespaces as $key => $ns ) {
+ $pdbk = $pdbks[$key];
+ $search[] = $tmpLinks[0][$key];
+ $title = $titles[$key];
+ if ( empty( $colours[$pdbk] ) ) {
+ $wgLinkCache->addBadLink( $pdbk );
+ $colours[$pdbk] = 0;
+ $replace[] = $sk->makeBrokenLinkObj( $title, $texts[$key], $queries[$key] );
+ } elseif ( $colours[$pdbk] == 1 ) {
+ $replace[] = $sk->makeKnownLinkObj( $title, $texts[$key], $queries[$key] );
+ } elseif ( $colours[$pdbk] == 2 ) {
+ $replace[] = $sk->makeStubLinkObj( $title, $texts[$key], $queries[$key] );
+ }
+ }
+ wfProfileOut( "$fname-construct" );
+ # Do the thing
+ wfProfileIn( "$fname-replace" );
+ $this->mBodytext = str_replace( $search, $replace, $this->mBodytext );
+ wfProfileOut( "$fname-replace" );
+ }
+ wfProfileOut( $fname );
+ return $colours;
+ }
+}
+
}
?>