Skip to content
Browse files

[Process] Added ProcessUtils::escapeArgument() to fix the bug in esca…

…peshellarg() function on Windows
  • Loading branch information...
1 parent cad4674 commit 28cdd4b7c065f3d34de380fdd9956bf9cb060543 @hason hason committed Jan 18, 2013
Showing with 116 additions and 1 deletion.
  1. +1 −0 CHANGELOG.md
  2. +1 −1 ProcessBuilder.php
  3. +60 −0 ProcessUtils.php
  4. +12 −0 Tests/ProcessBuilderTest.php
  5. +42 −0 Tests/ProcessUtilsTest.php
View
1 CHANGELOG.md
@@ -7,6 +7,7 @@ CHANGELOG
* added ProcessBuilder::setArguments() to reset the arguments on a builder
* added a way to retrieve the standard and error output incrementally
* added Process:restart()
+ * added ProcessUtils::escapeArgument() to fix the bug in escapeshellarg() function on Windows
2.1.0
-----
View
2 ProcessBuilder.php
@@ -143,7 +143,7 @@ public function getProcess()
$options = $this->options;
- $script = implode(' ', array_map('escapeshellarg', $this->arguments));
+ $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $this->arguments));
if ($this->inheritEnv) {
$env = $this->env ? $this->env + $_ENV : null;
View
60 ProcessUtils.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Process;
+
+/**
+ * ProcessUtils is a bunch of utility methods.
+ *
+ * This class contains static methods only and is not meant to be instantiated.
+ *
+ * @author Martin Hasoň <martin.hason@gmail.com>
+ */
+class ProcessUtils
+{
+ /**
+ * This class should not be instantiated
+ */
+ private function __construct()
+ {
+ }
+
+ /**
+ * Escapes a string to be used as a shell argument.
+ *
+ * @param string $argument The argument that will be escaped
+ *
+ * @return string The escaped argument
+ */
+ public static function escapeArgument($argument)
+ {
+ //Fix for PHP bug #43784 escapeshellarg removes % from given string
+ //Fix for PHP bug #49446 escapeshellarg dosn`t work on windows
+ //@see https://bugs.php.net/bug.php?id=43784
+ //@see https://bugs.php.net/bug.php?id=49446
+ if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+ $escapedArgument = '';
+ foreach(preg_split('/([%"])/i', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
+ if ('"' == $part) {
+ $escapedArgument .= '\\"';
+ } elseif ('%' == $part) {
+ $escapedArgument .= '^%';
+ } else {
+ $escapedArgument .= escapeshellarg($part);
+ }
+ }
+
+ return $escapedArgument;
+ }
+
+ return escapeshellarg($argument);
+ }
+}
View
12 Tests/ProcessBuilderTest.php
@@ -115,4 +115,16 @@ public function testShouldSetArguments()
$this->assertContains("second", $proc->getCommandLine());
}
+
+ public function testShouldEscapeArguments()
+ {
+ $pb = new ProcessBuilder(array('%path%', 'foo " bar'));
+ $proc = $pb->getProcess();
+
+ if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+ $this->assertSame('^%"path"^% "foo "\\"" bar"', $proc->getCommandLine());
+ } else {
+ $this->assertSame("'%path%' 'foo \" bar'", $proc->getCommandLine());
+ }
+ }
}
View
42 Tests/ProcessUtilsTest.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Process\Tests;
+
+use Symfony\Component\Process\ProcessUtils;
+
+class ProcessUtilsTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider dataArguments
+ */
+ public function testEscapeArgument($result, $argument)
+ {
+ $this->assertSame($result, ProcessUtils::escapeArgument($argument));
+ }
+
+ public function dataArguments()
+ {
+ if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+ return array(
+ array('"foo bar"', 'foo bar'),
+ array('^%"path"^%', '%path%'),
+ array('"<|>"\\"" "\\""\'f"', '<|>" "\'f'),
+ );
+ }
+
+ return array(
+ array("'foo bar'", 'foo bar'),
+ array("'%path%'", '%path%'),
+ array("'<|>\" \"'\\''f'", '<|>" "\'f'),
+ );
+ }
+}

0 comments on commit 28cdd4b

Please sign in to comment.
Something went wrong with that request. Please try again.