PageRenderTime 44ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/phpSec/Common/Exec.php

https://github.com/StarGest/phpSec
PHP | 122 lines | 50 code | 15 blank | 57 comment | 2 complexity | bc52f19d7cbfef3ab766bf3afb4c945d MD5 | raw file
  1. <?php namespace phpSec\Common;
  2. /**
  3. phpSec - A PHP security library
  4. @author Audun Larsen <larsen@xqus.com>
  5. @copyright Copyright (c) Audun Larsen, 2011, 2012
  6. @link https://github.com/phpsec/phpSec
  7. @license http://opensource.org/licenses/mit-license.php The MIT License
  8. @package phpSec
  9. */
  10. use \phpSec\Common\Core;
  11. /**
  12. * Execute external programs in a safe(er) way.
  13. * @package phpSec
  14. */
  15. class Exec {
  16. const STDIN = 0;
  17. const STDOUT = 1;
  18. const STDERR = 2;
  19. private $descSpecs = array(
  20. self::STDIN => array("pipe", "r"),
  21. self::STDOUT => array("pipe", "w"),
  22. self::STDERR => array("pipe", "w"),
  23. );
  24. /**
  25. * Array containing additional ENV variables.
  26. */
  27. public $_env = array();
  28. /**
  29. * Current Working Directory.
  30. * Defaults to where the script is located.
  31. */
  32. public $_cwd = null;
  33. /**
  34. * Execute an external program.
  35. *
  36. * This method uses as PDO like syntax to build commands.
  37. *
  38. * @param string $cmd
  39. * Command to execute. If you need to pass arguments to a command. A PDO like syntax can be used.
  40. * For example: "ls -lsa %path".
  41. *
  42. * @param array $args
  43. * An associative array containing the arguments to pass to $cmd.
  44. * For example: array('%path' => '/home');
  45. *
  46. * @param string $stdin
  47. * If the command requests input (e.g. a passphrase) this can be
  48. * passed here. Note that if a command requires multiple feedbacks
  49. * from a user this method can not be used.
  50. *
  51. * @return array
  52. * Returns an array containing return value and results from STDOUT and STDERR.
  53. */
  54. public function run($cmd, $args = array(), $stdin = null) {
  55. $cmd = $this->buildCommand($cmd, $args);
  56. $process = proc_open($cmd, $this->descSpecs, $pipes, $this->_cwd, $this->_env);
  57. if(is_resource($process)) {
  58. /* Write stuff to STDIN, and close it. */
  59. fwrite($pipes[self::STDIN], $stdin);
  60. fclose($pipes[self::STDIN]);
  61. /* Read STDOUT and STDERR. */
  62. $out['STDOUT'] = stream_get_contents($pipes[self::STDOUT]);
  63. $out['STDERR'] = stream_get_contents($pipes[self::STDERR]);
  64. /* Close STDOUT and STDERR to aviod potential deadlocks. */
  65. fclose($pipes[self::STDOUT]);
  66. fclose($pipes[self::STDERR]);
  67. /* Close process and get return value. */
  68. $out['return'] = proc_close($process);
  69. return $out;
  70. }
  71. return false;
  72. }
  73. /**
  74. * Builds a command that is safe to execute.
  75. *
  76. * @param string $cmd
  77. * Base command (with placeholders) to execute.
  78. *
  79. * @param array $args
  80. * An associative array containing data to filter.
  81. *
  82. * @return string
  83. * Returns a command that is safe to execute.
  84. */
  85. private function buildCommand($cmd, $args = array()) {
  86. while(list($name, $data) = each($args)) {
  87. $safeData = false;
  88. $filterType = mb_substr($name, 0, 1);
  89. switch($filterType) {
  90. case '%':
  91. $safeData = escapeshellarg($data);
  92. break;
  93. case '!':
  94. $safeData = escapeshellcmd($data);
  95. break;
  96. default:
  97. throw new \phpSec\Exception\InvalidArgumentException('Unknown variable type');
  98. break;
  99. }
  100. if($safeData !== false) {
  101. $cmd = str_replace($name, $safeData, $cmd);
  102. }
  103. }
  104. return $cmd;
  105. }
  106. }