diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index e63df021a..819fbcefb 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -125,7 +125,7 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface $fileName = $this->getFileName($package, $path); $processedUrl = $this->processUrl($package, $url); - $hostname = parse_url($processedUrl, PHP_URL_HOST); + $origin = RemoteFilesystem::getOrigin($processedUrl); $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl); if ($this->eventDispatcher) { @@ -150,7 +150,7 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface $retries = 3; while ($retries--) { try { - $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions()); + $rfs->copy($origin, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions()); break; } catch (TransportException $e) { // if we got an http response with a proper code, then requesting again will probably not help, abort diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 9d5b727cc..c595b20c2 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -206,8 +206,8 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) { $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl); - $hostname = parse_url($url, PHP_URL_HOST) ?: $url; - $json = $this->rfs->getContents($hostname, $url, false); + $origin = RemoteFilesystem::getOrigin($url); + $json = $this->rfs->getContents($origin, $url, false); $search = JsonFile::parseJson($json, $url); if (empty($search['results'])) { @@ -681,10 +681,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent); } - $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename; + $origin = RemoteFilesystem::getOrigin($filename); $rfs = $preFileDownloadEvent->getRemoteFilesystem(); - $json = $rfs->getContents($hostname, $filename, false); + $json = $rfs->getContents($origin, $filename, false); if ($sha256 && $sha256 !== hash('sha256', $json)) { // undo downgrade before trying again if http seems to be hijacked or modifying content somehow if ($this->allowSslDowngrade) { @@ -760,10 +760,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent); } - $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename; + $origin = RemoteFilesystem::getOrigin($filename); $rfs = $preFileDownloadEvent->getRemoteFilesystem(); $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime))); - $json = $rfs->getContents($hostname, $filename, false, $options); + $json = $rfs->getContents($origin, $filename, false, $options); if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) { return true; } diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 8c051bd50..529112811 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -304,6 +304,10 @@ class GitHubDriver extends VcsDriver */ protected function generateSshUrl() { + if (false !== strpos($this->originUrl, ':')) { + return 'ssh://git@' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git'; + } + return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git'; } diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index 2044ff702..7b593084f 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -67,9 +67,9 @@ class GitLabDriver extends VcsDriver private $isPrivate = true; /** - * @var int port number + * @var bool true if the origin has a port number or a path component in it */ - protected $portNumber; + private $hasNonstandardOrigin = false; const URL_REGEX = '#^(?:(?Phttps?)://(?P.+?)(?::(?P[0-9]+))?/|git@(?P[^:]+):)(?P.+)/(?P[^/]+?)(?:\.git|/)?$#'; @@ -94,11 +94,10 @@ class GitLabDriver extends VcsDriver ? $match['scheme'] : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https') ; - $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts); + $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts, $match['port']); - if (!empty($match['port']) && true === is_numeric($match['port'])) { - // If it is an HTTP based URL, and it has a port - $this->portNumber = (int) $match['port']; + if (false !== strpos($this->originUrl, ':') || false !== strpos($this->originUrl, '/')) { + $this->hasNonstandardOrigin = true; } $this->namespace = implode('/', $urlParts); @@ -259,10 +258,7 @@ class GitLabDriver extends VcsDriver */ public function getApiUrl() { - $domainName = $this->originUrl; - $portNumber = (true === is_numeric($this->portNumber)) ? sprintf(':%s', $this->portNumber) : ''; - - return $this->scheme.'://'.$domainName.$portNumber.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository); + return $this->scheme.'://'.$this->originUrl.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository); } /** @@ -360,6 +356,10 @@ class GitLabDriver extends VcsDriver */ protected function generateSshUrl() { + if ($this->hasNonstandardOrigin) { + return 'ssh://git@'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository.'.git'; + } + return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git'; } @@ -458,7 +458,7 @@ class GitLabDriver extends VcsDriver $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2']; $urlParts = explode('/', $match['parts']); - if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts)) { + if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts, $match['port'])) { return false; } @@ -492,16 +492,16 @@ class GitLabDriver extends VcsDriver * @param array $urlParts * @return bool|string */ - private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts) + private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts, $portNumber) { - if (in_array($guessedDomain, $configuredDomains)) { + if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array($guessedDomain.':'.$portNumber, $configuredDomains))) { return $guessedDomain; } while (null !== ($part = array_shift($urlParts))) { $guessedDomain .= '/' . $part; - if (in_array($guessedDomain, $configuredDomains)) { + if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array(preg_replace('{/}', ':'.$portNumber.'/', $guessedDomain, 1), $configuredDomains))) { return $guessedDomain; } } diff --git a/src/Composer/Util/GitLab.php b/src/Composer/Util/GitLab.php index 475c5e7ee..7a69ad251 100644 --- a/src/Composer/Util/GitLab.php +++ b/src/Composer/Util/GitLab.php @@ -53,7 +53,10 @@ class GitLab */ public function authorizeOAuth($originUrl) { - if (!in_array($originUrl, $this->config->get('gitlab-domains'), true)) { + // before composer 1.9, origin URLs had no port number in them + $bcOriginUrl = preg_replace('{:\d+}', '', $originUrl); + + if (!in_array($originUrl, $this->config->get('gitlab-domains'), true) && !in_array($bcOriginUrl, $this->config->get('gitlab-domains'), true)) { return false; } @@ -73,6 +76,12 @@ class GitLab return true; } + if (isset($authTokens[$bcOriginUrl])) { + $this->io->setAuthentication($originUrl, $authTokens[$bcOriginUrl], 'private-token'); + + return true; + } + return false; } diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 2b66585db..32767c161 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -1110,4 +1110,17 @@ class RemoteFilesystem $io->writeError('<'.$type.'>'.ucfirst($type).' from '.$url.': '.$data[$type].''); } } + + public static function getOrigin($urlOrPath) + { + $hostPort = parse_url($urlOrPath, PHP_URL_HOST); + if (!$hostPort) { + return $urlOrPath; + } + if (parse_url($urlOrPath, PHP_URL_PORT)) { + $hostPort .= ':'.parse_url($urlOrPath, PHP_URL_PORT); + } + + return $hostPort; + } }