diff --git a/.travis.yml b/.travis.yml index 800a4f2f1..fa96bc75b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,12 @@ php: - 5.4 - 5.5 - hhvm + - 5.6 matrix: allow_failures: - php: hhvm + - php: 5.6 before_script: - sudo apt-get install parallel diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index 445bcc1aa..1d2450630 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -14,6 +14,7 @@ namespace Composer\Command; use Composer\Composer; use Composer\Factory; +use Composer\Config; use Composer\Downloader\TransportException; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; @@ -48,6 +49,7 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { + $this->rfs = new RemoteFilesystem($this->getIO()); $this->process = new ProcessExecutor($this->getIO()); @@ -57,19 +59,6 @@ EOT $output->write('Checking git settings: '); $this->outputResult($output, $this->checkGit()); - $output->write('Checking http connectivity: '); - $this->outputResult($output, $this->checkHttp()); - - $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org')); - if (!empty($opts['http']['proxy'])) { - $output->write('Checking HTTP proxy: '); - $this->outputResult($output, $this->checkHttpProxy()); - $output->write('Checking HTTP proxy support for request_fulluri: '); - $this->outputResult($output, $this->checkHttpProxyFullUriRequestParam()); - $output->write('Checking HTTPS proxy support for request_fulluri: '); - $this->outputResult($output, $this->checkHttpsProxyFullUriRequestParam()); - } - $composer = $this->getComposer(false); if ($composer) { $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output); @@ -85,6 +74,19 @@ EOT $config = Factory::createConfig(); } + $output->write('Checking http connectivity: '); + $this->outputResult($output, $this->checkHttp($config)); + + $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org')); + if (!empty($opts['http']['proxy'])) { + $output->write('Checking HTTP proxy: '); + $this->outputResult($output, $this->checkHttpProxy()); + $output->write('Checking HTTP proxy support for request_fulluri: '); + $this->outputResult($output, $this->checkHttpProxyFullUriRequestParam()); + $output->write('Checking HTTPS proxy support for request_fulluri: '); + $this->outputResult($output, $this->checkHttpsProxyFullUriRequestParam()); + } + if ($oauth = $config->get('github-oauth')) { foreach ($oauth as $domain => $token) { $output->write('Checking '.$domain.' oauth access: '); @@ -135,13 +137,45 @@ EOT return true; } - private function checkHttp() + private function checkHttp(Config $config) { - $protocol = extension_loaded('openssl') ? 'https' : 'http'; + $disableTls = false; + $result = array(); + if($config->get('disable-tls') === true) { + $protocol = 'http'; + $disableTls = true; + $result[] = 'Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.'; + } else { + $protocol = 'https'; + } + if (!extension_loaded('openssl') && !$disableTls) { + $result[] = 'Composer is configured to use SSL/TLS protection but the openssl extension is not available.'; + } + + $remoteFilesystemOptions = array(); + if (!is_null($config->get('cafile'))) { + $remoteFilesystemOptions = array('ssl'=>array('cafile'=>$config->get('cafile'))); + } + try { + $remoteFilesystem = new RemoteFilesystem($this->getIO(), $remoteFilesystemOptions, $disableTls); + } catch (TransportException $e) { + if (preg_match('|cafile|', $e->getMessage())) { + $result[] = '[' . get_class($e) . '] ' . $e->getMessage() . ''; + $result[] = 'Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.'; + $result[] = 'You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.'; + } else { + throw $e; + } + } + try { - $json = $this->rfs->getContents('packagist.org', $protocol . '://packagist.org/packages.json', false); + $json = $remoteFilesystem->getContents('packagist.org', $protocol . '://packagist.org/packages.json', false, array(), $disableTls); } catch (\Exception $e) { - return $e; + array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage()); + } + + if (count($result) > 0) { + return $result; } return true; @@ -271,7 +305,13 @@ EOT if ($result instanceof \Exception) { $output->writeln('['.get_class($result).'] '.$result->getMessage()); } elseif ($result) { - $output->writeln($result); + if (is_array($result)) { + foreach ($result as $message) { + $output->writeln($message); + } + } else { + $output->writeln($result); + } } } } diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 07dd86033..7036a5727 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -63,7 +63,7 @@ EOT $disableTls = false; if($config->get('disable-tls') === true || $input->getOption('disable-tls')) { - $output->writeln('You are running Composer with SSL/TLS protection disabled.'); + $output->writeln('You are running Composer with SSL/TLS protection disabled.'); $baseUrl = 'http://' . self::HOMEPAGE; $disableTls = true; } elseif (!extension_loaded('openssl')) { @@ -74,13 +74,14 @@ EOT $baseUrl = 'https://' . self::HOMEPAGE; } + $remoteFilesystemOptions = array(); + if (!is_null($config->get('cafile'))) { + $remoteFilesystemOptions = array('ssl'=>array('cafile'=>$config->get('cafile'))); + } + if (!is_null($input->get('cafile'))) { + $remoteFilesystemOptions = array('ssl'=>array('cafile'=>$input->get('cafile'))); + } try { - if (!is_null($config->get('cafile'))) { - $remoteFilesystemOptions = array('ssl'=>array('cafile'=>$config->get('cafile'))); - } - if (!is_null($input->get('cafile'))) { - $remoteFilesystemOptions = array('ssl'=>array('cafile'=>$input->get('cafile'))); - } $remoteFilesystem = new RemoteFilesystem($this->getIO(), $remoteFilesystemOptions, $disableTls); } catch (TransportException $e) { if (preg_match('|cafile|', $e->getMessage())) { diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index f829cb459..57f02d81a 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -163,7 +163,7 @@ class Factory if (!isset($repo['type'])) { throw new \UnexpectedValueException('Repository '.$index.' ('.json_encode($repo).') must have a type defined'); } - $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index; + $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index; //CHECK: Why is scheme stripped? while (isset($repos[$name])) { $name .= '2'; } diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index f54715590..ff2e94c31 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -72,7 +72,7 @@ class RemoteFilesystem * * @return bool true */ - public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array(), $disableTls = false) + public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array(), $disableTls = false) //REFACTOR: to constructor for TLS opt { return $this->get($originUrl, $fileUrl, $options, $fileName, $progress, $disableTls); }