diff --git a/src/PHPVideoToolkit/ProcessBuilder.php b/src/PHPVideoToolkit/ProcessBuilder.php index c18140c..a75a1ad 100644 --- a/src/PHPVideoToolkit/ProcessBuilder.php +++ b/src/PHPVideoToolkit/ProcessBuilder.php @@ -151,7 +151,7 @@ protected function _combineArgumentList($commands) foreach ($commands as $argument) { // the array ois a flag for a raw argument - $command_string .= (is_array($argument) === true ? $argument : escapeshellarg($argument)).' '; + $command_string .= (is_array($argument) === true ? $argument : ProcessUtils::escapeArgument($argument)).' '; } } diff --git a/src/PHPVideoToolkit/ProcessUtils.php b/src/PHPVideoToolkit/ProcessUtils.php new file mode 100644 index 0000000..05e4277 --- /dev/null +++ b/src/PHPVideoToolkit/ProcessUtils.php @@ -0,0 +1,70 @@ + + */ +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 doesn't work on Windows + //@see https://bugs.php.net/bug.php?id=43784 + //@see https://bugs.php.net/bug.php?id=49446 + if ('\\' === DIRECTORY_SEPARATOR) { + if ('' === $argument) { + return escapeshellarg($argument); + } + + $escapedArgument = ''; + $quote = false; + foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) { + if ('"' === $part) { + $escapedArgument .= '\\"'; + } elseif (self::isSurroundedBy($part, '%')) { + // Avoid environment variable expansion + $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%'; + } else { + // escape trailing backslash + if ('\\' === substr($part, -1)) { + $part .= '\\'; + } + $quote = true; + $escapedArgument .= $part; + } + } + if ($quote) { + $escapedArgument = '"'.$escapedArgument.'"'; + } + + return $escapedArgument; + } + + return escapeshellarg($argument); + } + + private static function isSurroundedBy($arg, $char) + { + return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1]; + } +}