diff options
Diffstat (limited to 'vendor/miniflux/picofeed/lib/PicoFeed/Client/Curl.php')
-rw-r--r-- | vendor/miniflux/picofeed/lib/PicoFeed/Client/Curl.php | 402 |
1 files changed, 0 insertions, 402 deletions
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Client/Curl.php b/vendor/miniflux/picofeed/lib/PicoFeed/Client/Curl.php deleted file mode 100644 index f4a65782..00000000 --- a/vendor/miniflux/picofeed/lib/PicoFeed/Client/Curl.php +++ /dev/null @@ -1,402 +0,0 @@ -<?php - -namespace PicoFeed\Client; - -use PicoFeed\Logging\Logger; - -/** - * cURL HTTP client. - * - * @author Frederic Guillot - */ -class Curl extends Client -{ - protected $nbRedirects = 0; - - /** - * HTTP response body. - * - * @var string - */ - private $body = ''; - - /** - * Body size. - * - * @var int - */ - private $body_length = 0; - - /** - * HTTP response headers. - * - * @var array - */ - private $response_headers = array(); - - /** - * Counter on the number of header received. - * - * @var int - */ - private $response_headers_count = 0; - - /** - * cURL callback to read the HTTP body. - * - * If the function return -1, curl stop to read the HTTP response - * - * @param resource $ch cURL handler - * @param string $buffer Chunk of data - * - * @return int Length of the buffer - */ - public function readBody($ch, $buffer) - { - $length = strlen($buffer); - $this->body_length += $length; - - if ($this->body_length > $this->max_body_size) { - return -1; - } - - $this->body .= $buffer; - - return $length; - } - - /** - * cURL callback to read HTTP headers. - * - * @param resource $ch cURL handler - * @param string $buffer Header line - * - * @return int Length of the buffer - */ - public function readHeaders($ch, $buffer) - { - $length = strlen($buffer); - - if ($buffer === "\r\n" || $buffer === "\n") { - ++$this->response_headers_count; - } else { - if (!isset($this->response_headers[$this->response_headers_count])) { - $this->response_headers[$this->response_headers_count] = ''; - } - - $this->response_headers[$this->response_headers_count] .= $buffer; - } - - return $length; - } - - /** - * cURL callback to passthrough the HTTP body to the client. - * - * If the function return -1, curl stop to read the HTTP response - * - * @param resource $ch cURL handler - * @param string $buffer Chunk of data - * - * @return int Length of the buffer - */ - public function passthroughBody($ch, $buffer) - { - // do it only at the beginning of a transmission - if ($this->body_length === 0) { - list($status, $headers) = HttpHeaders::parse(explode("\n", $this->response_headers[$this->response_headers_count - 1])); - - if ($this->isRedirection($status)) { - return $this->handleRedirection($headers['Location']); - } - - // Do not work with PHP-FPM - if (strpos(PHP_SAPI, 'cgi') !== false) { - header(':', true, $status); - } - - if (isset($headers['Content-Type'])) { - header('Content-Type:' .$headers['Content-Type']); - } - } - - $length = strlen($buffer); - $this->body_length += $length; - - echo $buffer; - - return $length; - } - - /** - * Prepare HTTP headers. - * - * @return string[] - */ - private function prepareHeaders() - { - $headers = array( - 'Connection: close', - ); - - if ($this->etag) { - $headers[] = 'If-None-Match: '.$this->etag; - $headers[] = 'A-IM: feed'; - } - - if ($this->last_modified) { - $headers[] = 'If-Modified-Since: '.$this->last_modified; - } - - $headers = array_merge($headers, $this->request_headers); - - return $headers; - } - - /** - * Prepare curl proxy context. - * - * @param resource $ch - * - * @return resource $ch - */ - private function prepareProxyContext($ch) - { - if ($this->proxy_hostname) { - Logger::setMessage(get_called_class().' Proxy: '.$this->proxy_hostname.':'.$this->proxy_port); - - curl_setopt($ch, CURLOPT_PROXYPORT, $this->proxy_port); - curl_setopt($ch, CURLOPT_PROXYTYPE, 'HTTP'); - curl_setopt($ch, CURLOPT_PROXY, $this->proxy_hostname); - - if ($this->proxy_username) { - Logger::setMessage(get_called_class().' Proxy credentials: Yes'); - curl_setopt($ch, CURLOPT_PROXYUSERPWD, $this->proxy_username.':'.$this->proxy_password); - } else { - Logger::setMessage(get_called_class().' Proxy credentials: No'); - } - } - - return $ch; - } - - /** - * Prepare curl auth context. - * - * @param resource $ch - * - * @return resource $ch - */ - private function prepareAuthContext($ch) - { - if ($this->username && $this->password) { - curl_setopt($ch, CURLOPT_USERPWD, $this->username.':'.$this->password); - } - - return $ch; - } - - /** - * Set write/header functions. - * - * @param resource $ch - * - * @return resource $ch - */ - private function prepareDownloadMode($ch) - { - $this->body = ''; - $this->response_headers = array(); - $this->response_headers_count = 0; - $write_function = 'readBody'; - $header_function = 'readHeaders'; - - if ($this->isPassthroughEnabled()) { - $write_function = 'passthroughBody'; - } - - curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, $write_function)); - curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, $header_function)); - - return $ch; - } - - /** - * Prepare curl context. - * - * @return resource - */ - private function prepareContext() - { - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, $this->url); - curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->timeout); - curl_setopt($ch, CURLOPT_USERAGENT, $this->user_agent); - curl_setopt($ch, CURLOPT_HTTPHEADER, $this->prepareHeaders()); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); - curl_setopt($ch, CURLOPT_ENCODING, ''); - curl_setopt($ch, CURLOPT_COOKIEJAR, 'php://memory'); - curl_setopt($ch, CURLOPT_COOKIEFILE, 'php://memory'); - - // Disable SSLv3 by enforcing TLSv1.x for curl >= 7.34.0 and < 7.39.0. - // Versions prior to 7.34 and at least when compiled against openssl - // interpret this parameter as "limit to TLSv1.0" which fails for sites - // which enforce TLS 1.1+. - // Starting with curl 7.39.0 SSLv3 is disabled by default. - $version = curl_version(); - if ($version['version_number'] >= 467456 && $version['version_number'] < 468736) { - curl_setopt($ch, CURLOPT_SSLVERSION, 1); - } - - $ch = $this->prepareDownloadMode($ch); - $ch = $this->prepareProxyContext($ch); - $ch = $this->prepareAuthContext($ch); - - return $ch; - } - - /** - * Execute curl context. - */ - private function executeContext() - { - $ch = $this->prepareContext(); - curl_exec($ch); - - Logger::setMessage(get_called_class().' cURL total time: '.curl_getinfo($ch, CURLINFO_TOTAL_TIME)); - Logger::setMessage(get_called_class().' cURL dns lookup time: '.curl_getinfo($ch, CURLINFO_NAMELOOKUP_TIME)); - Logger::setMessage(get_called_class().' cURL connect time: '.curl_getinfo($ch, CURLINFO_CONNECT_TIME)); - Logger::setMessage(get_called_class().' cURL speed download: '.curl_getinfo($ch, CURLINFO_SPEED_DOWNLOAD)); - Logger::setMessage(get_called_class().' cURL effective url: '.curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)); - - $curl_errno = curl_errno($ch); - - if ($curl_errno) { - Logger::setMessage(get_called_class().' cURL error: '.curl_error($ch)); - curl_close($ch); - - $this->handleError($curl_errno); - } - - // Update the url if there where redirects - $this->url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); - - curl_close($ch); - } - - /** - * Do the HTTP request. - * - * @return array HTTP response ['body' => ..., 'status' => ..., 'headers' => ...] - */ - public function doRequest() - { - $this->executeContext(); - - list($status, $headers) = HttpHeaders::parse(explode("\n", $this->response_headers[$this->response_headers_count - 1])); - - if ($this->isRedirection($status)) { - if (empty($headers['Location'])) { - $status = 200; - } else { - return $this->handleRedirection($headers['Location']); - } - } - - return array( - 'status' => $status, - 'body' => $this->body, - 'headers' => $headers, - ); - } - - /** - * Handle HTTP redirects - * - * @param string $location Redirected URL - * @return array - * @throws MaxRedirectException - */ - private function handleRedirection($location) - { - $result = array(); - $this->url = Url::resolve($location, $this->url); - $this->body = ''; - $this->body_length = 0; - $this->response_headers = array(); - $this->response_headers_count = 0; - - while (true) { - $this->nbRedirects++; - - if ($this->nbRedirects >= $this->max_redirects) { - throw new MaxRedirectException('Maximum number of redirections reached'); - } - - $result = $this->doRequest(); - - if ($this->isRedirection($result['status'])) { - $this->url = Url::resolve($result['headers']['Location'], $this->url); - $this->body = ''; - $this->body_length = 0; - $this->response_headers = array(); - $this->response_headers_count = 0; - } else { - break; - } - } - - return $result; - } - - /** - * Handle cURL errors (throw individual exceptions). - * - * We don't use constants because they are not necessary always available - * (depends of the version of libcurl linked to php) - * - * @see http://curl.haxx.se/libcurl/c/libcurl-errors.html - * - * @param int $errno cURL error code - * @throws InvalidCertificateException - * @throws InvalidUrlException - * @throws MaxRedirectException - * @throws MaxSizeException - * @throws TimeoutException - */ - private function handleError($errno) - { - switch ($errno) { - case 78: // CURLE_REMOTE_FILE_NOT_FOUND - throw new InvalidUrlException('Resource not found', $errno); - case 6: // CURLE_COULDNT_RESOLVE_HOST - throw new InvalidUrlException('Unable to resolve hostname', $errno); - case 7: // CURLE_COULDNT_CONNECT - throw new InvalidUrlException('Unable to connect to the remote host', $errno); - case 23: // CURLE_WRITE_ERROR - throw new MaxSizeException('Maximum response size exceeded', $errno); - case 28: // CURLE_OPERATION_TIMEDOUT - throw new TimeoutException('Operation timeout', $errno); - case 35: // CURLE_SSL_CONNECT_ERROR - case 51: // CURLE_PEER_FAILED_VERIFICATION - case 58: // CURLE_SSL_CERTPROBLEM - case 60: // CURLE_SSL_CACERT - case 59: // CURLE_SSL_CIPHER - case 64: // CURLE_USE_SSL_FAILED - case 66: // CURLE_SSL_ENGINE_INITFAILED - case 77: // CURLE_SSL_CACERT_BADFILE - case 83: // CURLE_SSL_ISSUER_ERROR - $msg = 'Invalid SSL certificate caused by CURL error number ' . $errno; - throw new InvalidCertificateException($msg, $errno); - case 47: // CURLE_TOO_MANY_REDIRECTS - throw new MaxRedirectException('Maximum number of redirections reached', $errno); - case 63: // CURLE_FILESIZE_EXCEEDED - throw new MaxSizeException('Maximum response size exceeded', $errno); - default: - throw new InvalidUrlException('Unable to fetch the URL', $errno); - } - } -} |