Пример #1
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->rfs = new RemoteFilesystem($this->getIO());
     $output->write('Checking platform settings: ');
     $this->outputResult($output, $this->checkPlatform());
     $output->write('Checking http connectivity: ');
     $this->outputResult($output, $this->checkHttp());
     $opts = stream_context_get_options(StreamContextFactory::getContext());
     if (!empty($opts['http']['proxy'])) {
         $output->write('Checking HTTP proxy: ');
         $this->outputResult($output, $this->checkHttpProxy());
         $output->write('Checking HTTPS proxy support for request_fulluri: ');
         $this->outputResult($output, $this->checkHttpsProxyFullUriRequestParam());
     }
     $composer = $this->getComposer(false);
     if ($composer) {
         $output->write('Checking composer.json: ');
         $this->outputResult($output, $this->checkComposerSchema());
     }
     if ($composer) {
         $config = $composer->getConfig();
     } else {
         $config = Factory::createConfig();
     }
     if ($oauth = $config->get('github-oauth')) {
         foreach ($oauth as $domain => $token) {
             $output->write('Checking ' . $domain . ' oauth access: ');
             $this->outputResult($output, $this->checkGithubOauth($domain, $token));
         }
     }
     $output->write('Checking composer version: ');
     $this->outputResult($output, $this->checkVersion());
     return $this->failures;
 }
Пример #2
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $composer = $this->getComposer(false);
     if ($composer) {
         $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
         $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
         $this->getIO()->write('Checking composer.json: ', false);
         $this->outputResult($this->checkComposerSchema());
     }
     if ($composer) {
         $config = $composer->getConfig();
     } else {
         $config = Factory::createConfig();
     }
     $this->rfs = new RemoteFilesystem($this->getIO(), $config);
     $this->process = new ProcessExecutor($this->getIO());
     $this->getIO()->write('Checking platform settings: ', false);
     $this->outputResult($this->checkPlatform());
     $this->getIO()->write('Checking git settings: ', false);
     $this->outputResult($this->checkGit());
     $this->getIO()->write('Checking http connectivity: ', false);
     $this->outputResult($this->checkHttp());
     $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
     if (!empty($opts['http']['proxy'])) {
         $this->getIO()->write('Checking HTTP proxy: ', false);
         $this->outputResult($this->checkHttpProxy());
         $this->getIO()->write('Checking HTTP proxy support for request_fulluri: ', false);
         $this->outputResult($this->checkHttpProxyFullUriRequestParam());
         $this->getIO()->write('Checking HTTPS proxy support for request_fulluri: ', false);
         $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
     }
     if ($oauth = $config->get('github-oauth')) {
         foreach ($oauth as $domain => $token) {
             $this->getIO()->write('Checking ' . $domain . ' oauth access: ', false);
             $this->outputResult($this->checkGithubOauth($domain, $token));
         }
     } else {
         $this->getIO()->write('Checking github.com rate limit: ', false);
         try {
             $rate = $this->getGithubRateLimit('github.com');
             $this->outputResult(true);
             if (10 > $rate['remaining']) {
                 $this->getIO()->write('<warning>WARNING</warning>');
                 $this->getIO()->write(sprintf('<comment>Github has a rate limit on their API. ' . 'You currently have <options=bold>%u</options=bold> ' . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>', $rate['remaining'], $rate['limit']));
             }
         } catch (\Exception $e) {
             if ($e instanceof TransportException && $e->getCode() === 401) {
                 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
             } else {
                 $this->outputResult($e);
             }
         }
     }
     $this->getIO()->write('Checking disk free space: ', false);
     $this->outputResult($this->checkDiskSpace($config));
     $this->getIO()->write('Checking composer version: ', false);
     $this->outputResult($this->checkVersion());
     return $this->failures;
 }
Пример #3
0
 /**
  * Reads json file.
  *
  * @param   string  $json   path or json string
  *
  * @return  array
  */
 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');
     }
     return static::parseJson($json);
 }
Пример #4
0
 protected function initialize()
 {
     parent::initialize();
     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();
 }
