r37183 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r37182‎ | r37183 | r37184 >
Date:16:05, 6 July 2008
Author:skizzerz
Status:old
Tags:
Comment:
* usability update
Modified paths:
  • /trunk/extensions/RegexFunctions/RegexFunctions.php (modified) (history)

Diff [purge]

Index: trunk/extensions/RegexFunctions/RegexFunctions.php
@@ -16,7 +16,7 @@
1717 'name' => 'RegexFunctions',
1818 'author' => 'Ryan Schmidt',
1919 'url' => 'http://www.mediawiki.org/wiki/Extension:RegexFunctions',
20 - 'version' => '1.1',
 20+ 'version' => '1.2',
2121 'description' => 'Regular Expression parser functions',
2222 'descriptionmsg' => 'regexfunctions-desc',
2323 );
@@ -27,12 +27,14 @@
2828 //default globals
2929 //how many functions are allowed in a single page? Keep this at least above 3 for usability
3030 $wgRegexFunctionsPerPage = 10;
31 -//should we allow modifiers in the functions, e.g. the /g and /i modifiers for global and case-insensitive?
32 -//This does NOT enable the 'e' modifier for preg_replace, see the next variable for that
 31+//should we allow modifiers in the functions, e.g. the /i modifier for case-insensitive?
 32+//This does NOT enable the /e modifier for preg_replace, see the next variable for that
3333 $wgRegexFunctionsAllowModifiers = true;
34 -//should we allow the 'e' modifier in preg_replace? Requires AllowModifiers to be true.
35 -//Don't enable this unless you trust every single editor on your wiki, as it opens up a potential XSS vector
 34+//should we allow the /e modifier in preg_replace? Requires AllowModifiers to be true.
 35+//Don't enable this unless you trust every single editor on your wiki, as it may open up potential XSS vectors
3636 $wgRegexFunctionsAllowE = false;
 37+//should we allow internal options to be set (e.g. (?opts) or (?opts:some regex))
 38+$wgRegexFunctionsAllowOptions = true;
