浏览代码

TLS support for Factory::createComposer() - for JsonFile remotes

Pádraic Brady 11 年之前
父节点
当前提交
600b6c8cb3

+ 3 - 2
src/Composer/Command/Command.php

@@ -17,6 +17,7 @@ use Composer\Console\Application;
 use Composer\IO\IOInterface;
 use Composer\IO\NullIO;
 use Symfony\Component\Console\Command\Command as BaseCommand;
+use Symfony\Component\Console\Input\InputInterface;
 
 /**
  * Base class for Composer commands
@@ -42,13 +43,13 @@ abstract class Command extends BaseCommand
      * @throws \RuntimeException
      * @return Composer
      */
-    public function getComposer($required = true, $disablePlugins = false)
+    public function getComposer($required = true, $disablePlugins = false, InputInterface $input = null)
     {
         if (null === $this->composer) {
             $application = $this->getApplication();
             if ($application instanceof Application) {
                 /* @var $application    Application */
-                $this->composer = $application->getComposer($required, $disablePlugins);
+                $this->composer = $application->getComposer($required, $disablePlugins, $input);
             } elseif ($required) {
                 throw new \RuntimeException(
                     'Could not create a Composer\Composer instance, you must inject '.

+ 2 - 0
src/Composer/Command/RequireCommand.php

@@ -43,6 +43,8 @@ class RequireCommand extends InitCommand
                 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
                 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
                 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'),
+                new InputOption('disable-tls', null, InputOption::VALUE_NONE, 'Disable SSL/TLS protection for HTTPS requests'),
+                new InputOption('cafile', null, InputOption::VALUE_REQUIRED, 'The path to a valid CA certificate file for SSL/TLS certificate verification'),
             ))
             ->setHelp(<<<EOT
 The require command adds required packages to your composer.json and installs them

+ 2 - 2
src/Composer/Console/Application.php

@@ -169,11 +169,11 @@ class Application extends BaseApplication
      * @throws JsonValidationException
      * @return \Composer\Composer
      */
-    public function getComposer($required = true, $disablePlugins = false)
+    public function getComposer($required = true, $disablePlugins = false, InputInterface $input = null)
     {
         if (null === $this->composer) {
             try {
-                $this->composer = Factory::create($this->io, null, $disablePlugins);
+                $this->composer = Factory::create($this->io, null, $disablePlugins, $input);
             } catch (\InvalidArgumentException $e) {
                 if ($required) {
                     $this->io->write($e->getMessage());

+ 27 - 5
src/Composer/Factory.php

@@ -24,6 +24,7 @@ use Symfony\Component\Console\Formatter\OutputFormatterStyle;
 use Composer\EventDispatcher\EventDispatcher;
 use Composer\Autoload\AutoloadGenerator;
 use Composer\Package\Version\VersionParser;
+use Symfony\Component\Console\Input\InputInterface;
 
 /**
  * Creates a configured instance of composer.
@@ -184,7 +185,7 @@ class Factory
      * @throws \UnexpectedValueException
      * @return Composer
      */
-    public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false)
+    public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, InputInterface $input = null)
     {
         // load Composer configuration
         if (null === $localConfig) {
@@ -193,7 +194,28 @@ class Factory
 
         if (is_string($localConfig)) {
             $composerFile = $localConfig;
-            $file = new JsonFile($localConfig, new RemoteFilesystem($io));
+
+            $rfs = null;
+            if (preg_match("|^https?://|i", $localConfig)) {
+                $disableTls = false;
+                if($input->getOption('disable-tls')) {
+                    //$output->writeln('<warning>You are running Composer with SSL/TLS protection disabled.</warning>'); //TODO
+                    $disableTls = true;
+                } elseif (!extension_loaded('openssl')) {
+                    throw new \RuntimeException('The openssl extension is required for SSL/TLS protection but is not available. '
+                        . 'You can disable this error, at your own risk, by passing the \'--disable-tls\' option to this command.');
+                }
+
+                $rfsOptions = array();
+                if ($disableTls === false) {
+                    if (!is_null($input->get('cafile'))) {
+                        $rfsOptions = array('ssl'=>array('cafile'=>$input->get('cafile')));
+                    }
+                }
+                $rfs = new RemoteFilesystem($io, $rfsOptions, $disableTls);
+            }
+
+            $file = new JsonFile($localConfig, $rfs);
 
             if (!$file->exists()) {
                 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
@@ -275,7 +297,7 @@ class Factory
             $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
                 ? substr($composerFile, 0, -4).'lock'
                 : $composerFile . '.lock';
-            $locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io)), $rm, $im, md5_file($composerFile));
+            $locker = new Package\Locker($io, new JsonFile($lockFile, $rfs), $rm, $im, md5_file($composerFile)); // can we reuse same object?
             $composer->setLocker($locker);
         }
 
@@ -441,10 +463,10 @@ class Factory
      * @param  bool     $disablePlugins Whether plugins should not be loaded
      * @return Composer
      */
-    public static function create(IOInterface $io, $config = null, $disablePlugins = false)
+    public static function create(IOInterface $io, $config = null, $disablePlugins = false, InputInterface $input = null)
     {
         $factory = new static();
 
-        return $factory->createComposer($io, $config, $disablePlugins);
+        return $factory->createComposer($io, $config, $disablePlugins, $input);
     }
 }