Пример #5
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $ctx = StreamContextFactory::getContext();
     $latest = trim(file_get_contents('http://getcomposer.org/version', false, $ctx));
     if (Composer::VERSION !== $latest) {
         $output->writeln(sprintf("Updating to version <info>%s</info>.", $latest));
         $remoteFilename = 'http://getcomposer.org/composer.phar';
         $localFilename = $_SERVER['argv'][0];
         copy($remoteFilename, $localFilename, $ctx);
     } else {
         $output->writeln("<info>You are using the latest composer version.</info>");
     }
 }
Пример #6
0
 public function testSSLProxy()
 {
     $_SERVER['http_proxy'] = 'https://proxyserver/';
     if (extension_loaded('openssl')) {
         $context = StreamContextFactory::getContext();
         $options = stream_context_get_options($context);
         $this->assertSame(array('http' => array('proxy' => 'ssl://proxyserver/', 'request_fulluri' => true)), $options);
     } else {
         try {
             StreamContextFactory::getContext();
             $this->fail();
         } catch (\Exception $e) {
             $this->assertInstanceOf('RuntimeException', $e);
         }
     }
 }
Пример #7
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $composer = $this->getComposer(false);
     if ($composer) {
         $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
         $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
         $output->write('Checking composer.json: ');
         $this->outputResult($output, $this->checkComposerSchema());
     }
     if ($composer) {
         $config = $composer->getConfig();
     } else {
         $config = Factory::createConfig();
     }
     $this->rfs = new RemoteFilesystem($this->getIO(), $config);
     $this->process = new ProcessExecutor($this->getIO());
     $output->write('Checking platform settings: ');
     $this->outputResult($output, $this->checkPlatform());
     $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());
     }
     if ($oauth = $config->get('github-oauth')) {
         foreach ($oauth as $domain => $token) {
             $output->write('Checking ' . $domain . ' oauth access: ');
             $this->outputResult($output, $this->checkGithubOauth($domain, $token));
         }
     }
     $output->write('Checking disk free space: ');
     $this->outputResult($output, $this->checkDiskSpace($config));
     $output->write('Checking composer version: ');
     $this->outputResult($output, $this->checkVersion());
     return $this->failures;
 }