3739 //limit for rsplit and rreplace functions. -1 is unlimited
3840 $wgRegexFunctionsLimit = -1;
3941 //array of functions to disable, aka these functions cannot be used :)
@@ -59,7 +61,9 @@
6062
6163 class ExtRegexFunctions {
6264 var $num = 0;
63 -
 65+ var $modifiers = array('i', 'm', 's', 'x', 'A', 'D', 'S', 'U', 'X', 'J', 'u', 'e');
 66+ var $options = array('i', 'm', 's', 'x', 'U', 'X', 'J');
 67+
6468 function rmatch ( &$parser, $string = '', &$pattern = '', &$return = '', $notfound = '', $offset = 0 ) {
6569 global $wgRegexFunctionsPerPage, $wgRegexFunctionsAllowModifiers, $wgRegexFunctionsDisable;
6670 if(in_array('rmatch', $wgRegexFunctionsDisable))
@@ -67,21 +71,19 @@
6872 $this->num++;
6973 if($this->num > $wgRegexFunctionsPerPage)
7074 return;
71 - if(!$wgRegexFunctionsAllowModifiers)
72 - $pattern = str_replace('/', '\/', $pattern);
73 - $num = preg_match( $pattern, $string, $matches, PREG_OFFSET_CAPTURE, $offset );
 75+ $pattern = $this->sanitize($pattern, $wgRegexFunctionsAllowModifiers, false);
 76+ $num = preg_match( $pattern, $string, $matches, PREG_OFFSET_CAPTURE, (int) $offset );
7477 if($num === false)
7578 return;
7679 if($num === 0)
7780 return $notfound;
78 - $mn = 0;
79 - foreach($matches as $match) {
80 - if($mn > 9)
81 - break;
82 - $return = str_replace('$'.$mn, $matches[$mn][0], $return);
83 - $return = str_replace('\\\\'.$mn, $matches[$mn][1], $return);
84 - $mn++;
85 - }
 81+ //change all backslashes to $
 82+ $return = str_replace('\\', '%$', $return);
 83+ $return = preg_replace('/%?\$%?\$([0-9]+)/e', 'array_key_exists($1, $matches) ? $matches[$1][1] : \'\'', $return);
 84+ $return = preg_replace('/%?\$%?\$\{([0-9]+)\}/e', 'array_key_exists($1, $matches) ? $matches[$1][1] : \'\'', $return);
 85+ $return = preg_replace('/%?\$([0-9]+)/e', 'array_key_exists($1, $matches) ? $matches[$1][0] : \'\'', $return);
 86+ $return = preg_replace('/%?\$\{([0-9]+)\}/e', 'array_key_exists($1, $matches) ? $matches[$1][0] : \'\'', $return);
 87+ $return = str_replace('%$', '\\', $return);
8688 return $return;
8789 }
8890
@@ -92,10 +94,18 @@
9395 $this->num++;
9496 if($this->num > $wgRegexFunctionsPerPage)
9597 return;
96 - if(!$wgRegexFunctionsAllowModifiers)
97 - $pattern = str_replace('/', '\/', $pattern);
 98+ $pattern = $this->sanitize($pattern, $wgRegexFunctionsAllowModifiers, false);
9899 $res = preg_split( $pattern, $string, $wgRegexFunctionsLimit );
99 - return $res[$piece];
 100+ $p = (int) $piece;
 101+ //allow negative pieces to work from the end of the array
 102+ if($p < 0)
 103+ $p = $p + count($res);
 104+ //sanitation for pieces that don't exist
 105+ if($p < 0)
 106+ $p = 0;
 107+ if($p >= count($res))
 108+ $p = count($res) - 1;
 109+ return $res[$p];
100110 }
101111
102112 function rreplace ( &$parser, $string = '', &$pattern = '', &$replace = '' ) {
@@ -105,11 +115,44 @@
106116 $this->num++;
107117 if($this->num > $wgRegexFunctionsPerPage)
108118 return;
109 - if(!$wgRegexFunctionsAllowModifiers)
110 - $pattern = str_replace('/', '\/', $pattern);
111 - elseif(!$wgRegexFunctionsAllowE)
112 - $pattern = preg_replace('/(\/.*?)e(.*?)$/i', '$1$2', $pattern);
 119+ $pattern = $this->sanitize($pattern, $wgRegexFunctionsAllowModifiers, $wgRegexFunctionsAllowE);
113120 $res = preg_replace($pattern, $replace, $string, $wgRegexFunctionsLimit);
114121 return $res;
115122 }
 123+
 124+ //santizes a regex pattern
 125+ function sanitize($pattern, $m = false, $e = false) {
 126+ if(preg_match('/^\/(.*)([^\\\\])\/(.*?)$/', $pattern, $matches)) {
 127+ $pat = preg_replace('/([^\\\\])?\(\?(.*)(\:.*)?\)/Ue', '\'$1(?\' . $this->cleanupInternal(\'$2\') . \'$3)\'', $matches[1] . $matches[2]);
 128+ $ret = '/' . $pat . '/';
 129+ if($m) {
 130+ $mod = '';
 131+ foreach($this->modifiers as $val) {
 132+ if(strpos($matches[3], $val) !== false)
 133+ $mod .= $val;
 134+ }
 135+ if(!$e)
 136+ $mod = str_replace('e', '', $mod);
 137+ $ret .= $mod;
 138+ }
 139+ } else {
 140+ $pat = preg_replace('/([^\\\\])?\(\?(.*)(\:.*)?\)/Ue', '\'$1(?\' . $this->cleanupInternal(\'$2\') . \'$3)\'', $pattern);
 141+ $pat = preg_replace('!([^\\\\])/!', '$1\\/', $pat);
 142+ $ret = '/' . $pat . '/';
 143+ }
 144+ return $ret;
 145+ }
 146+
 147+ //cleans up internal options, making sure they are valid
 148+ function cleanupInternal($str) {
 149+ global $wgRegexFunctionsAllowOptions;
 150+ $ret = '';
 151+ if(!$wgRegexFunctionsAllowOptions)
 152+ return '';
 153+ foreach($this->options as $opt) {
 154+ if(strpos($str, $opt) !== false)
 155+ $ret .= $opt;
 156+ }
 157+ return $ret;
 158+ }
116159 }

Status & tagging log