exec.php 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. <?php
  2. // Secure `exec` wrapper functions
  3. define('SUDO_CMD', '/usr/bin/sudo');
  4. define('VESTA_BIN_DIR', '/usr/local/vesta/bin/');
  5. define('VESTA_CMD', SUDO_CMD.' '.VESTA_BIN_DIR);
  6. function check_error($return_var) {
  7. if ($return_var > 0) {
  8. header('Location: /error/');
  9. exit;
  10. }
  11. }
  12. function check_return_code($return_var, $output) {
  13. if ($return_var != 0) {
  14. $error = implode('<br>', $output);
  15. if (empty($error)) $error = __('Error code:', $return_var);
  16. $_SESSION['error_msg'] = $error;
  17. }
  18. }
  19. /**
  20. * Build shell command arguments from a string array.
  21. * @param string[] $arguments Unescaped command line arguments. (eg. ['-a', "b'c"], default: [])
  22. * @return string Escaped arguments.
  23. */
  24. function build_shell_args($arguments=[]) {
  25. $ret = [];
  26. // Convert $arguments to an array
  27. if (!is_array($arguments)) $arguments = !is_null($arguments) ? [$arguments] : [];
  28. foreach ($arguments as $arg) {
  29. // Convert $arg to a string if $arg is an array (for an argument like this: ?abc[def]=ghi)
  30. if (is_array($arg)) $arg = implode('', $arg);
  31. // Convert $arg to a string (just in case)
  32. if (!is_string($arg)) $arg = (string)$arg;
  33. // Append the argument
  34. $ret[] = escapeshellarg($arg);
  35. }
  36. return implode(' ', $ret);
  37. }
  38. /**
  39. * Execute a command.
  40. * @param string $command Command to execute. (eg. ls)
  41. * @param string[] $arguments (optional) Unescaped command line arguments. (eg. ['-a', '/'], default: [])
  42. * @param string &$output (optional) Variable to contain output from the command.
  43. * @return int Exit code (return status) of the executed command.
  44. */
  45. function safe_exec($command, $arguments=[], &$output=null) {
  46. $cmd = build_shell_args($command);
  47. $arg = build_shell_args($arguments);
  48. if (!empty($arg)) {
  49. $cmd .= ' ' . $arg;
  50. }
  51. // Execute
  52. exec($cmd, $rawOutput, $status);
  53. $output = implode("\n", $rawOutput);
  54. return $status;
  55. }
  56. /**
  57. * Execute a vesta command line APIs (VESTA_CMD/v-*).
  58. * (Wrapper function of `safe_exec`.)
  59. * @see safe_exec
  60. * @param string $command Command to execute. (eg. v-search-object)
  61. * @param string[] $arguments (optional) Unescaped command line arguments. (eg. ["We've", 'json'], default: [])
  62. * @param bool $checkReturn (optional) If this set to true, check_return_code will be called after the command executes. (default: true)
  63. * @param string &$output (optional) Variable to contain output from the command.
  64. * @return int Exit code (return status) of the executed command.
  65. */
  66. function v_exec($command, $arguments=[], $checkReturn=true, &$output=null) {
  67. // Check command
  68. if (preg_match('#^\.*$|/#', $command)) return -1;
  69. // Convert $arguments to an array
  70. if (!is_array($arguments)) $arguments = !is_null($arguments) ? [$arguments] : [];
  71. // Execute
  72. $status = safe_exec([SUDO_CMD, VESTA_BIN_DIR.$command], $arguments, $output);
  73. if ($checkReturn) {
  74. check_return_code($status, explode("\n", $output));
  75. }
  76. return $status;
  77. }