Пример #8
0
 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
 {
     if (strpos($originUrl, '.github.com') === strlen($originUrl) - 11) {
         $originUrl = 'github.com';
     }
     $this->bytesMax = 0;
     $this->originUrl = $originUrl;
     $this->fileUrl = $fileUrl;
     $this->fileName = $fileName;
     $this->progress = $progress;
     $this->lastProgress = null;
     $this->retryAuthFailure = true;
     $this->lastHeaders = array();
     if (preg_match('{^https?://(.+):(.+)@([^/]+)}i', $fileUrl, $match)) {
         $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2]));
     }
     if (isset($additionalOptions['retry-auth-failure'])) {
         $this->retryAuthFailure = (bool) $additionalOptions['retry-auth-failure'];
         unset($additionalOptions['retry-auth-failure']);
     }
     $options = $this->getOptionsForUrl($originUrl, $additionalOptions);
     if ($this->io->isDebug()) {
         $this->io->writeError((substr($fileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $fileUrl);
     }
     if (isset($options['github-token'])) {
         $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token=' . $options['github-token'];
         unset($options['github-token']);
     }
     if (isset($options['http'])) {
         $options['http']['ignore_errors'] = true;
     }
     $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
     if ($this->progress) {
         $this->io->writeError("    Downloading: <comment>Connecting...</comment>", false);
     }
     $errorMessage = '';
     $errorCode = 0;
     $result = false;
     set_error_handler(function ($code, $msg) use(&$errorMessage) {
         if ($errorMessage) {
             $errorMessage .= "\n";
         }
         $errorMessage .= preg_replace('{^file_get_contents\\(.*?\\): }', '', $msg);
     });
     try {
         $result = file_get_contents($fileUrl, false, $ctx);
     } catch (\Exception $e) {
         if ($e instanceof TransportException && !empty($http_response_header[0])) {
             $e->setHeaders($http_response_header);
         }
         if ($e instanceof TransportException && $result !== false) {
             $e->setResponse($result);
         }
         $result = false;
     }
     if ($errorMessage && !ini_get('allow_url_fopen')) {
         $errorMessage = 'allow_url_fopen must be enabled in php.ini (' . $errorMessage . ')';
     }
     restore_error_handler();
     if (isset($e) && !$this->retry) {
         throw $e;
     }
     if (!empty($http_response_header[0]) && preg_match('{^HTTP/\\S+ ([45]\\d\\d)}i', $http_response_header[0], $match)) {
         $errorCode = $match[1];
         if (!$this->retry) {
             $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded (' . $http_response_header[0] . ')', $errorCode);
             $e->setHeaders($http_response_header);
             $e->setResponse($result);
             throw $e;
         }
         $result = false;
     }
     if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http') {
         $decode = false;
         foreach ($http_response_header as $header) {
             if (preg_match('{^content-encoding: *gzip *$}i', $header)) {
                 $decode = true;
                 continue;
             } elseif (preg_match('{^HTTP/}i', $header)) {
                 $decode = false;
             }
         }
         if ($decode) {
             if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
                 $result = zlib_decode($result);
             } else {
                 $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,' . base64_encode($result));
             }
             if (!$result) {
                 throw new TransportException('Failed to decode zlib stream');
             }
         }
     }
     if ($this->progress && !$this->retry) {
         $this->io->overwriteError("    Downloading: <comment>100%</comment>");
     }
     if (false !== $result && null !== $fileName) {
         if ('' === $result) {
             throw new TransportException('"' . $this->fileUrl . '" appears broken, and returned an empty 200 response');
         }
         $errorMessage = '';
         set_error_handler(function ($code, $msg) use(&$errorMessage) {
             if ($errorMessage) {
                 $errorMessage .= "\n";
             }
             $errorMessage .= preg_replace('{^file_put_contents\\(.*?\\): }', '', $msg);
         });
         $result = (bool) file_put_contents($fileName, $result);
         restore_error_handler();
         if (false === $result) {
             throw new TransportException('The "' . $this->fileUrl . '" file could not be written to ' . $fileName . ': ' . $errorMessage);
         }
     }
     if ($this->retry) {
         $this->retry = false;
         $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
         $authHelper = new AuthHelper($this->io, $this->config);
         $authHelper->storeAuth($this->originUrl, $this->storeAuth);
         $this->storeAuth = false;
         return $result;
     }
     if (false === $result) {
         $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded: ' . $errorMessage, $errorCode);
         if (!empty($http_response_header[0])) {
             $e->setHeaders($http_response_header);
         }
         throw $e;
     }
     if (!empty($http_response_header[0])) {
         $this->lastHeaders = $http_response_header;
     }
     return $result;
 }
