Browse Source

Start on integrating well-maintained picofeed fork

Picofeed configuration does not seem to get passed to Guzzle.
rpm
J. King 4 years ago
parent
commit
e583ffea67
  1. 8
      composer.json
  2. 445
      composer.lock
  3. 3
      lib/AbstractException.php
  4. 6
      lib/Feed.php
  5. 36
      lib/Feed/Exception.php
  6. 3
      locale/en.php
  7. 6
      tests/cases/Feed/TestFetching.php

8
composer.json

@ -17,13 +17,19 @@
}
],
"repositories": [
{
"type": "vcs",
"url": "https://github.com/JKingweb/picoFeed-1"
}
],
"require": {
"php": "^7.1",
"ext-intl": "*",
"ext-json": "*",
"ext-hash": "*",
"ext-dom": "*",
"p3k/picofeed": "0.1.*",
"nicolus/picofeed": "dev-fixed",
"hosteurope/password-generator": "1.*",
"docopt/docopt": "1.*",
"jkingweb/druuid": "3.*",

445
composer.lock

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "356cebec1e1e689b4249b661f787b7d9",
"content-hash": "9710e0638278222dc8d6207d4141e529",
"packages": [
{
"name": "docopt/docopt",
@ -52,6 +52,195 @@
],
"time": "2019-12-03T02:48:46+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.5.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"psr/log": "^1.1"
},
"suggest": {
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.5-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2019-12-23T11:57:10+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"ext-zlib": "*",
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"suggest": {
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2019-07-01T23:21:34+00:00"
},
{
"name": "hosteurope/password-generator",
"version": "v1.0.1",
@ -137,6 +326,81 @@
],
"time": "2017-02-09T14:17:01+00:00"
},
{
"name": "kevinrob/guzzle-cache-middleware",
"version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/Kevinrob/guzzle-cache-middleware.git",
"reference": "6952064f7747756b0be7b4c234c0fd7535ea4c8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Kevinrob/guzzle-cache-middleware/zipball/6952064f7747756b0be7b4c234c0fd7535ea4c8c",
"reference": "6952064f7747756b0be7b4c234c0fd7535ea4c8c",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"cache/array-adapter": "^0.4",
"doctrine/cache": "^1.0",
"guzzlehttp/guzzle": "^6.0",
"illuminate/cache": "^5.0",
"league/flysystem": "^1.0",
"phpunit/phpunit": "^4.0 || ^5.0",
"psr/cache": "^1.0"
},
"suggest": {
"doctrine/cache": "This library have a lot of ready-to-use cache storage (to be use with Kevinrob\\GuzzleCache\\Storage\\DoctrineCacheStorage)",
"guzzlehttp/guzzle": "For using this library. It was created for Guzzle6. (but you can use it with any PSR-7 HTTP Client)",
"laravel/framework": "To be use with Kevinrob\\GuzzleCache\\Storage\\LaravelCacheStorage",
"league/flysystem": "To be use with Kevinrob\\GuzzleCache\\Storage\\FlysystemStorage",
"psr/cache": "To be use with Kevinrob\\GuzzleCache\\Storage\\Psr6CacheStorage"
},
"type": "library",
"autoload": {
"psr-4": {
"Kevinrob\\GuzzleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kevin Robatel",
"email": "kevinrob2@gmail.com",
"homepage": "https://github.com/Kevinrob"
}
],
"description": "A HTTP/1.1 Cache for Guzzle 6. It's a simple Middleware to be added in the HandlerStack. (RFC 7234)",
"homepage": "https://github.com/Kevinrob/guzzle-cache-middleware",
"keywords": [
"Etag",
"Flysystem",
"Guzzle",
"cache",
"cache-control",
"doctrine",
"expiration",
"guzzle6",
"handler",
"http",
"http 1.1",
"middleware",
"performance",
"php",
"promise",
"psr6",
"psr7",
"rfc7234",
"validation"
],
"time": "2017-08-17T12:23:43+00:00"
},
{
"name": "laminas/laminas-diactoros",
"version": "2.2.2",
@ -280,6 +544,56 @@
],
"time": "2019-12-31T17:06:16+00:00"
},
{
"name": "laminas/laminas-xml",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-xml.git",
"reference": "879cc66d1bba6a37705e98074f52a6960c220020"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-xml/zipball/879cc66d1bba6a37705e98074f52a6960c220020",
"reference": "879cc66d1bba6a37705e98074f52a6960c220020",
"shasum": ""
},
"require": {
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zendxml": "self.version"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\Xml\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Utility library for XML usage, best practices, and security in PHP",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"security",
"xml"
],
"time": "2019-12-31T18:05:42+00:00"
},
{
"name": "laminas/laminas-zendframework-bridge",
"version": "1.0.1",
@ -333,17 +647,17 @@
"time": "2020-01-07T22:58:31+00:00"
},
{
"name": "p3k/picofeed",
"version": "v0.1.35",
"name": "nicolus/picofeed",
"version": "dev-fixed",
"source": {
"type": "git",
"url": "https://github.com/aaronpk/picofeed.git",
"reference": "b2a48acb026df91d2e21dfc8b4edbc1fc48f01f1"
"url": "https://github.com/JKingweb/picoFeed-1.git",
"reference": "419bc85afb18a84e43274029cf8e198cc5785425"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aaronpk/picofeed/zipball/b2a48acb026df91d2e21dfc8b4edbc1fc48f01f1",
"reference": "b2a48acb026df91d2e21dfc8b4edbc1fc48f01f1",
"url": "https://api.github.com/repos/JKingweb/picoFeed-1/zipball/419bc85afb18a84e43274029cf8e198cc5785425",
"reference": "419bc85afb18a84e43274029cf8e198cc5785425",
"shasum": ""
},
"require": {
@ -352,16 +666,22 @@
"ext-libxml": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"php": ">=5.3.0",
"zendframework/zendxml": "^1.0"
"guzzlehttp/guzzle": "~6.0",
"kevinrob/guzzle-cache-middleware": "^2.1",
"laminas/laminas-xml": "^1.0",
"php": ">=7.1",
"psr/log": "^1.0"
},
"require-dev": {
"blastcloud/guzzler": "^1.5",
"monolog/monolog": "^1.23",
"php-coveralls/php-coveralls": "^2.1",
"phpdocumentor/reflection-docblock": "2.0.4",
"phpunit/phpunit": "4.8.26",
"symfony/yaml": "2.8.7"
"phpunit/phpunit": "^7.0.0"
},
"suggest": {
"ext-curl": "PicoFeed will use cURL if present"
"ext-curl": "PicoFeed will use cURL if present",
"monolog/monolog": "You can set a monolog Logger to get debug information from PicoFeed"
},
"bin": [
"picofeed"
@ -372,18 +692,23 @@
"PicoFeed": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Frédéric Guillot"
},
{
"name": "Nicolas Bailly"
}
],
"description": "Modern library to handle RSS/Atom feeds",
"homepage": "https://github.com/aaronpk/picoFeed",
"time": "2019-01-17T17:26:41+00:00"
"description": "RSS/Atom parsing library",
"homepage": "https://github.com/nicolus/picoFeed",
"support": {
"source": "https://github.com/JKingweb/picoFeed-1/tree/fixed"
},
"time": "2020-01-21T00:09:22+00:00"
},
{
"name": "psr/http-factory",
@ -541,51 +866,91 @@
"time": "2018-10-30T16:46:14+00:00"
},
{
"name": "zendframework/zendxml",
"version": "1.2.0",
"name": "psr/log",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/zendframework/ZendXml.git",
"reference": "eceab37a591c9e140772a1470338258857339e00"
"url": "https://github.com/php-fig/log.git",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/ZendXml/zipball/eceab37a591c9e140772a1470338258857339e00",
"reference": "eceab37a591c9e140772a1470338258857339e00",
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4",
"zendframework/zend-coding-standard": "~1.0.0"
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
"ZendXml\\": "src/"
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
"MIT"
],
"description": "Utility library for XML usage, best practices, and security in PHP",
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"ZendFramework",
"security",
"xml",
"zf"
"log",
"psr",
"psr-3"
],
"time": "2019-11-01T11:05:21+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"abandoned": "laminas/laminas-xml",
"time": "2019-01-22T19:42:14+00:00"
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"time": "2019-03-08T08:55:37+00:00"
}
],
"packages-dev": [
@ -631,7 +996,9 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {
"nicolus/picofeed": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {

3
lib/AbstractException.php

@ -77,11 +77,12 @@ abstract class AbstractException extends \Exception {
"User/ExceptionSession.invalid" => 10431,
"Feed/Exception.invalidCertificate" => 10501,
"Feed/Exception.invalidUrl" => 10502,
"Feed/Exception.maxRedirect" => 10503,
"Feed/Exception.tooManyRedirects" => 10503,
"Feed/Exception.maxSize" => 10504,
"Feed/Exception.timeout" => 10505,
"Feed/Exception.forbidden" => 10506,
"Feed/Exception.unauthorized" => 10507,
"Feed/Exception.transmissionError" => 10508,
"Feed/Exception.malformedXml" => 10511,
"Feed/Exception.xmlEntity" => 10512,
"Feed/Exception.subscriptionNotFound" => 10521,

6
lib/Feed.php

@ -101,6 +101,8 @@ class Feed {
return $client;
} catch (PicoFeedException $e) {
throw new Feed\Exception($url, $e);
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
throw new Feed\Exception($url, $e);
}
}
@ -121,6 +123,10 @@ class Feed {
// work around a PicoFeed memory leak
libxml_use_internal_errors(false);
throw new Feed\Exception($this->resource->getUrl(), $e);
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
// work around a PicoFeed memory leak
libxml_use_internal_errors(false);
throw new Feed\Exception($this->resource->getUrl(), $e);
}
// PicoFeed does not provide valid ids when there is no id element. Its solution

36
lib/Feed/Exception.php

@ -6,13 +6,39 @@
declare(strict_types=1);
namespace JKingWeb\Arsse\Feed;
use GuzzleHttp\Exception\GuzzleException;
class Exception extends \JKingWeb\Arsse\AbstractException {
public function __construct($url, \Throwable $e) {
$className = get_class($e);
// Convert the exception thrown by PicoFeed to the one to be thrown here.
$msgID = preg_replace('/^PicoFeed\\\(?:Client|Parser|Reader)\\\([A-Za-z]+)Exception$/', '$1', $className);
// If the message ID doesn't change then it's unknown.
$msgID = ($msgID !== $className) ? lcfirst($msgID) : '';
if ($e instanceof GuzzleException) {
switch ($e->getCode()) {
case 401:
$msgID = "unauthorized";
break;
case 403:
$msgID = "forbidden";
break;
case 404:
case 410:
$msgID = "invalidUrl";
break;
case 508:
$msgID = "tooManyRedirects";
break;
default:
$c = $e->getCode();
if ($c >= 400 && $c < 600) {
$msgID = "transmissionError";
}
}
}
if (!($msgID ?? "")) {
$className = get_class($e);
// Convert the exception thrown by PicoFeed to the one to be thrown here.
$msgID = preg_replace('/^(?:PicoFeed\\\(?:Client|Parser|Reader)|GuzzleHttp\\\Exception)\\\([A-Za-z]+)Exception$/', '$1', $className);
// If the message ID doesn't change then it's unknown.
$msgID = ($msgID !== $className) ? lcfirst($msgID) : '';
}
parent::__construct($msgID, ['url' => $url], $e);
}
}

3
locale/en.php

@ -146,11 +146,12 @@ return [
'Exception.JKingWeb/Arsse/User/ExceptionSession.invalid' => 'Session with ID {0} does not exist',
'Exception.JKingWeb/Arsse/Feed/Exception.invalidCertificate' => 'Could not download feed "{url}" because its server is serving an invalid SSL certificate',
'Exception.JKingWeb/Arsse/Feed/Exception.invalidUrl' => 'Feed URL "{url}" is invalid',
'Exception.JKingWeb/Arsse/Feed/Exception.maxRedirect' => 'Could not download feed "{url}" because its server reached its maximum number of HTTP redirections',
'Exception.JKingWeb/Arsse/Feed/Exception.tooManyRedirects' => 'Could not download feed "{url}" because its server reached its maximum number of HTTP redirections',
'Exception.JKingWeb/Arsse/Feed/Exception.maxSize' => 'Could not download feed "{url}" because its size exceeds the maximum allowed on its server',
'Exception.JKingWeb/Arsse/Feed/Exception.timeout' => 'Could not download feed "{url}" because its server timed out',
'Exception.JKingWeb/Arsse/Feed/Exception.forbidden' => 'Could not download feed "{url}" because you do not have permission to access it',
'Exception.JKingWeb/Arsse/Feed/Exception.unauthorized' => 'Could not download feed "{url}" because you provided insufficient or invalid credentials',
'Exception.JKingWeb/Arsse/Feed/Exception.transmissionError' => 'Could not download feed "{url}" because of a network error',
'Exception.JKingWeb/Arsse/Feed/Exception.malformedXml' => 'Could not parse feed "{url}" because it is malformed',
'Exception.JKingWeb/Arsse/Feed/Exception.xmlEntity' => 'Refused to parse feed "{url}" because it contains an XXE attack',
'Exception.JKingWeb/Arsse/Feed/Exception.subscriptionNotFound' => 'Unable to find a feed at location "{url}"',

6
tests/cases/Feed/TestFetching.php

@ -28,7 +28,7 @@ class TestFetching extends \JKingWeb\Arsse\Test\AbstractTest {
}
public function testHandle400(): void {
$this->assertException("unsupportedFeedFormat", "Feed");
$this->assertException("transmissionError", "Feed");
new Feed(null, $this->base."Fetching/Error?code=400");
}
@ -48,12 +48,12 @@ class TestFetching extends \JKingWeb\Arsse\Test\AbstractTest {
}
public function testHandle500(): void {
$this->assertException("unsupportedFeedFormat", "Feed");
$this->assertException("transmissionError", "Feed");
new Feed(null, $this->base."Fetching/Error?code=500");
}
public function testHandleARedirectLoop(): void {
$this->assertException("maxRedirect", "Feed");
$this->assertException("tooManyRedirects", "Feed");
new Feed(null, $this->base."Fetching/EndlessLoop?i=0");
}

Loading…
Cancel
Save