summaryrefslogtreecommitdiffstats
path: root/vendor/fguillot/picofeed/lib/PicoFeed/Client/Client.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/fguillot/picofeed/lib/PicoFeed/Client/Client.php')
m---------vendor/fguillot/picofeed0
-rw-r--r--vendor/fguillot/picofeed/lib/PicoFeed/Client/Client.php692
2 files changed, 692 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/Client.php b/vendor/fguillot/picofeed/lib/PicoFeed/Client/Client.php
new file mode 100644
index 000000000..55d2c562f
--- /dev/null
+++ b/vendor/fguillot/picofeed/lib/PicoFeed/Client/Client.php
@@ -0,0 +1,692 @@
+<?php
+
+namespace PicoFeed\Client;
+
+use LogicException;
+use PicoFeed\Logging\Logger;
+
+/**
+ * Client class
+ *
+ * @author Frederic Guillot
+ * @package client
+ */
+abstract class Client
+{
+ /**
+ * Flag that say if the resource have been modified
+ *
+ * @access private
+ * @var bool
+ */
+ private $is_modified = true;
+
+ /**
+ * HTTP Content-Type
+ *
+ * @access private
+ * @var string
+ */
+ private $content_type = '';
+
+ /**
+ * HTTP encoding
+ *
+ * @access private
+ * @var string
+ */
+ private $encoding = '';
+
+ /**
+ * HTTP Etag header
+ *
+ * @access protected
+ * @var string
+ */
+ protected $etag = '';
+
+ /**
+ * HTTP Last-Modified header
+ *
+ * @access protected
+ * @var string
+ */
+ protected $last_modified = '';
+
+ /**
+ * Proxy hostname
+ *
+ * @access protected
+ * @var string
+ */
+ protected $proxy_hostname = '';
+
+ /**
+ * Proxy port
+ *
+ * @access protected
+ * @var integer
+ */
+ protected $proxy_port = 3128;
+
+ /**
+ * Proxy username
+ *
+ * @access protected
+ * @var string
+ */
+ protected $proxy_username = '';
+
+ /**
+ * Proxy password
+ *
+ * @access protected
+ * @var string
+ */
+ protected $proxy_password = '';
+
+ /**
+ * Basic auth username
+ *
+ * @access protected
+ * @var string
+ */
+ protected $username = '';
+
+ /**
+ * Basic auth password
+ *
+ * @access protected
+ * @var string
+ */
+ protected $password = '';
+
+ /**
+ * Client connection timeout
+ *
+ * @access protected
+ * @var integer
+ */
+ protected $timeout = 10;
+
+ /**
+ * User-agent
+ *
+ * @access protected
+ * @var string
+ */
+ protected $user_agent = 'PicoFeed (https://github.com/fguillot/picoFeed)';
+
+ /**
+ * Real URL used (can be changed after a HTTP redirect)
+ *
+ * @access protected
+ * @var string
+ */
+ protected $url = '';
+
+ /**
+ * Page/Feed content
+ *
+ * @access protected
+ * @var string
+ */
+ protected $content = '';
+
+ /**
+ * Number maximum of HTTP redirections to avoid infinite loops
+ *
+ * @access protected
+ * @var integer
+ */
+ protected $max_redirects = 5;
+
+ /**
+ * Maximum size of the HTTP body response
+ *
+ * @access protected
+ * @var integer
+ */
+ protected $max_body_size = 2097152; // 2MB
+
+ /**
+ * HTTP response status code
+ *
+ * @access protected
+ * @var integer
+ */
+ protected $status_code = 0;
+
+ /**
+ * HTTP response body
+ *
+ * @access protected
+ * @var string
+ */
+ protected $body = '';
+
+ /**
+ * Body size
+ *
+ * @access protected
+ * @var integer
+ */
+ protected $body_length = 0;
+
+ /**
+ * HTTP response headers
+ *
+ * @access protected
+ * @var array
+ */
+ protected $headers = array();
+
+ /**
+ * Counter on the number of header received
+ *
+ * @access protected
+ * @var integer
+ */
+ protected $headers_counter = 0;
+
+ /**
+ * Do the HTTP request
+ *
+ * @abstract
+ * @access public
+ * @param bool $follow_location Flag used when there is an open_basedir restriction
+ * @return array
+ */
+ abstract public function doRequest($follow_location = true);
+
+ /**
+ * Get client instance: curl or stream driver
+ *
+ * @static
+ * @access public
+ * @return \PicoFeed\Client\Client
+ */
+ public static function getInstance()
+ {
+ if (function_exists('curl_init')) {
+ return new Curl;
+ }
+ else if (ini_get('allow_url_fopen')) {
+ return new Stream;
+ }
+
+ throw new LogicException('You must have "allow_url_fopen=1" or curl extension installed');
+ }
+
+ /**
+ * Perform the HTTP request
+ *
+ * @access public
+ * @param string $url URL
+ * @return Client
+ */
+ public function execute($url = '')
+ {
+ if ($url !== '') {
+ $this->url = $url;
+ }
+
+ Logger::setMessage(get_called_class().' Fetch URL: '.$this->url);
+ Logger::setMessage(get_called_class().' Etag provided: '.$this->etag);
+ Logger::setMessage(get_called_class().' Last-Modified provided: '.$this->last_modified);
+
+ $response = $this->doRequest();
+
+ $this->status_code = $response['status'];
+ $this->handleNotModifiedResponse($response);
+ $this->handleNotFoundResponse($response);
+ $this->handleNormalResponse($response);
+
+ return $this;
+ }
+
+ /**
+ * Handle not modified response
+ *
+ * @access public
+ * @param array $response Client response
+ */
+ public function handleNotModifiedResponse(array $response)
+ {
+ if ($response['status'] == 304) {
+ $this->is_modified = false;
+ }
+ else if ($response['status'] == 200) {
+ $this->is_modified = $this->hasBeenModified($response, $this->etag, $this->last_modified);
+ $this->etag = $this->getHeader($response, 'ETag');
+ $this->last_modified = $this->getHeader($response, 'Last-Modified');
+ }
+
+ if ($this->is_modified === false) {
+ Logger::setMessage(get_called_class().' Resource not modified');
+ }
+ }
+
+ /**
+ * Handle not found response
+ *
+ * @access public
+ * @param array $response Client response
+ */
+ public function handleNotFoundResponse(array $response)
+ {
+ if ($response['status'] == 404) {
+ throw new InvalidUrlException('Resource not found');
+ }
+ }
+
+ /**
+ * Handle normal response
+ *
+ * @access public
+ * @param array $response Client response
+ */
+ public function handleNormalResponse(array $response)
+ {
+ if ($response['status'] == 200) {
+ $this->content = $response['body'];
+ $this->content_type = $this->findContentType($response);
+ $this->encoding = $this->findCharset();
+ }
+ }
+
+ /**
+ * Handle manually redirections when there is an open base dir restriction
+ *
+ * @access private
+ * @param string $location Redirected URL
+ * @return array
+ */
+ public function handleRedirection($location)
+ {
+ $nb_redirects = 0;
+ $result = array();
+ $this->url = Url::resolve($location, $this->url);
+ $this->body = '';
+ $this->body_length = 0;
+ $this->headers = array();
+ $this->headers_counter = 0;
+
+ while (true) {
+
+ $nb_redirects++;
+
+ if ($nb_redirects >= $this->max_redirects) {
+ throw new MaxRedirectException('Maximum number of redirections reached');
+ }
+
+ $result = $this->doRequest(false);
+
+ if ($result['status'] == 301 || $result['status'] == 302) {
+ $this->url = $result['headers']['Location'];
+ $this->body = '';
+ $this->body_length = 0;
+ $this->headers = array();
+ $this->headers_counter = 0;
+ }
+ else {
+ break;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Check if a request has been modified according to the parameters
+ *
+ * @access public
+ * @param array $response
+ * @param string $etag
+ * @param string $lastModified
+ * @return boolean
+ */
+ private function hasBeenModified($response, $etag, $lastModified)
+ {
+ $headers = array(
+ 'Etag' => $etag,
+ 'Last-Modified' => $lastModified
+ );
+
+ // Compare the values for each header that is present
+ $presentCacheHeaderCount = 0;
+ foreach ($headers as $key => $value) {
+ if (isset($response['headers'][$key])) {
+ if ($response['headers'][$key] !== $value) {
+ return true;
+ }
+ $presentCacheHeaderCount++;
+ }
+ }
+
+ // If at least one header is present and the values match, the response
+ // was not modified
+ if ($presentCacheHeaderCount > 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Find content type from response headers
+ *
+ * @access public
+ * @param array $response Client response
+ * @return string
+ */
+ public function findContentType(array $response)
+ {
+ return strtolower($this->getHeader($response, 'Content-Type'));
+ }
+
+ /**
+ * Find charset from response headers
+ *
+ * @access public
+ * @return string
+ */
+ public function findCharset()
+ {
+ $result = explode('charset=', $this->content_type);
+ return isset($result[1]) ? $result[1] : '';
+ }
+
+ /**
+ * Get header value from a client response
+ *
+ * @access public
+ * @param array $response Client response
+ * @param string $header Header name
+ * @return string
+ */
+ public function getHeader(array $response, $header)
+ {
+ return isset($response['headers'][$header]) ? $response['headers'][$header] : '';
+ }
+
+ /**
+ * Set the Last-Modified HTTP header
+ *
+ * @access public
+ * @param string $last_modified Header value
+ * @return \PicoFeed\Client\Client
+ */
+ public function setLastModified($last_modified)
+ {
+ $this->last_modified = $last_modified;
+ return $this;
+ }
+
+ /**
+ * Get the value of the Last-Modified HTTP header
+ *
+ * @access public
+ * @return string
+ */
+ public function getLastModified()
+ {
+ return $this->last_modified;
+ }
+
+ /**
+ * Set the value of the Etag HTTP header
+ *
+ * @access public
+ * @param string $etag Etag HTTP header value
+ * @return \PicoFeed\Client\Client
+ */
+ public function setEtag($etag)
+ {
+ $this->etag = $etag;
+ return $this;
+ }
+
+ /**
+ * Get the Etag HTTP header value
+ *
+ * @access public
+ * @return string
+ */
+ public function getEtag()
+ {
+ return $this->etag;
+ }
+
+ /**
+ * Get the final url value
+ *
+ * @access public
+ * @return string
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ /**
+ * Set the url
+ *
+ * @access public
+ * @return string
+ * @return \PicoFeed\Client\Client
+ */
+ public function setUrl($url)
+ {
+ $this->url = $url;
+ return $this;
+ }
+
+ /**
+ * Get the HTTP response status code
+ *
+ * @access public
+ * @return integer
+ */
+ public function getStatusCode()
+ {
+ return $this->status_code;
+ }
+
+ /**
+ * Get the body of the HTTP response
+ *
+ * @access public
+ * @return string
+ */
+ public function getContent()
+ {
+ return $this->content;
+ }
+
+ /**
+ * Get the content type value from HTTP headers
+ *
+ * @access public
+ * @return string
+ */
+ public function getContentType()
+ {
+ return $this->content_type;
+ }
+
+ /**
+ * Get the encoding value from HTTP headers
+ *
+ * @access public
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->encoding;
+ }
+
+ /**
+ * Return true if the remote resource has changed
+ *
+ * @access public
+ * @return bool
+ */
+ public function isModified()
+ {
+ return $this->is_modified;
+ }
+
+ /**
+ * Set connection timeout
+ *
+ * @access public
+ * @param integer $timeout Connection timeout
+ * @return \PicoFeed\Client\Client
+ */
+ public function setTimeout($timeout)
+ {
+ $this->timeout = $timeout ?: $this->timeout;
+ return $this;
+ }
+
+ /**
+ * Set a custom user agent
+ *
+ * @access public
+ * @param string $user_agent User Agent
+ * @return \PicoFeed\Client\Client
+ */
+ public function setUserAgent($user_agent)
+ {
+ $this->user_agent = $user_agent ?: $this->user_agent;
+ return $this;
+ }
+
+ /**
+ * Set the mximum number of HTTP redirections
+ *
+ * @access public
+ * @param integer $max Maximum
+ * @return \PicoFeed\Client\Client
+ */
+ public function setMaxRedirections($max)
+ {
+ $this->max_redirects = $max ?: $this->max_redirects;
+ return $this;
+ }
+
+ /**
+ * Set the maximum size of the HTTP body
+ *
+ * @access public
+ * @param integer $max Maximum
+ * @return \PicoFeed\Client\Client
+ */
+ public function setMaxBodySize($max)
+ {
+ $this->max_body_size = $max ?: $this->max_body_size;
+ return $this;
+ }
+
+ /**
+ * Set the proxy hostname
+ *
+ * @access public
+ * @param string $hostname Proxy hostname
+ * @return \PicoFeed\Client\Client
+ */
+ public function setProxyHostname($hostname)
+ {
+ $this->proxy_hostname = $hostname ?: $this->proxy_hostname;
+ return $this;
+ }
+
+ /**
+ * Set the proxy port
+ *
+ * @access public
+ * @param integer $port Proxy port
+ * @return \PicoFeed\Client\Client
+ */
+ public function setProxyPort($port)
+ {
+ $this->proxy_port = $port ?: $this->proxy_port;
+ return $this;
+ }
+
+ /**
+ * Set the proxy username
+ *
+ * @access public
+ * @param string $username Proxy username
+ * @return \PicoFeed\Client\Client
+ */
+ public function setProxyUsername($username)
+ {
+ $this->proxy_username = $username ?: $this->proxy_username;
+ return $this;
+ }
+
+ /**
+ * Set the proxy password
+ *
+ * @access public
+ * @param string $password Password
+ * @return \PicoFeed\Client\Client
+ */
+ public function setProxyPassword($password)
+ {
+ $this->proxy_password = $password ?: $this->proxy_password;
+ return $this;
+ }
+
+ /**
+ * Set the username
+ *
+ * @access public
+ * @param string $username Basic Auth username
+ * @return \PicoFeed\Client\Client
+ */
+ public function setUsername($username)
+ {
+ $this->username = $username ?: $this->username;
+ return $this;
+ }
+
+ /**
+ * Set the password
+ *
+ * @access public
+ * @param string $password Basic Auth Password
+ * @return \PicoFeed\Client\Client
+ */
+ public function setPassword($password)
+ {
+ $this->password = $password ?: $this->password;
+ return $this;
+ }
+
+ /**
+ * Set config object
+ *
+ * @access public
+ * @param \PicoFeed\Config\Config $config Config instance
+ * @return \PicoFeed\Client\Client
+ */
+ public function setConfig($config)
+ {
+ if ($config !== null) {
+ $this->setTimeout($config->getGrabberTimeout());
+ $this->setUserAgent($config->getGrabberUserAgent());
+ $this->setMaxRedirections($config->getMaxRedirections());
+ $this->setMaxBodySize($config->getMaxBodySize());
+ $this->setProxyHostname($config->getProxyHostname());
+ $this->setProxyPort($config->getProxyPort());
+ $this->setProxyUsername($config->getProxyUsername());
+ $this->setProxyPassword($config->getProxyPassword());
+ }
+
+ return $this;
+ }
+}