Пример #9
0
 public function notifyInstalls()
 {
     foreach ($this->notifiablePackages as $repoUrl => $packages) {
         // non-batch API, deprecated
         if (strpos($repoUrl, '%package%')) {
             foreach ($packages as $package) {
                 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
                 $params = array('version' => $package->getPrettyVersion(), 'version_normalized' => $package->getVersion());
                 $opts = array('http' => array('method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => http_build_query($params, '', '&'), 'timeout' => 3));
                 $context = StreamContextFactory::getContext($opts);
                 @file_get_contents($url, false, $context);
             }
             continue;
         }
         $postData = array('downloads' => array());
         foreach ($packages as $package) {
             $postData['downloads'][] = array('name' => $package->getPrettyName(), 'version' => $package->getVersion());
         }
         $opts = array('http' => array('method' => 'POST', 'header' => 'Content-Type: application/json', 'content' => json_encode($postData), 'timeout' => 6));
         $context = StreamContextFactory::getContext($opts);
         @file_get_contents($repoUrl, false, $context);
     }
     $this->reset();
 }
Пример #10
0
 /**
  * Get file content or copy action.
  *
  * @param string  $originUrl         The origin URL
  * @param string  $fileUrl           The file URL
  * @param array   $additionalOptions context options
  * @param string  $fileName          the local filename
  * @param boolean $progress          Display the progression
  *
  * @throws TransportException|\Exception
  * @throws TransportException            When the file could not be downloaded
  *
  * @return bool|string
  */
 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
 {
     $this->bytesMax = 0;
     $this->originUrl = $originUrl;
     $this->fileUrl = $fileUrl;
     $this->fileName = $fileName;
     $this->progress = $progress;
     $this->lastProgress = null;
     // capture username/password from URL if there is one
     if (preg_match('{^https?://(.+):(.+)@([^/]+)}i', $fileUrl, $match)) {
         $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2]));
     }
     $options = $this->getOptionsForUrl($originUrl, $additionalOptions);
     if ($this->io->isDebug()) {
         $this->io->write((substr($fileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $fileUrl);
     }
     if (isset($options['github-token'])) {
         $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token=' . $options['github-token'];
         unset($options['github-token']);
     }
     $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
     if ($this->progress) {
         $this->io->write("    Downloading: <comment>connection...</comment>", false);
     }
     $errorMessage = '';
     $errorCode = 0;
     $result = false;
     set_error_handler(function ($code, $msg) use(&$errorMessage) {
         if ($errorMessage) {
             $errorMessage .= "\n";
         }
         $errorMessage .= preg_replace('{^file_get_contents\\(.*?\\): }', '', $msg);
     });
     try {
         $result = file_get_contents($fileUrl, false, $ctx);
     } catch (\Exception $e) {
         if ($e instanceof TransportException && !empty($http_response_header[0])) {
             $e->setHeaders($http_response_header);
         }
     }
     if ($errorMessage && !ini_get('allow_url_fopen')) {
         $errorMessage = 'allow_url_fopen must be enabled in php.ini (' . $errorMessage . ')';
     }
     restore_error_handler();
     if (isset($e) && !$this->retry) {
         throw $e;
     }
     // fix for 5.4.0 https://bugs.php.net/bug.php?id=61336
     if (!empty($http_response_header[0]) && preg_match('{^HTTP/\\S+ ([45]\\d\\d)}i', $http_response_header[0], $match)) {
         $result = false;
         $errorCode = $match[1];
     }
     // decode gzip
     if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http') {
         $decode = false;
         foreach ($http_response_header as $header) {
             if (preg_match('{^content-encoding: *gzip *$}i', $header)) {
                 $decode = true;
                 continue;
             } elseif (preg_match('{^HTTP/}i', $header)) {
                 $decode = false;
             }
         }
         if ($decode) {
             if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
                 $result = zlib_decode($result);
             } else {
                 // work around issue with gzuncompress & co that do not work with all gzip checksums
                 $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,' . base64_encode($result));
             }
         }
     }
     if ($this->progress) {
         $this->io->overwrite("    Downloading: <comment>100%</comment>");
     }
     // handle copy command if download was successful
     if (false !== $result && null !== $fileName) {
         if ('' === $result) {
             throw new TransportException('"' . $this->fileUrl . '" appears broken, and returned an empty 200 response');
         }
         $errorMessage = '';
         set_error_handler(function ($code, $msg) use(&$errorMessage) {
             if ($errorMessage) {
                 $errorMessage .= "\n";
             }
             $errorMessage .= preg_replace('{^file_put_contents\\(.*?\\): }', '', $msg);
         });
         $result = (bool) file_put_contents($fileName, $result);
         restore_error_handler();
         if (false === $result) {
             throw new TransportException('The "' . $this->fileUrl . '" file could not be written to ' . $fileName . ': ' . $errorMessage);
         }
     }
     if ($this->retry) {
         $this->retry = false;
         return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
     }
     if (false === $result) {
         $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded: ' . $errorMessage, $errorCode);
         if (!empty($http_response_header[0])) {
             $e->setHeaders($http_response_header);
         }
         throw $e;
     }
     return $result;
 }
 /**
  * @author Markus Tacker <*****@*****.**>
  */
 public function testEnsureThatfixHttpHeaderFieldMovesContentTypeToEndOfOptions()
 {
     $options = array('http' => array('header' => "X-Foo: bar\r\nContent-Type: application/json\r\nAuthorization: Basic aW52YWxpZA=="));
     $expectedOptions = array('http' => array('header' => array("X-Foo: bar", "Authorization: Basic aW52YWxpZA==", "Content-Type: application/json")));
     $context = StreamContextFactory::getContext($options);
     $ctxoptions = stream_context_get_options($context);
     $this->assertEquals(join("\n", $ctxoptions['http']['header']), join("\n", $expectedOptions['http']['header']));
 }
