EVOLUTION-MANAGER
Edit File: ProcessExecutor.php
<?php /* * This file is part of Composer. * * (c) Nils Adermann <naderman@naderman.de> * Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\IO\IOInterface; use Composer\Util\Platform; use Symfony\Component\Process\Process; use Symfony\Component\Process\ProcessUtils; /** * @author Robert Schönthal <seroscho@googlemail.com> */ class ProcessExecutor { protected static $timeout = 300; protected $captureOutput; protected $errorOutput; protected $io; public function __construct(IOInterface $io = null) { $this->io = $io; } /** * runs a process on the commandline * * @param string $command the command to execute * @param mixed $output the output will be written into this var if passed by ref * if a callable is passed it will be used as output handler * @param string $cwd the working directory * @return int statuscode */ public function execute($command, &$output = null, $cwd = null) { if ($this->io && $this->io->isDebug()) { $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) { // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx) we obfuscate that if (preg_match('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+)$}', $m['user'])) { return '://***:***@'; } return '://'.$m['user'].':***@'; }, $command); $safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand); $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand); } // make sure that null translate to the proper directory in case the dir is a symlink // and we call a git command, because msysgit does not handle symlinks properly if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) { $cwd = realpath(getcwd()); } if (null !== $cwd && !is_dir($cwd)) { throw new \RuntimeException('The given CWD for the process does not exist: '.$cwd); } $this->captureOutput = func_num_args() > 1; $this->errorOutput = null; // TODO in v3, commands should be passed in as arrays of cmd + args if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) { $process = Process::fromShellCommandline($command, $cwd, null, null, static::getTimeout()); } else { $process = new Process($command, $cwd, null, null, static::getTimeout()); } $callback = is_callable($output) ? $output : array($this, 'outputHandler'); $process->run($callback); if ($this->captureOutput && !is_callable($output)) { $output = $process->getOutput(); } $this->errorOutput = $process->getErrorOutput(); return $process->getExitCode(); } public function splitLines($output) { $output = trim($output); return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output); } /** * Get any error output from the last command * * @return string */ public function getErrorOutput() { return $this->errorOutput; } public function outputHandler($type, $buffer) { if ($this->captureOutput) { return; } if (null === $this->io) { echo $buffer; return; } if (method_exists($this->io, 'writeRaw')) { if (Process::ERR === $type) { $this->io->writeErrorRaw($buffer, false); } else { $this->io->writeRaw($buffer, false); } } else { if (Process::ERR === $type) { $this->io->writeError($buffer, false); } else { $this->io->write($buffer, false); } } } public static function getTimeout() { return static::$timeout; } public static function setTimeout($timeout) { static::$timeout = $timeout; } /** * 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 escape($argument) { return self::escapeArgument($argument); } /** * Escapes a string to be used as a shell argument for Symfony Process. * * This method expects cmd.exe to be started with the /V:ON option, which * enables delayed environment variable expansion using ! as the delimiter. * If this is not the case, any escaped ^^!var^^! will be transformed to * ^!var^! and introduce two unintended carets. * * Modified from https://github.com/johnstevenson/winbox-args * MIT Licensed (c) John Stevenson <john-stevenson@blueyonder.co.uk> * * @param string $argument * * @return string */ private static function escapeArgument($argument) { if ('' === ($argument = (string) $argument)) { return escapeshellarg($argument); } if (!Platform::isWindows()) { return "'".str_replace("'", "'\\''", $argument)."'"; } // New lines break cmd.exe command parsing $argument = strtr($argument, "\n", ' '); $quote = strpbrk($argument, " \t") !== false; $argument = preg_replace('/(\\\\*)"/', '$1$1\\"', $argument, -1, $dquotes); $meta = $dquotes || preg_match('/%[^%]+%|![^!]+!/', $argument); if (!$meta && !$quote) { $quote = strpbrk($argument, '^&|<>()') !== false; } if ($quote) { $argument = '"'.preg_replace('/(\\\\*)$/', '$1$1', $argument).'"'; } if ($meta) { $argument = preg_replace('/(["^&|<>()%])/', '^$1', $argument); $argument = preg_replace('/(!)/', '^^$1', $argument); } return $argument; } }