0

I was working on a dynamic way to update a config.php file and I ran into an interesting glitch that I can't quite solve. Below is my code for updating the config.php file:

if( isset( $_POST['submitted'] ) ) {

    $config_keys = array();
    foreach( $_POST as $key => $value ) {
        if( substr( $key, 0, 7 ) == 'config-' ) {
            $config_keys[ substr( $key, 7 ) ] = $value;
        }
    }

    $config_content = file_get_contents( dirname(__FILE__) . '/../../inc/config.php' );

    foreach( $config_keys as $key => $value ) {

        $config_content = preg_replace(
                                "/config\['$key'\](\s*)=(\s*)(['\"]?).*?(['\"]?);/",
                                "config['$key']$1=$2$3$value$4;",
                                $config_content
                            );

        $config[$key] = $value;

    }

    file_put_contents( dirname(__FILE__) . '/../../inc/config.php', $config_content );

}

The logic is fairly sound. It searches for any POST variables prefixed by "config-" then uses everything after "config-" as the name of the key in our config file to update. The config file takes the form:

$config['var1'] = 'value1';
$config['var2'] = 123;
$config['var3'] = '...';

In 90% of cases this works perfectly, however if $value begins with a numeral then $3 and the first numeral of $value are completely ignored during the replacement.

For instance, I have the following value in my config file:

$config['ls_key'] = '136609a7b4....'; // Rest of key has been truncated

If I don't change this value and leave the key untouched but submit my form then this line suddenly looks like so:

$config['ls_key'] = 36609a7b4...'; // Rest of key has been truncated

The lack of single quote prevents the config file from parsing (breaking the entire site) and we've lost data to boot! After reading the PHP preg_replace manual I have tried using braces in several locations (modifying "Example #1 Using backreferences followed by numeric literals"). None of the following worked:

"config['$key']$1=$2${3}$value$4;",
"config['$key']$1=$2$3${value}$4;",
"config['$key']$1=$2$3{$value}$4;",
"config['$key']$1=$2{$3}$value$4;", // This one actually leads to syntax errors
"config['$key']${1}=${2}${3}$value${4};",

The first 3 lead to the exact same problem, having no effect on the replacement. The fourth doesn't work at all (syntax errors), and the fifth actually causes EVERY backreference to be ignored. I've also tried using single quotes and concatenation like so:

'config[\'$key\']$1=$2$3' . $value . '$4;',

Again, I had the same problem as the 3 prior examples and my original script.

Hoping someone has solved this before or at least has a new idea.

2
  • 1
    Your first try with ${3} should work afais. Commented Jan 9, 2012 at 15:53
  • Unfortunately I tried this and it didn't work. Commented Jan 9, 2012 at 16:57

2 Answers 2

2

Seems the double quoting interpolation is messing things up. This replacement works:

'config[\''.$key.'\']$1=$2${3}'.$value.'$4;'

Also note that you should properly escape the following (meta characters):

  • $key in the regex with preg_quote
  • $key and $value in the replacement, there is no built in function to do this (preg_quote escapes too much)

And also escape the regex delimiter and quote delimiter used if present.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. Worked perfectly. I do realize that I need to use preg_quote with $key in the regex, although I didn't think about escaping anything in the replacement. Do you think addslashes will be sufficient?
@steven_desu, addslashes doesn't escape $, so it's not enough. Also what if the original value was an unquoted number, and your new value is some string? This simplistic parsing has many holes. Only give users access to this if you want to allow them to run arbitrary code on your server. :p
0

Try \g{1} for the group 1 (and accordingly for the other groups)

See the php manual on backreferences

Update:

Of course Qtax is right, this is the syntax for backreferences within the regular expression. (+1 for Qtax)

2 Comments

\g{N} and friends do not work in the replacement part afaik.
Qtax is right. Didn't work. Using \g{3} in place of $3 put the following in $config_content: $config['ls_key'] = \g{3}136609a7b4...'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.