0

I run an open source project which is hosted on github. I'm currently about to release a new version which is running on PHP 7. This is where I'm needing help. I'm fairly strong with majority of PHP functions and equally comfortable with mysqli but in all my time running my project I've never worked with regex. I have two patterns with the now defunct /e modifier in use and have no idea how to fix them, so I'm hoping by asking the question here to actually learn something and also fix my problems.

Problem one is coming from one preg_replace I used for Geshi syntax highlighter for code tag.

// [php]code[/php]
    if (stripos($s, '[php]') !== false) {
    $s = preg_replace("#\[(php|sql|html)\](.+?)\[\/\\1\]#ise", "source_highlighter('\\2','\\1')", $s);
}

The second one handles media tags like liveleak etc:

   if (stripos($s, '[media=') !== false) {
   $s = preg_replace("#\[media=(youtube|liveleak|GameTrailers|vimeo|imdb)\](.+?)\[/media\]#ies", "_MediaTag('\\2','\\1')", $s);
   }

Both are not working and throwing this error:

PHP Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead.

Trouble is I have no idea how to work with regex, I've tried using tutorials over the past few weeks and still don't really understand it, any help would be really appreciated.

melpomene
  • 84,125
  • 8
  • 85
  • 148
Bigjoos
  • 9
  • 1
  • 3

1 Answers1

3

The PHP manual describes the modifier this way: (emphasis mine)

If this deprecated modifier is set, preg_replace() does normal substitution of backreferences in the replacement string, evals it as PHP code(!!), and uses the result for replacing the search string. Single quotes, double quotes, backslashes () and NULL chars will be escaped by backslashes in substituted backreferences.

First of all, the very concept of this modifier was always evil. It included an eval case into source-code, the existence of which was usually overlooked and therefore quite easily exploited.

The online PHP documentation ... http://php.net/manual/en/reference.pcre.pattern.modifiers.php ... talks very extensively about this modifier, why it is evil, and specifically how to use preg_replace_callback() to replace it.

Let's take your first regex, the one for "Geshi syntax":

$s = preg_replace(
  "#\[(php|sql|html)\](.+?)\[\/\\1\]#ise", 
  "source_highlighter('\\2','\\1')", 
  $s);

This could be replaced by something like:

$s = preg_replace_callback(
   "#\[(php|sql|html)\](.+?)\[\/\\1\]#ise",
   function($subs) {
      return source_highlighter($subs[2], $subs[1]);
   },
   $s);

After the regex has been evaluated against the string and the matching groups (if any) have been identified, the array is handed to the callback. (The array looks like the one returned by a normal match.) The value returned by the callback is the final replacement string.

Now, the presence of an executable subroutine is made explicit, and it becomes impossible for a clever L33T H4X0R to influence what it consists of or to inject arbitrary code.

Furthermore, it's much more flexible. You can, after all, insert an entire subroutine. (It can be an anonymous one, as shown, or it can be a reference to a subroutine that's used many times.)

Frankly, the /e modifier was a bad idea that won't be missed . . . Callbacks do the same thing, and much more.

Mike Robinson
  • 8,490
  • 5
  • 28
  • 41
  • Thanks for the detailed answer Mike, that's helped me out greatly. Got both tags functioning now with no errors. I had looked at few of the duplicate answers but did not have any success myself, thanks again !! – Bigjoos Jun 26 '16 at 16:43
  • '\\2' and '\\1' convert to $subs[1] and $subs[0], not 2 and 1. – ion Sep 06 '17 at 22:05