diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php index a859cac13..df61b3c3e 100644 --- a/src/Composer/Util/StreamContextFactory.php +++ b/src/Composer/Util/StreamContextFactory.php @@ -34,27 +34,53 @@ final class StreamContextFactory // Handle system proxy if (isset($_SERVER['HTTP_PROXY']) || isset($_SERVER['http_proxy'])) { // Some systems seem to rely on a lowercased version instead... - $proxy = isset($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']; + $proxy = parse_url(isset($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']); + } else { + $proxy = false; + } - // http(s):// is not supported in proxy - if ('http://' == substr($proxy, 0, 7)) { - $proxy = 'tcp://' . rtrim(substr($proxy, 7), '/') . (parse_url($proxy, PHP_URL_PORT) ? '' : ':80'); - } else if ('https://' == substr($proxy, 0, 8)) { - $proxy = 'ssl://' . rtrim(substr($proxy, 8), '/') . (parse_url($proxy, PHP_URL_PORT) ? '' : ':443'); + if (false !== $proxy) { + $proxyURL = (isset($proxy['scheme']) ? $proxy['scheme'] : '') . '://'; + $proxyURL .= isset($proxy['host']) ? $proxy['host'] : ''; + + if (isset($proxy['port'])) { + $proxyURL .= ":" . $proxy['port']; + } elseif ('http://' == substr($proxyURL, 0, 7)) { + $proxyURL .= ":80"; + } elseif ('https://' == substr($proxyURL, 0, 8)) { + $proxyURL .= ":443"; } - if (0 === strpos($proxy, 'ssl:') && !extension_loaded('openssl')) { + // http(s):// is not supported in proxy + $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL); + + if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) { throw new \RuntimeException('You must enable the openssl extension to use a proxy over https'); } $options['http'] = array( - 'proxy' => $proxy, + 'proxy' => $proxyURL, 'request_fulluri' => true, ); + + if (isset($proxy['user'])) { + $auth = $proxy['user']; + if (isset($proxy['pass'])) { + $auth .= ':' . $proxy['pass']; + } + $auth = base64_encode($auth); + + // Preserve headers if already set in default options + if (isset($defaultOptions['http']['header'])) { + $defaultOptions['http']['header'] .= "Proxy-Authorization: Basic {$auth}\r\n"; + } else { + $options['http']['header'] = "Proxy-Authorization: Basic {$auth}\r\n"; + } + } } $options = array_merge_recursive($options, $defaultOptions); - + return stream_context_create($options, $defaultParams); } } diff --git a/tests/Composer/Test/Util/StreamContextFactoryTest.php b/tests/Composer/Test/Util/StreamContextFactoryTest.php index 237d4aaa9..dc60fe3bb 100644 --- a/tests/Composer/Test/Util/StreamContextFactoryTest.php +++ b/tests/Composer/Test/Util/StreamContextFactoryTest.php @@ -63,12 +63,11 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase $context = StreamContextFactory::getContext(array('http' => array('method' => 'GET'))); $options = stream_context_get_options($context); - $this->assertSame('http://proxyserver/', $_SERVER['HTTP_PROXY']); - $this->assertEquals(array('http' => array( - 'proxy' => 'tcp://username:password@proxyserver.net:3128', + 'proxy' => 'tcp://proxyserver.net:3128', 'request_fulluri' => true, 'method' => 'GET', + 'header' => "Proxy-Authorization: Basic " . base64_encode('username:password') . "\r\n" )), $options); } @@ -80,9 +79,10 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase $options = stream_context_get_options($context); $this->assertEquals(array('http' => array( - 'proxy' => 'tcp://username:password@proxyserver.net:80', + 'proxy' => 'tcp://proxyserver.net:80', 'request_fulluri' => true, 'method' => 'GET', + 'header' => "Proxy-Authorization: Basic " . base64_encode('username:password') . "\r\n" )), $options); }