Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird bug in PHP, Spaces in Paths and Windows

I've got to fix this little bug. First, let's talk about a small fact: In CLI on Windows, you can't run a program with a space in its path, unless escaped:

C:\>a b/c.bat
'a' is not recognized as an internal or external command,
operable program or batch file.

C:\>"a b/c.bat"

C:\>

I'm using proc_open...proc_close in PHP to run a process (program), example:

function _pipeExec($cmd,$input=''){
    $proc=proc_open($cmd,array(0=>array('pipe','r'),
        1=>array('pipe','w'),2=>array('pipe','w')),$pipes);
    fwrite($pipes[0],$input);
    fclose($pipes[0]);
    $stdout=stream_get_contents($pipes[1]); // max execusion time exceeded ssue
    fclose($pipes[1]);
    $stderr=stream_get_contents($pipes[2]);
    fclose($pipes[2]);
    $rtn=proc_close($proc);
    return array(
        'stdout'=>$stdout,
        'stderr'=>$stderr,
        'return'=>(int)$rtn
    );
}

// example 1
_pipeExec('C:\\a b\\c.bat -switch');
// example 2
_pipeExec('"C:\\a b\\c.bat" -switch');
// example 3 (sounds stupid but I had to try)
_pipeExec('""C:\\a b\\c.bat"" -switch');

Example 1

  • RESULT: 1
  • STDERR: 'C:\a' is not recognized as an internal or external command, operable program or batch file.
  • STDOUT:

Example 2

  • RESULT: 1
  • STDERR: 'C:\a' is not recognized as an internal or external command, operable program or batch file.
  • STDOUT:

Example 3

  • RESULT: 1
  • STDERR: The filename, directory name, or volume label syntax is incorrect.
  • STDOUT:

So you see, either case (double quotes or not) the code fails. Is it me or am I missing something?

like image 936
Christian Avatar asked Nov 19 '10 14:11

Christian


2 Answers

Most unfortunately, the fix doesn't work as expected, however Pekka's first suggestion gave me an idea:

$file='C:\a b\c';
$cmdl='/d /b /g';

if(strtolower(substr(PHP_OS,0,3))=='win') // if windows...
    $file='cd '.escapeshellarg(dirname($file)).' && '.basename($file);

_pipeExec($file.' '.$cmdl);

This is platform-specific, and I hope I don't have to fix this over linux as well. So far it works well!

like image 56
Christian Avatar answered Oct 18 '22 20:10

Christian


Another way of solving this is by putting additional double quotes at the beginning and the end of the command.

$process = 'C:\\Program Files\\nodejs\\node.exe';
$arg1 = 'C:\\Path to File\\foo.js';

$cmd = sprintf('"%s" %s', $process, escapeshellarg($arg1));
if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
    $cmd = '"'.$cmd.'"';
}

_pipeExec($cmd);

I have found this solution on https://bugs.php.net/bug.php?id=49139
It looks weird, but hey - it's Windows... :D

like image 37
naitsirch Avatar answered Oct 18 '22 18:10

naitsirch