From 7ae14306898e3ddeda09e0bec705cf57dade9809 Mon Sep 17 00:00:00 2001 From: frederik Date: Wed, 24 Sep 2014 17:18:15 +0200 Subject: [PATCH] #3297 ProcessUtil class using ProcessUtil of Symfony Console --- src/Composer/Command/HomeCommand.php | 3 +- src/Composer/Command/InitCommand.php | 3 +- src/Composer/Downloader/GitDownloader.php | 48 +++++++------------ src/Composer/Downloader/GzipDownloader.php | 3 +- src/Composer/Downloader/HgDownloader.php | 11 +++-- src/Composer/Downloader/RarDownloader.php | 3 +- src/Composer/Downloader/ZipDownloader.php | 3 +- .../EventDispatcher/EventDispatcher.php | 3 +- src/Composer/Installer/LibraryInstaller.php | 5 +- src/Composer/Installer/PearInstaller.php | 4 +- src/Composer/Package/Locker.php | 5 +- src/Composer/Repository/Vcs/GitDriver.php | 9 ++-- src/Composer/Repository/Vcs/HgDriver.php | 9 ++-- src/Composer/Util/Filesystem.php | 8 ++-- src/Composer/Util/ProcessUtil.php | 37 ++++++++++++++ src/Composer/Util/Svn.php | 8 ++-- 16 files changed, 98 insertions(+), 64 deletions(-) create mode 100644 src/Composer/Util/ProcessUtil.php diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php index 8bf68cac6..38538f461 100644 --- a/src/Composer/Command/HomeCommand.php +++ b/src/Composer/Command/HomeCommand.php @@ -23,6 +23,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Exception\InvalidArgumentException; +use Composer\Util\ProcessUtil; /** * @author Robert Schönthal @@ -120,7 +121,7 @@ EOT */ private function openBrowser($url) { - $url = escapeshellarg($url); + $url = ProcessUtil::escapeArgument($url); if (defined('PHP_WINDOWS_VERSION_MAJOR')) { return passthru('start "web" explorer "' . $url . '"'); diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index d7ee60677..ea292b9b8 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -20,6 +20,7 @@ use Composer\Package\Version\VersionSelector; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Package\Version\VersionParser; +use Composer\Util\ProcessUtil; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -438,7 +439,7 @@ EOT $finder = new ExecutableFinder(); $gitBin = $finder->find('git'); - $cmd = new Process(sprintf('%s config -l', escapeshellarg($gitBin))); + $cmd = new Process(sprintf('%s config -l', ProcessUtil::escapeArgument($gitBin))); $cmd->run(); if ($cmd->isSuccessful()) { diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index e87972214..d319f143d 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -19,6 +19,7 @@ use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; use Composer\Util\Filesystem; use Composer\Config; +use Composer\Util\ProcessUtil; /** * @author Jordi Boggiano @@ -47,9 +48,12 @@ class GitDownloader extends VcsDownloader $command = 'git clone --no-checkout %s %s && cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer'; $this->io->write(" Cloning ".$ref); - $downloader = $this; - $commandCallable = function ($url) use ($ref, $path, $command, $downloader) { - return sprintf($command, $downloader->shellEscapeUrl ($url), escapeshellarg($path), escapeshellarg($ref)); + $commandCallable = function ($url) use ($ref, $path, $command) { + return sprintf( + $command, + ProcessUtil::escapeArgument($url), + ProcessUtil::escapeArgument($path), + ProcessUtil::escapeArgument($ref)); }; $this->gitUtil->runCommand($commandCallable, $url, $path, true); @@ -62,23 +66,6 @@ class GitDownloader extends VcsDownloader $package->setSourceReference($newRef); } } - - /** - * Escape url. Usernames and password are rawurlencoded earlier in the process. So when the username contains a @ sign, - * it is escaped to %40. Windows replaces a % with a space., because the % sign is used for variables like %appdata%. To - * escape the % sign, one has to escape the % sign with a carat. - * - * http://windowsitpro.com/windows-server/how-can-i-pass-percent-sign-value-regexe - */ - - public function shellEscapeUrl ($url) { - $escapedUrl = escapeshellarg($url); - if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { - $escapedUrl = str_replace('%','^%', $escapedUrl); - } - - return $escapedUrl; - } /** * {@inheritDoc} @@ -95,9 +82,8 @@ class GitDownloader extends VcsDownloader $this->io->write(" Checking out ".$ref); $command = 'git remote set-url composer %s && git fetch composer && git fetch --tags composer'; - $downloader = $this; - $commandCallable = function ($url) use ($command, $downloader) { - return sprintf($command, $downloader->shellEscapeUrl ($url)); + $commandCallable = function ($url) use ($command) { + return sprintf($command, ProcessUtil::escapeArgument ($url)); }; $this->gitUtil->runCommand($commandCallable, $url, $path); @@ -244,7 +230,7 @@ class GitDownloader extends VcsDownloader && $branches && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches) ) { - $command = sprintf('git checkout -B %s %s && git reset --hard %2$s', escapeshellarg($branch), escapeshellarg('composer/'.$reference)); + $command = sprintf('git checkout -B %s %s && git reset --hard %2$s', ProcessUtil::escapeArgument($branch), ProcessUtil::escapeArgument('composer/'.$reference)); if (0 === $this->process->execute($command, $output, $path)) { return; } @@ -257,19 +243,19 @@ class GitDownloader extends VcsDownloader $branch = 'v' . $branch; } - $command = sprintf('git checkout %s', escapeshellarg($branch)); - $fallbackCommand = sprintf('git checkout -B %s %s', escapeshellarg($branch), escapeshellarg('composer/'.$branch)); + $command = sprintf('git checkout %s', ProcessUtil::escapeArgument($branch)); + $fallbackCommand = sprintf('git checkout -B %s %s', ProcessUtil::escapeArgument($branch), ProcessUtil::escapeArgument('composer/'.$branch)); if (0 === $this->process->execute($command, $output, $path) || 0 === $this->process->execute($fallbackCommand, $output, $path) ) { - $command = sprintf('git reset --hard %s', escapeshellarg($reference)); + $command = sprintf('git reset --hard %s', ProcessUtil::escapeArgument($reference)); if (0 === $this->process->execute($command, $output, $path)) { return; } } } - $command = sprintf($template, escapeshellarg($gitRef)); + $command = sprintf($template, ProcessUtil::escapeArgument($gitRef)); if (0 === $this->process->execute($command, $output, $path)) { return; } @@ -288,7 +274,7 @@ class GitDownloader extends VcsDownloader foreach ($this->process->splitLines($output) as $line) { if (preg_match('{^composer/'.preg_quote($branch).'(?:\.x)?$}i', trim($line))) { // find the previous commit by date in the given branch - if (0 === $this->process->execute(sprintf($guessTemplate, $date, escapeshellarg(trim($line))), $output, $path)) { + if (0 === $this->process->execute(sprintf($guessTemplate, $date, ProcessUtil::escapeArgument(trim($line))), $output, $path)) { $newReference = trim($output); } @@ -305,7 +291,7 @@ class GitDownloader extends VcsDownloader } // checkout the new recovered ref - $command = sprintf($template, escapeshellarg($newReference)); + $command = sprintf($template, ProcessUtil::escapeArgument($newReference)); if (0 === $this->process->execute($command, $output, $path)) { $this->io->write(' '.$reference.' is gone (history was rewritten?), recovered by checking out '.$newReference); @@ -325,7 +311,7 @@ class GitDownloader extends VcsDownloader if ($protocols[0] !== 'git') { $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git'; } - $cmd = sprintf('git remote set-url --push origin %s', escapeshellarg($pushUrl)); + $cmd = sprintf('git remote set-url --push origin %s', ProcessUtil::escapeArgument($pushUrl)); $this->process->execute($cmd, $ignoredOutput, $path); } } diff --git a/src/Composer/Downloader/GzipDownloader.php b/src/Composer/Downloader/GzipDownloader.php index 073b18c30..ab186be05 100644 --- a/src/Composer/Downloader/GzipDownloader.php +++ b/src/Composer/Downloader/GzipDownloader.php @@ -18,6 +18,7 @@ use Composer\EventDispatcher\EventDispatcher; use Composer\Package\PackageInterface; use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; +use Composer\Util\ProcessUtil; /** * GZip archive downloader. @@ -40,7 +41,7 @@ class GzipDownloader extends ArchiveDownloader // Try to use gunzip on *nix if (!defined('PHP_WINDOWS_VERSION_BUILD')) { - $command = 'gzip -cd ' . escapeshellarg($file) . ' > ' . escapeshellarg($targetFilepath); + $command = 'gzip -cd ' . ProcessUtil::escapeArgument($file) . ' > ' . ProcessUtil::escapeArgument($targetFilepath); if (0 === $this->process->execute($command, $ignoredOutput)) { return; diff --git a/src/Composer/Downloader/HgDownloader.php b/src/Composer/Downloader/HgDownloader.php index 69e8ba886..835ad57eb 100644 --- a/src/Composer/Downloader/HgDownloader.php +++ b/src/Composer/Downloader/HgDownloader.php @@ -13,6 +13,7 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; +use Composer\Util\ProcessUtil; /** * @author Per Bernhardt @@ -24,10 +25,10 @@ class HgDownloader extends VcsDownloader */ public function doDownload(PackageInterface $package, $path, $url) { - $url = escapeshellarg($url); - $ref = escapeshellarg($package->getSourceReference()); + $url = ProcessUtil::escapeArgument($url); + $ref = ProcessUtil::escapeArgument($package->getSourceReference()); $this->io->write(" Cloning ".$package->getSourceReference()); - $command = sprintf('hg clone %s %s', $url, escapeshellarg($path)); + $command = sprintf('hg clone %s %s', $url, ProcessUtil::escapeArgument($path)); if (0 !== $this->process->execute($command, $ignoredOutput)) { throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()); } @@ -42,8 +43,8 @@ class HgDownloader extends VcsDownloader */ public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url) { - $url = escapeshellarg($url); - $ref = escapeshellarg($target->getSourceReference()); + $url = ProcessUtil::escapeArgument($url); + $ref = ProcessUtil::escapeArgument($target->getSourceReference()); $this->io->write(" Updating to ".$target->getSourceReference()); if (!is_dir($path.'/.hg')) { diff --git a/src/Composer/Downloader/RarDownloader.php b/src/Composer/Downloader/RarDownloader.php index bb62ee0a8..a2980c22e 100644 --- a/src/Composer/Downloader/RarDownloader.php +++ b/src/Composer/Downloader/RarDownloader.php @@ -18,6 +18,7 @@ use Composer\EventDispatcher\EventDispatcher; use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; use RarArchive; +use Composer\Util\ProcessUtil; /** * RAR archive downloader. @@ -42,7 +43,7 @@ class RarDownloader extends ArchiveDownloader // Try to use unrar on *nix if (!defined('PHP_WINDOWS_VERSION_BUILD')) { - $command = 'unrar x ' . escapeshellarg($file) . ' ' . escapeshellarg($path) . ' && chmod -R u+w ' . escapeshellarg($path); + $command = 'unrar x ' . ProcessUtil::escapeArgument($file) . ' ' . ProcessUtil::escapeArgument($path) . ' && chmod -R u+w ' . ProcessUtil::escapeArgument($path); if (0 === $this->process->execute($command, $ignoredOutput)) { return; diff --git a/src/Composer/Downloader/ZipDownloader.php b/src/Composer/Downloader/ZipDownloader.php index b35d6a5af..397f970c0 100644 --- a/src/Composer/Downloader/ZipDownloader.php +++ b/src/Composer/Downloader/ZipDownloader.php @@ -18,6 +18,7 @@ use Composer\EventDispatcher\EventDispatcher; use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; use ZipArchive; +use Composer\Util\ProcessUtil; /** * @author Jordi Boggiano @@ -38,7 +39,7 @@ class ZipDownloader extends ArchiveDownloader // try to use unzip on *nix if (!defined('PHP_WINDOWS_VERSION_BUILD')) { - $command = 'unzip '.escapeshellarg($file).' -d '.escapeshellarg($path) . ' && chmod -R u+w ' . escapeshellarg($path); + $command = 'unzip '.ProcessUtil::escapeArgument($file).' -d '.ProcessUtil::escapeArgument($path) . ' && chmod -R u+w ' . ProcessUtil::escapeArgument($path); try { if (0 === $this->process->execute($command, $ignoredOutput)) { return; diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 7e882ddb3..44a3da2bd 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -19,6 +19,7 @@ use Composer\Script; use Composer\Script\CommandEvent; use Composer\Script\PackageEvent; use Composer\Util\ProcessExecutor; +use Composer\Util\ProcessUtil; /** * The Event Dispatcher. @@ -152,7 +153,7 @@ class EventDispatcher throw $e; } } else { - $args = implode(' ', array_map('escapeshellarg', $event->getArguments())); + $args = implode(' ', array_map(array('Composer\Util\ProcessUtil','escapeArgument'), $event->getArguments())); if (0 !== ($exitCode = $this->process->execute($callable . ($args === '' ? '' : ' '.$args)))) { $event->getIO()->write(sprintf('Script %s handling the %s event returned with an error', $callable, $event->getName())); diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 4facfd494..2c37527d5 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -17,6 +17,7 @@ use Composer\IO\IOInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; use Composer\Util\Filesystem; +use Composer\Util\ProcessUtil; /** * Package installation manager. @@ -296,7 +297,7 @@ class LibraryInstaller implements InstallerInterface } return "@ECHO OFF\r\n". - "SET BIN_TARGET=%~dp0/".trim(escapeshellarg($binPath), '"')."\r\n". + "SET BIN_TARGET=%~dp0/".trim(ProcessUtil::escapeArgument($binPath), '"')."\r\n". "{$caller} \"%BIN_TARGET%\" %*\r\n"; } @@ -307,7 +308,7 @@ class LibraryInstaller implements InstallerInterface return "#!/usr/bin/env sh\n". 'SRC_DIR="`pwd`"'."\n". 'cd "`dirname "$0"`"'."\n". - 'cd '.escapeshellarg(dirname($binPath))."\n". + 'cd '.ProcessUtil::escapeArgument(dirname($binPath))."\n". 'BIN_TARGET="`pwd`/'.basename($binPath)."\"\n". 'cd "$SRC_DIR"'."\n". '"$BIN_TARGET" "$@"'."\n"; diff --git a/src/Composer/Installer/PearInstaller.php b/src/Composer/Installer/PearInstaller.php index defadd9cf..bdd41b950 100644 --- a/src/Composer/Installer/PearInstaller.php +++ b/src/Composer/Installer/PearInstaller.php @@ -124,7 +124,7 @@ class PearInstaller extends LibraryInstaller "pushd .\r\n". "cd %~dp0\r\n". "set PHP_PROXY=%CD%\\composer-php.bat\r\n". - "cd ".escapeshellarg(dirname($binPath))."\r\n". + "cd ".ProcessUtil::escapeArgument(dirname($binPath))."\r\n". "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n". "popd\r\n". "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n"; @@ -134,7 +134,7 @@ class PearInstaller extends LibraryInstaller return "@echo off\r\n". "pushd .\r\n". "cd %~dp0\r\n". - "cd ".escapeshellarg(dirname($binPath))."\r\n". + "cd ".ProcessUtil::escapeArgument(dirname($binPath))."\r\n". "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n". "popd\r\n". $caller." \"%BIN_TARGET%\" %*\r\n"; diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index 2fa9b011a..159552172 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -22,6 +22,7 @@ use Composer\Package\Loader\ArrayLoader; use Composer\Package\Version\VersionParser; use Composer\Util\Git as GitUtil; use Composer\IO\IOInterface; +use Composer\Util\ProcessUtil; /** * Reads/writes project lockfile (composer.lock). @@ -341,13 +342,13 @@ class Locker case 'git': GitUtil::cleanEnv(); - if (0 === $this->process->execute('git log -n1 --pretty=%ct '.escapeshellarg($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) { + if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessUtil::escapeArgument($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) { $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC')); } break; case 'hg': - if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.escapeshellarg($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) { + if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessUtil::escapeArgument($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) { $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC')); } break; diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index 20cfa93fc..eea945e1e 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -19,6 +19,7 @@ use Composer\Util\Git as GitUtil; use Composer\IO\IOInterface; use Composer\Cache; use Composer\Config; +use Composer\Util\ProcessUtil; /** * @author Jordi Boggiano @@ -62,7 +63,7 @@ class GitDriver extends VcsDriver if (is_dir($this->repoDir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $this->repoDir) && trim($output) === '.') { try { $commandCallable = function ($url) { - return sprintf('git remote set-url origin %s && git remote update --prune origin', escapeshellarg($url)); + return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessUtil::escapeArgument($url)); }; $gitUtil->runCommand($commandCallable, $this->url, $this->repoDir); } catch (\Exception $e) { @@ -74,7 +75,7 @@ class GitDriver extends VcsDriver $repoDir = $this->repoDir; $commandCallable = function ($url) use ($repoDir) { - return sprintf('git clone --mirror %s %s', escapeshellarg($url), escapeshellarg($repoDir)); + return sprintf('git clone --mirror %s %s', ProcessUtil::escapeArgument($url), ProcessUtil::escapeArgument($repoDir)); }; $gitUtil->runCommand($commandCallable, $this->url, $this->repoDir, true); @@ -147,7 +148,7 @@ class GitDriver extends VcsDriver } if (!isset($this->infoCache[$identifier])) { - $resource = sprintf('%s:composer.json', escapeshellarg($identifier)); + $resource = sprintf('%s:composer.json', ProcessUtil::escapeArgument($identifier)); $this->process->execute(sprintf('git show %s', $resource), $composer, $this->repoDir); if (!trim($composer)) { @@ -157,7 +158,7 @@ class GitDriver extends VcsDriver $composer = JsonFile::parseJson($composer, $resource); if (!isset($composer['time'])) { - $this->process->execute(sprintf('git log -1 --format=%%at %s', escapeshellarg($identifier)), $output, $this->repoDir); + $this->process->execute(sprintf('git log -1 --format=%%at %s', ProcessUtil::escapeArgument($identifier)), $output, $this->repoDir); $date = new \DateTime('@'.trim($output), new \DateTimeZone('UTC')); $composer['time'] = $date->format('Y-m-d H:i:s'); } diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index 7b9d1ff8c..1fba69f10 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -17,6 +17,7 @@ use Composer\Json\JsonFile; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\IO\IOInterface; +use Composer\Util\ProcessUtil; /** * @author Per Bernhardt @@ -56,7 +57,7 @@ class HgDriver extends VcsDriver // clean up directory and do a fresh clone into it $fs->removeDirectory($this->repoDir); - if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', escapeshellarg($this->url), escapeshellarg($this->repoDir)), $output, $cacheDir)) { + if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', ProcessUtil::escapeArgument($this->url), ProcessUtil::escapeArgument($this->repoDir)), $output, $cacheDir)) { $output = $this->process->getErrorOutput(); if (0 !== $this->process->execute('hg --version', $ignoredOutput)) { @@ -116,7 +117,7 @@ class HgDriver extends VcsDriver public function getComposerInformation($identifier) { if (!isset($this->infoCache[$identifier])) { - $this->process->execute(sprintf('hg cat -r %s composer.json', escapeshellarg($identifier)), $composer, $this->repoDir); + $this->process->execute(sprintf('hg cat -r %s composer.json', ProcessUtil::escapeArgument($identifier)), $composer, $this->repoDir); if (!trim($composer)) { return; @@ -125,7 +126,7 @@ class HgDriver extends VcsDriver $composer = JsonFile::parseJson($composer, $identifier); if (!isset($composer['time'])) { - $this->process->execute(sprintf('hg log --template "{date|rfc3339date}" -r %s', escapeshellarg($identifier)), $output, $this->repoDir); + $this->process->execute(sprintf('hg log --template "{date|rfc3339date}" -r %s', ProcessUtil::escapeArgument($identifier)), $output, $this->repoDir); $date = new \DateTime(trim($output), new \DateTimeZone('UTC')); $composer['time'] = $date->format('Y-m-d H:i:s'); } @@ -215,7 +216,7 @@ class HgDriver extends VcsDriver } $processExecutor = new ProcessExecutor(); - $exit = $processExecutor->execute(sprintf('hg identify %s', escapeshellarg($url)), $ignored); + $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessUtil::escapeArgument($url)), $ignored); return $exit === 0; } diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 6044c25d6..9ed24c503 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -112,9 +112,9 @@ class Filesystem } if (defined('PHP_WINDOWS_VERSION_BUILD')) { - $cmd = sprintf('rmdir /S /Q %s', escapeshellarg(realpath($directory))); + $cmd = sprintf('rmdir /S /Q %s', ProcessUtil::escapeArgument(realpath($directory))); } else { - $cmd = sprintf('rm -rf %s', escapeshellarg($directory)); + $cmd = sprintf('rm -rf %s', ProcessUtil::escapeArgument($directory)); } $result = $this->getProcess()->execute($cmd, $output) === 0; @@ -269,7 +269,7 @@ class Filesystem if (defined('PHP_WINDOWS_VERSION_BUILD')) { // Try to copy & delete - this is a workaround for random "Access denied" errors. - $command = sprintf('xcopy %s %s /E /I /Q', escapeshellarg($source), escapeshellarg($target)); + $command = sprintf('xcopy %s %s /E /I /Q', ProcessUtil::escapeArgument($source), ProcessUtil::escapeArgument($target)); $result = $this->processExecutor->execute($command, $output); // clear stat cache because external processes aren't tracked by the php stat cache @@ -283,7 +283,7 @@ class Filesystem } else { // We do not use PHP's "rename" function here since it does not support // the case where $source, and $target are located on different partitions. - $command = sprintf('mv %s %s', escapeshellarg($source), escapeshellarg($target)); + $command = sprintf('mv %s %s', ProcessUtil::escapeArgument($source), ProcessUtil::escapeArgument($target)); $result = $this->processExecutor->execute($command, $output); // clear stat cache because external processes aren't tracked by the php stat cache diff --git a/src/Composer/Util/ProcessUtil.php b/src/Composer/Util/ProcessUtil.php new file mode 100644 index 000000000..75b6fd9df --- /dev/null +++ b/src/Composer/Util/ProcessUtil.php @@ -0,0 +1,37 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Util; + +use Symfony\Component\Process\ProcessUtils; + +/** + * @author Frederik Bosch + */ + +class ProcessUtil +{ + + /** + * 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 escapeArgument ($argument) + { + return ProcessUtils::escapeArgument($argument); + } + + +} diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php index 4ec13297f..e6d370abf 100644 --- a/src/Composer/Util/Svn.php +++ b/src/Composer/Util/Svn.php @@ -188,11 +188,11 @@ class Svn $cmd, '--non-interactive ', $this->getCredentialString(), - escapeshellarg($url) + ProcessUtil::escapeArgument($url) ); if ($path) { - $cmd .= ' ' . escapeshellarg($path); + $cmd .= ' ' . ProcessUtil::escapeArgument($path); } return $cmd; @@ -214,8 +214,8 @@ class Svn return sprintf( ' %s--username %s --password %s ', $this->getAuthCache(), - escapeshellarg($this->getUsername()), - escapeshellarg($this->getPassword()) + ProcessUtil::escapeArgument($this->getUsername()), + ProcessUtil::escapeArgument($this->getPassword()) ); }