2

I'm building a simple JS terminal shell emulator which posts its commands via AJAX to PHP.
Please leave security aside, this is only for learning and demo purposes. Now my problem is, str_replace() won't work as expected, in fact, it returns the unchanged input string. It should work like this:
The name of this host is $hostname --> Yes, this string contains a variable --> Replace $hostname with testserver --> return The name of this host is testserver

What am I doing wrong?

This is my respond script for echo and export:

<?
// get environment variables from JSON
$vars = json_decode(file_get_contents('environment.json'), true);

// get request params
$method = $_SERVER['REQUEST_METHOD'];
$action = $_POST['action'];
$data = $_POST['data'];

switch ($action) {

case 'echo':
    $cmd = $data;

        // if the string in question contains a variable, eg. "the time is $time"
        if (strpos($cmd,'$')) {
        $output = '';

        // for each environment variable as variable => value
        foreach ($vars as $var => $val) {

            // replace every variable in the string with its value in the command
            $output = str_replace($var,$val,$cmd);
        }
        echo $output;
    } else { 

        // if it does not contain a variable, answer back the query string 
        // ("echo " gets stripped off in JS)
        echo $cmd; 
    }
break;

case 'export':

    // separate a variable declaration by delimiter "="
    $cmd = explode('=',$data);

    // add a $-sign to the first word which will be our new variable
    $var = '$' . array_shift($cmd);

    // grab our variable value from the array
    $val = array_shift($cmd);

    // now append everything to the $vars-array and save it to the JSON-file 
    $vars[$var] = $val;
    file_put_contents("environment.json",json_encode($vars));
break;
}
5
  • Please show the contents of environment.json Commented Oct 15, 2014 at 8:08
  • The reason is not to be found in your use of str_replace, so please post the combination $var, $val and $cmd you use. Commented Oct 15, 2014 at 8:09
  • 1
    Beware with strpos, if the word you are searching for is in the first place, it will return 0 and not false, so you should use if (strpos($cmd,'$')) !== false Commented Oct 15, 2014 at 8:09
  • IMHO It would be smarter to create a separate object or an array of closures and address the keys as command names instead of using a switch with logic. Commented Oct 15, 2014 at 8:11
  • @Alexander, Sal00m, hd: environment.json contains {"$hostname":"testserver","$test":"123"} Commented Oct 15, 2014 at 8:39

1 Answer 1

2

Better using :

if (strpos($cmd,'$') !== false) {

Then, every single replace will take the "first" data as its input data. You should proceed like this :

    $output = $cmd;

    // for each environment variable as variable => value
    foreach ($vars as $var => $val) {

        // replace every variable in the string with its value in the command
        $output = str_replace($var, $val, $output);
    }
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, that solved it. But I don't understand why, could you explain? That'd be great...
Each time you're running the loop again, you're taking the "initial" data ($cmd), and replace in it. So, each time you're looping, you're losing the previous changes you've made on the previous loop.

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.