2

I have a PHP script that needs to execute programmes that will work on files that have spaces in the names. Most PHP functions for executing external commands (e.g. exec()) take an 1 string argument for the command line to execute. However then you have to do things like escapeshellarg() to make your input safe.

Is there some way to execute an external command in PHP with an array. So rather than:

exec("ls -l ".escapeshellarg($filename));

I can go:

exec(array("ls", "-l", $filename));

This would mean I don't have to worry about escaping the arguments. I want to avoid using escapeshellarg(), since the version I am using has a bug that strips out non-ASCII characters.

Java has this functionality http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html#exec%28java.lang.String[]%29

jww
  • 97,681
  • 90
  • 411
  • 885
Amandasaurus
  • 58,203
  • 71
  • 188
  • 248
  • 1
    I know this is obvious, but for anyone else who comes along: NEVER run external commands based on user input. If the script is not on any web server, fine, but otherwise, make sure you check, double-check, and check 5 more times that there is no way anyone could use this script to perform any command they aren't supposed to. – Matchu Jan 23 '10 at 18:05

3 Answers3

2

Sounds like this isn't possible with PHP's builtin functions.

Amandasaurus
  • 58,203
  • 71
  • 188
  • 248
  • You still can use the combination of pcntl_fork/pcntl_exec functions. Hovewer in order to obtain a program's output you have to deal with temporary files, since (sounds like) there is no pipe(2) function :) – alvelcom Dec 22 '14 at 20:43
1
function myExec ( command, arguments )
{
    exec( command + ' ' + implode( ' ', array_map( escapeshellarg, arguments ) ) );
}
poke
  • 369,085
  • 72
  • 557
  • 602
  • Good suggestion, but I want to avoid using escapeshellarg() (I've updated the question accordingly). The version I'm using has a bug that strips out non-ASCII characters. – Amandasaurus Jan 23 '10 at 18:16
  • Feel free to replace that function by any other function (define one yourself for example) that filters the characters correctly. I just wanted to give you an idea how to do it :) – poke Jan 24 '10 at 19:37
-1

Poke's answer is good - however, how many commands do they need to run? I would think about implementing a whitelist of commands and arguments - that way, you can be pretty darn sure they aren't injection malicious input. Something like:

$whitelistCommandArray = array('ls' => 'ls', ...);
if (isset($whitelistCommandArray[$userSuppliedCommand]])
{
    //ok its a valid command, lets parse the args next
    ...
}
else echo "Unsupported command";

Update/edit:

Is a whitelist of arguments feasible? What if OP needs to edit a multitude of files? – Matchu

heh I dont know - it could be - totally depends on your needs.

$whitelistArray = array('ls' => array('a', 'l', 'h'), ...);

Something like that work - with both the command and then an array of arguments for it.

mr-sk
  • 13,174
  • 11
  • 66
  • 101
  • Is a whitelist of arguments feasible? What if OP needs to edit a multitude of files? – Matchu Jan 23 '10 at 18:55
  • Yes I do need this script to run on thousands of files that could be named anything and almost certainly will have spaces in their names. – Amandasaurus Jan 24 '10 at 12:20