// ...and <mw:toc> markers
$wrappedtext = preg_replace_callback( '/\<\\/?mw:toc\>/',
array( &$this, 'replaceCallback' ), $wrappedtext );
-
+ // ... and <math> tags
+ $wrappedtext = preg_replace_callback( '/\<math(.*?)\<\\/math\>/s',
+ array( &$this, 'replaceCallback' ), $wrappedtext );
// Modify inline Microdata <link> and <meta> elements so they say <html-link> and <html-meta> so
// we can trick Tidy into not stripping them out by including them in tidy's new-empty-tags config
$wrappedtext = preg_replace( '!<(link|meta)([^>]*?)(/{0,1}>)!', '<html-$1$2$3', $wrappedtext );
* @return string Corrected HTML output
*/
public static function tidy( $text ) {
- global $wgTidyInternal;
-
$wrapper = new MWTidyWrapper;
$wrappedtext = $wrapper->getWrapped( $text );
$retVal = null;
- if ( $wgTidyInternal ) {
- $correctedtext = self::execInternalTidy( $wrappedtext, false, $retVal );
- } else {
- $correctedtext = self::execExternalTidy( $wrappedtext, false, $retVal );
- }
+ list( $correctedtext, $errors ) = self::clean( $wrappedtext, $retVal );
if ( $retVal < 0 ) {
wfDebug( "Possible tidy configuration error!\n" );
return $text . "\n<!-- Tidy was unable to run -->\n";
- } elseif ( is_null( $correctedtext ) ) {
+ } elseif ( $correctedtext === '' && $text !== '' ) {
wfDebug( "Tidy error detected!\n" );
return $text . "\n<!-- Tidy found serious XHTML errors -->\n";
}
* @return bool Whether the HTML is valid
*/
public static function checkErrors( $text, &$errorStr = null ) {
+ $retval = 0;
+ list( $outputStr, $errorStr ) = self::clean( $text, $retval );
+ return ( $retval < 0 && $errorStr == '' ) || $retval == 0;
+ }
+
+ /**
+ * Perform a clean/repair operation
+ * @param string $text HTML to check
+ * @param int &$retval Exit code (-1 on internal error)
+ * @return string|null
+ */
+ private static function clean( $text, &$retval = null ) {
global $wgTidyInternal;
- $retval = 0;
if ( $wgTidyInternal ) {
- $errorStr = self::execInternalTidy( $text, true, $retval );
+ return self::internalClean( $text, $retval );
} else {
- $errorStr = self::execExternalTidy( $text, true, $retval );
+ return self::externalClean( $text, $retval );
}
-
- return ( $retval < 0 && $errorStr == '' ) || $retval == 0;
}
/**
* Also called in OutputHandler.php for full page validation
*
* @param string $text HTML to check
- * @param bool $stderr Whether to read result from STDERR rather than STDOUT
* @param int &$retval Exit code (-1 on internal error)
* @return string|null
*/
- private static function execExternalTidy( $text, $stderr = false, &$retval = null ) {
+ private static function externalClean( $text, &$retval = null ) {
global $wgTidyConf, $wgTidyBin, $wgTidyOpts;
wfProfileIn( __METHOD__ );
- $cleansource = '';
$opts = ' -utf8';
- if ( $stderr ) {
- $descriptorspec = array(
- 0 => array( 'pipe', 'r' ),
- 1 => array( 'file', wfGetNull(), 'a' ),
- 2 => array( 'pipe', 'w' )
- );
- } else {
- $descriptorspec = array(
- 0 => array( 'pipe', 'r' ),
- 1 => array( 'pipe', 'w' ),
- 2 => array( 'file', wfGetNull(), 'a' )
- );
- }
+ $descriptorspec = array(
+ 0 => array( 'pipe', 'r' ),
+ 1 => array( 'pipe', 'w' ),
+ 2 => array( 'pipe', 'w' ),
+ );
- $readpipe = $stderr ? 2 : 1;
+ $outputBuffer = '';
+ $errorBuffer = '';
$pipes = array();
$process = proc_open(
// for tidyParseStdin and tidySaveStdout in console/tidy.c
fwrite( $pipes[0], $text );
fclose( $pipes[0] );
- while ( !feof( $pipes[$readpipe] ) ) {
- $cleansource .= fgets( $pipes[$readpipe], 1024 );
+
+ while ( !feof( $pipes[1] ) ) {
+ $outputBuffer .= fgets( $pipes[1], 1024 );
}
- fclose( $pipes[$readpipe] );
+ fclose( $pipes[1] );
+
+ while ( !feof( $pipes[2] ) ) {
+ $errorBuffer .= fgets( $pipes[2], 1024 );
+ }
+ fclose( $pipes[2] );
+
$retval = proc_close( $process );
} else {
wfWarn( "Unable to start external tidy process" );
$retval = -1;
}
- if ( !$stderr && $cleansource == '' && $text != '' ) {
- // Some kind of error happened, so we couldn't get the corrected text.
- // Just give up; we'll use the source text and append a warning.
- $cleansource = null;
- }
-
wfProfileOut( __METHOD__ );
- return $cleansource;
+ return array( $outputBuffer, $errorBuffer );
}
/**
* saving the overhead of spawning a new process.
*
* @param string $text HTML to check
- * @param bool $stderr Whether to read result from error status instead of output
* @param int &$retval Exit code (-1 on internal error)
* @return string|null
*/
- private static function execInternalTidy( $text, $stderr = false, &$retval = null ) {
+ private static function internalClean( $text, &$retval = null ) {
global $wgTidyConf, $wgDebugTidy;
wfProfileIn( __METHOD__ );
- if ( !class_exists( 'tidy' ) ) {
+ if ( ( !wfIsHHVM() && !class_exists( 'tidy' ) ) ||
+ ( wfIsHHVM() && !function_exists( 'tidy_repair_string' ) )
+ ) {
wfWarn( "Unable to load internal tidy class." );
$retval = -1;
return null;
}
- $tidy = new tidy;
- $tidy->parseString( $text, $wgTidyConf, 'utf8' );
-
- if ( $stderr ) {
+ $outputBuffer = '';
+ $errorBuffer = '';
+
+ if ( wfIsHHVM() ) {
+ // Use the tidy extension for HHVM from
+ // https://github.com/wikimedia/mediawiki-php-tidy
+ //
+ // This currently does not support the object-oriented interface, but
+ // tidy_repair_string() can be used for the most common tasks.
+ $result = tidy_repair_string( $text, $wgTidyConf, 'utf8' );
+ $outputBuffer .= $result;
+ $retval = $result === false ? -1 : 0;
+ } else {
+ $tidy = new tidy;
+ $tidy->parseString( $text, $wgTidyConf, 'utf8' );
+ $tidy->cleanRepair();
$retval = $tidy->getStatus();
-
- wfProfileOut( __METHOD__ );
- return $tidy->errorBuffer;
+ $outputBuffer .= tidy_get_output( $tidy );
+ if ( $retval > 0 ) {
+ $errorBuffer .= $tidy->errorBuffer;
+ }
}
- $tidy->cleanRepair();
- $retval = $tidy->getStatus();
- if ( $retval == 2 ) {
- // 2 is magic number for fatal error
- // http://www.php.net/manual/en/function.tidy-get-status.php
- $cleansource = null;
- } else {
- $cleansource = tidy_get_output( $tidy );
- if ( $wgDebugTidy && $retval > 0 ) {
- $cleansource .= "<!--\nTidy reports:\n" .
- str_replace( '-->', '-->', $tidy->errorBuffer ) .
- "\n-->";
- }
+ if ( $wgDebugTidy && $errorBuffer && $retval > 0 ) {
+ $outputBuffer .= "<!--\nTidy reports:\n" .
+ str_replace( '-->', '-->', $tidy->errorBuffer ) .
+ "\n-->";
}
wfProfileOut( __METHOD__ );
- return $cleansource;
+ return array( $outputBuffer, $errorBuffer );
}
}