diff --git a/composer.json b/composer.json index fd2ca0d..a63b574 100644 --- a/composer.json +++ b/composer.json @@ -3,10 +3,10 @@ "preferred-install": "dist" }, "require": { - "fguillot/simple-validator": "dev-master", - "fguillot/json-rpc": "dev-master", - "fguillot/picodb": "0.0.2", - "fguillot/picofeed": "dev-master", + "fguillot/simple-validator": "v0.0.3", + "fguillot/json-rpc": "v0.0.3", + "fguillot/picodb": "v0.0.3", + "fguillot/picofeed": "v0.1.4", "fguillot/picofarad": "dev-master" }, "autoload": { diff --git a/vendor/autoload.php b/vendor/autoload.php index 60bac52..f24ff95 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInitf813f763f87d109605f7c55600b459d5::getLoader(); +return ComposerAutoloaderInit3973a10bce966c867b4a041e7bc913b0::getLoader(); diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index 5e1469e..70d78bc 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -54,8 +54,6 @@ class ClassLoader private $useIncludePath = false; private $classMap = array(); - private $classMapAuthoritative = false; - public function getPrefixes() { if (!empty($this->prefixesPsr0)) { @@ -250,27 +248,6 @@ class ClassLoader return $this->useIncludePath; } - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoritative - */ - public function setClassMapAuthoritative($classMapAuthoritative) - { - $this->classMapAuthoritative = $classMapAuthoritative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function isClassMapAuthoritative() - { - return $this->classMapAuthoritative; - } - /** * Registers this instance as an autoloader. * @@ -322,9 +299,6 @@ class ClassLoader if (isset($this->classMap[$class])) { return $this->classMap[$class]; } - if ($this->classMapAuthoritative) { - return false; - } $file = $this->findFileWithExtension($class, '.php'); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 22338e2..b1ca374 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'JsonRPC\\AuthenticationFailure' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Server.php', 'JsonRPC\\Client' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Client.php', 'JsonRPC\\InvalidJsonFormat' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Server.php', 'JsonRPC\\InvalidJsonRpcFormat' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Server.php', diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index e346483..c68bc33 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitf813f763f87d109605f7c55600b459d5 +class ComposerAutoloaderInit3973a10bce966c867b4a041e7bc913b0 { private static $loader; @@ -19,9 +19,9 @@ class ComposerAutoloaderInitf813f763f87d109605f7c55600b459d5 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInitf813f763f87d109605f7c55600b459d5', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit3973a10bce966c867b4a041e7bc913b0', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInitf813f763f87d109605f7c55600b459d5', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit3973a10bce966c867b4a041e7bc913b0', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ class ComposerAutoloaderInitf813f763f87d109605f7c55600b459d5 $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequiref813f763f87d109605f7c55600b459d5($file); + composerRequire3973a10bce966c867b4a041e7bc913b0($file); } return $loader; } } -function composerRequiref813f763f87d109605f7c55600b459d5($file) +function composerRequire3973a10bce966c867b4a041e7bc913b0($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 89498fc..211005e 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,43 +1,4 @@ [ - { - "name": "fguillot/picodb", - "version": "v0.0.2", - "version_normalized": "0.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/fguillot/picoDb.git", - "reference": "b3ef5f79e7e5e33729fdbf9c02c8a252a3d76b6b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fguillot/picoDb/zipball/b3ef5f79e7e5e33729fdbf9c02c8a252a3d76b6b", - "reference": "b3ef5f79e7e5e33729fdbf9c02c8a252a3d76b6b", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2015-01-25 16:20:14", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "PicoDb": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "WTFPL" - ], - "authors": [ - { - "name": "Frédéric Guillot", - "homepage": "http://fredericguillot.com" - } - ], - "description": "Minimalist database query builder", - "homepage": "https://github.com/fguillot/picoDb" - }, { "name": "fguillot/picofarad", "version": "dev-master", @@ -79,8 +40,8 @@ }, { "name": "fguillot/simple-validator", - "version": "dev-master", - "version_normalized": "9999999-dev", + "version": "v0.0.3", + "version_normalized": "0.0.3.0", "source": { "type": "git", "url": "https://github.com/fguillot/simpleValidator.git", @@ -117,23 +78,23 @@ }, { "name": "fguillot/json-rpc", - "version": "dev-master", - "version_normalized": "9999999-dev", + "version": "v0.0.3", + "version_normalized": "0.0.3.0", "source": { "type": "git", "url": "https://github.com/fguillot/JsonRPC.git", - "reference": "1a397be7739ddabba87b07f0354655bd91087518" + "reference": "ef2f1aa1c07f0e3e8878c53b3a5fc81daedbebb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/1a397be7739ddabba87b07f0354655bd91087518", - "reference": "1a397be7739ddabba87b07f0354655bd91087518", + "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/ef2f1aa1c07f0e3e8878c53b3a5fc81daedbebb8", + "reference": "ef2f1aa1c07f0e3e8878c53b3a5fc81daedbebb8", "shasum": "" }, "require": { "php": ">=5.3.0" }, - "time": "2015-04-14 01:50:16", + "time": "2015-05-20 15:08:40", "type": "library", "installation-source": "dist", "autoload": { @@ -155,18 +116,57 @@ "homepage": "https://github.com/fguillot/JsonRPC" }, { - "name": "fguillot/picofeed", - "version": "dev-master", - "version_normalized": "9999999-dev", + "name": "fguillot/picodb", + "version": "v0.0.3", + "version_normalized": "0.0.3.0", "source": { "type": "git", - "url": "https://github.com/fguillot/picoFeed.git", - "reference": "a6087e8264550891c1b8a6da77eca0cab9328709" + "url": "https://github.com/fguillot/picoDb.git", + "reference": "f65d11cb52de34e0fd236a34184ca1a310da244a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fguillot/picoFeed/zipball/a6087e8264550891c1b8a6da77eca0cab9328709", - "reference": "a6087e8264550891c1b8a6da77eca0cab9328709", + "url": "https://api.github.com/repos/fguillot/picoDb/zipball/f65d11cb52de34e0fd236a34184ca1a310da244a", + "reference": "f65d11cb52de34e0fd236a34184ca1a310da244a", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2015-05-17 23:57:05", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "PicoDb": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frédéric Guillot", + "homepage": "http://fredericguillot.com" + } + ], + "description": "Minimalist database query builder", + "homepage": "https://github.com/fguillot/picoDb" + }, + { + "name": "fguillot/picofeed", + "version": "v0.1.4", + "version_normalized": "0.1.4.0", + "source": { + "type": "git", + "url": "https://github.com/fguillot/picoFeed.git", + "reference": "efa4a3ff139d147ac294070d8b60005abefa19ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fguillot/picoFeed/zipball/efa4a3ff139d147ac294070d8b60005abefa19ad", + "reference": "efa4a3ff139d147ac294070d8b60005abefa19ad", "shasum": "" }, "require": { @@ -180,7 +180,7 @@ "suggest": { "ext-curl": "PicoFeed will use cURL if present" }, - "time": "2015-04-27 22:22:06", + "time": "2015-06-21 13:45:50", "bin": [ "picofeed" ], diff --git a/vendor/fguillot/json-rpc/README.markdown b/vendor/fguillot/json-rpc/README.markdown index 38c8430..a0793bf 100644 --- a/vendor/fguillot/json-rpc/README.markdown +++ b/vendor/fguillot/json-rpc/README.markdown @@ -57,6 +57,8 @@ $server->register('random', function ($start, $end) { // Return the response to the client echo $server->execute(); + +?> ``` Class/Method binding: @@ -85,9 +87,57 @@ $server->bind('mySecondProcedure', new Api, 'doSomething'); // The procedure and the method are the same $server->bind('doSomething', 'Api'); +// Attach the class, client will be able to call directly Api::doSomething() +$server->attach(new Api); + echo $server->execute(); + +?> ``` +Before callback: + +Before each procedure execution, a custom method can be called. + +This method receive the following arguments: `$username, $password, $class, $method`. + +```php +authentication(['myuser' => 'mypassword']); + +// Register the before callback +$server->before('beforeProcedure'); + +$server->attach(new Api); + +echo $server->execute(); + +?> +``` + +You can use this method to implements a custom authentication system or anything else. +If you would like to reject the authentication, you can throw the exception `JsonRPC\AuthenticationFailure`. + ### Client Example with positional parameters: @@ -108,8 +158,6 @@ Example with named arguments: ```php authentication(['jsonrpc' => 'toto']); +$server->authentication(['user1' => 'password1', 'user2' => 'password2']); // Procedures registration @@ -258,7 +306,57 @@ On the client, set credentials like that: use JsonRPC\Client; $client = new Client('http://localhost/server.php'); -$client->authentication('jsonrpc', 'toto'); +$client->authentication('user1', 'password1'); ``` If the authentication failed, the client throw a RuntimeException. + +Using an alternative authentication header: + +```php + +use JsonRPC\Server; + +$server = new Server; +$server->setAuthenticationHeader('X-Authentication'); +$server->authentication(['myusername' => 'mypassword']); +``` + +The example above will use the HTTP header `X-Authentication` instead of the standard `Authorization: Basic [BASE64_CREDENTIALS]`. +The username/password values need be encoded in base64: `base64_encode('username:password')`. + +### Exceptions + +If you want to send an error to the client you can throw an exception. +You should configure which exceptions should be relayed to the client first: + +```php +attachException('MyException'); + +// Procedures registration + +[...] + +// Return the response to the client +echo $server->execute(); +``` + +Then you can throw that exception inside your procedure: + +``` +throw new MyException("An error occured", 123); +``` + +To relay all exceptions regardless of type, leave out the exception class name: + +``` +$server->attachException(); +``` diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Client.php b/vendor/fguillot/json-rpc/src/JsonRPC/Client.php index 37ab6d5..e0c65f1 100644 --- a/vendor/fguillot/json-rpc/src/JsonRPC/Client.php +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Client.php @@ -23,6 +23,15 @@ class Client */ private $url; + /** + * If the only argument passed to a function is an array + * assume it contains named arguments + * + * @access public + * @var boolean + */ + public $named_arguments = true; + /** * HTTP client timeout * @@ -78,7 +87,6 @@ class Client * @var array */ private $headers = array( - 'Connection: close', 'Content-Type: application/json', 'Accept: application/json' ); @@ -89,6 +97,13 @@ class Client */ public $ssl_verify_peer = true; + /** + * cURL handle + * + * @access private + */ + private $ch; + /** * Constructor * @@ -102,6 +117,17 @@ class Client $this->url = $url; $this->timeout = $timeout; $this->headers = array_merge($this->headers, $headers); + $this->ch = curl_init(); + } + + /** + * Destructor + * + * @access public + */ + public function __destruct() + { + curl_close($this->ch); } /** @@ -115,7 +141,7 @@ class Client public function __call($method, array $params) { // Allow to pass an array and use named arguments - if (count($params) === 1 && is_array($params[0])) { + if ($this->named_arguments && count($params) === 1 && is_array($params[0])) { $params = $params[0]; } @@ -284,25 +310,29 @@ class Client */ public function doRequest($payload) { - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, $this->url); - curl_setopt($ch, CURLOPT_HEADER, false); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->timeout); - curl_setopt($ch, CURLOPT_USERAGENT, 'JSON-RPC PHP Client'); - curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->ssl_verify_peer); - curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); + curl_setopt_array($this->ch, array( + CURLOPT_URL => $this->url, + CURLOPT_HEADER => false, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_CONNECTTIMEOUT => $this->timeout, + CURLOPT_USERAGENT => 'JSON-RPC PHP Client', + CURLOPT_HTTPHEADER => $this->headers, + CURLOPT_FOLLOWLOCATION => false, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_SSL_VERIFYPEER => $this->ssl_verify_peer, + CURLOPT_POSTFIELDS => json_encode($payload) + )); if ($this->username && $this->password) { - curl_setopt($ch, CURLOPT_USERPWD, $this->username.':'.$this->password); + curl_setopt($this->ch, CURLOPT_USERPWD, $this->username.':'.$this->password); } - $http_body = curl_exec($ch); - $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $http_body = curl_exec($this->ch); + $http_code = curl_getinfo($this->ch, CURLINFO_HTTP_CODE); + + if (curl_errno($this->ch)) { + throw new RuntimeException(curl_error($this->ch)); + } if ($http_code === 401 || $http_code === 403) { throw new RuntimeException('Access denied'); @@ -315,8 +345,6 @@ class Client error_log('==> Response: '.PHP_EOL.json_encode($response, JSON_PRETTY_PRINT)); } - curl_close($ch); - return is_array($response) ? $response : array(); } } diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Server.php b/vendor/fguillot/json-rpc/src/JsonRPC/Server.php index 0213fd2..d0dba62 100644 --- a/vendor/fguillot/json-rpc/src/JsonRPC/Server.php +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Server.php @@ -12,6 +12,7 @@ use ReflectionMethod; class InvalidJsonRpcFormat extends Exception {}; class InvalidJsonFormat extends Exception {}; +class AuthenticationFailure extends Exception {}; /** * JsonRPC server class @@ -33,7 +34,6 @@ class Server /** * List of procedures * - * @static * @access private * @var array */ @@ -42,7 +42,6 @@ class Server /** * List of classes * - * @static * @access private * @var array */ @@ -51,12 +50,43 @@ class Server /** * List of instances * - * @static * @access private * @var array */ private $instances = array(); + /** + * List of exception classes that should be relayed to client + * + * @access private + * @var array + */ + private $exceptions = array(); + + /** + * Method name to execute before the procedure + * + * @access private + * @var string + */ + private $before = ''; + + /** + * Username + * + * @access private + * @var string + */ + private $username = ''; + + /** + * Password + * + * @access private + * @var string + */ + private $password = ''; + /** * Constructor * @@ -70,6 +100,78 @@ class Server $this->payload = $payload; $this->callbacks = $callbacks; $this->classes = $classes; + + + } + + /** + * Define alternative authentication header + * + * @access public + * @param string $header Header name + * @return Server + */ + public function setAuthenticationHeader($header) + { + if (! empty($header)) { + + $header = 'HTTP_'.str_replace('-', '_', strtoupper($header)); + + if (isset($_SERVER[$header])) { + list($this->username, $this->password) = explode(':', @base64_decode($_SERVER[$header])); + } + } + + return $this; + } + + /** + * Get username + * + * @access public + * @return string + */ + public function getUsername() + { + return $this->username ?: @$_SERVER['PHP_AUTH_USER']; + } + + /** + * Get password + * + * @access public + * @return string + */ + public function getPassword() + { + return $this->password ?: @$_SERVER['PHP_AUTH_PW']; + } + + /** + * Send authentication failure response + * + * @access public + */ + public function sendAuthenticationFailureResponse() + { + header('WWW-Authenticate: Basic realm="JsonRPC"'); + header('Content-Type: application/json'); + header('HTTP/1.0 401 Unauthorized'); + echo '{"error": "Authentication failed"}'; + exit; + } + + /** + * Send forbidden response + * + * @access public + */ + public function sendForbiddenResponse() + { + header('Content-Type: application/json'); + header('HTTP/1.0 403 Forbidden'); + echo '{"error": "Access Forbidden"}'; + exit; } /** @@ -80,14 +182,10 @@ class Server * @access public * @param array $hosts List of hosts */ - public function allowHosts(array $hosts) { - + public function allowHosts(array $hosts) + { if (! in_array($_SERVER['REMOTE_ADDR'], $hosts)) { - - header('Content-Type: application/json'); - header('HTTP/1.0 403 Forbidden'); - echo '{"error": "Access Forbidden"}'; - exit; + $this->sendForbiddenResponse(); } } @@ -98,19 +196,15 @@ class Server * * @access public * @param array $users Map of username/password + * @return Server */ public function authentication(array $users) { - if (! isset($_SERVER['PHP_AUTH_USER']) || - ! isset($users[$_SERVER['PHP_AUTH_USER']]) || - $users[$_SERVER['PHP_AUTH_USER']] !== $_SERVER['PHP_AUTH_PW']) { - - header('WWW-Authenticate: Basic realm="JsonRPC"'); - header('Content-Type: application/json'); - header('HTTP/1.0 401 Unauthorized'); - echo '{"error": "Authentication failed"}'; - exit; + if (! isset($users[$this->getUsername()]) || $users[$this->getUsername()] !== $this->getPassword()) { + $this->sendAuthenticationFailureResponse(); } + + return $this; } /** @@ -119,10 +213,12 @@ class Server * @access public * @param string $procedure Procedure name * @param closure $callback Callback + * @return Server */ public function register($name, Closure $callback) { $this->callbacks[$name] = $callback; + return $this; } /** @@ -132,6 +228,7 @@ class Server * @param string $procedure Procedure name * @param mixed $class Class name or instance * @param string $method Procedure name + * @return Server */ public function bind($procedure, $class, $method = '') { @@ -140,6 +237,7 @@ class Server } $this->classes[$procedure] = array($class, $method); + return $this; } /** @@ -147,10 +245,39 @@ class Server * * @access public * @param mixed $instance Instance name + * @return Server */ public function attach($instance) { $this->instances[] = $instance; + return $this; + } + + /** + * Bind an exception + * If this exception occurs it is relayed to the client as JSON-RPC error + * + * @access public + * @param mixed $exception Exception class. Defaults to all. + * @return Server + */ + public function attachException($exception = 'Exception') + { + $this->exceptions[] = $exception; + return $this; + } + + /** + * Attach a method that will be called before the procedure + * + * @access public + * @param string $before + * @return Server + */ + public function before($before) + { + $this->before = $before; + return $this; } /** @@ -327,6 +454,25 @@ class Server $this->payload ); } + catch (AuthenticationFailure $e) { + $this->sendAuthenticationFailureResponse(); + } + catch (Exception $e) { + + foreach ($this->exceptions as $class) { + if ($e instanceof $class) { + return $this->getResponse(array( + 'error' => array( + 'code' => $e->getCode(), + 'message' => $e->getMessage() + )), + $this->payload + ); + } + } + + throw $e; + } } /** @@ -342,7 +488,7 @@ class Server if (isset($this->callbacks[$procedure])) { return $this->executeCallback($this->callbacks[$procedure], $params); } - else if (isset($this->classes[$procedure])) { + else if (isset($this->classes[$procedure]) && method_exists($this->classes[$procedure][0], $this->classes[$procedure][1])) { return $this->executeMethod($this->classes[$procedure][0], $this->classes[$procedure][1], $params); } @@ -388,6 +534,13 @@ class Server */ public function executeMethod($class, $method, $params) { + $instance = is_string($class) ? new $class : $class; + + // Execute before action + if (! empty($this->before) && method_exists($instance, $this->before)) { + $instance->{$this->before}($this->getUsername(), $this->getPassword(), get_class($class), $method); + } + $reflection = new ReflectionMethod($class, $method); $arguments = $this->getArguments( @@ -397,10 +550,7 @@ class Server $reflection->getNumberOfParameters() ); - return $reflection->invokeArgs( - is_string($class) ? new $class : $class, - $arguments - ); + return $reflection->invokeArgs($instance, $arguments); } /** diff --git a/vendor/fguillot/json-rpc/tests/ServerProcedureTest.php b/vendor/fguillot/json-rpc/tests/ServerProcedureTest.php index 5232dcd..636b383 100644 --- a/vendor/fguillot/json-rpc/tests/ServerProcedureTest.php +++ b/vendor/fguillot/json-rpc/tests/ServerProcedureTest.php @@ -40,7 +40,7 @@ class ServerProcedureTest extends PHPUnit_Framework_TestCase } /** - * @expectedException ReflectionException + * @expectedException BadFunctionCallException */ public function testClassNotFound() { @@ -50,7 +50,7 @@ class ServerProcedureTest extends PHPUnit_Framework_TestCase } /** - * @expectedException ReflectionException + * @expectedException BadFunctionCallException */ public function testMethodNotFound() { diff --git a/vendor/fguillot/picodb/LICENSE b/vendor/fguillot/picodb/LICENSE new file mode 100644 index 0000000..6a362bc --- /dev/null +++ b/vendor/fguillot/picodb/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Frederic Guillot + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/fguillot/picodb/README.md b/vendor/fguillot/picodb/README.md index 6867679..69700e4 100644 --- a/vendor/fguillot/picodb/README.md +++ b/vendor/fguillot/picodb/README.md @@ -12,7 +12,7 @@ Features - Requires only PDO - Use prepared statements - Handle schema versions (migrations) -- License: [WTFPL](http://www.wtfpl.net) +- License: MIT Requirements ------------ @@ -124,7 +124,7 @@ or $db->table('toto')->desc('column1')->findAll(); ``` -or +or ```php #db->table('toto')->orderBy('column1', 'ASC')->findAll(); diff --git a/vendor/fguillot/picodb/composer.json b/vendor/fguillot/picodb/composer.json index b1ba885..140fd54 100644 --- a/vendor/fguillot/picodb/composer.json +++ b/vendor/fguillot/picodb/composer.json @@ -3,7 +3,7 @@ "description": "Minimalist database query builder", "homepage": "https://github.com/fguillot/picoDb", "type": "library", - "license": "WTFPL", + "license": "MIT", "authors": [ { "name": "Frédéric Guillot", diff --git a/vendor/fguillot/picodb/lib/PicoDb/Database.php b/vendor/fguillot/picodb/lib/PicoDb/Database.php index d9ac615..e02fd13 100644 --- a/vendor/fguillot/picodb/lib/PicoDb/Database.php +++ b/vendor/fguillot/picodb/lib/PicoDb/Database.php @@ -248,7 +248,7 @@ class Database $this->setLogMessage($e->getMessage()); - throw new RuntimeException('SQL error'); + throw new RuntimeException('SQL error'.($this->log_queries ? ': '.$e->getMessage() : '')); } } diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php index 27d4cbd..c90a49c 100644 --- a/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php +++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php @@ -27,6 +27,10 @@ class Mysql extends PDO $dsn = 'mysql:host='.$settings['hostname'].';dbname='.$settings['database'].';charset='.$settings['charset']; + if (! empty($settings['port'])) { + $dsn .= ';port='.$settings['port']; + } + $options = array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET sql_mode = STRICT_ALL_TABLES', ); diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php index d9fadbe..71aa638 100644 --- a/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php +++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php @@ -26,6 +26,10 @@ class Postgres extends PDO $dsn = 'pgsql:host='.$settings['hostname'].';dbname='.$settings['database']; + if (! empty($settings['port'])) { + $dsn .= ';port='.$settings['port']; + } + parent::__construct($dsn, $settings['username'], $settings['password']); if (isset($settings['schema_table'])) { @@ -66,7 +70,7 @@ class Postgres extends PDO public function escapeIdentifier($value) { - return $value; + return '"'.$value.'"'; } public function operatorLikeCaseSensitive() diff --git a/vendor/fguillot/picodb/lib/PicoDb/Table.php b/vendor/fguillot/picodb/lib/PicoDb/Table.php index 43e6867..e6f145f 100644 --- a/vendor/fguillot/picodb/lib/PicoDb/Table.php +++ b/vendor/fguillot/picodb/lib/PicoDb/Table.php @@ -13,16 +13,22 @@ class Table protected $table_name = ''; protected $values = array(); + private $columns = array(); + private $sql_limit = ''; private $sql_offset = ''; private $sql_order = ''; + private $joins = array(); + + private $condition = ''; private $conditions = array(); private $or_conditions = array(); private $is_or_condition = false; - private $columns = array(); + private $distinct = false; private $group_by = array(); + private $filter_callback = null; /** @@ -82,7 +88,7 @@ class Table 'UPDATE %s SET %s %s', $this->db->escapeIdentifier($this->table_name), implode(', ', $columns), - $this->conditions() + $this->buildCondition() ); return $this->db->execute($sql, $values) !== false; @@ -124,7 +130,7 @@ class Table $sql = sprintf( 'DELETE FROM %s %s', $this->db->escapeIdentifier($this->table_name), - $this->conditions() + $this->buildCondition() ); $result = $this->db->execute($sql, $this->values); @@ -155,7 +161,7 @@ class Table $rq = $this->db->execute($this->buildSelectQuery(), $this->values); $results = $rq->fetchAll(PDO::FETCH_ASSOC); - if (is_callable($this->filter_callback)) { + if (is_callable($this->filter_callback) && ! empty($results)) { return call_user_func($this->filter_callback, $results); } @@ -227,7 +233,7 @@ class Table empty($this->columns) ? '*' : implode(', ', $this->columns), $this->db->escapeIdentifier($this->table_name), implode(' ', $this->joins), - $this->conditions(), + $this->buildCondition(), empty($this->group_by) ? '' : 'GROUP BY '.implode(', ', $this->group_by), $this->sql_order, $this->sql_limit, @@ -244,16 +250,37 @@ class Table public function count() { $sql = sprintf( - 'SELECT COUNT(*) FROM %s '.implode(' ', $this->joins).$this->conditions().$this->sql_order.$this->sql_limit.$this->sql_offset, + 'SELECT COUNT(*) FROM %s '.implode(' ', $this->joins).$this->buildCondition().$this->sql_order.$this->sql_limit.$this->sql_offset, $this->db->escapeIdentifier($this->table_name) ); $rq = $this->db->execute($sql, $this->values); - $result = $rq->fetchColumn(); + return $result ? (int) $result : 0; } + /** + * Sum + * + * @access public + * @param string $column + * @return float + */ + public function sum($column) + { + $sql = sprintf( + 'SELECT SUM(%s) FROM %s '.implode(' ', $this->joins).$this->buildCondition().$this->sql_order.$this->sql_limit.$this->sql_offset, + $this->db->escapeIdentifier($column), + $this->db->escapeIdentifier($this->table_name) + ); + + $rq = $this->db->execute($sql, $this->values); + $result = $rq->fetchColumn(); + + return $result ? (float) $result : 0; + } + /** * Left join * @@ -262,14 +289,15 @@ class Table * @param string $foreign_column Foreign key on the join table * @param string $local_column Local column * @param string $local_table Local table + * @param string $alias Join table alias * @return \PicoDb\Table */ - public function join($table, $foreign_column, $local_column, $local_table = '') + public function join($table, $foreign_column, $local_column, $local_table = '', $alias = '') { $this->joins[] = sprintf( 'LEFT JOIN %s ON %s=%s', $this->db->escapeIdentifier($table), - $this->db->escapeIdentifier($table).'.'.$this->db->escapeIdentifier($foreign_column), + $this->db->escapeIdentifier($alias ?: $table).'.'.$this->db->escapeIdentifier($foreign_column), $this->db->escapeIdentifier($local_table ?: $this->table_name).'.'.$this->db->escapeIdentifier($local_column) ); @@ -277,13 +305,53 @@ class Table } /** - * Build conditions + * Left join * * @access public + * @param string $table1 + * @param string $alias1 + * @param string $column1 + * @param string $table2 + * @param string $column2 + * @return \PicoDb\Table + */ + public function left($table1, $alias1, $column1, $table2, $column2) + { + $this->joins[] = sprintf( + 'LEFT JOIN %s AS %s ON %s=%s', + $this->db->escapeIdentifier($table1), + $this->db->escapeIdentifier($alias1), + $this->db->escapeIdentifier($alias1).'.'.$this->db->escapeIdentifier($column1), + $this->db->escapeIdentifier($table2).'.'.$this->db->escapeIdentifier($column2) + ); + + return $this; + } + + /** + * Add custom condition + * + * @access private + * @return Table + */ + private function condition($condition) + { + $this->condition = $condition; + return $this; + } + + /** + * Build condition + * + * @access private * @return string */ - public function conditions() + private function buildCondition() { + if (! empty($this->condition)) { + return 'WHERE '.$this->condition; + } + return empty($this->conditions) ? '' : ' WHERE '.implode(' AND ', $this->conditions); } @@ -292,6 +360,7 @@ class Table * * @access public * @param string $sql + * @return Table */ public function addCondition($sql) { @@ -301,6 +370,8 @@ class Table else { $this->conditions[] = $sql; } + + return $this; } /** diff --git a/vendor/fguillot/picofeed/docs/favicon.markdown b/vendor/fguillot/picofeed/docs/favicon.markdown index b502169..b9ea73b 100644 --- a/vendor/fguillot/picofeed/docs/favicon.markdown +++ b/vendor/fguillot/picofeed/docs/favicon.markdown @@ -21,7 +21,7 @@ PicoFeed will try first to find the favicon from the meta tags and fallback to t When the HTML page is parsed, relative links and protocol relative links are converted to absolute url. -Download a know favicon +Download a known favicon ----------------------- It's possible to download a known favicon using the second optional parameter of Favicon::find(). The link to the favicon can be a relative or protocol relative url as well, but it has to be relative to the specified website. @@ -93,4 +93,4 @@ $config->setClientUserAgent('My RSS Reader'); $favicon = new Favicon($config); $favicon->find('https://github.com'); -``` \ No newline at end of file +``` diff --git a/vendor/fguillot/picofeed/docs/installation.markdown b/vendor/fguillot/picofeed/docs/installation.markdown index ecc6b3b..eb8706b 100644 --- a/vendor/fguillot/picofeed/docs/installation.markdown +++ b/vendor/fguillot/picofeed/docs/installation.markdown @@ -5,7 +5,7 @@ Versions -------- - Development version: master -- Stable version: v0.1.3 +- Stable version: v0.1.4 Installation with Composer -------------------------- @@ -15,7 +15,7 @@ Configure your `composer.json`: ```json { "require": { - "fguillot/picofeed": "0.1.3" + "fguillot/picofeed": "0.1.4" } } ``` @@ -23,7 +23,7 @@ Configure your `composer.json`: Or simply: ```bash -composer require fguillot/picofeed:0.1.3 +composer require fguillot/picofeed:0.1.4 ``` And download the code: diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php b/vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php index 72afe92..36c5ca6 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Client/Stream.php @@ -62,7 +62,7 @@ class Stream extends Client { foreach($headers as $header) { if (stripos($header, 'Location') === 0) { - list($name, $value) = explode(': ', $header); + list(, $value) = explode(': ', $header); $this->url = Url::resolve($value, $this->url); } diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Encoding/Encoding.php b/vendor/fguillot/picofeed/lib/PicoFeed/Encoding/Encoding.php index 0590c47..5821dd4 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Encoding/Encoding.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Encoding/Encoding.php @@ -15,7 +15,21 @@ class Encoding return $input; } - // convert input to utf-8; ignore malformed characters - return iconv($encoding, 'UTF-8//IGNORE', $input); + // suppress all notices since it isn't possible to silence only the + // notice "Wrong charset, conversion from $in_encoding to $out_encoding is not allowed" + set_error_handler(function() {}, E_NOTICE); + + // convert input to utf-8 and strip invalid characters + $value = iconv($encoding, 'UTF-8//IGNORE', $input); + + // stop silencing of notices + restore_error_handler(); + + // return input if something went wrong, maybe it's usable anyway + if ($value === false) { + return $input; + } + + return $value; } } diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Filter/Filter.php b/vendor/fguillot/picofeed/lib/PicoFeed/Filter/Filter.php index 123f989..e3e4ad3 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Filter/Filter.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Filter/Filter.php @@ -107,7 +107,7 @@ class Filter } /** - * Dirty quickfixes before XML parsing + * Fixes before XML parsing * * @static * @access public @@ -116,17 +116,37 @@ class Filter */ public static function normalizeData($data) { - $invalid_chars = array( - "\x10", - "\xc3\x20", - "", - "\xe2\x80\x9c\x08", + $entities = array( + '/(&#)(\d+);/m', // decimal encoded + '/(&#x)([a-f0-9]+);/mi', // hex encoded ); - foreach ($invalid_chars as $needle) { - $data = str_replace($needle, '', $data); - } + // strip invalid XML 1.0 characters which are encoded as entities + $data = preg_replace_callback($entities, function($matches) { + $code_point = $matches[2]; - return $data; + // convert hex entity to decimal + if (strtolower($matches[1]) === '&#x') { + $code_point = hexdec($code_point); + } + + $code_point = (int) $code_point; + + // replace invalid characters + if ($code_point < 9 + || ($code_point > 10 && $code_point < 13) + || ($code_point > 13 && $code_point < 32) + || ($code_point > 55295 && $code_point < 57344) + || ($code_point > 65533 && $code_point < 65536) + || $code_point > 1114111 + ) { + return ''; + }; + + return $matches[0]; + }, $data); + + // strip every utf-8 character than isn't in the range of valid XML 1.0 characters + return (string) preg_replace('/[^\x{0009}\x{000A}\x{000D}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/u', '', $data); } } diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Parser/DateParser.php b/vendor/fguillot/picofeed/lib/PicoFeed/Parser/DateParser.php index 92d0012..4612a86 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Parser/DateParser.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Parser/DateParser.php @@ -88,7 +88,7 @@ class DateParser * @access public * @param string $format Date format * @param string $value Original date value - * @return DateTime + * @return DateTime|boolean */ public function getValidDate($format, $value) { diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Parser/Parser.php b/vendor/fguillot/picofeed/lib/PicoFeed/Parser/Parser.php index 810494b..b2b05e1 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Parser/Parser.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Parser/Parser.php @@ -117,9 +117,6 @@ abstract class Parser // Encode everything in UTF-8 Logger::setMessage(get_called_class().': HTTP Encoding "'.$http_encoding.'" ; XML Encoding "'.$xml_encoding.'"'); $this->content = Encoding::convert($this->content, $xml_encoding ?: $http_encoding); - - // Workarounds - $this->content = Filter::normalizeData($this->content); } /** @@ -135,9 +132,15 @@ abstract class Parser $xml = XmlParser::getSimpleXml($this->content); if ($xml === false) { - Logger::setMessage(get_called_class().': XML parsing error'); - Logger::setMessage(XmlParser::getErrors()); - throw new MalformedXmlException('XML parsing error'); + Logger::setMessage(get_called_class().': Applying XML workarounds'); + $this->content = Filter::normalizeData($this->content); + $xml = XmlParser::getSimpleXml($this->content); + + if ($xml === false) { + Logger::setMessage(get_called_class().': XML parsing error'); + Logger::setMessage(XmlParser::getErrors()); + throw new MalformedXmlException('XML parsing error'); + } } $this->namespaces = $xml->getNamespaces(true); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Parser/Rss20.php b/vendor/fguillot/picofeed/lib/PicoFeed/Parser/Rss20.php index 2529b59..84b6e0f 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Parser/Rss20.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Parser/Rss20.php @@ -23,7 +23,13 @@ class Rss20 extends Parser */ public function getItemsTree(SimpleXMLElement $xml) { - return $xml->channel->item; + $items = array(); + + if (isset($xml->channel->item)) { + $items = $xml->channel->item; + } + + return $items; } /** diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/abstrusegoose.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/abstrusegoose.com.php new file mode 100644 index 0000000..1d103c2 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/abstrusegoose.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%alt="(.+)" title="(.+)" */>%' => "/>
$1
$2" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/amazingsuperpowers.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/amazingsuperpowers.com.php new file mode 100644 index 0000000..b773c6f --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/amazingsuperpowers.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/anythingcomic.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/anythingcomic.com.php new file mode 100644 index 0000000..df8b8b7 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/anythingcomic.com.php @@ -0,0 +1,13 @@ + array( + '%.*%' => array( + 'body' => array( + '//img[@id="comic_image"]', + '//div[@class="comment-wrapper"][position()=1]' + ), + 'strip' => array(), + 'test_url' => 'http://www.anythingcomic.com/comics/2108929/stress-free/', + ) + ), +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/buttersafe.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/buttersafe.com.php new file mode 100644 index 0000000..eda3f19 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/buttersafe.com.php @@ -0,0 +1,13 @@ + array( + '%.*%' => array( + 'test_url' => 'http://buttersafe.com/2015/04/21/the-incredible-flexible-man/', + 'body' => array( + '//div[@id="comic"]', + '//div[@class="post-comic"]', + ), + 'strip' => array() + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/channelate.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/channelate.com.php new file mode 100644 index 0000000..68475cb --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/channelate.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%href="http://www.channelate.com/(\\d+)/(\\d+)/(\\d+)/[^"]*"%' => 'href="http://www.channelate.com/extra-panel/$1$2$3/"' + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/cowbirdsinlove.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/cowbirdsinlove.com.php new file mode 100644 index 0000000..b773c6f --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/cowbirdsinlove.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/drawingboardcomic.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/drawingboardcomic.com.php new file mode 100644 index 0000000..e5ade2e --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/drawingboardcomic.com.php @@ -0,0 +1,15 @@ + array( + '%.*%' => array( + 'body' => array('//img[@id="comicimage"]'), + 'strip' => array(), + 'test_url' => 'http://drawingboardcomic.com/index.php?comic=208', + ) + ), + 'filter' => array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/endlessorigami.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/endlessorigami.com.php new file mode 100644 index 0000000..4dd63da --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/endlessorigami.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%-\\d+x\\d+%' => "", + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/escapistmagazine.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/escapistmagazine.com.php index 6b6b20b..eaa6a42 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/escapistmagazine.com.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/escapistmagazine.com.php @@ -35,7 +35,12 @@ return array( 'body' => array('//*[@class="body"]'), 'test_url' => 'http://www.escapistmagazine.com/articles/view/comicsandcosplay/comics/fraughtwithperil/12166-The-Escapist-Presents-Escapist-Comics-Critical-Miss-B-lyeh-Fhlop?utm_source=rss&utm_medium=rss&utm_campaign=articles', 'strip' => array() - ) + ), + '%/articles/view/video-games/columns/.*%' => array( + 'body' => array('//*[@id="article_content"]'), + 'test_url' => 'http://www.escapistmagazine.com/articles/view/video-games/columns/experienced-points/13971-What-50-Shades-and-Batman-Have-in-Common.2', + 'strip' => array() + ), ) ); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/exocomics.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/exocomics.com.php new file mode 100644 index 0000000..406e25f --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/exocomics.com.php @@ -0,0 +1,15 @@ + array( + '%.*%' => array( + 'body' => array('//a[@class="comic"]/img'), + 'strip' => array(), + 'test_url' => 'http://www.exocomics.com/379', + ) + ), + 'filter' => array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/explosm.net.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/explosm.net.php index 83a0890..3a65871 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/explosm.net.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/explosm.net.php @@ -5,6 +5,7 @@ return array( 'test_url' => 'http://explosm.net/comics/3803/', 'body' => array( '//div[@id="comic-container"]', + '//div[@id="comic-container"]//img/@src' ), 'strip' => array( ), diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/extrafabulouscomics.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/extrafabulouscomics.com.php new file mode 100644 index 0000000..6f0fbec --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/extrafabulouscomics.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%-\\d+x\\d+%' => "", + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/giantitp.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/giantitp.com.php new file mode 100644 index 0000000..5acf091 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/giantitp.com.php @@ -0,0 +1,12 @@ + array( + '%/comics/oots.*%' => array( + 'test_url' => 'http://www.giantitp.com/comics/oots0989.html', + 'body' => array( + '//td[@align="center"]/img' + ), + 'strip' => array() + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/gocomics.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/gocomics.com.php new file mode 100644 index 0000000..b93f565 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/gocomics.com.php @@ -0,0 +1,12 @@ + array( + '%.*%' => array( + 'test_url' => 'http://www.gocomics.com/pearlsbeforeswine/2015/05/30', + 'body' => array( + '//div[1]/p[1]/a[1]/img', + ), + 'strip' => array(), + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/happletea.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/happletea.com.php new file mode 100644 index 0000000..1821c3b --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/happletea.com.php @@ -0,0 +1,18 @@ + array( + '%.*%' => array( + 'body' => array( + '//div[@id="comic"]', + '//div[@class="entry"]' + ), + 'strip' => array('//div[@class="ssba"]'), + 'test_url' => 'http://www.happletea.com/comic/mans-best-friend/', + ) + ), + 'filter' => array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/imogenquest.net.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/imogenquest.net.php new file mode 100644 index 0000000..b773c6f --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/imogenquest.net.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/invisiblebread.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/invisiblebread.com.php new file mode 100644 index 0000000..ac15132 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/invisiblebread.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%()%' => '$1' + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/ir.amd.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/ir.amd.com.php new file mode 100644 index 0000000..63a7dbb --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/ir.amd.com.php @@ -0,0 +1,10 @@ + array( + '%.*%' => array( + 'body' => array('//span[@class="ccbnTxt"]'), + 'strip' => array(), + 'test_url' => 'http://ir.amd.com/phoenix.zhtml?c=74093&p=RssLanding&cat=news&id=2055819', + ) + ), +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/lastplacecomics.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/lastplacecomics.com.php new file mode 100644 index 0000000..6f0fbec --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/lastplacecomics.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%-\\d+x\\d+%' => "", + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/loadingartist.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/loadingartist.com.php index 3e07a22..4dd63da 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/loadingartist.com.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/loadingartist.com.php @@ -1,10 +1,8 @@ array( - '%/comic.*%' => array( - 'test_url' => 'http://www.loadingartist.com/comic/lifted-spirits/', - 'body' => array('//div[@class="comic"]'), - 'strip' => array(), + 'filter' => array( + '%.*%' => array( + '%-\\d+x\\d+%' => "", ) ) -); \ No newline at end of file +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/lukesurl.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/lukesurl.com.php new file mode 100644 index 0000000..a1b98b1 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/lukesurl.com.php @@ -0,0 +1,15 @@ + array( + '%.*%' => array( + 'body' => array('//div[@id="comic"]//img'), + 'strip' => array(), + 'test_url' => 'http://www.lukesurl.com/archives/comic/665-3-of-clubs', + ) + ), + 'filter' => array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/marriedtothesea.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/marriedtothesea.com.php new file mode 100644 index 0000000..d42157b --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/marriedtothesea.com.php @@ -0,0 +1,12 @@ + array( + '%.*%' => array( + 'test_url' => 'http://www.marriedtothesea.com/index.php?date=052915', + 'body' => array( + '//div[@align]/a/img', + ), + 'strip' => array(), + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/marycagle.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/marycagle.com.php new file mode 100644 index 0000000..570953e --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/marycagle.com.php @@ -0,0 +1,13 @@ + array( + '%.*%' => array( + 'body' => array( + '//img[@id="cc-comic"]', + '//div[@class="cc-newsbody"]' + ), + 'strip' => array(), + 'test_url' => 'http://www.marycagle.com/letsspeakenglish/74-grim-reality/', + ) + ), +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/mrlovenstein.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/mrlovenstein.com.php new file mode 100644 index 0000000..4d8dc6e --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/mrlovenstein.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%alt="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/nedroid.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/nedroid.com.php new file mode 100644 index 0000000..b773c6f --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/nedroid.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/oglaf.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/oglaf.com.php new file mode 100644 index 0000000..d995907 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/oglaf.com.php @@ -0,0 +1,19 @@ + array( + '%.*%' => array( + 'body' => array( + '//img[@id="strip"]', + '//a/div[@id="nx"]/..' + ), + 'strip' => array(), + 'test_url' => 'http://oglaf.com/slodging/' + ) + ), + 'filter' => array( + '%.*%' => array( + '%alt="(.+)" title="(.+)" */>%' => "/>
$1
$2
", + '%%' => 'Next page', + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/optipess.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/optipess.com.php new file mode 100644 index 0000000..b773c6f --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/optipess.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/peebleslab.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/peebleslab.com.php new file mode 100644 index 0000000..43b5ed4 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/peebleslab.com.php @@ -0,0 +1,9 @@ + array( + '%.*%' => array( + // the extra space is required to strip the title cleanly + '%title="(.+) " */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/pixelbeat.org.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/pixelbeat.org.php new file mode 100644 index 0000000..4aeb388 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/pixelbeat.org.php @@ -0,0 +1,12 @@ + array( + '%.*%' => array( + 'test_url' => 'http://www.pixelbeat.org/programming/sigpipe_handling.html#1425573246', + 'body' => array( + '//div[@class="contentText"]', + ), + 'strip' => array(), + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/popstrip.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/popstrip.com.php new file mode 100644 index 0000000..1cc8fd9 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/popstrip.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%( '$1$2$1bonus.png"/>' + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/satwcomic.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/satwcomic.com.php index 173f563..067f8f9 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/satwcomic.com.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/satwcomic.com.php @@ -4,7 +4,8 @@ return array( '%.*%' => array( 'test_url' => 'http://satwcomic.com/day-at-the-beach', 'body' => array( - '//div[@class="container"]/center/a/img' + '//div[@class="container"]/center/a/img', + '//span[@itemprop="articleBody"]' ), 'strip' => array(), ) diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/sentfromthemoon.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/sentfromthemoon.com.php new file mode 100644 index 0000000..58bfc03 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/sentfromthemoon.com.php @@ -0,0 +1,18 @@ + array( + '%.*%' => array( + 'body' => array( + '//div[@class="comicpane"]/a/img', + '//div[@class="entry"]' + ), + 'strip' => array(), + 'test_url' => 'http://sentfromthemoon.com/archives/1417' + ) + ), + 'filter' => array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/smbc-comics.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/smbc-comics.com.php new file mode 100644 index 0000000..f339a40 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/smbc-comics.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%()%' => '$1$2$1after$2' + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/stupidfox.net.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/stupidfox.net.php new file mode 100644 index 0000000..d45551f --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/stupidfox.net.php @@ -0,0 +1,13 @@ + array( + '%.*%' => array( + 'test_url' => 'http://stupidfox.net/134-sleepy-time', + 'body' => array( + '//div[@class="comicmid"]/center/a/img', + '//div[@class="stand_high"]' + ), + 'strip' => array(), + ) + ) +); \ No newline at end of file diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/subtraction.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/subtraction.com.php new file mode 100644 index 0000000..a210a62 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/subtraction.com.php @@ -0,0 +1,15 @@ + array( + '%.*%' => array( + 'test_url' => 'http://www.subtraction.com/2015/06/06/time-lapse-video-of-one-world-trade-center/', + 'body' => array('//article/div[@class="entry-content"]'), + 'strip' => array() + ) + ), + 'filter' => array( + '%.*%' => array( + '%\+%' => '', + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/theawkwardyeti.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/theawkwardyeti.com.php new file mode 100644 index 0000000..6f0fbec --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/theawkwardyeti.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%-\\d+x\\d+%' => "", + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/thedoghousediaries.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/thedoghousediaries.com.php new file mode 100644 index 0000000..58bfc03 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/thedoghousediaries.com.php @@ -0,0 +1,18 @@ + array( + '%.*%' => array( + 'body' => array( + '//div[@class="comicpane"]/a/img', + '//div[@class="entry"]' + ), + 'strip' => array(), + 'test_url' => 'http://sentfromthemoon.com/archives/1417' + ) + ), + 'filter' => array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/treelobsters.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/treelobsters.com.php new file mode 100644 index 0000000..b773c6f --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/treelobsters.com.php @@ -0,0 +1,8 @@ + array( + '%.*%' => array( + '%title="(.+)" */>%' => "/>
$1" + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/voz.vn.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/voz.vn.php new file mode 100644 index 0000000..1aeb7d1 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/voz.vn.php @@ -0,0 +1,10 @@ + array( + '%.*%' => array( + 'body' => array('//div[@class="entry-content"]'), + 'strip' => array(), + 'test_url' => 'http://voz.vn/2015/06/06/muon-trai-nghiem-bphone-hay-den-fpt-shop/', + ) + ), +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/www.lemonde.fr.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/www.lemonde.fr.php deleted file mode 100644 index e72ddcf..0000000 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/www.lemonde.fr.php +++ /dev/null @@ -1,17 +0,0 @@ - array( - '%.*%' => array( - 'test_url' => array( - 'http://www.lemonde.fr/societe/article/2013/08/30/boris-boillon-ancien-ambassadeur-de-sarkozy-arrete-avec-350-000-euros-en-liquide_3469109_3224.html', - 'http://www.lemonde.fr/afrique/article/2015/04/06/plonge-dans-la-crise-l-angola-revele-son-vrai-visage_4610364_3212.html', - ), - 'body' => array( - '//div[@id="articleBody"]', - '//div[@itemprop="articleBody"]', - ), - 'strip' => array( - ), - ) - ) -); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/www.nextinpact.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/www.nextinpact.com.php deleted file mode 100644 index 2010e09..0000000 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/www.nextinpact.com.php +++ /dev/null @@ -1,13 +0,0 @@ - array( - '%.*%' => array( - 'test_url' => 'http://www.pcinpact.com/news/85954-air-france-ne-vous-demande-plus-deteindre-vos-appareils-electroniques.htm?utm_source=PCi_RSS_Feed&utm_medium=news&utm_campaign=pcinpact', - 'body' => array( - '//div[contains(@id, "actu_content")]', - ), - 'strip' => array( - ), - ) - ) -); \ No newline at end of file diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/www.zeit.de.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/www.zeit.de.php new file mode 100644 index 0000000..a952043 --- /dev/null +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/www.zeit.de.php @@ -0,0 +1,41 @@ + array( + '%^/zeit-magazin.*%' => array( + 'test_url' => 'http://www.zeit.de/zeit-magazin/2015/15/pegida-kathrin-oertel-lutz-bachmann', + 'body' => array( + '//article[@class="article"]' + ), + 'strip' => array( + '//header/div/h1', + '//header/div/div[@class="article__head__subtitle"]', + '//header/div/div[@class="article__column__author"]', + '//header/div/div[@class="article__column__author"]', + '//header/div/span[@class="article__head__meta-wrap"]', + '//form', + '//style', + '//div[contains(@class, "ad-tile")]', + '//div[@class="iqd-mobile-adplace"]', + '//div[@id="iq-artikelanker"]', + '//div[@id="js-social-services"]', + '//section[@id="js-comments"]', + '//aside' + ) + ), + '%.*%' => array( + 'test_url' => 'http://www.zeit.de/politik/ausland/2015-04/thessaloniki-krise-griechenland-yannis-boutaris/', + 'body' => array( + '//div[@class="article-body"]' + ), + 'strip' => array( + '//*[@class="articleheader"]', + '//*[@class="excerpt"]', + '//div[contains(@class, "ad")]', + '//div[@itemprop="video"]', + '//*[@class="articlemeta"]', + '//*[@class="articlemeta-clear"]', + '//*[@class="zol_inarticletools"]' + ) + ) + ) +); diff --git a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/xkcd.com.php b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/xkcd.com.php index 6f83cb8..4d8dc6e 100644 --- a/vendor/fguillot/picofeed/lib/PicoFeed/Rules/xkcd.com.php +++ b/vendor/fguillot/picofeed/lib/PicoFeed/Rules/xkcd.com.php @@ -1,13 +1,8 @@ array( + 'filter' => array( '%.*%' => array( - 'test_url' => 'http://xkcd.com/1472/', - 'body' => array( - '//div[@id="comic"]', - ), - 'strip' => array( - ), + '%alt="(.+)" */>%' => "/>
$1" ) ) ); diff --git a/vendor/fguillot/picofeed/tests/Filter/AttributeFilterTest.php b/vendor/fguillot/picofeed/tests/Filter/AttributeFilterTest.php index 5dcfda1..6c68ef4 100644 --- a/vendor/fguillot/picofeed/tests/Filter/AttributeFilterTest.php +++ b/vendor/fguillot/picofeed/tests/Filter/AttributeFilterTest.php @@ -4,6 +4,7 @@ namespace PicoFeed\Filter; use PHPUnit_Framework_TestCase; use PicoFeed\Client\Url; +use PicoFeed\Config\Config; class AttributeFilterTest extends PHPUnit_Framework_TestCase @@ -190,4 +191,134 @@ class AttributeFilterTest extends PHPUnit_Framework_TestCase $this->assertEquals('title=""a""', $filter->toHtml(array('title' => '"a"'))); $this->assertEquals('title="ç" alt="b"', $filter->toHtml(array('title' => 'ç', 'alt' => 'b'))); } + + public function testNoImageProxySet() + { + $f = Filter::html('

Image My Image

', 'http://foo'); + + $this->assertEquals( + '

Image My Image

', + $f->execute() + ); + } + + public function testImageProxyWithHTTPLink() + { + $config = new Config; + $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); + + $f = Filter::html('

Image My Image

', 'http://foo'); + $f->setConfig($config); + + $this->assertEquals( + '

Image My Image

', + $f->execute() + ); + } + + public function testImageProxyWithHTTPSLink() + { + $config = new Config; + $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); + + $f = Filter::html('

Image My Image

', 'http://foo'); + $f->setConfig($config); + + $this->assertEquals( + '

Image My Image

', + $f->execute() + ); + } + + public function testImageProxyLimitedToUnknownProtocol() + { + $config = new Config; + $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); + $config->setFilterImageProxyProtocol('tripleX'); + + $f = Filter::html('

Image My Image

', 'http://foo'); + $f->setConfig($config); + + $this->assertEquals( + '

Image My Image

', + $f->execute() + ); + } + + public function testImageProxyLimitedToHTTPwithHTTPLink() + { + $config = new Config; + $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); + $config->setFilterImageProxyProtocol('http'); + + $f = Filter::html('

Image My Image

', 'http://foo'); + $f->setConfig($config); + + $this->assertEquals( + '

Image My Image

', + $f->execute() + ); + } + + public function testImageProxyLimitedToHTTPwithHTTPSLink() + { + $config = new Config; + $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); + $config->setFilterImageProxyProtocol('http'); + + $f = Filter::html('

Image My Image

', 'http://foo'); + $f->setConfig($config); + + $this->assertEquals( + '

Image My Image

', + $f->execute() + ); + } + + public function testImageProxyLimitedToHTTPSwithHTTPLink() + { + $config = new Config; + $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); + $config->setFilterImageProxyProtocol('https'); + + $f = Filter::html('

Image My Image

', 'http://foo'); + $f->setConfig($config); + + $this->assertEquals( + '

Image My Image

', + $f->execute() + ); + } + + public function testImageProxyLimitedToHTTPSwithHTTPSLink() + { + $config = new Config; + $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); + $config->setFilterImageProxyProtocol('https'); + + $f = Filter::html('

Image My Image

', 'http://foo'); + $f->setConfig($config); + + $this->assertEquals( + '

Image My Image

', + $f->execute() + ); + } + + public function testsetFilterImageProxyCallback() + { + $config = new Config; + $config->setFilterImageProxyCallback(function ($image_url) { + $key = hash_hmac('sha1', $image_url, 'secret'); + return 'https://mypublicproxy/'.$key.'/'.rawurlencode($image_url); + }); + + $f = Filter::html('

Image My Image

', 'http://foo'); + $f->setConfig($config); + + $this->assertEquals( + '

Image My Image

', + $f->execute() + ); + } } diff --git a/vendor/fguillot/picofeed/tests/Filter/FilterTest.php b/vendor/fguillot/picofeed/tests/Filter/FilterTest.php index f5f98a9..9b4077b 100644 --- a/vendor/fguillot/picofeed/tests/Filter/FilterTest.php +++ b/vendor/fguillot/picofeed/tests/Filter/FilterTest.php @@ -91,133 +91,35 @@ class FilterTest extends PHPUnit_Framework_TestCase $this->assertEquals('

Testboo

', $f->execute()); } - public function testNoImageProxySet() + public function testNormalizeData() { - $f = Filter::html('

Image My Image

', 'http://foo'); + // invalid data link escape control character + $this->assertEquals('random text', Filter::normalizeData("random\x10 text")); + $this->assertEquals('random text', Filter::normalizeData("random text")); + $this->assertEquals('random text', Filter::normalizeData("random text")); - $this->assertEquals( - '

Image My Image

', - $f->execute() - ); - } + // invalid unit seperator control character (lower and upper case) + $this->assertEquals('random text', Filter::normalizeData("random\x1f text")); + $this->assertEquals('random text', Filter::normalizeData("random\x1F text")); + $this->assertEquals('random text', Filter::normalizeData("random text")); + $this->assertEquals('random text', Filter::normalizeData("random text")); + $this->assertEquals('random text', Filter::normalizeData("random text")); - public function testImageProxyWithHTTPLink() - { - $config = new Config; - $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); + /* + * Do not test invalid multibyte characters. The output depends on php + * version and character. + * + * php 5.3: always null + * php >5.3: sometime null, sometimes the stripped string + */ - $f = Filter::html('

Image My Image

', 'http://foo'); - $f->setConfig($config); + // invalid backspace control character + valid multibyte character + $this->assertEquals('“random“ text', Filter::normalizeData("\xe2\x80\x9crandom\xe2\x80\x9c\x08 text")); + $this->assertEquals('“random“ text', Filter::normalizeData("“random“ text")); + $this->assertEquals('“random“ text', Filter::normalizeData("“random“ text")); - $this->assertEquals( - '

Image My Image

', - $f->execute() - ); - } - - public function testImageProxyWithHTTPSLink() - { - $config = new Config; - $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); - - $f = Filter::html('

Image My Image

', 'http://foo'); - $f->setConfig($config); - - $this->assertEquals( - '

Image My Image

', - $f->execute() - ); - } - - public function testImageProxyLimitedToUnknownProtocol() - { - $config = new Config; - $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); - $config->setFilterImageProxyProtocol('tripleX'); - - $f = Filter::html('

Image My Image

', 'http://foo'); - $f->setConfig($config); - - $this->assertEquals( - '

Image My Image

', - $f->execute() - ); - } - - public function testImageProxyLimitedToHTTPwithHTTPLink() - { - $config = new Config; - $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); - $config->setFilterImageProxyProtocol('http'); - - $f = Filter::html('

Image My Image

', 'http://foo'); - $f->setConfig($config); - - $this->assertEquals( - '

Image My Image

', - $f->execute() - ); - } - - public function testImageProxyLimitedToHTTPwithHTTPSLink() - { - $config = new Config; - $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); - $config->setFilterImageProxyProtocol('http'); - - $f = Filter::html('

Image My Image

', 'http://foo'); - $f->setConfig($config); - - $this->assertEquals( - '

Image My Image

', - $f->execute() - ); - } - - public function testImageProxyLimitedToHTTPSwithHTTPLink() - { - $config = new Config; - $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); - $config->setFilterImageProxyProtocol('https'); - - $f = Filter::html('

Image My Image

', 'http://foo'); - $f->setConfig($config); - - $this->assertEquals( - '

Image My Image

', - $f->execute() - ); - } - - public function testImageProxyLimitedToHTTPSwithHTTPSLink() - { - $config = new Config; - $config->setFilterImageProxyUrl('http://myproxy/?url=%s'); - $config->setFilterImageProxyProtocol('https'); - - $f = Filter::html('

Image My Image

', 'http://foo'); - $f->setConfig($config); - - $this->assertEquals( - '

Image My Image

', - $f->execute() - ); - } - - public function testsetFilterImageProxyCallback() - { - $config = new Config; - $config->setFilterImageProxyCallback(function ($image_url) { - $key = hash_hmac('sha1', $image_url, 'secret'); - return 'https://mypublicproxy/'.$key.'/'.rawurlencode($image_url); - }); - - $f = Filter::html('

Image My Image

', 'http://foo'); - $f->setConfig($config); - - $this->assertEquals( - '

Image My Image

', - $f->execute() - ); + // do not convert valid entities to utf-8 character + $this->assertEquals('random text', Filter::normalizeData('random text')); + $this->assertEquals('random text', Filter::normalizeData('random text')); } } \ No newline at end of file diff --git a/vendor/fguillot/picofeed/tests/Parser/ParserTest.php b/vendor/fguillot/picofeed/tests/Parser/ParserTest.php index 41ee04b..7747a0d 100644 --- a/vendor/fguillot/picofeed/tests/Parser/ParserTest.php +++ b/vendor/fguillot/picofeed/tests/Parser/ParserTest.php @@ -33,4 +33,15 @@ class ParserTest extends PHPUnit_Framework_TestCase $this->assertEquals('Blandine Grosjean', XmlParser::getNamespaceValue($xml->channel->item[0], $namespaces, 'creator')); $this->assertEquals('Pierre-Carl Langlais', XmlParser::getNamespaceValue($xml->channel->item[1], $namespaces, 'creator')); } + + public function testFeedsWithInvalidCharacters() + { + $parser = new Rss20(file_get_contents('tests/fixtures/lincoln_loop.xml')); + $feed = $parser->execute(); + $this->assertNotEmpty($feed->items); + + $parser = new Rss20(file_get_contents('tests/fixtures/next_inpact_full.xml')); + $feed = $parser->execute(); + $this->assertNotEmpty($feed->items); + } } diff --git a/vendor/fguillot/picofeed/tests/Parser/Rss20ParserTest.php b/vendor/fguillot/picofeed/tests/Parser/Rss20ParserTest.php index 71ee74f..dd2b978 100644 --- a/vendor/fguillot/picofeed/tests/Parser/Rss20ParserTest.php +++ b/vendor/fguillot/picofeed/tests/Parser/Rss20ParserTest.php @@ -257,14 +257,6 @@ class Rss20ParserTest extends PHPUnit_Framework_TestCase $this->assertNotEmpty($feed->items); $this->assertEquals('http://geekstammtisch.de/#GST001', $feed->items[1]->getUrl()); - $parser = new Rss20(file_get_contents('tests/fixtures/lincoln_loop.xml')); - $feed = $parser->execute(); - $this->assertNotEmpty($feed->items); - - $parser = new Rss20(file_get_contents('tests/fixtures/next_inpact_full.xml')); - $feed = $parser->execute(); - $this->assertNotEmpty($feed->items); - $parser = new Rss20(file_get_contents('tests/fixtures/jeux-linux.fr.xml')); $feed = $parser->execute(); $this->assertNotEmpty($feed->items); diff --git a/vendor/fguillot/picofeed/tests/Reader/FaviconTest.php b/vendor/fguillot/picofeed/tests/Reader/FaviconTest.php index 81c9a04..e278503 100644 --- a/vendor/fguillot/picofeed/tests/Reader/FaviconTest.php +++ b/vendor/fguillot/picofeed/tests/Reader/FaviconTest.php @@ -84,7 +84,7 @@ class FaviconTest extends PHPUnit_Framework_TestCase { $favicon = new Favicon; - $this->assertTrue($favicon->exists('https://en.wikipedia.org/favicon.ico')); + $this->assertTrue($favicon->exists('https://miniflux.net/favicon.ico')); $this->assertFalse($favicon->exists('http://minicoders.com/favicon.ico')); $this->assertFalse($favicon->exists('http://blabla')); $this->assertFalse($favicon->exists('')); diff --git a/vendor/fguillot/picofeed/tests/Reader/ReaderTest.php b/vendor/fguillot/picofeed/tests/Reader/ReaderTest.php index 55abe53..f8fce66 100644 --- a/vendor/fguillot/picofeed/tests/Reader/ReaderTest.php +++ b/vendor/fguillot/picofeed/tests/Reader/ReaderTest.php @@ -231,7 +231,7 @@ class ReaderTest extends PHPUnit_Framework_TestCase $reader = new Reader; $client = $reader->discover('http://planete-jquery.fr'); - $this->assertInstanceOf('PicoFeed\Parser\Rss20', $reader->getParser($client->getUrl(), $client->getContent(), $client->getEncoding())); + $this->assertInstanceOf('PicoFeed\Parser\Rss10', $reader->getParser($client->getUrl(), $client->getContent(), $client->getEncoding())); $reader = new Reader; $client = $reader->discover('http://cabinporn.com/');