Update of PicoFeed and PicoDb
This commit is contained in:
parent
6bd2e32615
commit
415a7a6c58
@ -38,9 +38,9 @@ if (! extension_loaded('pdo_sqlite')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for curl
|
// Check for curl
|
||||||
if (! function_exists('curl_init')) {
|
if (! function_exists('curl_init') || ! ini_get('allow_url_fopen')) {
|
||||||
|
|
||||||
die('PHP extension required: curl');
|
die('You must have "allow_url_fopen=1" or curl extension installed');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if /data is writeable
|
// Check if /data is writeable
|
||||||
|
19
vendor/PicoDb/Table.php
vendored
19
vendor/PicoDb/Table.php
vendored
@ -259,6 +259,25 @@ class Table
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function orderBy($column)
|
||||||
|
{
|
||||||
|
if ($column[0] == '-') {
|
||||||
|
$order = 'DESC';
|
||||||
|
} else {
|
||||||
|
$order = 'ASC';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->sql_order === '') {
|
||||||
|
$this->sql_order = ' ORDER BY '.$this->db->escapeIdentifier($column).' '.$order;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->sql_order .= ', '.$this->db->escapeIdentifier($column).' '.$order;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function asc($column)
|
public function asc($column)
|
||||||
{
|
{
|
||||||
if ($this->sql_order === '') {
|
if ($this->sql_order === '') {
|
||||||
|
139
vendor/PicoFeed/Client.php
vendored
Normal file
139
vendor/PicoFeed/Client.php
vendored
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<?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');
|
||||||
|
}
|
||||||
|
|
||||||
|
Logging::log('Fetch URL: '.$this->url);
|
||||||
|
Logging::log('Etag: '.$this->etag);
|
||||||
|
Logging::log('Last-Modified: '.$this->last_modified);
|
||||||
|
|
||||||
|
$response = $this->doRequest();
|
||||||
|
|
||||||
|
if (is_array($response)) {
|
||||||
|
|
||||||
|
if ($response['status'] == 304) {
|
||||||
|
$this->is_modified = false;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
|
||||||
|
if (strpos($line, 'HTTP') === 0 && strpos($line, '301') === false && strpos($line, '302') === false) {
|
||||||
|
|
||||||
|
$status = (int) substr($line, 9, 3);
|
||||||
|
}
|
||||||
|
else if (strpos($line, ':') !== false) {
|
||||||
|
|
||||||
|
list($name, $value) = explode(': ', $line);
|
||||||
|
$headers[trim($name)] = trim($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logging::log('HTTP status code: '.$status);
|
||||||
|
|
||||||
|
foreach ($headers as $name => $value) {
|
||||||
|
Logging::log('HTTP headers: '.$name.' => '.$value);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
93
vendor/PicoFeed/Clients/Curl.php
vendored
Normal file
93
vendor/PicoFeed/Clients/Curl.php
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PicoFeed\Clients;
|
||||||
|
|
||||||
|
use \PicoFeed\Logging;
|
||||||
|
|
||||||
|
class Curl extends \PicoFeed\Client
|
||||||
|
{
|
||||||
|
private $body = '';
|
||||||
|
private $body_length = 0;
|
||||||
|
private $headers = array();
|
||||||
|
private $headers_counter = 0;
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function readHeaders($ch, $buffer)
|
||||||
|
{
|
||||||
|
$length = strlen($buffer);
|
||||||
|
|
||||||
|
if ($buffer === "\r\n") {
|
||||||
|
$this->headers_counter++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
if (! isset($this->headers[$this->headers_counter])) {
|
||||||
|
$this->headers[$this->headers_counter] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->headers[$this->headers_counter] .= $buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function doRequest()
|
||||||
|
{
|
||||||
|
$request_headers = array('Connection: close');
|
||||||
|
|
||||||
|
if ($this->etag) $request_headers[] = 'If-None-Match: '.$this->etag;
|
||||||
|
if ($this->last_modified) $request_headers[] = 'If-Modified-Since: '.$this->last_modified;
|
||||||
|
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $this->url);
|
||||||
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->timeout);
|
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
|
||||||
|
curl_setopt($ch, CURLOPT_USERAGENT, $this->user_agent);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
|
||||||
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||||
|
curl_setopt($ch, CURLOPT_MAXREDIRS, $this->max_redirects);
|
||||||
|
curl_setopt($ch, CURLOPT_ENCODING, '');
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // For auto-signed certificates...
|
||||||
|
curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, 'readBody'));
|
||||||
|
curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'readHeaders'));
|
||||||
|
curl_exec($ch);
|
||||||
|
|
||||||
|
Logging::log('cURL total time: '.curl_getinfo($ch, CURLINFO_TOTAL_TIME));
|
||||||
|
Logging::log('cURL dns lookup time: '.curl_getinfo($ch, CURLINFO_NAMELOOKUP_TIME));
|
||||||
|
Logging::log('cURL connect time: '.curl_getinfo($ch, CURLINFO_CONNECT_TIME));
|
||||||
|
Logging::log('cURL speed download: '.curl_getinfo($ch, CURLINFO_SPEED_DOWNLOAD));
|
||||||
|
|
||||||
|
if (curl_errno($ch)) {
|
||||||
|
|
||||||
|
Logging::log('cURL error: '.curl_error($ch));
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
list($status, $headers) = $this->parseHeaders(explode("\r\n", $this->headers[$this->headers_counter - 1]));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'status' => $status,
|
||||||
|
'body' => $this->body,
|
||||||
|
'headers' => $headers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
56
vendor/PicoFeed/Clients/Stream.php
vendored
Normal file
56
vendor/PicoFeed/Clients/Stream.php
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PicoFeed\Clients;
|
||||||
|
|
||||||
|
use \PicoFeed\Logging;
|
||||||
|
|
||||||
|
class Stream extends \PicoFeed\Client
|
||||||
|
{
|
||||||
|
public function doRequest()
|
||||||
|
{
|
||||||
|
// Prepare HTTP headers for the request
|
||||||
|
$headers = array(
|
||||||
|
'Connection: close',
|
||||||
|
'User-Agent: '.$this->user_agent,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->etag) $headers[] = 'If-None-Match: '.$this->etag;
|
||||||
|
if ($this->last_modified) $headers[] = 'If-Modified-Since: '.$this->last_modified;
|
||||||
|
|
||||||
|
// Create context
|
||||||
|
$context_options = array(
|
||||||
|
'http' => array(
|
||||||
|
'method' => 'GET',
|
||||||
|
'protocol_version' => 1.1,
|
||||||
|
'timeout' => $this->timeout,
|
||||||
|
'max_redirects' => $this->max_redirects,
|
||||||
|
'header' => implode("\r\n", $headers)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$context = stream_context_create($context_options);
|
||||||
|
|
||||||
|
// Make HTTP request
|
||||||
|
$stream = @fopen($this->url, 'r', false, $context);
|
||||||
|
if (! is_resource($stream)) return false;
|
||||||
|
|
||||||
|
// 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) return false;
|
||||||
|
|
||||||
|
// Get HTTP headers response
|
||||||
|
$metadata = stream_get_meta_data($stream);
|
||||||
|
|
||||||
|
list($status, $headers) = $this->parseHeaders($metadata['wrapper_data']);
|
||||||
|
|
||||||
|
fclose($stream);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'status' => $status,
|
||||||
|
'body' => $body,
|
||||||
|
'headers' => $headers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
19
vendor/PicoFeed/Reader.php
vendored
19
vendor/PicoFeed/Reader.php
vendored
@ -4,7 +4,7 @@ namespace PicoFeed;
|
|||||||
|
|
||||||
require_once __DIR__.'/Logging.php';
|
require_once __DIR__.'/Logging.php';
|
||||||
require_once __DIR__.'/Parser.php';
|
require_once __DIR__.'/Parser.php';
|
||||||
require_once __DIR__.'/RemoteResource.php';
|
require_once __DIR__.'/Client.php';
|
||||||
|
|
||||||
class Reader
|
class Reader
|
||||||
{
|
{
|
||||||
@ -26,15 +26,18 @@ class Reader
|
|||||||
$url = 'http://'.$url;
|
$url = 'http://'.$url;
|
||||||
}
|
}
|
||||||
|
|
||||||
$resource = new RemoteResource($url, $timeout, $user_agent);
|
$client = Client::create();
|
||||||
$resource->setLastModified($last_modified);
|
$client->url = $url;
|
||||||
$resource->setEtag($etag);
|
$client->timeout = $timeout;
|
||||||
$resource->execute();
|
$client->user_agent = $user_agent;
|
||||||
|
$client->last_modified = $last_modified;
|
||||||
|
$client->etag = $etag;
|
||||||
|
$client->execute();
|
||||||
|
|
||||||
$this->content = $resource->getContent();
|
$this->content = $client->getContent();
|
||||||
$this->url = $resource->getUrl();
|
$this->url = $client->getUrl();
|
||||||
|
|
||||||
return $resource;
|
return $client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user