- <?php
- class AppCmdShell
- {
- const OS_UNIX = 1;
- const OS_WIN = 2;
- /**
- * Output produced by the last executed shell command.
- *
- * @var string
- */
- public $output = '';
- /**
- * Result/exit code from the last executed shell command.
- *
- * @var int|null
- */
- public $result;
- /**
- * Current OS. See OS_* constants.
- *
- * @var int
- */
- public $os;
- /**
- * Get current work dir.
- *
- * @return string
- * @throws AppCmdShellCommandFailedException
- */
- public function pwd()
- {
- $command = null;
- if ($this->os == self::OS_WIN) {
- $command = 'echo %CD%';
- }
- else {
- $command = 'pwd';
- }
- $this->execute($command);
- return rtrim($this->path($this->output, self::OS_UNIX), '/').'/';
- }
- /**
- * Just a reminder stub.
- *
- * @param string $dir
- */
- public function cd($dir)
- {
- throw new AppCheckException('Don\'t use cd in shell. It has no effect under PHP!');
- }
- /**
- * Execute a shell command.
- * Saves output and result to $this->ouput and $this->result respectively.
- *
- * @param string $command Command string to execute
- *
- * @param bool $collectStdErrOuput By default PHP returns contents of only STDOUT descriptor which is OK
- * for successful calls. But if some errors occured in the shell command
- * during its execution then in most of the cases STDOUT will be empty but
- * STDERR may be not. So pass true here if you want to receive STDERR
- * descriptor contents as well as STDOUT.
- *
- * @param bool $checkExecutionResult If true and command execution has failed (i.e. command reports an error)
- * then exception will be thrown
- *
- * @return int|null Command exit/result code
- * of null if something went worng with PHP (e.g. shell commands execution
- * is disabled by current PHP configuration).
- * Usually 0 means no errors while non-zero value represents code
- * of the error occurred.
- *
- * @throws AppCheckException If shell command execution failed due to various reasons(related to PHP)
- * such as disabled exec() function and/or safe_mode enabled.
- *
- * @throws AppCmdShellCommandFailedException If shell command execution failed and $checkExecutionResult is true.
- */
- public function execute($command, $collectStdErrOuput = true, $checkExecutionResult = true)
- {
- // Reseet last call data
- $this->output = null;
- $this->result = null;
- // Check for safe_mode enabled
- if (ini_get('safe_mode')) {
- throw new AppCheckException('Could not execute a shell command: PHP safe mode is On.');
- }
- // Some unix magic here ro redirect STDERR to STDOUT.
- $stdErrRedirect = ($collectStdErrOuput ? " 2>&1" : '');
- // Remember last error occurred before exec(). So we can check whether exec() failed after its execution.
- $lastError = error_get_last();
- // Execute
- $output = array();
- $result = null;
- @exec("{$command}{$stdErrRedirect}", $output, $result);
- // Detect whether exec() has failed.
- // Get current last error and compare with previously saved one.
- // Note: safe_mode is not detected this way. We are checking for safe_mode enabled above.
- $error = error_get_last();
- if ($error != $lastError)
- {
- throw new AppCheckException('Could not execute a shell command. Ensure PHP configuration allows '.
- 'running shell commands, e.g. exec() function is not disabled.');
- }
- // Work with output
- $output = join("\n", $output);
- // For the windows machine we need to convert cp866 -> utf-8 to be able to read Cyrillic output.
- if (strtolower(substr(PHP_OS, 0, 3)) == 'win')
- {
- if (function_exists('iconv')) {
- $output = iconv('cp866', 'utf-8', $output);
- }
- }
- // Check for errors
- if ($checkExecutionResult)
- {
- if ($result != 0) {
- throw new AppCmdShellCommandFailedException($command, $output, $result);
- }
- }
- // Store last call data
- $this->output = $output;
- $this->result = $result;
- // Done
- return $result;
- }
- public function escape($argument)
- {
- return escapeshellarg($argument);
- }
- public function path($path, $targetOs = null)
- {
- if (!isset($targetOs)) {
- $targetOs = $this->os;
- }
- if ($targetOs == self::OS_WIN) {
- $path = str_replace('/', '\\', $path);
- }
- else {
- $path = str_replace('\\', '/', $path);
- }
- return $path;
- }
- public function __construct()
- {
- $this->os = (substr(strtolower(PHP_OS), 0, 3) == 'win' ? self::OS_WIN : self::OS_UNIX);
- }
- }
- ?>