From ca32f08966f1b51fcb19460f0996bb0c4048e6fe Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Sat, 3 Dec 2011 13:29:22 +0100 Subject: Update to MediaWiki 1.18.0 * also update ArchLinux skin to chagnes in MonoBook * Use only css to hide our menu bar when printing --- includes/parser/Tidy.php | 163 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 124 insertions(+), 39 deletions(-) (limited to 'includes/parser/Tidy.php') diff --git a/includes/parser/Tidy.php b/includes/parser/Tidy.php index 38f22fd8..3a6d3e9c 100644 --- a/includes/parser/Tidy.php +++ b/includes/parser/Tidy.php @@ -5,6 +5,74 @@ * @file */ +/** + * Class used to hide mw:editsection tokens from Tidy so that it doesn't break them + * or break on them. This is a bit of a hack for now, but hopefully in the future + * we may create a real postprocessor or something that will replace this. + * It's called wrapper because for now it basically takes over MWTidy::tidy's task + * of wrapping the text in a xhtml block + * + * This re-uses some of the parser's UNIQ tricks, though some of it is private so it's + * duplicated. Perhaps we should create an abstract marker hiding class. + */ +class MWTidyWrapper { + + /** + * @var ReplacementArray + */ + protected $mTokens; + + protected $mUniqPrefix; + + protected $mMarkerIndex; + + public function __construct() { + $this->mTokens = null; + $this->mUniqPrefix = null; + } + + /** + * @param $text string + * @return string + */ + public function getWrapped( $text ) { + $this->mTokens = new ReplacementArray; + $this->mUniqPrefix = "\x7fUNIQ" . + dechex( mt_rand( 0, 0x7fffffff ) ) . dechex( mt_rand( 0, 0x7fffffff ) ); + $this->mMarkerIndex = 0; + + $wrappedtext = preg_replace_callback( ParserOutput::EDITSECTION_REGEX, + array( &$this, 'replaceEditSectionLinksCallback' ), $text ); + + $wrappedtext = ''. + 'test'.$wrappedtext.''; + + return $wrappedtext; + } + + /** + * @param $m array + * + * @return string + */ + function replaceEditSectionLinksCallback( $m ) { + $marker = "{$this->mUniqPrefix}-item-{$this->mMarkerIndex}" . Parser::MARKER_SUFFIX; + $this->mMarkerIndex++; + $this->mTokens->setPair( $marker, $m[0] ); + return $marker; + } + + /** + * @param $text string + * @return string + */ + public function postprocess( $text ) { + return $this->mTokens->replace( $text ); + } + +} + /** * Class to interact with HTML tidy * @@ -15,7 +83,6 @@ * @ingroup Parser */ class MWTidy { - /** * Interface with html tidy, used if $wgUseTidy = true. * If tidy isn't able to correct the markup, the original will be @@ -27,20 +94,26 @@ class MWTidy { public static function tidy( $text ) { global $wgTidyInternal; - $wrappedtext = ''. -'test'.$text.''; + $wrapper = new MWTidyWrapper; + $wrappedtext = $wrapper->getWrapped( $text ); - if( $wgTidyInternal ) { - $correctedtext = self::execInternalTidy( $wrappedtext ); + $retVal = null; + if ( $wgTidyInternal ) { + $correctedtext = self::execInternalTidy( $wrappedtext, false, $retVal ); } else { - $correctedtext = self::execExternalTidy( $wrappedtext ); + $correctedtext = self::execExternalTidy( $wrappedtext, false, $retVal ); } - if( is_null( $correctedtext ) ) { + + if ( $retVal < 0 ) { + wfDebug( "Possible tidy configuration error!\n" ); + return $text . "\n\n"; + } elseif ( is_null( $correctedtext ) ) { wfDebug( "Tidy error detected!\n" ); return $text . "\n\n"; } + $correctedtext = $wrapper->postprocess( $correctedtext ); // restore any hidden tokens + return $correctedtext; } @@ -60,6 +133,7 @@ class MWTidy { } else { $errorStr = self::execExternalTidy( $text, true, $retval ); } + return ( $retval < 0 && $errorStr == '' ) || $retval == 0; } @@ -68,7 +142,7 @@ class MWTidy { * Also called in OutputHandler.php for full page validation * * @param $text String: HTML to check - * @param $stderr Boolean: Whether to read from STDERR rather than STDOUT + * @param $stderr Boolean: Whether to read result from STDERR rather than STDOUT * @param &$retval Exit code (-1 on internal error) * @return mixed String or null */ @@ -79,7 +153,7 @@ class MWTidy { $cleansource = ''; $opts = ' -utf8'; - if( $stderr ) { + if ( $stderr ) { $descriptorspec = array( 0 => array( 'pipe', 'r' ), 1 => array( 'file', wfGetNull(), 'a' ), @@ -96,73 +170,84 @@ class MWTidy { $readpipe = $stderr ? 2 : 1; $pipes = array(); - if( function_exists( 'proc_open' ) ) { - $process = proc_open( "$wgTidyBin -config $wgTidyConf $wgTidyOpts$opts", $descriptorspec, $pipes ); - if ( is_resource( $process ) ) { - // Theoretically, this style of communication could cause a deadlock - // here. If the stdout buffer fills up, then writes to stdin could - // block. This doesn't appear to happen with tidy, because tidy only - // writes to stdout after it's finished reading from stdin. Search - // for tidyParseStdin and tidySaveStdout in console/tidy.c - fwrite( $pipes[0], $text ); - fclose( $pipes[0] ); - while ( !feof( $pipes[$readpipe] ) ) { - $cleansource .= fgets( $pipes[$readpipe], 1024 ); - } - fclose( $pipes[$readpipe] ); - $retval = proc_close( $process ); - } else { - $retval = -1; + $process = proc_open( + "$wgTidyBin -config $wgTidyConf $wgTidyOpts$opts", $descriptorspec, $pipes ); + + if ( is_resource( $process ) ) { + // Theoretically, this style of communication could cause a deadlock + // here. If the stdout buffer fills up, then writes to stdin could + // block. This doesn't appear to happen with tidy, because tidy only + // writes to stdout after it's finished reading from stdin. Search + // for tidyParseStdin and tidySaveStdout in console/tidy.c + fwrite( $pipes[0], $text ); + fclose( $pipes[0] ); + while ( !feof( $pipes[$readpipe] ) ) { + $cleansource .= fgets( $pipes[$readpipe], 1024 ); } + fclose( $pipes[$readpipe] ); + $retval = proc_close( $process ); } else { - $retval = -1; + wfWarn( "Unable to start external tidy process" ); + $retval = -1; } - if( !$stderr && $cleansource == '' && $text != '' ) { + 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; } /** - * Use the HTML tidy PECL extension to use the tidy library in-process, + * Use the HTML tidy extension to use the tidy library in-process, * saving the overhead of spawning a new process. * - * 'pear install tidy' should be able to compile the extension module. + * @param $text String: HTML to check + * @param $stderr Boolean: Whether to read result from error status instead of output + * @param &$retval Exit code (-1 on internal error) + * @return mixed String or null */ private static function execInternalTidy( $text, $stderr = false, &$retval = null ) { global $wgTidyConf, $wgDebugTidy; wfProfileIn( __METHOD__ ); + if ( !MWInit::classExists( 'tidy' ) ) { + wfWarn( "Unable to load internal tidy class." ); + $retval = -1; + + wfProfileOut( __METHOD__ ); + return null; + } + $tidy = new tidy; $tidy->parseString( $text, $wgTidyConf, 'utf8' ); - if( $stderr ) { + if ( $stderr ) { $retval = $tidy->getStatus(); + wfProfileOut( __METHOD__ ); return $tidy->errorBuffer; } else { $tidy->cleanRepair(); $retval = $tidy->getStatus(); - if( $retval == 2 ) { + 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 .= "', '-->', $tidy->errorBuffer ) . - "\n-->"; + if ( $wgDebugTidy && $retval > 0 ) { + $cleansource .= "', '-->', $tidy->errorBuffer ) . + "\n-->"; + } } wfProfileOut( __METHOD__ ); return $cleansource; } } - } -- cgit v1.2.3-54-g00ecf