Пример #12
0
    /**
     * @dataProvider dataSSLProxy
     */
    public function testSSLProxy($expected, $proxy)
    {
        $_SERVER['http_proxy'] = $proxy;

        if (extension_loaded('openssl')) {
            $context = StreamContextFactory::getContext();
            $options = stream_context_get_options($context);

            $this->assertEquals(array('http' => array(
                'proxy' => $expected,
                'request_fulluri' => true,
            )), $options);
        } else {
            try {
                StreamContextFactory::getContext();
                $this->fail();
            } catch (\Exception $e) {
                $this->assertInstanceOf('RuntimeException', $e);
            }
        }
    }
Пример #13
0
 /**
  * Get file content or copy action.
  *
  * @param string  $originUrl The orgin URL
  * @param string  $fileUrl   The file URL
  * @param string  $fileName  the local filename
  * @param boolean $progress  Display the progression
  * @param boolean $firstCall Whether this is the first attempt at fetching this resource
  *
  * @throws \RuntimeException When the file could not be downloaded
  */
 protected function get($originUrl, $fileUrl, $fileName = null, $progress = true, $firstCall = true)
 {
     $this->firstCall = $firstCall;
     $this->bytesMax = 0;
     $this->result = null;
     $this->originUrl = $originUrl;
     $this->fileUrl = $fileUrl;
     $this->fileName = $fileName;
     $this->progress = $progress;
     $this->lastProgress = null;
     $options = $this->getOptionsForUrl($originUrl);
     $ctx = StreamContextFactory::getContext($options, array('notification' => array($this, 'callbackGet')));
     if ($this->progress) {
         $this->io->overwrite("    Downloading: <comment>connection...</comment>", false);
     }
     if (null !== $fileName) {
         $result = @copy($fileUrl, $fileName, $ctx);
     } else {
         $result = @file_get_contents($fileUrl, false, $ctx);
     }
     // avoid overriding if content was loaded by a sub-call to get()
     if (null === $this->result) {
         $this->result = $result;
     }
     if ($this->progress) {
         $this->io->overwrite("    Downloading", false);
     }
     if (false === $this->result) {
         throw new \RuntimeException("The '{$fileUrl}' file could not be downloaded");
     }
 }
