summaryrefslogtreecommitdiffstats
path: root/vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php')
m---------vendor/fguillot/picofeed0
-rw-r--r--vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php181
2 files changed, 181 insertions, 0 deletions
diff --git a/vendor/fguillot/picofeed b/vendor/fguillot/picofeed
deleted file mode 160000
-Subproject 0a1d0d3950f7f047dc8fb1d80aa6296e15f306d
diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php b/vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php
new file mode 100644
index 000000000..b80e731d6
--- /dev/null
+++ b/vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php
@@ -0,0 +1,181 @@
+<?php
+
+namespace PicoFeed\Client;
+
+use PicoFeed\Logging\Logger;
+
+/**
+ * Stream context HTTP client
+ *
+ * @author Frederic Guillot
+ * @package Client
+ */
+class Stream extends Client
+{
+ /**
+ * Prepare HTTP headers
+ *
+ * @access private
+ * @return string[]
+ */
+ private function prepareHeaders()
+ {
+ $headers = array(
+ 'Connection: close',
+ 'User-Agent: '.$this->user_agent,
+ );
+
+ if (function_exists('gzdecode')) {
+ $headers[] = 'Accept-Encoding: gzip';
+ }
+
+ if ($this->etag) {
+ $headers[] = 'If-None-Match: '.$this->etag;
+ }
+
+ if ($this->last_modified) {
+ $headers[] = 'If-Modified-Since: '.$this->last_modified;
+ }
+
+ if ($this->proxy_username) {
+ $headers[] = 'Proxy-Authorization: Basic '.base64_encode($this->proxy_username.':'.$this->proxy_password);
+ }
+
+ if ($this->username && $this->password) {
+ $headers[] = 'Authorization: Basic '.base64_encode($this->username.':'.$this->password);
+ }
+
+ return $headers;
+ }
+
+ /**
+ * Prepare stream context
+ *
+ * @access private
+ * @return array
+ */
+ private function prepareContext()
+ {
+ $context = array(
+ 'http' => array(
+ 'method' => 'GET',
+ 'protocol_version' => 1.1,
+ 'timeout' => $this->timeout,
+ 'follow_location' => 0,
+ )
+ );
+
+ if ($this->proxy_hostname) {
+
+ Logger::setMessage(get_called_class().' Proxy: '.$this->proxy_hostname.':'.$this->proxy_port);
+
+ $context['http']['proxy'] = 'tcp://'.$this->proxy_hostname.':'.$this->proxy_port;
+ $context['http']['request_fulluri'] = true;
+
+ if ($this->proxy_username) {
+ Logger::setMessage(get_called_class().' Proxy credentials: Yes');
+ }
+ else {
+ Logger::setMessage(get_called_class().' Proxy credentials: No');
+ }
+ }
+
+ $context['http']['header'] = implode("\r\n", $this->prepareHeaders());
+
+ return $context;
+ }
+
+ /**
+ * Do the HTTP request
+ *
+ * @access public
+ * @param bool $follow_location Flag used when there is an open_basedir restriction
+ * @return array HTTP response ['body' => ..., 'status' => ..., 'headers' => ...]
+ */
+ public function doRequest($follow_location = false)
+ {
+ // Create context
+ $context = stream_context_create($this->prepareContext());
+
+ // Make HTTP request
+ $stream = @fopen($this->url, 'r', false, $context);
+ if (! is_resource($stream)) {
+ throw new InvalidUrlException('Unable to establish a connection');
+ }
+
+ // Get the entire body until the max size
+ $body = stream_get_contents($stream, $this->max_body_size + 1);
+
+ // If the body size is too large abort everything
+ if (strlen($body) > $this->max_body_size) {
+ throw new MaxSizeException('Content size too large');
+ }
+
+ // Get HTTP headers response
+ $metadata = stream_get_meta_data($stream);
+
+ if ($metadata['timed_out']) {
+ throw new TimeoutException('Operation timeout');
+ }
+
+ list($status, $headers) = HttpHeaders::parse($metadata['wrapper_data']);
+
+ fclose($stream);
+
+ // Do redirect manual to get only the headers of the last request and
+ // the final url
+ if ($status == 301 || $status == 302) {
+ return $this->handleRedirection($headers['Location']);
+ }
+
+ return array(
+ 'status' => $status,
+ 'body' => $this->decodeBody($body, $headers),
+ 'headers' => $headers
+ );
+ }
+
+ /**
+ * Decode body response according to the HTTP headers
+ *
+ * @access public
+ * @param string $body Raw body
+ * @param HttpHeaders $headers HTTP headers
+ * @return string
+ */
+ public function decodeBody($body, HttpHeaders $headers)
+ {
+ if (isset($headers['Transfer-Encoding']) && $headers['Transfer-Encoding'] === 'chunked') {
+ $body = $this->decodeChunked($body);
+ }
+
+ if (isset($headers['Content-Encoding']) && $headers['Content-Encoding'] === 'gzip') {
+ $body = @gzdecode($body);
+ }
+
+ return $body;
+ }
+
+ /**
+ * Decode a chunked body
+ *
+ * @access public
+ * @param string $str Raw body
+ * @return string Decoded body
+ */
+ public function decodeChunked($str)
+ {
+ for ($result = ''; ! empty($str); $str = trim($str)) {
+
+ // Get the chunk length
+ $pos = strpos($str, "\r\n");
+ $len = hexdec(substr($str, 0, $pos));
+
+ // Append the chunk to the result
+ $result .= substr($str, $pos + 2, $len);
+ $str = substr($str, $pos + 2 + $len);
+ }
+
+ return $result;
+ }
+}