ProcessUtils.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Process;
  11. use Symfony\Component\Process\Exception\InvalidArgumentException;
  12. /**
  13. * ProcessUtils is a bunch of utility methods.
  14. *
  15. * This class contains static methods only and is not meant to be instantiated.
  16. *
  17. * @author Martin Hasoň <martin.hason@gmail.com>
  18. */
  19. class ProcessUtils
  20. {
  21. /**
  22. * This class should not be instantiated
  23. */
  24. private function __construct()
  25. {
  26. }
  27. /**
  28. * Escapes a string to be used as a shell argument.
  29. *
  30. * @param string $argument The argument that will be escaped
  31. *
  32. * @return string The escaped argument
  33. */
  34. public static function escapeArgument($argument)
  35. {
  36. //Fix for PHP bug #43784 escapeshellarg removes % from given string
  37. //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
  38. //@see https://bugs.php.net/bug.php?id=43784
  39. //@see https://bugs.php.net/bug.php?id=49446
  40. if (defined('PHP_WINDOWS_VERSION_BUILD')) {
  41. if ('' === $argument) {
  42. return escapeshellarg($argument);
  43. }
  44. $escapedArgument = '';
  45. $quote = false;
  46. foreach (preg_split('/(")/i', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
  47. if ('"' === $part) {
  48. $escapedArgument .= '\\"';
  49. } elseif (self::isSurroundedBy($part, '%')) {
  50. // Avoid environment variable expansion
  51. $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
  52. } else {
  53. // escape trailing backslash
  54. if ('\\' === substr($part, -1)) {
  55. $part .= '\\';
  56. }
  57. $quote = true;
  58. $escapedArgument .= $part;
  59. }
  60. }
  61. if ($quote) {
  62. $escapedArgument = '"'.$escapedArgument.'"';
  63. }
  64. return $escapedArgument;
  65. }
  66. return escapeshellarg($argument);
  67. }
  68. /**
  69. * Validates and normalized a Process input
  70. *
  71. * @param string $caller The name of method call that validates the input
  72. * @param mixed $input The input to validate
  73. *
  74. * @return string The validated input
  75. *
  76. * @throws InvalidArgumentException In case the input is not valid
  77. */
  78. public static function validateInput($caller, $input)
  79. {
  80. if (null !== $input) {
  81. if (is_scalar($input) || (is_object($input) && method_exists($input, '__toString'))) {
  82. return (string) $input;
  83. }
  84. throw new InvalidArgumentException(sprintf('%s only accepts strings.', $caller));
  85. }
  86. return $input;
  87. }
  88. private static function isSurroundedBy($arg, $char)
  89. {
  90. return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
  91. }
  92. }