X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FMath.php;h=8cf9b8d897709a6f072dbe320beacfef2a474fcb;hb=1d0d879be013f8cc8bfd993608b1e740deef56b1;hp=1bf68b2bddd7e25346374d889eeb694277e655b2;hpb=e2ae8925ffad7d057355fe6016dda333d3908775;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Math.php b/includes/Math.php index 1bf68b2bdd..8cf9b8d897 100644 --- a/includes/Math.php +++ b/includes/Math.php @@ -1,7 +1,8 @@ parsing - * @package MediaWiki + * @file + * @ingroup Parser */ /** @@ -9,9 +10,8 @@ * to rasterized PNG and HTML and MathML approximations. An appropriate * rendering form is picked and returned. * - * by Tomasz Wegrzanowski, with additions by Brion Vibber (2003, 2004) - * - * @package MediaWiki + * @author Tomasz Wegrzanowski, with additions by Brion Vibber (2003, 2004) + * @ingroup Parser */ class MathRenderer { var $mode = MW_MATH_MODERN; @@ -22,8 +22,9 @@ class MathRenderer { var $mathml = ''; var $conservativeness = 0; - function MathRenderer( $tex ) { + function __construct( $tex, $params=array() ) { $this->tex = $tex; + $this->params = $params; } function setOutputMode( $mode ) { @@ -32,22 +33,26 @@ class MathRenderer { function render() { global $wgTmpDirectory, $wgInputEncoding; - global $wgTexvc; - $fname = 'MathRenderer::render'; + global $wgTexvc, $wgMathCheckFiles, $wgTexvcBackgroundColor; if( $this->mode == MW_MATH_SOURCE ) { # No need to render or parse anything more! return ('$ '.htmlspecialchars( $this->tex ).' $'); } + if( $this->tex == '' ) { + return; # bug 8372 + } if( !$this->_recall() ) { - # Ensure that the temp and output directories are available before continuing... - if( !file_exists( $wgTmpDirectory ) ) { - if( !@mkdir( $wgTmpDirectory ) ) { + if( $wgMathCheckFiles ) { + # Ensure that the temp and output directories are available before continuing... + if( !file_exists( $wgTmpDirectory ) ) { + if( !wfMkdirParents( $wgTmpDirectory ) ) { + return $this->_error( 'math_bad_tmpdir' ); + } + } elseif( !is_dir( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) { return $this->_error( 'math_bad_tmpdir' ); } - } elseif( !is_dir( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) { - return $this->_error( 'math_bad_tmpdir' ); } if( function_exists( 'is_executable' ) && !is_executable( $wgTexvc ) ) { @@ -57,7 +62,8 @@ class MathRenderer { escapeshellarg( $wgTmpDirectory ).' '. escapeshellarg( $wgTmpDirectory ).' '. escapeshellarg( $this->tex ).' '. - escapeshellarg( $wgInputEncoding ); + escapeshellarg( $wgInputEncoding ).' '. + escapeshellarg( $wgTexvcBackgroundColor ); if ( wfIsWindows() ) { # Invoke it within cygwin sh, because texvc expects sh features in its default shell @@ -73,13 +79,15 @@ class MathRenderer { } $retval = substr ($contents, 0, 1); + $errmsg = ''; if (($retval == 'C') || ($retval == 'M') || ($retval == 'L')) { - if ($retval == 'C') + if ($retval == 'C') { $this->conservativeness = 2; - else if ($retval == 'M') + } else if ($retval == 'M') { $this->conservativeness = 1; - else + } else { $this->conservativeness = 0; + } $outdata = substr ($contents, 33); $i = strpos($outdata, "\000"); @@ -88,32 +96,49 @@ class MathRenderer { $this->mathml = substr($outdata, $i+1); } else if (($retval == 'c') || ($retval == 'm') || ($retval == 'l')) { $this->html = substr ($contents, 33); - if ($retval == 'c') + if ($retval == 'c') { $this->conservativeness = 2; - else if ($retval == 'm') + } else if ($retval == 'm') { $this->conservativeness = 1; - else + } else { $this->conservativeness = 0; - $this->mathml = NULL; + } + $this->mathml = null; } else if ($retval == 'X') { - $this->html = NULL; + $this->html = null; $this->mathml = substr ($contents, 33); $this->conservativeness = 0; } else if ($retval == '+') { - $this->html = NULL; - $this->mathml = NULL; + $this->html = null; + $this->mathml = null; $this->conservativeness = 0; } else { $errbit = htmlspecialchars( substr($contents, 1) ); switch( $retval ) { - case 'E': return $this->_error( 'math_lexing_error', $errbit ); - case 'S': return $this->_error( 'math_syntax_error', $errbit ); - case 'F': return $this->_error( 'math_unknown_function', $errbit ); - default: return $this->_error( 'math_unknown_error', $errbit ); + case 'E': + $errmsg = $this->_error( 'math_lexing_error', $errbit ); + break; + case 'S': + $errmsg = $this->_error( 'math_syntax_error', $errbit ); + break; + case 'F': + $errmsg = $this->_error( 'math_unknown_function', $errbit ); + break; + default: + $errmsg = $this->_error( 'math_unknown_error', $errbit ); } } - $this->hash = substr ($contents, 1, 32); + if ( !$errmsg ) { + $this->hash = substr ($contents, 1, 32); + } + + wfRunHooks( 'MathAfterTexvc', array( &$this, &$errmsg ) ); + + if ( $errmsg ) { + return $errmsg; + } + if (!preg_match("/^[a-f0-9]{32}$/", $this->hash)) { return $this->_error( 'math_unknown_error' ); } @@ -122,6 +147,10 @@ class MathRenderer { return $this->_error( 'math_image_error' ); } + if( filesize( "$wgTmpDirectory/{$this->hash}.png" ) == 0 ) { + return $this->_error( 'math_image_error' ); + } + $hashpath = $this->_getHashPath(); if( !file_exists( $hashpath ) ) { if( !@wfMkdirParents( $hashpath, 0755 ) ) { @@ -141,18 +170,25 @@ class MathRenderer { $md5_sql = pack('H32', $this->md5); # Binary packed, not hex - $dbw =& wfGetDB( DB_MASTER ); + $dbw = wfGetDB( DB_MASTER ); $dbw->replace( 'math', array( 'math_inputhash' ), array( - 'math_inputhash' => $md5_sql, - 'math_outputhash' => $outmd5_sql, + 'math_inputhash' => $dbw->encodeBlob($md5_sql), + 'math_outputhash' => $dbw->encodeBlob($outmd5_sql), 'math_html_conservativeness' => $this->conservativeness, 'math_html' => $this->html, 'math_mathml' => $this->mathml, - ), $fname, array( 'IGNORE' ) + ), __METHOD__ ); } - + + // If we're replacing an older version of the image, make sure it's current. + global $wgUseSquid; + if ( $wgUseSquid ) { + $urls = array( $this->_mathImageUrl() ); + $u = new SquidUpdate( $urls ); + $u->doUpdate(); + } } return $this->_doRender(); @@ -166,29 +202,40 @@ class MathRenderer { } function _recall() { - global $wgMathDirectory; - $fname = 'MathRenderer::_recall'; + global $wgMathDirectory, $wgMathCheckFiles; $this->md5 = md5( $this->tex ); - $dbr =& wfGetDB( DB_SLAVE ); + $dbr = wfGetDB( DB_SLAVE ); $rpage = $dbr->selectRow( 'math', array( 'math_outputhash','math_html_conservativeness','math_html','math_mathml' ), - array( 'math_inputhash' => pack("H32", $this->md5)), # Binary packed, not hex - $fname + array( 'math_inputhash' => $dbr->encodeBlob(pack("H32", $this->md5))), # Binary packed, not hex + __METHOD__ ); if( $rpage !== false ) { # Tailing 0x20s can get dropped by the database, add it back on if necessary: - $xhash = unpack( 'H32md5', $rpage->math_outputhash . " " ); + $xhash = unpack( 'H32md5', $dbr->decodeBlob($rpage->math_outputhash) . " " ); $this->hash = $xhash ['md5']; $this->conservativeness = $rpage->math_html_conservativeness; $this->html = $rpage->math_html; $this->mathml = $rpage->math_mathml; - if( file_exists( $this->_getHashPath() . "/{$this->hash}.png" ) ) { + $filename = $this->_getHashPath() . "/{$this->hash}.png"; + + if( !$wgMathCheckFiles ) { + // Short-circuit the file existence & migration checks return true; } + + if( file_exists( $filename ) ) { + if( filesize( $filename ) == 0 ) { + // Some horrible error corrupted stuff :( + @unlink( $filename ); + } else { + return true; + } + } if( file_exists( $wgMathDirectory . "/{$this->hash}.png" ) ) { $hashpath = $this->_getHashPath(); @@ -220,40 +267,66 @@ class MathRenderer { */ function _doRender() { if( $this->mode == MW_MATH_MATHML && $this->mathml != '' ) { - return "{$this->mathml}"; + return Xml::tags( 'math', + $this->_attribs( 'math', + array( 'xmlns' => 'http://www.w3.org/1998/Math/MathML' ) ), + $this->mathml ); } if (($this->mode == MW_MATH_PNG) || ($this->html == '') || (($this->mode == MW_MATH_SIMPLE) && ($this->conservativeness != 2)) || (($this->mode == MW_MATH_MODERN || $this->mode == MW_MATH_MATHML) && ($this->conservativeness == 0))) { return $this->_linkToMathImage(); } else { - return ''.$this->html.''; + return Xml::tags( 'span', + $this->_attribs( 'span', + array( 'class' => 'texhtml' ) ), + $this->html ); } } + function _attribs( $tag, $defaults=array(), $overrides=array() ) { + $attribs = Sanitizer::validateTagAttributes( $this->params, $tag ); + $attribs = Sanitizer::mergeAttributes( $defaults, $attribs ); + $attribs = Sanitizer::mergeAttributes( $attribs, $overrides ); + return $attribs; + } + function _linkToMathImage() { - global $wgMathPath; - $url = htmlspecialchars( "$wgMathPath/" . substr($this->hash, 0, 1) - .'/'. substr($this->hash, 1, 1) .'/'. substr($this->hash, 2, 1) - . "/{$this->hash}.png" ); - $alt = trim(str_replace("\n", ' ', htmlspecialchars( $this->tex ))); - return "\"$alt\""; + $url = $this->_mathImageUrl(); + + return Xml::element( 'img', + $this->_attribs( + 'img', + array( + 'class' => 'tex', + 'alt' => $this->tex ), + array( + 'src' => $url ) ) ); } + function _mathImageUrl() { + global $wgMathPath; + $dir = $this->_getHashSubPath(); + return "$wgMathPath/$dir/{$this->hash}.png"; + } + function _getHashPath() { global $wgMathDirectory; - $path = $wgMathDirectory .'/'. substr($this->hash, 0, 1) - .'/'. substr($this->hash, 1, 1) - .'/'. substr($this->hash, 2, 1); + $path = $wgMathDirectory .'/' . $this->_getHashSubPath(); wfDebug( "TeX: getHashPath, hash is: $this->hash, path is: $path\n" ); return $path; } + + function _getHashSubPath() { + return substr($this->hash, 0, 1) + .'/'. substr($this->hash, 1, 1) + .'/'. substr($this->hash, 2, 1); + } - function renderMath( $tex ) { + public static function renderMath( $tex, $params=array() ) { global $wgUser; - $math = new MathRenderer( $tex ); + $math = new MathRenderer( $tex, $params ); $math->setOutputMode( $wgUser->getOption('math')); return $math->render(); } } -?>