Improve handling of non-standard ports for GitLab and GitHub installs, fixes #8173

main
Jordi Boggiano 5 years ago
parent 5ddc40e93c
commit 0261ce8092
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC

@ -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

@ -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;
}

@ -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';
}

@ -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 = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)(?::(?P<port>[0-9]+))?/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.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;
}
}

@ -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;
}

@ -1110,4 +1110,17 @@ class RemoteFilesystem
$io->writeError('<'.$type.'>'.ucfirst($type).' from '.$url.': '.$data[$type].'</'.$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;
}
}

Loading…
Cancel
Save