Fine grained options for wgMathDisableTeXFilter

Add new option to filter only new input.
Now the complete list of possible settings is:
MW_MATH_CHECK_ALWAYS  backwards compatible to false
MW_MATH_CHECK_NEVER   backwards compatible to true
MW_MATH_CHECK_NEW     new option

Change-Id: I455b41c8b8d918f4c34f6c115194d227a8394e0a
This commit is contained in:
physikerwelt (Moritz Schubotz) 2014-09-05 21:59:13 -04:00 committed by Physikerwelt
parent c3894c2c49
commit ccc4114812
4 changed files with 144 additions and 38 deletions

View File

@ -92,7 +92,7 @@ class MathHooks {
* @return array
*/
static function mathTagHook( $content, $attributes, $parser ) {
global $wgUseMathJax, $wgMathDisableTexFilter;
global $wgUseMathJax;
if ( trim( $content ) === '' ) { // bug 8372
return '';
@ -111,14 +111,13 @@ class MathHooks {
$renderer = MathRenderer::getRenderer( $content, $attributes, $mode );
if ( !$wgMathDisableTexFilter ) {
$checkResult = $renderer->checkTex();
$checkResult = $renderer->checkTex();
if ( $checkResult !== true ) {
// Returns the error message
return $renderer->getLastError();
}
if ( $checkResult !== true ) {
// Returns the error message
return $renderer->getLastError();
}
if ( $renderer->render() ) {
wfDebugLog( "Math" , "Rendering successful. Writing output" );
$renderedMath = $renderer->getHtmlOutput();

View File

@ -188,12 +188,29 @@ $wgMathDefaultLaTeXMLSetting = array(
* The link to the texvccheck executable
*/
$wgMathTexvcCheckExecutable = __DIR__ . '/texvccheck/texvccheck';
/**
* Option to disable the tex filter. If set to true any LaTeX espression is parsed
* this can be a potential security risk. If set to false only a subset of the TeX
* commands is allowed. See the wikipedia page Help:Math for details.
/**@{
* Math check constants
*/
$wgMathDisableTexFilter = false;
define( 'MW_MATH_CHECK_ALWAYS', 0 ); /// backwards compatible to false
define( 'MW_MATH_CHECK_NEVER' , 1 ); /// backwards compatible to true
define( 'MW_MATH_CHECK_NEW' , 2 );
/**@}*/
/**
* Option to disable the TeX security filter:
* In general every math object, which is rendered by the math extension has its rendering cached in
* a database.
* MW_MATH_CHECK_ALWAYS: If set to MW_MATH_CHECK_ALWAYS only a subset of the TeX commands is allowed.
* See the Wikipedia page Help:Math for details about the allowed commands.
* MW_MATH_CHECK_NONE: If set to MW_MATH_CHECK_NONE any TeX expression is parsed.
* This can be a potential security risk.
* MW_MATH_CHECK_NEW checks only new equations. If the database does not yet contain the given math object,
* then it is passed through texvccheck.
* Please make sure to truncate the database tables (math, mathoid, mathlatexml) when switching from
* MW_MATH_CHECK_NONE to MW_MATH_CHECK_NEW. Otherwise, unchecked content contained in the database
* will be displayed.
*/
$wgMathDisableTexFilter = MW_MATH_CHECK_NEW;
/** Stores debug information in the database and provides more detailed debug output */
$wgMathDebug = false;

View File

@ -262,7 +262,7 @@ abstract class MathRenderer {
wfProfileIn( __METHOD__ );
/** @var DatabaseBase */
$dbr = wfGetDB( DB_SLAVE );
/** @var ResultWrapper asdf */
/** @var ResultWrapper */
$rpage = $dbr->selectRow( $this->getMathTableName(),
$this->dbInArray(),
array( 'math_inputhash' => $this->getInputHash() ),
@ -600,8 +600,21 @@ abstract class MathRenderer {
return $this->texSecure;
}
/**
* @global $wgMathDisableTexFilter
* @return bool
*/
public function checkTex() {
if ( !$this->texSecure ) {
global $wgMathDisableTexFilter;
if ( $this->texSecure || (int) $wgMathDisableTexFilter == MW_MATH_CHECK_NEVER ) {
// equation was already checked or checking is disabled
return true;
} else {
if( (int) $wgMathDisableTexFilter == MW_MATH_CHECK_NEW ){
if( $this->readFromDatabase() ){
return true;
}
}
$checker = new MathInputCheckTexvc( $this->userInputTex );
if ( $checker->isValid() ) {
$this->setTex( $checker->getValidTex() );
@ -611,8 +624,6 @@ abstract class MathRenderer {
$this->lastError = $checker->getError();
return false;
}
} else {
return true;
}
}

View File

@ -6,19 +6,18 @@
*/
class MathRendererTest extends MediaWikiTestCase {
const SOME_TEX = "a+b";
const TEXVCCHECK_INPUT = '\forall \epsilon \exist \delta';
const TEXVCCHECK_OUTPUT = '\forall \epsilon \exists \delta '; // be aware of the s at exists
/**
* Checks the tex and hash functions
* @covers MathRenderer::getTex()
* @covers MathRenderer::__construct()
*/
public function testBasics() {
$renderer = $this->getMockForAbstractClass( 'MathRenderer'
, array ( self::SOME_TEX ) );
$renderer = $this->getMockForAbstractClass( 'MathRenderer', array( self::SOME_TEX ) );
// check if the TeX input was corretly passed to the class
$this->assertEquals( self::SOME_TEX, $renderer->getTex()
, "test getTex" );
$this->assertEquals( $renderer->isChanged(), false
, "test if changed is initially false" );
$this->assertEquals( self::SOME_TEX, $renderer->getTex(), "test getTex" );
$this->assertEquals( $renderer->isChanged(), false, "test if changed is initially false" );
}
/**
@ -26,12 +25,14 @@ class MathRendererTest extends MediaWikiTestCase {
* @covers MathRenderer::writeCache()
*/
public function testWriteCacheSkip() {
$renderer = $this->getMockBuilder( 'MathRenderer' )
->setMethods( array( 'writeToDatabase' , 'render', 'getMathTableName', 'getHtmlOutput' ) )
->disableOriginalConstructor()
->getMock();
$renderer->expects( $this->never() )
->method( 'writeToDatabase' );
$renderer =
$this->getMockBuilder( 'MathRenderer' )->setMethods( array(
'writeToDatabase',
'render',
'getMathTableName',
'getHtmlOutput'
) )->disableOriginalConstructor()->getMock();
$renderer->expects( $this->never() )->method( 'writeToDatabase' );
$renderer->writeCache();
}
@ -40,22 +41,100 @@ class MathRendererTest extends MediaWikiTestCase {
* @covers MathRenderer::writeCache()
*/
public function testWriteCache() {
$renderer = $this->getMockBuilder( 'MathRenderer' )
->setMethods( array( 'writeToDatabase' , 'render', 'getMathTableName', 'getHtmlOutput' ) )
->disableOriginalConstructor()
->getMock();
$renderer->expects( $this->never() )
->method( 'writeToDatabase' );
$renderer =
$this->getMockBuilder( 'MathRenderer' )->setMethods( array(
'writeToDatabase',
'render',
'getMathTableName',
'getHtmlOutput'
) )->disableOriginalConstructor()->getMock();
$renderer->expects( $this->never() )->method( 'writeToDatabase' );
$renderer->writeCache();
}
public function testSetPurge() {
$renderer = $this->getMockBuilder( 'MathRenderer' )
->setMethods( array( 'render', 'getMathTableName', 'getHtmlOutput' ) )
->disableOriginalConstructor()
->getMock();
$renderer =
$this->getMockBuilder( 'MathRenderer' )->setMethods( array(
'render',
'getMathTableName',
'getHtmlOutput'
) )->disableOriginalConstructor()->getMock();
$renderer->setPurge();
$this->assertEquals( $renderer->isPurge(), true, "Test purge." );
}
public function testCheckingAlways() {
$this->setMwGlobals( "wgMathDisableTexFilter", MW_MATH_CHECK_ALWAYS );
$renderer =
$this->getMockBuilder( 'MathRenderer' )->setMethods( array(
'render',
'getMathTableName',
'getHtmlOutput',
'readFromDatabase',
'setTex'
) )->setConstructorArgs( array( self::TEXVCCHECK_INPUT ) )->getMock();
$renderer->expects( $this->never() )->method( 'readFromDatabase' );
$renderer->expects( $this->once() )->method( 'setTex' )->with( self::TEXVCCHECK_OUTPUT );
$this->assertEquals( $renderer->checkTex(), true );
// now setTex sould not be called again
$this->assertEquals( $renderer->checkTex(), true );
}
public function testCheckingNever() {
$this->setMwGlobals( "wgMathDisableTexFilter", MW_MATH_CHECK_NEVER );
$renderer =
$this->getMockBuilder( 'MathRenderer' )->setMethods( array(
'render',
'getMathTableName',
'getHtmlOutput',
'readFromDatabase',
'setTex'
) )->setConstructorArgs( array( self::TEXVCCHECK_INPUT ) )->getMock();
$renderer->expects( $this->never() )->method( 'readFromDatabase' );
$renderer->expects( $this->never() )->method( 'setTex' );
$this->assertEquals( $renderer->checkTex(), true );
}
public function testCheckingNewUnknown() {
$this->setMwGlobals( "wgMathDisableTexFilter", MW_MATH_CHECK_NEW );
$renderer =
$this->getMockBuilder( 'MathRenderer' )->setMethods( array(
'render',
'getMathTableName',
'getHtmlOutput',
'readFromDatabase',
'setTex'
) )->setConstructorArgs( array( self::TEXVCCHECK_INPUT ) )->getMock();
$renderer->expects( $this->once() )->method( 'readFromDatabase' )
->will( $this->returnValue( false ) );
$renderer->expects( $this->once() )->method( 'setTex' )->with( self::TEXVCCHECK_OUTPUT );
$this->assertEquals( $renderer->checkTex(), true );
// now setTex sould not be called again
$this->assertEquals( $renderer->checkTex(), true );
}
public function testCheckingNewKnown() {
$this->setMwGlobals( "wgMathDisableTexFilter", MW_MATH_CHECK_NEW );
$renderer =
$this->getMockBuilder( 'MathRenderer' )->setMethods( array(
'render',
'getMathTableName',
'getHtmlOutput',
'readFromDatabase',
'setTex'
) )->setConstructorArgs( array( self::TEXVCCHECK_INPUT ) )->getMock();
$renderer->expects( $this->exactly( 2 ) )->method( 'readFromDatabase' )
->will( $this->returnValue( true ) );
$renderer->expects( $this->never() )->method( 'setTex' );
$this->assertEquals( $renderer->checkTex(), true );
// we don't mark a object as checked even though we rely on the database cache
// so readFromDatabase will be called again
$this->assertEquals( $renderer->checkTex(), true );
}
}