X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/?a=blobdiff_plain;f=includes%2Fparser%2FStripState.php;h=d329f693fe10161b52f4c7e51d006564d405fe34;hb=0c2687f44eb0e8c7f480b7303f89056682ba0bfb;hp=298aad3313cc4e3fefd308e4076987bd7e15929a;hpb=577f3d79115173f4dd16bb46f6d0ef2c82b55add;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/parser/StripState.php b/includes/parser/StripState.php index 298aad3313..d329f693fe 100644 --- a/includes/parser/StripState.php +++ b/includes/parser/StripState.php @@ -26,32 +26,38 @@ * @ingroup Parser */ class StripState { - protected $prefix; protected $data; protected $regex; - protected $tempType, $tempMergePrefix; + protected $parser; + protected $circularRefGuard; - protected $recursionLevel = 0; + protected $depth = 0; + protected $highestDepth = 0; + protected $expandSize = 0; - const UNSTRIP_RECURSION_LIMIT = 20; + protected $depthLimit = 20; + protected $sizeLimit = 5000000; /** - * @param string|null $prefix - * @since 1.26 The prefix argument should be omitted, as the strip marker - * prefix string is now a constant. + * @param Parser|null $parser + * @param array $options */ - public function __construct( $prefix = null ) { - if ( $prefix !== null ) { - wfDeprecated( __METHOD__ . ' with called with $prefix argument' . - ' (call with no arguments instead)', '1.26' ); - } + public function __construct( Parser $parser = null, $options = [] ) { $this->data = [ 'nowiki' => [], 'general' => [] ]; $this->regex = '/' . Parser::MARKER_PREFIX . "([^\x7f<>&'\"]+)" . Parser::MARKER_SUFFIX . '/'; $this->circularRefGuard = []; + $this->parser = $parser; + + if ( isset( $options['depthLimit'] ) ) { + $this->depthLimit = $options['depthLimit']; + } + if ( isset( $options['sizeLimit'] ) ) { + $this->sizeLimit = $options['sizeLimit']; + } } /** @@ -122,56 +128,109 @@ class StripState { return $text; } - $oldType = $this->tempType; - $this->tempType = $type; - $text = preg_replace_callback( $this->regex, [ $this, 'unstripCallback' ], $text ); - $this->tempType = $oldType; + $callback = function ( $m ) use ( $type ) { + $marker = $m[1]; + if ( isset( $this->data[$type][$marker] ) ) { + if ( isset( $this->circularRefGuard[$marker] ) ) { + return $this->getWarning( 'parser-unstrip-loop-warning' ); + } + + if ( $this->depth > $this->highestDepth ) { + $this->highestDepth = $this->depth; + } + if ( $this->depth >= $this->depthLimit ) { + return $this->getLimitationWarning( 'unstrip-depth', $this->depthLimit ); + } + + $value = $this->data[$type][$marker]; + if ( $value instanceof Closure ) { + $value = $value(); + } + + $this->expandSize += strlen( $value ); + if ( $this->expandSize > $this->sizeLimit ) { + return $this->getLimitationWarning( 'unstrip-size', $this->sizeLimit ); + } + + $this->circularRefGuard[$marker] = true; + $this->depth++; + $ret = $this->unstripType( $type, $value ); + $this->depth--; + unset( $this->circularRefGuard[$marker] ); + + return $ret; + } else { + return $m[0]; + } + }; + + $text = preg_replace_callback( $this->regex, $callback, $text ); return $text; } /** - * @param array $m - * @return array + * Get warning HTML and register a limitation warning with the parser + * + * @param string $type + * @param int $max + * @return string */ - protected function unstripCallback( $m ) { - $marker = $m[1]; - if ( isset( $this->data[$this->tempType][$marker] ) ) { - if ( isset( $this->circularRefGuard[$marker] ) ) { - return '' - . wfMessage( 'parser-unstrip-loop-warning' )->inContentLanguage()->text() - . ''; - } - if ( $this->recursionLevel >= self::UNSTRIP_RECURSION_LIMIT ) { - return '' . - wfMessage( 'parser-unstrip-recursion-limit' ) - ->numParams( self::UNSTRIP_RECURSION_LIMIT )->inContentLanguage()->text() . - ''; - } - $this->circularRefGuard[$marker] = true; - $this->recursionLevel++; - $value = $this->data[$this->tempType][$marker]; - if ( $value instanceof Closure ) { - $value = $value(); - } - $ret = $this->unstripType( $this->tempType, $value ); - $this->recursionLevel--; - unset( $this->circularRefGuard[$marker] ); - return $ret; - } else { - return $m[0]; + private function getLimitationWarning( $type, $max = '' ) { + if ( $this->parser ) { + $this->parser->limitationWarn( $type, $max ); } + return $this->getWarning( "$type-warning", $max ); + } + + /** + * Get warning HTML + * + * @param string $message + * @param int $max + * @return string + */ + private function getWarning( $message, $max = '' ) { + return '' . + wfMessage( $message ) + ->numParams( $max )->inContentLanguage()->text() . + ''; + } + + /** + * Get an array of parameters to pass to ParserOutput::setLimitReportData() + * + * @unstable Should only be called by Parser + * @return array + */ + public function getLimitReport() { + return [ + [ 'limitreport-unstrip-depth', + [ + $this->highestDepth, + $this->depthLimit + ], + ], + [ 'limitreport-unstrip-size', + [ + $this->expandSize, + $this->sizeLimit + ], + ] + ]; } /** * Get a StripState object which is sufficient to unstrip the given text. * It will contain the minimum subset of strip items necessary. * + * @deprecated since 1.31 * @param string $text - * * @return StripState */ public function getSubState( $text ) { - $subState = new StripState(); + wfDeprecated( __METHOD__, '1.31' ); + + $subState = new StripState; $pos = 0; while ( true ) { $startPos = strpos( $text, Parser::MARKER_PREFIX, $pos ); @@ -202,11 +261,14 @@ class StripState { * will not be preserved. The strings in the $texts array will have their * strip markers rewritten, the resulting array of strings will be returned. * + * @deprecated since 1.31 * @param StripState $otherState * @param array $texts * @return array */ public function merge( $otherState, $texts ) { + wfDeprecated( __METHOD__, '1.31' ); + $mergePrefix = wfRandomString( 16 ); foreach ( $otherState->data as $type => $items ) { @@ -215,21 +277,14 @@ class StripState { } } - $this->tempMergePrefix = $mergePrefix; - $texts = preg_replace_callback( $otherState->regex, [ $this, 'mergeCallback' ], $texts ); - $this->tempMergePrefix = null; + $callback = function ( $m ) use ( $mergePrefix ) { + $key = $m[1]; + return Parser::MARKER_PREFIX . $mergePrefix . '-' . $key . Parser::MARKER_SUFFIX; + }; + $texts = preg_replace_callback( $otherState->regex, $callback, $texts ); return $texts; } - /** - * @param array $m - * @return string - */ - protected function mergeCallback( $m ) { - $key = $m[1]; - return Parser::MARKER_PREFIX . $this->tempMergePrefix . '-' . $key . Parser::MARKER_SUFFIX; - } - /** * Remove any strip markers found in the given text. *