diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 4ad2e81d2..88da8adc8 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -23,6 +23,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Composer\Json\JsonFile; +use Composer\Util\RemoteFilesystem; /** * Install a package as new project into new directory. @@ -86,7 +87,7 @@ EOT if (null === $repositoryUrl) { $sourceRepo = new ComposerRepository(array('url' => 'http://packagist.org')); } elseif (".json" === substr($repositoryUrl, -5)) { - $sourceRepo = new FilesystemRepository(new JsonFile($repositoryUrl)); + $sourceRepo = new FilesystemRepository(new JsonFile($repositoryUrl, new RemoteFilesystem($io))); } elseif (0 === strpos($repositoryUrl, 'http')) { $sourceRepo = new ComposerRepository(array('url' => $repositoryUrl)); } else { diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 426fc6882..721e44461 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -13,7 +13,7 @@ namespace Composer\Command; use Composer\Composer; -use Composer\Util\StreamContextFactory; +use Composer\Util\RemoteFilesystem; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -40,9 +40,8 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { - $ctx = StreamContextFactory::getContext(); - - $latest = trim(file_get_contents('http://getcomposer.org/version', false, $ctx)); + $rfs = new RemoteFilesystem($this->getIO()); + $latest = trim($rfs->getContents('getcomposer.org', 'http://getcomposer.org/version', false)); if (Composer::VERSION !== $latest) { $output->writeln(sprintf("Updating to version %s.", $latest)); @@ -50,7 +49,7 @@ EOT $remoteFilename = 'http://getcomposer.org/composer.phar'; $localFilename = $_SERVER['argv'][0]; - copy($remoteFilename, $localFilename, $ctx); + $rfs->copy('getcomposer.org', $remoteFilename, $localFilename); } else { $output->writeln("You are using the latest composer version."); } diff --git a/src/Composer/Command/ValidateCommand.php b/src/Composer/Command/ValidateCommand.php index 878a058aa..b65841d71 100644 --- a/src/Composer/Command/ValidateCommand.php +++ b/src/Composer/Command/ValidateCommand.php @@ -17,6 +17,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; use Composer\Json\JsonFile; use Composer\Json\JsonValidationException; +use Composer\Util\RemoteFilesystem; /** * @author Robert Schönthal @@ -55,7 +56,7 @@ EOT $laxValid = false; try { - $json = new JsonFile($file); + $json = new JsonFile($file, new RemoteFilesystem($this->getIO())); $json->read(); $json->validateSchema(JsonFile::LAX_SCHEMA); diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 958844930..2815f22b7 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -16,6 +16,7 @@ use Composer\Json\JsonFile; use Composer\IO\IOInterface; use Composer\Repository\RepositoryManager; use Composer\Util\ProcessExecutor; +use Composer\Util\RemoteFilesystem; /** * Creates an configured instance of composer. @@ -38,7 +39,7 @@ class Factory $composerFile = getenv('COMPOSER') ?: 'composer.json'; } - $file = new JsonFile($composerFile); + $file = new JsonFile($composerFile, new RemoteFilesystem($io)); if (!$file->exists()) { if ($composerFile === 'composer.json') { $message = 'Composer could not find a composer.json file in '.getcwd(); @@ -98,7 +99,7 @@ class Factory // init locker $lockFile = substr($composerFile, -5) === '.json' ? substr($composerFile, 0, -4).'lock' : $composerFile . '.lock'; - $locker = new Package\Locker(new JsonFile($lockFile), $rm, md5_file($composerFile)); + $locker = new Package\Locker(new JsonFile($lockFile, new RemoteFilesystem($io)), $rm, md5_file($composerFile)); // initialize composer $composer = new Composer(); diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index 458265e3e..5c891814e 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -17,6 +17,7 @@ use Composer\Composer; use JsonSchema\Validator; use Seld\JsonLint\JsonParser; use Composer\Util\StreamContextFactory; +use Composer\Util\RemoteFilesystem; /** * Reads/writes json files. @@ -34,15 +35,22 @@ class JsonFile const JSON_UNESCAPED_UNICODE = 256; private $path; + private $rfs; /** * Initializes json file reader/parser. * * @param string $lockFile path to a lockfile + * @param RemoteFilesystem $rfs required for loading http/https json files */ - public function __construct($path) + public function __construct($path, RemoteFilesystem $rfs = null) { $this->path = $path; + + if (null === $rfs && preg_match('{^https?://}i', $path)) { + throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed'); + } + $this->rfs = $rfs; } public function getPath() @@ -67,15 +75,14 @@ class JsonFile */ public function read() { - $ctx = StreamContextFactory::getContext(array( - 'http' => array( - 'header' => 'User-Agent: Composer/'.Composer::VERSION."\r\n" - ) - )); - - $json = file_get_contents($this->path, false, $ctx); - if (!$json) { - throw new \RuntimeException('Could not read '.$this->path.', you are probably offline'); + try { + if ($this->rfs) { + $json = $this->rfs->getContents($this->path, $this->path, false); + } else { + $json = file_get_contents($this->path); + } + } catch (\Exception $e) { + throw new \RuntimeException('Could not read '.$this->path.', you are probably offline ('.$e->getMessage().')'); } return static::parseJson($json); diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 03a13b8e2..c05af141d 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -15,6 +15,8 @@ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; use Composer\Package\LinkConstraint\VersionConstraint; use Composer\Json\JsonFile; +use Composer\IO\IOInterface; +use Composer\Util\RemoteFilesystem; /** * @author Jordi Boggiano @@ -22,9 +24,10 @@ use Composer\Json\JsonFile; class ComposerRepository extends ArrayRepository { protected $url; + protected $io; protected $packages; - public function __construct(array $config) + public function __construct(array $config, IOInterface $io) { if (!preg_match('{^\w+://}', $config['url'])) { // assume http as the default protocol @@ -36,12 +39,13 @@ class ComposerRepository extends ArrayRepository } $this->url = $config['url']; + $this->io = $io; } protected function initialize() { parent::initialize(); - $json = new JsonFile($this->url.'/packages.json'); + $json = new JsonFile($this->url.'/packages.json', new RemoteFilesystem($this->io)); $packages = $json->read(); if (!$packages) { throw new \UnexpectedValueException('Could not parse package list from the '.$this->url.' repository'); diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index a1a2f4272..44a454128 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -13,7 +13,7 @@ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; -use Composer\Util\StreamContextFactory; +use Composer\Util\RemoteFilesystem; /** * @author Benjamin Eberlei @@ -23,9 +23,9 @@ class PearRepository extends ArrayRepository { private $url; private $channel; - private $streamContext; + private $rfs; - public function __construct(array $config) + public function __construct(array $config, IOInterface $io, RemoteFilesystem $rfs = null) { if (!preg_match('{^https?://}', $config['url'])) { $config['url'] = 'http://'.$config['url']; @@ -36,8 +36,8 @@ class PearRepository extends ArrayRepository } $this->url = rtrim($config['url'], '/'); - $this->channel = !empty($config['channel']) ? $config['channel'] : null; + $this->rfs = $rfs ?: new RemoteFilesystem($io); } protected function initialize() @@ -47,7 +47,6 @@ class PearRepository extends ArrayRepository set_error_handler(function($severity, $message, $file, $line) { throw new \ErrorException($message, $severity, $severity, $file, $line); }); - $this->streamContext = StreamContextFactory::getContext(); $this->fetchFromServer(); restore_error_handler(); } @@ -120,7 +119,7 @@ class PearRepository extends ArrayRepository ); try { - $deps = file_get_contents($releaseLink . "/deps.".$pearVersion.".txt", false, $this->streamContext); + $deps = $this->rfs->getContents($this->url, $releaseLink . "/deps.".$pearVersion.".txt", false); } catch (\ErrorException $e) { if (strpos($e->getMessage(), '404')) { continue; @@ -289,7 +288,7 @@ class PearRepository extends ArrayRepository */ private function requestXml($url) { - $content = file_get_contents($url, false, $this->streamContext); + $content = $this->rfs->getContents($this->url, $url, false); if (!$content) { throw new \UnexpectedValueException('The PEAR channel at '.$url.' did not respond.'); }