Alexia has uploaded a new change for review. https://gerrit.wikimedia.org/r/296264
Change subject: Replace eval modifier with callbacks. ...................................................................... Replace eval modifier with callbacks. Change-Id: I9fde8ed91aec6f11d193b4f02c5b5d2d200c05df --- M RegexFunctions.php 1 file changed, 41 insertions(+), 45 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/RegexFunctions refs/changes/64/296264/1 diff --git a/RegexFunctions.php b/RegexFunctions.php index fc1781f..144ef80 100644 --- a/RegexFunctions.php +++ b/RegexFunctions.php @@ -36,11 +36,7 @@ // how many functions are allowed in a single page? Keep this at least above 3 for usability $wgRegexFunctionsPerPage = 10; // should we allow modifiers in the functions, e.g. the /i modifier for case-insensitive? -// This does NOT enable the /e modifier for preg_replace, see the next variable for that $wgRegexFunctionsAllowModifiers = true; -// should we allow the /e modifier in preg_replace? Requires AllowModifiers to be true. -// Don't enable this unless you trust every single editor on your wiki, as it may open up potential XSS vectors -$wgRegexFunctionsAllowE = false; // should we allow internal options to be set (e.g. (?opts) or (?opts:some regex)) $wgRegexFunctionsAllowOptions = true; // limit for rsplit and rreplace functions. -1 is unlimited @@ -49,6 +45,7 @@ $wgRegexFunctionsDisable = array(); class ExtRegexFunctions { + public static $rmatches; //Holder for rmatch's matches to pass into closure callback function. private static $num = 0; private static $modifiers = array( 'i', 'm', 's', 'x', 'A', 'D', 'S', 'U', 'X', 'J', 'u', 'e' @@ -78,40 +75,39 @@ } $pattern = self::sanitize( $pattern, - $wgRegexFunctionsAllowModifiers, - false + $wgRegexFunctionsAllowModifiers ); $num = preg_match( $pattern, $string, $matches, PREG_OFFSET_CAPTURE, (int) $offset ); - if( $num === false ) { + if ( $num === false ) { return; } - if( $num === 0 ) { + if ( $num === 0 ) { + if ( $notfound == '$0' ) { + //Return the original string if specified to display it with $0. + return $string; + } return $notfound; } + self::$rmatches = $matches; // change all backslashes to $ $return = str_replace( '\\', '%$', $return ); - $return = preg_replace( - '/%?\$%?\$([0-9]+)/e', - 'array_key_exists($1, $matches) ? $matches[$1][1] : \'\'', - $return - ); - $return = preg_replace( - '/%?\$%?\$\{([0-9]+)\}/e', - 'array_key_exists($1, $matches) ? $matches[$1][1] : \'\'', - $return - ); - $return = preg_replace( - '/%?\$([0-9]+)/e', - 'array_key_exists($1, $matches) ? $matches[$1][0] : \'\'', - $return - ); - $return = preg_replace( - '/%?\$\{([0-9]+)\}/e', - 'array_key_exists($1, $matches) ? $matches[$1][0] : \'\'', - $return - ); + $slashyReplacements = [ + '/%?\$%?\$([0-9]+)/', + '/%?\$%?\$\{([0-9]+)\}/', + '/%?\$([0-9]+)/', + '/%?\$\{([0-9]+)\}/' + ]; + foreach ( $slashyReplacements as $regex ) { + $return = preg_replace_callback( + $regex, + function ( $_matches ) { + return array_key_exists($_matches[1], ExtRegexFunctions::$rmatches) ? ExtRegexFunctions::$rmatches[$_matches[1]][0] : ''; + }, + $return + ); + } $return = str_replace( '%$', '\\', $return ); return $return; } @@ -127,8 +123,7 @@ } $pattern = self::sanitize( $pattern, - $wgRegexFunctionsAllowModifiers, - false + $wgRegexFunctionsAllowModifiers ); $res = preg_split( $pattern, $string, $wgRegexFunctionsLimit ); $p = (int) $piece; @@ -147,7 +142,7 @@ } public static function rreplace( &$parser, $string = '', $pattern = '', $replace = '' ) { - global $wgRegexFunctionsPerPage, $wgRegexFunctionsAllowModifiers, $wgRegexFunctionsAllowE, $wgRegexFunctionsLimit, $wgRegexFunctionsDisable; + global $wgRegexFunctionsPerPage, $wgRegexFunctionsAllowModifiers, $wgRegexFunctionsLimit, $wgRegexFunctionsDisable; if( in_array( 'rreplace', $wgRegexFunctionsDisable ) ) { return; } @@ -157,8 +152,7 @@ } $pattern = self::sanitize( str_replace(chr(0), '', $pattern), - $wgRegexFunctionsAllowModifiers, - $wgRegexFunctionsAllowE + $wgRegexFunctionsAllowModifiers ); $res = preg_replace( $pattern, @@ -170,11 +164,13 @@ } // santizes a regex pattern - private static function sanitize( $pattern, $m = false, $e = false ) { + private static function sanitize( $pattern, $m = false ) { if( preg_match( '/^\/(.*)([^\\\\])\/(.*?)$/', $pattern, $matches ) ) { - $pat = preg_replace( - '/([^\\\\])?\(\?(.*\:)?(.*)\)/Ue', - '\'$1(?\' . self::cleanupInternal(\'$2\') . \'$3)\'', + $pat = preg_replace_callback( + '/([^\\\\])?\(\?(.*\:)?(.*)\)/U', + function ( $_matches ) { + return "{$_matches[1]}(" . self::cleanupInternal( $_matches[2] ) . "{$_matches[3]})"; + }, $matches[1] . $matches[2] ); $ret = '/' . $pat . '/'; @@ -185,15 +181,15 @@ $mod .= $val; } } - if( !$e ) { - $mod = str_replace( 'e', '', $mod ); - } + $mod = str_replace( 'e', '', $mod ); //Get rid of eval modifier. $ret .= $mod; } } else { - $pat = preg_replace( - '/([^\\\\])?\(\?(.*\:)?(.*)\)/Ue', - '\'$1(?\' . self::cleanupInternal(\'$2\') . \'$3)\'', + $pat = preg_replace_callback( + '/([^\\\\])?\(\?(.*\:)?(.*)\)/U', + function ( $_matches ) { + return "{$_matches[1]}(" . self::cleanupInternal( $_matches[2] ) . "{$_matches[3]})"; + }, $pattern ); $pat = preg_replace( '!([^\\\\])/!', '$1\\/', $pat ); @@ -206,10 +202,10 @@ private static function cleanupInternal( $str ) { global $wgRegexFunctionsAllowOptions; $ret = ''; - if( !$wgRegexFunctionsAllowOptions ) { + if ( !$wgRegexFunctionsAllowOptions ) { return ''; } - foreach( self::$options as $opt ) { + foreach ( self::$options as $opt ) { if( strpos( $str, $opt ) !== false ) { $ret .= $opt; } -- To view, visit https://gerrit.wikimedia.org/r/296264 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I9fde8ed91aec6f11d193b4f02c5b5d2d200c05df Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/RegexFunctions Gerrit-Branch: master Gerrit-Owner: Alexia <was...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits