From f3b0890cf48fe44882cc45b4a84b02889d5a9a92 Mon Sep 17 00:00:00 2001 From: Frederik Bosch Date: Wed, 24 Sep 2014 15:16:30 +0200 Subject: [PATCH] GitDownloader.php: better escaping for Windows Compability for Windows usernames and passwords. When usernames and passwords contain characters that are rawurlencoded to a string containing a % sign (e.g. @ becomes %40), the procent was replaced with a space. Git can there not authenticate. --- src/Composer/Downloader/GitDownloader.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 695996b5c..6c8b60dd9 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -48,7 +48,7 @@ class GitDownloader extends VcsDownloader $this->io->write(" Cloning ".$ref); $commandCallable = function ($url) use ($ref, $path, $command) { - return sprintf($command, escapeshellarg($url), escapeshellarg($path), escapeshellarg($ref)); + return sprintf($command, $this->shellEscapeUrl ($url), escapeshellarg($path), escapeshellarg($ref)); }; $this->gitUtil->runCommand($commandCallable, $url, $path, true); @@ -61,6 +61,23 @@ 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 + */ + + private function shellEscapeUrl ($url) { + $escapedUrl = escapeshellarg($url); + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + $escapedUrl = str_replace('%','^%', $escapedUrl); + } + + return $escapedUrl; + } /** * {@inheritDoc} @@ -78,7 +95,7 @@ class GitDownloader extends VcsDownloader $command = 'git remote set-url composer %s && git fetch composer && git fetch --tags composer'; $commandCallable = function ($url) use ($command) { - return sprintf($command, escapeshellarg($url)); + return sprintf($command, $this->shellEscapeUrl ($url)); }; $this->gitUtil->runCommand($commandCallable, $url, $path);