Пример #14
0
 /**
  * Get file content or copy action.
  *
  * @param string  $originUrl The origin URL
  * @param string  $fileUrl   The file URL
  * @param string  $fileName  the local filename
  * @param boolean $progress  Display the progression
  *
  * @throws TransportException When the file could not be downloaded
  */
 protected function get($originUrl, $fileUrl, $fileName = null, $progress = true)
 {
     $this->bytesMax = 0;
     $this->result = null;
     $this->originUrl = $originUrl;
     $this->fileUrl = $fileUrl;
     $this->fileName = $fileName;
     $this->progress = $progress;
     $this->lastProgress = null;
     $options = $this->getOptionsForUrl($originUrl);
     $ctx = StreamContextFactory::getContext($options, array('notification' => array($this, 'callbackGet')));
     if ($this->progress) {
         $this->io->write("    Downloading: <comment>connection...</comment>", false);
     }
     $result = @file_get_contents($fileUrl, false, $ctx);
     // fix for 5.4.0 https://bugs.php.net/bug.php?id=61336
     if (!empty($http_response_header[0]) && preg_match('{^HTTP/\\S+ 404}i', $http_response_header[0])) {
         $result = false;
     }
     // decode gzip
     if (false !== $result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http') {
         $decode = false;
         foreach ($http_response_header as $header) {
             if (preg_match('{^content-encoding: *gzip *$}i', $header)) {
                 $decode = true;
                 continue;
             } elseif (preg_match('{^HTTP/}i', $header)) {
                 $decode = false;
             }
         }
         if ($decode) {
             if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
                 $result = zlib_decode($result);
             } else {
                 // work around issue with gzuncompress & co that do not work with all gzip checksums
                 $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,' . base64_encode($result));
             }
         }
     }
     if ($this->progress) {
         $this->io->overwrite("    Downloading: <comment>100%</comment>");
     }
     // handle copy command if download was successful
     if (false !== $result && null !== $fileName) {
         $result = (bool) @file_put_contents($fileName, $result);
         if (false === $result) {
             throw new TransportException('The "' . $fileUrl . '" file could not be written to ' . $fileName);
         }
     }
     // avoid overriding if content was loaded by a sub-call to get()
     if (null === $this->result) {
         $this->result = $result;
     }
     if (false === $this->result) {
         throw new TransportException('The "' . $fileUrl . '" file could not be downloaded');
     }
 }
