I am using preg_replace_callback()
, and I am concerned that I might have some sort of security risk. I am hoping to get a review of the below substitute()
function. The purpose of the function is to parse a user provided template with user provided data. A quick description on how it is used is shown below.
The user posts data to the server, which is saved in a database (escaped for SQL injection of course). Note that the application will limit which array indexes are allowed (i.e. firstname, lastname, and phone only in this example).
$userProvidedString='Hello {?firstname?} {?lastname?}, Our database shows that your phone number is {?phone?}.';
$userProvidedArray=array(
0 => array('firstname'=>'John','lastname'=>'Doe','phone'=>'(555) 222-1212'),
1 => array('firstname'=>'Jane','lastname'=>'Doe','phone'=>'(555) 333-1212'),
2 => array('firstname'=>'Mike','lastname'=>'Moe','phone'=>'(444) 222-1212'),
);
Later the data is pulled from the database, and parsed as follows:
foreach($userProvidedArray AS $contact)
{
$customMessage=substitute($userProvidedString,$contact);
}
My question relates to the substitute()
function. Specifically, does my use of preg_replace_callback()
pose any security issues? Previously, I was using
$template_new= preg_replace('/\{\?(\w+)\?\}/e', '$contact["$1"]', $userProvidedString);
which uses the /e flag which I assume can be dangerous.
Does that danger still remain? Any other recommendations for it? I am currently using PHP 5.3.18, but will hopefully upgrade to 5.4 soon.
function substitute($template, $values, $deliminator='{??}') {
//Replaces occurrences of {?name?} with $values['name] if it exists in $values. Deliminators can be changed
$deliminator="\\".implode("\\",str_split($deliminator));
$half = (int) ( (strlen($deliminator) / 2) );
$pattern = '/'.substr($deliminator, 0, $half).'(\w+)'.substr($deliminator, $half).'/';
return preg_replace_callback(
$pattern,
function ($matches) use ($values) {
if (isset($values[$matches[1]])) {
return $values[$matches[1]];
}
return $matches[0];
},
$template);
}