From 541285022d133330cdb200704c58f79bb32cff68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Pluchino?= Date: Tue, 17 Jan 2012 12:52:14 +0100 Subject: [PATCH] Replace CURL with copy() and file_get_contents() --- src/Composer/Downloader/FileDownloader.php | 148 +++++++++------------ src/Composer/Repository/Vcs/VcsDriver.php | 117 +++++++++------- 2 files changed, 129 insertions(+), 136 deletions(-) diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index df7556b2c..70d8243a0 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -77,19 +77,34 @@ abstract class FileDownloader implements DownloaderInterface } } - $auth = $this->io->getAuthentification($package->getSourceUrl()); + // Handle system proxy + $params = array('http' => array()); if (isset($_SERVER['HTTP_PROXY'])) { // http(s):// is not supported in proxy $proxy = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $_SERVER['HTTP_PROXY']); - + if (0 === strpos($proxy, 'ssl:') && !extension_loaded('openssl')) { throw new \RuntimeException('You must enable the openssl extension to use a proxy over https'); - } + } + + $params['http'] = array( + 'proxy' => $proxy, + 'request_fulluri' => true, + ); } + if ($this->io->hasAuthentification($package->getSourceUrl())) { + $auth = $this->io->getAuthentification($package->getSourceUrl()); + $authStr = base64_encode($auth['username'] . ':' . $auth['password']); + $params['http'] = array_merge($params['http'], array('header' => "Authorization: Basic $authStr\r\n")); + } + + $ctx = stream_context_create($params); + stream_context_set_params($ctx, array("notification" => array($this, 'callbackGet'))); + $this->io->overwrite(" Downloading: connection...", 80); - $this->copy($url, $fileName, $auth['username'], $auth['password']); + copy($url, $fileName, $ctx); $this->io->overwriteln(" Downloading", 80); if (!file_exists($fileName)) { @@ -120,7 +135,6 @@ abstract class FileDownloader implements DownloaderInterface rmdir($contentDir); } - $this->io->overwrite(''); $this->io->writeln(''); } @@ -144,92 +158,56 @@ abstract class FileDownloader implements DownloaderInterface } /** - * Download notification action. + * Get notification action. * - * @param integer $sizeTotal The total size - * @param integer $sizeLoaded The loaded size + * @param integer $notificationCode The notification code + * @param integer $severity The severity level + * @param string $message The message + * @param integer $messageCode The message code + * @param integer $bytesTransferred The loaded size + * @param integer $bytesMax The total size */ - protected function callbackDownload($sizeTotal, $sizeLoaded) + protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax) { - if ($sizeTotal > 1024) { - $progression = 0; - - if ($sizeTotal > 0) { - $progression = ($sizeLoaded / $sizeTotal * 100); - } - - $levels = array(0, 5, 10, 15, 20, 25, 30, 35, 40, 35, 50, 55, 60, - 65, 70, 75, 80, 85, 90, 95, 100); - - $progression = round($progression, 0); - - if (in_array($progression, $levels)) { - $this->io->overwrite(" Downloading: $progression%", 80); - } + switch ($notificationCode) { + case STREAM_NOTIFY_AUTH_REQUIRED: + throw new \LogicException("Authentification is required"); + break; + + case STREAM_NOTIFY_FAILURE: + throw new \LogicException("File not found"); + break; + + case STREAM_NOTIFY_FILE_SIZE_IS: + if ($this->bytesMax < $bytesMax) { + $this->bytesMax = $bytesMax; + } + break; + + case STREAM_NOTIFY_PROGRESS: + if ($this->bytesMax > 0) { + $progression = 0; + + if ($this->bytesMax > 0) { + $progression = ($bytesTransferred / $this->bytesMax * 100); + } + + $levels = array(0, 5, 10, 15, 20, 25, 30, 35, 40, 35, 50, + 55, 60, 65, 70, 75, 80, 85, 90, 95, 100); + + $progression = round($progression, 0); + + if (in_array($progression, $levels)) { + $this->io->overwrite(" Downloading: $progression%", 80); + } + } + break; + + default: + break; } } - /** - * Copy the content in file directory. - * - * @param string $url The file URL - * @param string $filename The local path - * @param string $username The username - * @param string $password The password - */ - protected function copy($url, $filename, $username = null, $password = null) - { - // create directory - if (!file_exists(dirname($filename))) { - mkdir(dirname($filename), 0777, true); - } - - $fh = fopen($filename, 'c+'); - - // curl options - $defaults = array( - CURLOPT_RETURNTRANSFER => true, - CURLOPT_BINARYTRANSFER => true, - CURLOPT_BUFFERSIZE => 128000, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_NOPROGRESS => false, - CURLOPT_PROGRESSFUNCTION => array($this, 'callbackDownload'), - CURLOPT_URL => $url, - CURLOPT_HTTPGET => true, - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_FILE => $fh, - ); - - // add authorization to curl options - if (null !== $username && null !== $password) { - $defaults[CURLOPT_USERPWD] = $username . ':' . $password; - } - - // init curl - $ch = curl_init(); - - // curl options - curl_setopt_array($ch, $defaults); - - // run curl - $curl_result = curl_exec($ch); - $curl_info = curl_getinfo($ch); - $curl_errorCode = curl_errno($ch); - $curl_error = curl_error($ch); - $code = $curl_info['http_code']; - $code = null ? 0 : $code; - - //close streams - curl_close($ch); - fclose($fh); - - if (200 !== $code) { - return false; - } - - return true; - } - /** * Extract file to directory * diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 27eafb3cd..857899cd5 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -24,6 +24,8 @@ abstract class VcsDriver protected $url; protected $io; private $firstCall; + private $contentUrl; + private $content; /** * Constructor. @@ -60,74 +62,87 @@ abstract class VcsDriver */ protected function getContents($url) { + $this->contentUrl = $url; $auth = $this->io->getAuthentification($this->url); - - // curl options - $defaults = array( - CURLOPT_RETURNTRANSFER => true, - CURLOPT_BINARYTRANSFER => true, - CURLOPT_BUFFERSIZE => 64000, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_NOPROGRESS => true, - CURLOPT_URL => $url, - CURLOPT_HTTPGET => true, - CURLOPT_SSL_VERIFYPEER => false - ); + $params = array(); // add authorization to curl options if ($this->io->hasAuthentification($this->url)) { - $defaults[CURLOPT_USERPWD] = $auth['username'] . ':' . $auth['password']; + $authStr = base64_encode($auth['username'] . ':' . $auth['password']); + $params['http'] = array('header' => "Authorization: Basic $authStr\r\n"); } else if (null !== $this->io->getLastUsername()) { - $defaults[CURLOPT_USERPWD] = $this->io->getLastUsername() . ':' . $this->io->getLastPassword(); + $authStr = base64_encode($this->io->getLastUsername() . ':' . $this->io->getLastPassword()); + $params['http'] = array('header' => "Authorization: Basic $authStr\r\n"); } - // init curl - $ch = curl_init(); - curl_setopt_array($ch, $defaults); + $ctx = stream_context_create($params); + stream_context_set_params($ctx, array("notification" => array($this, 'callbackGet'))); - // run curl - $curl_result = curl_exec($ch); - $curl_info = curl_getinfo($ch); - $curl_errorCode = curl_errno($ch); - $curl_error = curl_error($ch); - $code = $curl_info['http_code']; - $code = null ? 0 : $code; + $content = @file_get_contents($url, false, $ctx); - //close streams - curl_close($ch); - - // for private repository returning 404 error when the authentification is incorrect - $ps = $this->firstCall && 404 === $code && null === $this->io->getLastUsername() && null === $auth['username']; - - if ($this->firstCall) { - $this->firstCall = false; + // content get after authentification + if (false === $content) { + $content = $this->content; + $this->content = null; + $this->contentUrl = null; } - // auth required - if (401 === $code || $ps) { - if (!$this->io->isInteractive()) { - $mess = "The '$url' URL not found"; + return $content; + } - if (401 === $code || $ps) { - $mess = "The '$url' URL required the authentification.\nYou must be used the interactive console"; + /** + * Get notification action. + * + * @param integer $notificationCode The notification code + * @param integer $severity The severity level + * @param string $message The message + * @param integer $messageCode The message code + * @param integer $bytesTransferred The loaded size + * @param integer $bytesMax The total size + */ + protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax) + { + switch ($notificationCode) { + case STREAM_NOTIFY_AUTH_REQUIRED: + case STREAM_NOTIFY_FAILURE: + // for private repository returning 404 error when the authentification is incorrect + $auth = $this->io->getAuthentification($this->url); + $ps = $this->firstCall && 404 === $messageCode + && null === $this->io->getLastUsername() + && null === $auth['username']; + + if (404 === $messageCode && !$this->firstCall) { + throw new \LogicException("The '" . $this->contentUrl . "' URL not found"); + } + + if ($this->firstCall) { + $this->firstCall = false; } - throw new \LogicException($mess); - } + // get authentification informations + if (401 === $messageCode || $ps) { + if (!$this->io->isInteractive()) { + $mess = "The '" . $this->contentUrl . "' URL not found"; + + if (401 === $code || $ps) { + $mess = "The '" . $this->contentUrl . "' URL required the authentification.\nYou must be used the interactive console"; + } + + throw new \LogicException($mess); + } - $this->io->writeln("Authorization required for " . $this->owner.'/' . $this->repository . ":"); - $username = $this->io->ask(' Username: '); - $password = $this->io->askAndHideAnswer(' Password: '); - $this->io->setAuthentification($this->url, $username, $password); + $this->io->writeln("Authorization for " . $this->contentUrl . ":"); + $username = $this->io->ask(' Username: '); + $password = $this->io->askAndHideAnswer(' Password: '); + $this->io->setAuthentification($this->url, $username, $password); - return $this->getContents($url); + $this->content = $this->getContents($this->contentUrl); + } + break; + + default: + break; } - - if (404 === $code) { - throw new \LogicException("The '$url' URL not found"); - } - - return $curl_result; } }