Пример #15
0
 /**
  * Get file content or copy action.
  *
  * @param string  $originUrl         The origin URL
  * @param string  $fileUrl           The file URL
  * @param array   $additionalOptions context options
  * @param string  $fileName          the local filename
  * @param boolean $progress          Display the progression
  *
  * @throws TransportException|\Exception
  * @throws TransportException            When the file could not be downloaded
  *
  * @return bool|string
  */
 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
 {
     if (strpos($originUrl, '.github.com') === strlen($originUrl) - 11) {
         $originUrl = 'github.com';
     }
     $this->bytesMax = 0;
     $this->originUrl = $originUrl;
     $this->fileUrl = $fileUrl;
     $this->fileName = $fileName;
     $this->progress = $progress;
     $this->lastProgress = null;
     $this->retryAuthFailure = true;
     $this->lastHeaders = array();
     // capture username/password from URL if there is one
     if (preg_match('{^https?://(.+):(.+)@([^/]+)}i', $fileUrl, $match)) {
         $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2]));
     }
     if (isset($additionalOptions['retry-auth-failure'])) {
         $this->retryAuthFailure = (bool) $additionalOptions['retry-auth-failure'];
         unset($additionalOptions['retry-auth-failure']);
     }
     $options = $this->getOptionsForUrl($originUrl, $additionalOptions);
     if ($this->io->isDebug()) {
         $this->io->writeError((substr($fileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $fileUrl);
     }
     if (isset($options['github-token'])) {
         $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token=' . $options['github-token'];
         unset($options['github-token']);
     }
     if (isset($options['http'])) {
         $options['http']['ignore_errors'] = true;
     }
     if ($this->degradedMode && substr($fileUrl, 0, 21) === 'http://packagist.org/') {
         // access packagist using the resolved IPv4 instead of the hostname to force IPv4 protocol
         $fileUrl = 'http://' . gethostbyname('packagist.org') . substr($fileUrl, 20);
     }
     $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
     if ($this->progress) {
         $this->io->writeError("    Downloading: <comment>Connecting...</comment>", false);
     }
     $errorMessage = '';
     $errorCode = 0;
     $result = false;
     set_error_handler(function ($code, $msg) use(&$errorMessage) {
         if ($errorMessage) {
             $errorMessage .= "\n";
         }
         $errorMessage .= preg_replace('{^file_get_contents\\(.*?\\): }', '', $msg);
     });
     try {
         $result = file_get_contents($fileUrl, false, $ctx);
     } catch (\Exception $e) {
         if ($e instanceof TransportException && !empty($http_response_header[0])) {
             $e->setHeaders($http_response_header);
         }
         if ($e instanceof TransportException && $result !== false) {
             $e->setResponse($result);
         }
         $result = false;
     }
     if ($errorMessage && !ini_get('allow_url_fopen')) {
         $errorMessage = 'allow_url_fopen must be enabled in php.ini (' . $errorMessage . ')';
     }
     restore_error_handler();
     if (isset($e) && !$this->retry) {
         if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
             $this->degradedMode = true;
             $this->io->writeError(array('<error>' . $e->getMessage() . '</error>', '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>'));
             return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
         }
         throw $e;
     }
     // fail 4xx and 5xx responses and capture the response
     if (!empty($http_response_header[0]) && preg_match('{^HTTP/\\S+ ([45]\\d\\d)}i', $http_response_header[0], $match)) {
         $errorCode = $match[1];
         if (!$this->retry) {
             $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded (' . $http_response_header[0] . ')', $errorCode);
             $e->setHeaders($http_response_header);
             $e->setResponse($result);
             throw $e;
         }
         $result = false;
     }
     if ($this->progress && !$this->retry) {
         $this->io->overwriteError("    Downloading: <comment>100%</comment>");
     }
     // decode gzip
     if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http') {
         $decode = false;
         foreach ($http_response_header as $header) {
             if (preg_match('{^content-encoding: *gzip *$}i', $header)) {
                 $decode = true;
             } elseif (preg_match('{^HTTP/}i', $header)) {
                 // In case of redirects, http_response_headers contains the headers of all responses
                 // so we reset the flag when a new response is being parsed as we are only interested in the last response
                 $decode = false;
             }
         }
         if ($decode) {
             try {
                 if (PHP_VERSION_ID >= 50400) {
                     $result = zlib_decode($result);
                 } else {
                     // work around issue with gzuncompress & co that do not work with all gzip checksums
                     $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,' . base64_encode($result));
                 }
                 if (!$result) {
                     throw new TransportException('Failed to decode zlib stream');
                 }
             } catch (\Exception $e) {
                 if ($this->degradedMode) {
                     throw $e;
                 }
                 $this->degradedMode = true;
                 $this->io->writeError(array('<error>Failed to decode response: ' . $e->getMessage() . '</error>', '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>'));
                 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
             }
         }
     }
     // handle copy command if download was successful
     if (false !== $result && null !== $fileName) {
         if ('' === $result) {
             throw new TransportException('"' . $this->fileUrl . '" appears broken, and returned an empty 200 response');
         }
         $errorMessage = '';
         set_error_handler(function ($code, $msg) use(&$errorMessage) {
             if ($errorMessage) {
                 $errorMessage .= "\n";
             }
             $errorMessage .= preg_replace('{^file_put_contents\\(.*?\\): }', '', $msg);
         });
         $result = (bool) file_put_contents($fileName, $result);
         restore_error_handler();
         if (false === $result) {
             throw new TransportException('The "' . $this->fileUrl . '" file could not be written to ' . $fileName . ': ' . $errorMessage);
         }
     }
     if ($this->retry) {
         $this->retry = false;
         $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
         $authHelper = new AuthHelper($this->io, $this->config);
         $authHelper->storeAuth($this->originUrl, $this->storeAuth);
         $this->storeAuth = false;
         return $result;
     }
     if (false === $result) {
         $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded: ' . $errorMessage, $errorCode);
         if (!empty($http_response_header[0])) {
             $e->setHeaders($http_response_header);
         }
         if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
             $this->degradedMode = true;
             $this->io->writeError(array('<error>' . $e->getMessage() . '</error>', '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>'));
             return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
         }
         throw $e;
     }
     if (!empty($http_response_header[0])) {
         $this->lastHeaders = $http_response_header;
     }
     return $result;
 }
