2013-07-17 01:54:44 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace PicoFeed;
|
|
|
|
|
|
|
|
require_once __DIR__.'/Logging.php';
|
|
|
|
|
|
|
|
abstract class Client
|
|
|
|
{
|
|
|
|
public $etag = '';
|
|
|
|
public $last_modified = '';
|
|
|
|
public $is_modified = true;
|
|
|
|
public $content = '';
|
|
|
|
public $url = '';
|
|
|
|
public $timeout = 10;
|
|
|
|
public $max_redirects = 5;
|
|
|
|
public $max_body_size = 2097152; // 2MB
|
|
|
|
public $user_agent = 'PicoFeed (https://github.com/fguillot/picoFeed)';
|
|
|
|
|
|
|
|
|
|
|
|
public static function create($adapter = null)
|
|
|
|
{
|
|
|
|
return $adapter ?: self::chooseAdapter();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static function chooseAdapter()
|
|
|
|
{
|
|
|
|
if (function_exists('curl_init')) {
|
|
|
|
|
|
|
|
require_once __DIR__.'/Clients/Curl.php';
|
|
|
|
return new Clients\Curl;
|
|
|
|
|
|
|
|
} else if (ini_get('allow_url_fopen')) {
|
|
|
|
|
|
|
|
require_once __DIR__.'/Clients/Stream.php';
|
|
|
|
return new Clients\Stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new \LogicException('You must have "allow_url_fopen=1" or curl extension installed');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function execute()
|
|
|
|
{
|
|
|
|
if ($this->url === '') {
|
|
|
|
throw new \LogicException('The URL is missing');
|
|
|
|
}
|
|
|
|
|
2013-08-30 01:34:11 +02:00
|
|
|
Logging::log(\get_called_class().' Fetch URL: '.$this->url);
|
|
|
|
Logging::log(\get_called_class().' Etag provided: '.$this->etag);
|
|
|
|
Logging::log(\get_called_class().' Last-Modified provided: '.$this->last_modified);
|
2013-07-17 01:54:44 +02:00
|
|
|
|
|
|
|
$response = $this->doRequest();
|
|
|
|
|
|
|
|
if (is_array($response)) {
|
|
|
|
|
|
|
|
if ($response['status'] == 304) {
|
|
|
|
$this->is_modified = false;
|
2013-08-30 01:54:37 +02:00
|
|
|
Logging::log(\get_called_class().' Resource not modified');
|
2013-07-17 01:54:44 +02:00
|
|
|
}
|
2013-08-30 02:52:44 +02:00
|
|
|
else if ($response['status'] == 404) {
|
|
|
|
Logging::log(\get_called_class().' Resource not found');
|
|
|
|
}
|
2013-07-17 01:54:44 +02:00
|
|
|
else {
|
|
|
|
$this->etag = isset($response['headers']['ETag']) ? $response['headers']['ETag'] : '';
|
|
|
|
$this->last_modified = isset($response['headers']['Last-Modified']) ? $response['headers']['Last-Modified'] : '';
|
|
|
|
$this->content = $response['body'];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function parseHeaders(array $lines)
|
|
|
|
{
|
|
|
|
$status = 200;
|
|
|
|
$headers = array();
|
|
|
|
|
|
|
|
foreach ($lines as $line) {
|
|
|
|
|
2013-08-15 03:18:23 +02:00
|
|
|
if (strpos($line, 'HTTP') === 0/* && strpos($line, '301') === false && strpos($line, '302') === false*/) {
|
2013-07-17 01:54:44 +02:00
|
|
|
$status = (int) substr($line, 9, 3);
|
|
|
|
}
|
|
|
|
else if (strpos($line, ':') !== false) {
|
|
|
|
|
2013-07-19 01:24:17 +02:00
|
|
|
@list($name, $value) = explode(': ', $line);
|
|
|
|
if ($value) $headers[trim($name)] = trim($value);
|
2013-07-17 01:54:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-30 01:34:11 +02:00
|
|
|
Logging::log(\get_called_class().' HTTP status code: '.$status);
|
2013-07-17 01:54:44 +02:00
|
|
|
|
|
|
|
foreach ($headers as $name => $value) {
|
2013-08-30 01:54:37 +02:00
|
|
|
Logging::log(\get_called_class().' HTTP header: '.$name.' => '.$value);
|
2013-07-17 01:54:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return array($status, $headers);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function setLastModified($last_modified)
|
|
|
|
{
|
|
|
|
$this->last_modified = $last_modified;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function getLastModified()
|
|
|
|
{
|
|
|
|
return $this->last_modified;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function setEtag($etag)
|
|
|
|
{
|
|
|
|
$this->etag = $etag;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function getEtag()
|
|
|
|
{
|
|
|
|
return $this->etag;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function getUrl()
|
|
|
|
{
|
|
|
|
return $this->url;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function getContent()
|
|
|
|
{
|
|
|
|
return $this->content;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function isModified()
|
|
|
|
{
|
|
|
|
return $this->is_modified;
|
|
|
|
}
|
|
|
|
}
|