# See design.doc
function linkToMathImage ( $tex, $outputhash )
{
global $wgMathPath;
return "";
}
function renderMath( $tex )
{
global $wgUser, $wgMathDirectory, $wgTmpDirectory, $wgInputEncoding;
$mf = wfMsg( "math_failure" );
$munk = wfMsg( "math_unknown_error" );
$fname = "renderMath";
$math = $wgUser->getOption("math");
if ($math == 3)
return ('$ '.wfEscapeHTML($tex).' $');
$md5 = md5($tex);
$md5_sql = mysql_escape_string(pack("H32", $md5));
if ($math == 0)
$sql = "SELECT math_outputhash FROM math WHERE math_inputhash = '".$md5_sql."'";
else
$sql = "SELECT math_outputhash,math_html_conservativeness,math_html FROM math WHERE math_inputhash = '".$md5_sql."'";
$res = wfQuery( $sql, $fname );
if ( wfNumRows( $res ) == 0 )
{
$cmd = "./math/texvc ".escapeshellarg($wgTmpDirectory)." ".
escapeshellarg($wgMathDirectory)." ".escapeshellarg($tex)." ".escapeshellarg($wgInputEncoding);
$contents = `$cmd`;
if (strlen($contents) == 0)
return "".$mf." (".$munk."): ".wfEscapeHTML($tex)."";
$retval = substr ($contents, 0, 1);
if (($retval == "C") || ($retval == "M") || ($retval == "L")) {
if ($retval == "C")
$conservativeness = 2;
else if ($retval == "M")
$conservativeness = 1;
else
$conservativeness = 0;
$outdata = substr ($contents, 33);
$i = strpos($outdata, "\000");
$outhtml = substr($outdata, 0, $i);
$mathml = substr($outdata, $i+1);
$sql_html = "'".mysql_escape_string($outhtml)."'";
$sql_mathml = "'".mysql_escape_string($mathml)."'";
} else if (($retval == "c") || ($retval == "m") || ($retval == "l")) {
$outhtml = substr ($contents, 33);
if ($retval == "c")
$conservativeness = 2;
else if ($retval == "m")
$conservativeness = 1;
else
$conservativeness = 0;
$sql_html = "'".mysql_escape_string($outhtml)."'";
$mathml = '';
$sql_mathml = 'NULL';
} else if ($retval == "X") {
$outhtml = '';
$mathml = substr ($contents, 33);
$sql_html = 'NULL';
$sql_mathml = "'".mysql_escape_string($mathml)."'";
$conservativeness = 0;
} else if ($retval == "+") {
$outhtml = '';
$mathml = '';
$sql_html = 'NULL';
$sql_mathml = 'NULL';
$conservativeness = 0;
} else {
if ($retval == "E")
$errmsg = wfMsg( "math_lexing_error" );
else if ($retval == "S")
$errmsg = wfMsg( "math_syntax_error" );
else if ($retval == "F")
$errmsg = wfMsg( "math_unknown_function" );
else
$errmsg = $munk;
return "
".$mf." (".$errmsg.substr($contents, 1)."): ".wfEscapeHTML($tex)."
";
}
$outmd5 = substr ($contents, 1, 32);
if (!preg_match("/^[a-f0-9]{32}$/", $outmd5))
return "".$mf." (".$munk."): ".wfEscapeHTML($tex)."";
$outmd5_sql = mysql_escape_string(pack("H32", $outmd5));
$sql = "REPLACE INTO math VALUES ('".$md5_sql."', '".$outmd5_sql."', ".$conservativeness.", ".$sql_html.", ".$sql_mathml.")";
$res = wfQuery( $sql, $fname );
# we don't really care if it fails
if (($math == 0) || ($rpage->math_html == '') || (($math == 1) && ($conservativeness != 2)) || (($math == 4) && ($conservativeness == 0)))
return linkToMathImage($tex, $outmd5);
else
return $outhtml;
} else {
$rpage = wfFetchObject ( $res );
$outputhash = unpack( "H32md5", $rpage->math_outputhash . " " );
$outputhash = $outputhash ['md5'];
if (($math == 0) || ($rpage->math_html == '') || (($math == 1) && ($rpage->math_html_conservativeness != 2)) || (($math == 4) && ($rpage->math_html_conservativeness == 0)))
return linkToMathImage ( $tex, $outputhash );
else
return $rpage->math_html;
}
}
class OutputPage {
var $mHeaders, $mCookies, $mMetatags, $mKeywords;
var $mLinktags, $mPagetitle, $mBodytext, $mDebugtext;
var $mHTMLtitle, $mRobotpolicy, $mIsarticle, $mPrintable;
var $mSubtitle, $mRedirect, $mAutonumber, $mHeadtext;
var $mLastModified;
var $mDTopen, $mLastSection; # Used for processing DL, PRE
var $mLanguageLinks, $mSupressQuickbar;
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 =
$this->mSubtitle = $this->mDebugtext = $this->mRobotpolicy = "";
$this->mIsarticle = $this->mPrintable = true;
$this->mSupressQuickbar = $this->mDTopen = $this->mPrintable = false;
$this->mLanguageLinks = array();
$this->mAutonumber = 0;
}
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 ) ); }
function checkLastModified ( $timestamp )
{
global $wgLang, $wgCachePages, $wgUser;
if( !$wgCachePages ) return;
if( preg_match( '/MSIE ([1-4]|5\.0)/', $_SERVER["HTTP_USER_AGENT"] ) ) {
# IE 5.0 has probs with our caching
#wfDebug( "-- bad client, not caching\n", false );
return;
}
if( $wgUser->getOption( "nocache" ) ) return;
if( $_SERVER["HTTP_IF_MODIFIED_SINCE"] != "" ) {
$ismodsince = wfUnix2Timestamp( strtotime( $_SERVER["HTTP_IF_MODIFIED_SINCE"] ) );
#wfDebug( "-- client send If-Modified-Since: " . $_SERVER["HTTP_IF_MODIFIED_SINCE"] . "\n", false );
$lastmod = gmdate( "D, j M Y H:i:s", wfTimestamp2Unix(
max( $timestamp, $wgUser->mTouched ) ) ) . " GMT";
#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!
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}" );
#wfDebug( "CACHED client: $ismodsince ; user: $wgUser->mTouched ; page: $timestamp\n", false );
exit;
} else {
#wfDebug( "READY client: $ismodsince ; user: $wgUser->mTouched ; page: $timestamp\n", false );
$this->mLastModified = $lastmod;
}
}
}
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; }
function getLanguageLinks() {
global $wgUseNewInterlanguage, $wgTitle, $wgLanguageCode;
global $wgDBconnection, $wgDBname, $wgDBintlname;
if ( ! $wgUseNewInterlanguage )
return $this->mLanguageLinks;
mysql_select_db( $wgDBintlname, $wgDBconnection ) or die(
htmlspecialchars(mysql_error()) );
$list = array();
$sql = "SELECT * FROM ilinks WHERE lang_from=\"" .
"{$wgLanguageCode}\" AND title_from=\"" . $wgTitle->getDBkey() . "\"";
$res = mysql_query( $sql, $wgDBconnection );
while ( $q = mysql_fetch_object ( $res ) ) {
$list[] = $q->lang_to . ":" . $q->title_to;
}
mysql_free_result( $res );
mysql_select_db( $wgDBname, $wgDBconnection ) or die(
htmlspecialchars(mysql_error()) );
return $list;
}
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 sections, pass the rest off
# to doWikiPass2() which does all the real work.
#
function addWikiText( $text, $linestart = true )
{
global $wgUseTeX;
wfProfileIn( "OutputPage::addWikiText" );
$unique = "3iyZiyA7iMwg5rhxP0Dcc9oTnj8qD1jm1Sfv4";
$unique2 = "4LIQ9nXtiYFPCSfitVwDw7EYwQlL4GeeQ7qSO";
$unique3 = "fPaA8gDfdLBqzj68Yjg9Hil3qEF8JGO0uszIp";
$nwlist = array();
$nwsecs = 0;
$mathlist = array();
$mathsecs = 0;
$prelist = array ();
$presecs = 0;
$stripped = "";
$stripped2 = "";
$stripped3 = "";
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]);
$stripped .= $unique;
$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]);
$stripped2 .= $unique2;
$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;
$prelist[$presecs] = "". wfEscapeHTMLTagsOnly($q[0]). "
";
$stripped3 .= $unique3;
$stripped2 = $q[1];
}
}
$text = $this->doWikiPass2( $stripped3, $linestart );
for ( $i = 1; $i <= $presecs; ++$i ) {
$text = preg_replace( "/{$unique3}/", str_replace( '$', '\$', $prelist[$i] ), $text, 1 );
}
for ( $i = 1; $i <= $mathsecs; ++$i ) {
$text = preg_replace( "/{$unique2}/", str_replace( '$', '\$', $mathlist[$i] ), $text, 1 );
}
for ( $i = 1; $i <= $nwsecs; ++$i ) {
$text = preg_replace( "/{$unique}/", str_replace( '$', '\$', $nwlist[$i] ), $text, 1 );
}
$this->addHTML( $text );
wfProfileOut();
}
# 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;
wfProfileIn( "OutputPage::output" );
$sk = $wgUser->getSkin();
wfProfileIn( "OutputPage::output-headers" );
if( $this->mLastModified != "" ) {
header( "Cache-Control: private, must-revalidate, max-age=0" );
header( "Last-modified: {$this->mLastModified}" );
} else {
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!
header( "Content-type: text/html; charset={$wgOutputEncoding}" );
header( "Content-language: {$wgLanguageCode}" );
if ( "" != $this->mRedirect ) {
header( "Location: {$this->mRedirect}" );
wfProfileOut();
return;
}
$exp = time() + $wgCookieExpiration;
foreach( $this->mCookies as $name => $val ) {
setcookie( $name, $val, $exp, "/" );
}
wfProfileOut();
wfProfileIn( "OutputPage::output-middle" );
$sk->initPage();
$this->out( $this->headElement() );
$this->out( "\ngetBodyOptions();
foreach ( $ops as $name => $val ) {
$this->out( " $name='$val'" );
}
$this->out( ">\n" );
if ( $wgDebugComments ) {
$this->out( "\n" );
}
$this->out( $sk->beforeContent() );
wfProfileOut();
wfProfileIn( "OutputPage::output-bodytext" );
$this->out( $this->mBodytext );
wfProfileOut();
wfProfileIn( "OutputPage::output-after" );
$this->out( $sk->afterContent() );
wfProfileOut();
wfProfileOut(); # A hack - we can't report after here
$this->out( $this->reportTime() );
$this->out( "\n