Пример #16
0
 public function notifyInstalls(IOInterface $io)
 {
     foreach ($this->notifiablePackages as $repoUrl => $packages) {
         $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
         if ($io->hasAuthentication($repositoryName)) {
             $auth = $io->getAuthentication($repositoryName);
             $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
             $authHeader = 'Authorization: Basic ' . $authStr;
         }
         // non-batch API, deprecated
         if (strpos($repoUrl, '%package%')) {
             foreach ($packages as $package) {
                 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
                 $params = array('version' => $package->getPrettyVersion(), 'version_normalized' => $package->getVersion());
                 $opts = array('http' => array('method' => 'POST', 'header' => array('Content-type: application/x-www-form-urlencoded'), 'content' => http_build_query($params, '', '&'), 'timeout' => 3));
                 if (isset($authHeader)) {
                     $opts['http']['header'][] = $authHeader;
                 }
                 $context = StreamContextFactory::getContext($url, $opts);
                 @file_get_contents($url, false, $context);
             }
             continue;
         }
         $postData = array('downloads' => array());
         foreach ($packages as $package) {
             $postData['downloads'][] = array('name' => $package->getPrettyName(), 'version' => $package->getVersion());
         }
         $opts = array('http' => array('method' => 'POST', 'header' => array('Content-Type: application/json'), 'content' => json_encode($postData), 'timeout' => 6));
         if (isset($authHeader)) {
             $opts['http']['header'][] = $authHeader;
         }
         $context = StreamContextFactory::getContext($repoUrl, $opts);
         @file_get_contents($repoUrl, false, $context);
     }
     $this->reset();
 }
Пример #17
0
 /**
  * Fetch certificate common name and fingerprint for validation of SAN.
  *
  * @todo Remove when PHP 5.6 is minimum supported version.
  */
 private function getCertificateCnAndFp($url, $options)
 {
     if (PHP_VERSION_ID >= 50600) {
         throw new \BadMethodCallException(sprintf('%s must not be used on PHP >= 5.6', __METHOD__));
     }
     $context = StreamContextFactory::getContext($url, $options, array('options' => array('ssl' => array('capture_peer_cert' => true, 'verify_peer' => false))));
     // Ideally this would just use stream_socket_client() to avoid sending a
     // HTTP request but that does not capture the certificate.
     if (false === ($handle = @fopen($url, 'rb', false, $context))) {
         return;
     }
     // Close non authenticated connection without reading any content.
     fclose($handle);
     $handle = null;
     $params = stream_context_get_params($context);
     if (!empty($params['options']['ssl']['peer_certificate'])) {
         $peerCertificate = $params['options']['ssl']['peer_certificate'];
         if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
             return array('cn' => $commonName, 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate));
         }
     }
 }
Пример #18
0
 /**
  * Get file content or copy action.
  *
  * @param string  $originUrl The orgin URL
  * @param string  $fileUrl   The file URL
  * @param string  $fileName  the local filename
  * @param boolean $progress  Display the progression
  * @param boolean $firstCall Whether this is the first attempt at fetching this resource
  *
  * @throws TransportException When the file could not be downloaded
  */
 protected function get($originUrl, $fileUrl, $fileName = null, $progress = true, $firstCall = true)
 {
     $this->firstCall = $firstCall;
     $this->bytesMax = 0;
     $this->result = null;
     $this->originUrl = $originUrl;
     $this->fileUrl = $fileUrl;
     $this->fileName = $fileName;
     $this->progress = $progress;
     $this->lastProgress = null;
     $options = $this->getOptionsForUrl($originUrl);
     $ctx = StreamContextFactory::getContext($options, array('notification' => array($this, 'callbackGet')));
     if ($this->progress) {
         $this->io->write("    Downloading: <comment>connection...</comment>", false);
     }
     if (null !== $fileName) {
         $result = @copy($fileUrl, $fileName, $ctx);
     } else {
         $result = @file_get_contents($fileUrl, false, $ctx);
     }
     // fix for 5.4.0 https://bugs.php.net/bug.php?id=61336
     if (!empty($http_response_header[0]) && preg_match('{^HTTP/\\S+ 404}i', $http_response_header[0])) {
         $result = false;
     }
     // avoid overriding if content was loaded by a sub-call to get()
     if (null === $this->result) {
         $this->result = $result;
     }
     if ($this->progress) {
         $this->io->overwrite("    Downloading", false);
     }
     if (false === $this->result) {
         throw new TransportException("The '{$fileUrl}' file could not be downloaded");
     }
 }