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

Reply via email to