From cc235c6af36e4cbfcdced1ee323559a32ca65114 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 26 Mar 2017 15:02:35 +0200 Subject: SimplePie light manual update --- lib/SimplePie/SimplePie.php | 86 ++++++----- lib/SimplePie/SimplePie/Author.php | 5 +- lib/SimplePie/SimplePie/Cache.php | 11 +- lib/SimplePie/SimplePie/Cache/Base.php | 5 +- lib/SimplePie/SimplePie/Cache/DB.php | 5 +- lib/SimplePie/SimplePie/Cache/File.php | 5 +- lib/SimplePie/SimplePie/Cache/Memcache.php | 5 +- lib/SimplePie/SimplePie/Cache/Memcached.php | 166 +++++++++++++++++++++ lib/SimplePie/SimplePie/Cache/MySQL.php | 23 ++- lib/SimplePie/SimplePie/Cache/Redis.php | 166 +++++++++++++++++++++ lib/SimplePie/SimplePie/Caption.php | 5 +- lib/SimplePie/SimplePie/Category.php | 5 +- lib/SimplePie/SimplePie/Content/Type/Sniffer.php | 5 +- lib/SimplePie/SimplePie/Copyright.php | 5 +- lib/SimplePie/SimplePie/Core.php | 5 +- lib/SimplePie/SimplePie/Credit.php | 5 +- lib/SimplePie/SimplePie/Decode/HTML/Entities.php | 5 +- lib/SimplePie/SimplePie/Enclosure.php | 7 +- lib/SimplePie/SimplePie/Exception.php | 5 +- lib/SimplePie/SimplePie/File.php | 16 +- lib/SimplePie/SimplePie/HTTP/Parser.php | 5 +- lib/SimplePie/SimplePie/IRI.php | 67 ++++++--- lib/SimplePie/SimplePie/Item.php | 37 ++--- lib/SimplePie/SimplePie/Locator.php | 60 +++++++- lib/SimplePie/SimplePie/Misc.php | 10 +- lib/SimplePie/SimplePie/Net/IPv6.php | 5 +- lib/SimplePie/SimplePie/Parse/Date.php | 11 +- lib/SimplePie/SimplePie/Parser.php | 5 +- lib/SimplePie/SimplePie/Rating.php | 5 +- lib/SimplePie/SimplePie/Registry.php | 5 +- lib/SimplePie/SimplePie/Restriction.php | 5 +- lib/SimplePie/SimplePie/Sanitize.php | 6 +- lib/SimplePie/SimplePie/Source.php | 5 +- lib/SimplePie/SimplePie/XML/Declaration/Parser.php | 5 +- lib/SimplePie/SimplePie/gzdecode.php | 5 +- 35 files changed, 586 insertions(+), 190 deletions(-) create mode 100644 lib/SimplePie/SimplePie/Cache/Memcached.php create mode 100644 lib/SimplePie/SimplePie/Cache/Redis.php (limited to 'lib') diff --git a/lib/SimplePie/SimplePie.php b/lib/SimplePie/SimplePie.php index 0f2fdbb87..7240fdf66 100644 --- a/lib/SimplePie/SimplePie.php +++ b/lib/SimplePie/SimplePie.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -34,7 +34,7 @@ * * @package SimplePie * @version 1.4-dev-FreshRSS - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -614,6 +614,12 @@ class SimplePie */ public $item_limit = 0; + /** + * @var bool Stores if last-modified and/or etag headers were sent with the + * request when checking a feed. + */ + public $check_modified = false; + /** * @var array Stores the default attributes to be stripped by strip_attributes(). * @see SimplePie::strip_attributes() @@ -626,7 +632,7 @@ class SimplePie * @see SimplePie::add_attributes() * @access private */ - public $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')); //FreshRSS + public $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')); /** * @var array Stores the default tags to be stripped by strip_htmltags(). @@ -657,9 +663,9 @@ class SimplePie */ public function __construct() { - if (version_compare(PHP_VERSION, '5.2', '<')) + if (version_compare(PHP_VERSION, '5.3', '<')) { - trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.'); + trigger_error('Please upgrade to PHP 5.3 or newer.'); die(); } @@ -814,7 +820,7 @@ class SimplePie { $this->timeout = (int) $timeout; } - + /** * Set custom curl options * @@ -1169,7 +1175,7 @@ class SimplePie $this->sanitize->strip_attributes($attribs); } - public function add_attributes($attribs = '') //FreshRSS + public function add_attributes($attribs = '') { if ($attribs === '') { @@ -1191,11 +1197,11 @@ class SimplePie * * Allows you to override SimplePie's output to match that of your webpage. * This is useful for times when your webpages are not being served as - * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and + * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and * is similar to {@see set_input_encoding()}. * * It should be noted, however, that not all character encodings can support - * all characters. If your page is being served as ISO-8859-1 and you try + * all characters. If your page is being served as ISO-8859-1 and you try * to display a Japanese feed, you'll likely see garbled characters. * Because of this, it is highly recommended to ensure that your webpages * are served as UTF-8. @@ -1293,7 +1299,7 @@ class SimplePie /** * Initialize the feed object * - * This is what makes everything happen. Period. This is where all of the + * This is what makes everything happen. Period. This is where all of the * configuration options get processed, feeds are fetched, cached, and * parsed, and all of that other good stuff. * @@ -1361,6 +1367,7 @@ class SimplePie $this->error = null; $this->data = array(); + $this->check_modified = false; $this->multifeed_objects = array(); $cache = false; @@ -1380,6 +1387,7 @@ class SimplePie return $this->data['mtime']; } elseif ($fetched === false) { + $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__)); return false; } @@ -1486,11 +1494,19 @@ class SimplePie if (isset($parser)) { // We have an error, just set SimplePie_Misc::error to it and quit - $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d, encoding %s, URL: %s', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column(), $encoding, $this->feed_url); + $this->error = $this->feed_url; + $this->error .= sprintf(' is invalid XML, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column()); } else { - $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.'; + $this->error = 'The data could not be converted to UTF-8.'; + if (!extension_loaded('mbstring') && !extension_loaded('iconv')) { + $this->error .= ' You MUST have either the iconv or mbstring extension installed.'; + } elseif (!extension_loaded('mbstring')) { + $this->error .= ' Try installing the mbstring extension.'; + } elseif (!extension_loaded('iconv')) { + $this->error .= ' Try installing the iconv extension.'; + } } $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__)); @@ -1575,6 +1591,7 @@ class SimplePie } else { + $this->check_modified = false; $cache->touch(); $this->error = $file->error; return !empty($this->data); @@ -1669,7 +1686,7 @@ class SimplePie $locate = null; } - $file->body = trim($file->body); + $file->body = trim($file->body); //FreshRSS $this->raw_data = $file->body; $this->permanent_url = $file->permanent_url; $headers = $file->headers; @@ -1870,7 +1887,7 @@ class SimplePie * @todo Support * @todo Also, |atom:link|@rel=self * @param bool $permanent Permanent mode to return only the original URL or the first redirection - * iff it is a 301 redirection + * iff it is a 301 redirection * @return string|null */ public function subscribe_url($permanent = false) @@ -2169,7 +2186,7 @@ class SimplePie * Get a category for the feed * * @since Unknown - * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1 + * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1 * @return SimplePie_Category|null */ public function get_category($key = 0) @@ -2254,7 +2271,7 @@ class SimplePie * Get an author for the feed * * @since 1.1 - * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1 + * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1 * @return SimplePie_Author|null */ public function get_author($key = 0) @@ -2352,7 +2369,7 @@ class SimplePie * Get a contributor for the feed * * @since 1.1 - * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1 + * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1 * @return SimplePie_Author|null */ public function get_contributor($key = 0) @@ -2438,7 +2455,7 @@ class SimplePie * Get a single link for the feed * * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8) - * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1 + * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1 * @param string $rel The relationship of the link to return * @return string|null Link URL */ @@ -2949,7 +2966,7 @@ class SimplePie * * @see get_item_quantity() * @since Beta 2 - * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1 + * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1 * @return SimplePie_Item|null */ public function get_item($key = 0) @@ -2976,7 +2993,7 @@ class SimplePie * @since Beta 2 * @param int $start Index to start at * @param int $end Number of items to return. 0 for all items after `$start` - * @return array|null List of {@see SimplePie_Item} objects + * @return SimplePie_Item[]|null List of {@see SimplePie_Item} objects */ public function get_items($start = 0, $end = 0) { @@ -3147,7 +3164,19 @@ class SimplePie */ public static function sort_items($a, $b) { - return $a->get_date('U') <= $b->get_date('U'); + $a_date = $a->get_date('U'); + $b_date = $b->get_date('U'); + if ($a_date && $b_date) { + return $a_date > $b_date ? -1 : 1; + } + // Sort items without dates to the top. + if ($a_date) { + return 1; + } + if ($b_date) { + return -1; + } + return 0; } /** @@ -3180,20 +3209,7 @@ class SimplePie } } - $do_sort = true; - foreach ($items as $item) - { - if (!$item->get_date('U')) - { - $do_sort = false; - break; - } - } - $item = null; - if ($do_sort) - { - usort($items, array(get_class($urls[0]), 'sort_items')); - } + usort($items, array(get_class($urls[0]), 'sort_items')); if ($end === 0) { diff --git a/lib/SimplePie/SimplePie/Author.php b/lib/SimplePie/SimplePie/Author.php index 19563c5cc..e6768ff29 100644 --- a/lib/SimplePie/SimplePie/Author.php +++ b/lib/SimplePie/SimplePie/Author.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Cache.php b/lib/SimplePie/SimplePie/Cache.php index 86b618693..d98cc6511 100644 --- a/lib/SimplePie/SimplePie/Cache.php +++ b/lib/SimplePie/SimplePie/Cache.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -62,8 +61,10 @@ class SimplePie_Cache * @var array */ protected static $handlers = array( - 'mysql' => 'SimplePie_Cache_MySQL', - 'memcache' => 'SimplePie_Cache_Memcache', + 'mysql' => 'SimplePie_Cache_MySQL', + 'memcache' => 'SimplePie_Cache_Memcache', + 'memcached' => 'SimplePie_Cache_Memcached', + 'redis' => 'SimplePie_Cache_Redis' ); /** diff --git a/lib/SimplePie/SimplePie/Cache/Base.php b/lib/SimplePie/SimplePie/Cache/Base.php index d3f353961..333fb05cf 100644 --- a/lib/SimplePie/SimplePie/Cache/Base.php +++ b/lib/SimplePie/SimplePie/Cache/Base.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Cache/DB.php b/lib/SimplePie/SimplePie/Cache/DB.php index d728a9a6d..7e8f77532 100644 --- a/lib/SimplePie/SimplePie/Cache/DB.php +++ b/lib/SimplePie/SimplePie/Cache/DB.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Cache/File.php b/lib/SimplePie/SimplePie/Cache/File.php index 72e75a4b6..6ba6c5f6e 100644 --- a/lib/SimplePie/SimplePie/Cache/File.php +++ b/lib/SimplePie/SimplePie/Cache/File.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Cache/Memcache.php b/lib/SimplePie/SimplePie/Cache/Memcache.php index 23b1c9367..5190eef93 100644 --- a/lib/SimplePie/SimplePie/Cache/Memcache.php +++ b/lib/SimplePie/SimplePie/Cache/Memcache.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Cache/Memcached.php b/lib/SimplePie/SimplePie/Cache/Memcached.php new file mode 100644 index 000000000..1f73b3890 --- /dev/null +++ b/lib/SimplePie/SimplePie/Cache/Memcached.php @@ -0,0 +1,166 @@ +options = array( + 'host' => '127.0.0.1', + 'port' => 11211, + 'extras' => array( + 'timeout' => 3600, // one hour + 'prefix' => 'simplepie_', + ), + ); + $this->options = SimplePie_Misc::array_merge_recursive($this->options, SimplePie_Cache::parse_URL($location)); + + $this->name = $this->options['extras']['prefix'] . md5("$name:$type"); + + $this->cache = new Memcached(); + $this->cache->addServer($this->options['host'], (int)$this->options['port']); + } + + /** + * Save data to the cache + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) { + if ($data instanceof SimplePie) { + $data = $data->data; + } + + return $this->setData(serialize($data)); + } + + /** + * Retrieve the data saved to the cache + * @return array Data for SimplePie::$data + */ + public function load() { + $data = $this->cache->get($this->name); + + if ($data !== false) { + return unserialize($data); + } + return false; + } + + /** + * Retrieve the last modified time for the cache + * @return int Timestamp + */ + public function mtime() { + $data = $this->cache->get($this->name . '_mtime'); + return (int) $data; + } + + /** + * Set the last modified time to the current time + * @return bool Success status + */ + public function touch() { + $data = $this->cache->get($this->name); + return $this->setData($data); + } + + /** + * Remove the cache + * @return bool Success status + */ + public function unlink() { + return $this->cache->delete($this->name, 0); + } + + /** + * Set the last modified time and data to Memcached + * @return bool Success status + */ + private function setData($data) { + + if ($data !== false) { + $this->cache->set($this->name . '_mtime', time(), (int)$this->options['extras']['timeout']); + return $this->cache->set($this->name, $data, (int)$this->options['extras']['timeout']); + } + + return false; + } +} diff --git a/lib/SimplePie/SimplePie/Cache/MySQL.php b/lib/SimplePie/SimplePie/Cache/MySQL.php index 511ef6d3a..8686b6c67 100644 --- a/lib/SimplePie/SimplePie/Cache/MySQL.php +++ b/lib/SimplePie/SimplePie/Cache/MySQL.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -94,6 +93,7 @@ class SimplePie_Cache_MySQL extends SimplePie_Cache_DB 'path' => '', 'extras' => array( 'prefix' => '', + 'cache_purge_time' => 2592000 ), ); @@ -131,16 +131,20 @@ class SimplePie_Cache_MySQL extends SimplePie_Cache_DB $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'); if ($query === false) { + trigger_error("Can't create " . $this->options['extras']['prefix'] . "cache_data table, check permissions", E_USER_WARNING); $this->mysql = null; + return; } } if (!in_array($this->options['extras']['prefix'] . 'items', $db)) { - $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` MEDIUMBLOB CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'); + $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` MEDIUMBLOB NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'); if ($query === false) { + trigger_error("Can't create " . $this->options['extras']['prefix'] . "items table, check permissions", E_USER_WARNING); $this->mysql = null; + return; } } } @@ -158,6 +162,17 @@ class SimplePie_Cache_MySQL extends SimplePie_Cache_DB return false; } + $query = $this->mysql->prepare('DELETE i, cd FROM `' . $this->options['extras']['prefix'] . 'cache_data` cd, ' . + '`' . $this->options['extras']['prefix'] . 'items` i ' . + 'WHERE cd.id = i.feed_id ' . + 'AND cd.mtime < (unix_timestamp() - :purge_time)'); + $query->bindValue(':purge_time', $this->options['extras']['cache_purge_time']); + + if (!$query->execute()) + { + return false; + } + if ($data instanceof SimplePie) { $data = clone $data; diff --git a/lib/SimplePie/SimplePie/Cache/Redis.php b/lib/SimplePie/SimplePie/Cache/Redis.php new file mode 100644 index 000000000..04d72c79a --- /dev/null +++ b/lib/SimplePie/SimplePie/Cache/Redis.php @@ -0,0 +1,166 @@ + + * @link http://galvani.cz/ + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version 0.2.9 + */ + + +/** + * Caches data to redis + * + * Registered for URLs with the "redis" protocol + * + * For example, `redis://localhost:6379/?timeout=3600&prefix=sp_&dbIndex=0` will + * connect to redis on `localhost` on port 6379. All tables will be + * prefixed with `simple_primary-` and data will expire after 3600 seconds + * + * @package SimplePie + * @subpackage Caching + * @uses Redis + */ +class SimplePie_Cache_Redis implements SimplePie_Cache_Base { + /** + * Redis instance + * + * @var \Redis + */ + protected $cache; + + /** + * Options + * + * @var array + */ + protected $options; + + /** + * Cache name + * + * @var string + */ + protected $name; + + /** + * Cache Data + * + * @var type + */ + protected $data; + + /** + * Create a new cache object + * + * @param string $location Location string (from SimplePie::$cache_location) + * @param string $name Unique ID for the cache + * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data + */ + public function __construct($location, $name, $options = null) { + //$this->cache = \flow\simple\cache\Redis::getRedisClientInstance(); + $parsed = SimplePie_Cache::parse_URL($location); + $redis = new Redis(); + $redis->connect($parsed['host'], $parsed['port']); + $this->cache = $redis; + + if (!is_null($options) && is_array($options)) { + $this->options = $options; + } else { + $this->options = array ( + 'prefix' => 'rss:simple_primary:', + 'expire' => 0, + ); + } + + $this->name = $this->options['prefix'] . $name; + } + + /** + * @param \Redis $cache + */ + public function setRedisClient(\Redis $cache) { + $this->cache = $cache; + } + + /** + * Save data to the cache + * + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) { + if ($data instanceof SimplePie) { + $data = $data->data; + } + $response = $this->cache->set($this->name, serialize($data)); + if ($this->options['expire']) { + $this->cache->expire($this->name, $this->options['expire']); + } + + return $response; + } + + /** + * Retrieve the data saved to the cache + * + * @return array Data for SimplePie::$data + */ + public function load() { + $data = $this->cache->get($this->name); + + if ($data !== false) { + return unserialize($data); + } + return false; + } + + /** + * Retrieve the last modified time for the cache + * + * @return int Timestamp + */ + public function mtime() { + + $data = $this->cache->get($this->name); + + if ($data !== false) { + return time(); + } + + return false; + } + + /** + * Set the last modified time to the current time + * + * @return bool Success status + */ + public function touch() { + + $data = $this->cache->get($this->name); + + if ($data !== false) { + $return = $this->cache->set($this->name, $data); + if ($this->options['expire']) { + return $this->cache->expire($this->name, $this->ttl); + } + return $return; + } + + return false; + } + + /** + * Remove the cache + * + * @return bool Success status + */ + public function unlink() { + return $this->cache->set($this->name, null); + } + +} diff --git a/lib/SimplePie/SimplePie/Caption.php b/lib/SimplePie/SimplePie/Caption.php index a77b02ef1..abf07de1b 100644 --- a/lib/SimplePie/SimplePie/Caption.php +++ b/lib/SimplePie/SimplePie/Caption.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Category.php b/lib/SimplePie/SimplePie/Category.php index c6a273989..92d511e1a 100644 --- a/lib/SimplePie/SimplePie/Category.php +++ b/lib/SimplePie/SimplePie/Category.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Content/Type/Sniffer.php b/lib/SimplePie/SimplePie/Content/Type/Sniffer.php index ec0bf0952..b68b73134 100644 --- a/lib/SimplePie/SimplePie/Content/Type/Sniffer.php +++ b/lib/SimplePie/SimplePie/Content/Type/Sniffer.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Copyright.php b/lib/SimplePie/SimplePie/Copyright.php index 09f22f8df..3f3d07d3b 100644 --- a/lib/SimplePie/SimplePie/Copyright.php +++ b/lib/SimplePie/SimplePie/Copyright.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Core.php b/lib/SimplePie/SimplePie/Core.php index 7cf34876f..c856ba361 100644 --- a/lib/SimplePie/SimplePie/Core.php +++ b/lib/SimplePie/SimplePie/Core.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2009, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Credit.php b/lib/SimplePie/SimplePie/Credit.php index 50aef1c68..9bad9ef34 100644 --- a/lib/SimplePie/SimplePie/Credit.php +++ b/lib/SimplePie/SimplePie/Credit.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Decode/HTML/Entities.php b/lib/SimplePie/SimplePie/Decode/HTML/Entities.php index 46b3a1dff..de3f2cb53 100644 --- a/lib/SimplePie/SimplePie/Decode/HTML/Entities.php +++ b/lib/SimplePie/SimplePie/Decode/HTML/Entities.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Enclosure.php b/lib/SimplePie/SimplePie/Enclosure.php index fa0217800..15060e193 100644 --- a/lib/SimplePie/SimplePie/Enclosure.php +++ b/lib/SimplePie/SimplePie/Enclosure.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -451,7 +450,7 @@ class SimplePie_Enclosure /** * Get the duration of the enclosure * - * @param string $convert Convert seconds into hh:mm:ss + * @param bool $convert Convert seconds into hh:mm:ss * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found) */ public function get_duration($convert = false) diff --git a/lib/SimplePie/SimplePie/Exception.php b/lib/SimplePie/SimplePie/Exception.php index 73e104d69..53c015e77 100644 --- a/lib/SimplePie/SimplePie/Exception.php +++ b/lib/SimplePie/SimplePie/Exception.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/File.php b/lib/SimplePie/SimplePie/File.php index 45994d102..c1fab42dc 100644 --- a/lib/SimplePie/SimplePie/File.php +++ b/lib/SimplePie/SimplePie/File.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -64,7 +63,7 @@ class SimplePie_File var $redirects = 0; var $error; var $method = SIMPLEPIE_FILE_SOURCE_NONE; - var $permanent_url; //FreshRSS + var $permanent_url; public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false, $curl_options = array(), $syslog_enabled = SIMPLEPIE_SYSLOG) { @@ -108,6 +107,7 @@ class SimplePie_File curl_setopt($fp, CURLOPT_URL, $url); curl_setopt($fp, CURLOPT_HEADER, 1); curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($fp, CURLOPT_FAILONERROR, 1); curl_setopt($fp, CURLOPT_TIMEOUT, $timeout); curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($fp, CURLOPT_REFERER, $url); @@ -144,7 +144,7 @@ class SimplePie_File if ($parser->parse()) { $this->headers = $parser->headers; - $this->body = $parser->body; + $this->body = trim($parser->body); $this->status_code = $parser->status_code; if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) { @@ -237,7 +237,7 @@ class SimplePie_File $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url); $previousStatusCode = $this->status_code; $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen); - $this->permanent_url = ($previousStatusCode == 301) ? $location : $url; //FreshRSS + $this->permanent_url = ($previousStatusCode == 301) ? $location : $url; return; } if (isset($this->headers['content-encoding'])) @@ -255,7 +255,7 @@ class SimplePie_File } else { - $this->body = $decoder->data; + $this->body = trim($decoder->data); } break; @@ -298,7 +298,7 @@ class SimplePie_File else { $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS; - if (empty($url) || !($this->body = file_get_contents($url))) + if (empty($url) || !($this->body = trim(file_get_contents($url)))) { $this->error = 'file_get_contents could not read the file'; $this->success = false; diff --git a/lib/SimplePie/SimplePie/HTTP/Parser.php b/lib/SimplePie/SimplePie/HTTP/Parser.php index 2fc3a6779..63ae1e03d 100644 --- a/lib/SimplePie/SimplePie/HTTP/Parser.php +++ b/lib/SimplePie/SimplePie/HTTP/Parser.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/IRI.php b/lib/SimplePie/SimplePie/IRI.php index ed0574701..2b3fbaf07 100644 --- a/lib/SimplePie/SimplePie/IRI.php +++ b/lib/SimplePie/SimplePie/IRI.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -259,6 +258,15 @@ class SimplePie_IRI $this->set_iri($iri); } + /** + * Clean up + */ + public function __destruct() { + $this->set_iri(null, true); + $this->set_path(null, true); + $this->set_authority(null, true); + } + /** * Create a new IRI object by resolving a relative IRI * @@ -768,24 +776,20 @@ class SimplePie_IRI */ public function is_valid() { - $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null; - if ($this->ipath !== '' && - ( - $isauthority && ( - $this->ipath[0] !== '/' || - substr($this->ipath, 0, 2) === '//' - ) || - ( - $this->scheme === null && - !$isauthority && - strpos($this->ipath, ':') !== false && - (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/')) - ) - ) - ) - { - return false; - } + if ($this->ipath === '') return true; + + $isauthority = $this->iuserinfo !== null || $this->ihost !== null || + $this->port !== null; + if ($isauthority && $this->ipath[0] === '/') return true; + + if (!$isauthority && (substr($this->ipath, 0, 2) === '//')) return false; + + // Relative urls cannot have a colon in the first path segment (and the + // slashes themselves are not included so skip the first character). + if (!$this->scheme && !$isauthority && + strpos($this->ipath, ':') !== false && + strpos($this->ipath, '/', 1) !== false && + strpos($this->ipath, ':') < strpos($this->ipath, '/', 1)) return false; return true; } @@ -797,9 +801,14 @@ class SimplePie_IRI * @param string $iri * @return bool */ - public function set_iri($iri) + public function set_iri($iri, $clear_cache = false) { static $cache; + if ($clear_cache) + { + $cache = null; + return; + } if (!$cache) { $cache = array(); @@ -879,9 +888,14 @@ class SimplePie_IRI * @param string $authority * @return bool */ - public function set_authority($authority) + public function set_authority($authority, $clear_cache = false) { static $cache; + if ($clear_cache) + { + $cache = null; + return; + } if (!$cache) $cache = array(); @@ -1049,9 +1063,14 @@ class SimplePie_IRI * @param string $ipath * @return bool */ - public function set_path($ipath) + public function set_path($ipath, $clear_cache = false) { static $cache; + if ($clear_cache) + { + $cache = null; + return; + } if (!$cache) { $cache = array(); diff --git a/lib/SimplePie/SimplePie/Item.php b/lib/SimplePie/SimplePie/Item.php index 19ba7c8f4..daecf0a15 100644 --- a/lib/SimplePie/SimplePie/Item.php +++ b/lib/SimplePie/SimplePie/Item.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -203,14 +202,13 @@ class SimplePie_Item * * Uses ``, ``, `` or the `about` attribute * for RDF. If none of these are supplied (or `$hash` is true), creates an - * MD5 hash based on the permalink and title. If either of those are not - * supplied, creates a hash based on the full feed data. + * MD5 hash based on the permalink, title and content. * * @since Beta 2 * @param boolean $hash Should we force using a hash instead of the supplied ID? * @return string */ - public function get_id($hash = false) + public function get_id($hash = false, $fn = '') { if (!$hash) { @@ -238,23 +236,10 @@ class SimplePie_Item { return $this->sanitize($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'], SIMPLEPIE_CONSTRUCT_TEXT); } - elseif (($return = $this->get_permalink()) !== null) - { - return $return; - } - elseif (($return = $this->get_title()) !== null) - { - return $return; - } - } - if ($this->get_permalink() !== null || $this->get_title() !== null) - { - return md5($this->get_permalink() . $this->get_title()); - } - else - { - return md5(serialize($this->data)); } + if ($fn === '' || !is_callable($fn)) $fn = 'md5'; + return call_user_func($fn, + $this->get_permalink().$this->get_title().$this->get_content()); } /** @@ -457,7 +442,7 @@ class SimplePie_Item * Uses ``, `` or `` * * @since Beta 3 - * @return array|null List of {@see SimplePie_Category} objects + * @return SimplePie_Category[]|null List of {@see SimplePie_Category} objects */ public function get_categories() { @@ -1105,7 +1090,7 @@ class SimplePie_Item * @since Beta 2 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4). * @todo If an element exists at a level, but its value is empty, we should fall back to the value from the parent (if it exists). - * @return array|null List of SimplePie_Enclosure items + * @return SimplePie_Enclosure[]|null List of SimplePie_Enclosure items */ public function get_enclosures() { @@ -2682,7 +2667,9 @@ class SimplePie_Item // PLAYER if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) { - $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'])) { + $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } } else { diff --git a/lib/SimplePie/SimplePie/Locator.php b/lib/SimplePie/SimplePie/Locator.php index ba4a843b0..36bc02895 100644 --- a/lib/SimplePie/SimplePie/Locator.php +++ b/lib/SimplePie/SimplePie/Locator.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -226,7 +225,7 @@ class SimplePie_Locator } if ($link->hasAttribute('href') && $link->hasAttribute('rel')) { - $rel = array_unique($this->registry->call('Misc', 'space_seperated_tokens', array(strtolower($link->getAttribute('rel'))))); + $rel = array_unique($this->registry->call('Misc', 'space_separated_tokens', array(strtolower($link->getAttribute('rel'))))); $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1; if ($this->base_location < $line) @@ -275,7 +274,7 @@ class SimplePie_Locator { $href = trim($link->getAttribute('href')); $parsed = $this->registry->call('Misc', 'parse_url', array($href)); - if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme'])) + if ($parsed['scheme'] === '' || preg_match('/^(https?|feed)?$/i', $parsed['scheme'])) { if (method_exists($link, 'getLineNo') && $this->base_location < $link->getLineNo()) { @@ -312,6 +311,57 @@ class SimplePie_Locator return null; } + public function get_rel_link($rel) + { + if ($this->dom === null) + { + throw new SimplePie_Exception('DOMDocument not found, unable to use '. + 'locator'); + } + if (!class_exists('DOMXpath')) + { + throw new SimplePie_Exception('DOMXpath not found, unable to use '. + 'get_rel_link'); + } + + $xpath = new DOMXpath($this->dom); + $query = '//a[@rel and @href] | //link[@rel and @href]'; + foreach ($xpath->query($query) as $link) + { + $href = trim($link->getAttribute('href')); + $parsed = $this->registry->call('Misc', 'parse_url', array($href)); + if ($parsed['scheme'] === '' || + preg_match('/^https?$/i', $parsed['scheme'])) + { + if (method_exists($link, 'getLineNo') && + $this->base_location < $link->getLineNo()) + { + $href = + $this->registry->call('Misc', 'absolutize_url', + array(trim($link->getAttribute('href')), + $this->base)); + } + else + { + $href = + $this->registry->call('Misc', 'absolutize_url', + array(trim($link->getAttribute('href')), + $this->http_base)); + } + if ($href === false) + { + return null; + } + $rel_values = explode(' ', strtolower($link->getAttribute('rel'))); + if (in_array($rel, $rel_values)) + { + return $href; + } + } + } + return null; + } + public function extension(&$array) { foreach ($array as $key => $value) diff --git a/lib/SimplePie/SimplePie/Misc.php b/lib/SimplePie/SimplePie/Misc.php index 2d154cbcb..ca2810611 100644 --- a/lib/SimplePie/SimplePie/Misc.php +++ b/lib/SimplePie/SimplePie/Misc.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -1947,7 +1946,7 @@ class SimplePie_Misc return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string); } - public static function space_seperated_tokens($string) + public static function space_separated_tokens($string) { $space_characters = "\x20\x09\x0A\x0B\x0C\x0D"; $string_length = strlen($string); @@ -2178,7 +2177,8 @@ function embed_wmedia(width, height, link) { /** * Get the SimplePie build timestamp * - * Return SimplePie.php modification time. + * Uses the git index if it exists, otherwise uses the modification time + * of the newest file. */ public static function get_build() { diff --git a/lib/SimplePie/SimplePie/Net/IPv6.php b/lib/SimplePie/SimplePie/Net/IPv6.php index 2ff1afc90..47658aff2 100644 --- a/lib/SimplePie/SimplePie/Net/IPv6.php +++ b/lib/SimplePie/SimplePie/Net/IPv6.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Parse/Date.php b/lib/SimplePie/SimplePie/Parse/Date.php index 50bb5cffa..1f2156655 100644 --- a/lib/SimplePie/SimplePie/Parse/Date.php +++ b/lib/SimplePie/SimplePie/Parse/Date.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -331,8 +330,8 @@ class SimplePie_Parse_Date 'CCT' => 23400, 'CDT' => -18000, 'CEDT' => 7200, - 'CET' => 3600, 'CEST' => 7200, + 'CET' => 3600, 'CGST' => -7200, 'CGT' => -10800, 'CHADT' => 49500, @@ -631,7 +630,7 @@ class SimplePie_Parse_Date /** * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as * well as allowing any of upper or lower case "T", horizontal tabs, or - * spaces to be used as the time seperator (including more than one)) + * spaces to be used as the time separator (including more than one)) * * @access protected * @return int Timestamp @@ -691,7 +690,7 @@ class SimplePie_Parse_Date } // Convert the number of seconds to an integer, taking decimals into account - $second = round($match[6] + $match[7] / pow(10, strlen($match[7]))); + $second = round((int)$match[6] + (int)$match[7] / pow(10, strlen($match[7]))); return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone; } diff --git a/lib/SimplePie/SimplePie/Parser.php b/lib/SimplePie/SimplePie/Parser.php index 7fb7bd9be..e3966218c 100644 --- a/lib/SimplePie/SimplePie/Parser.php +++ b/lib/SimplePie/SimplePie/Parser.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Rating.php b/lib/SimplePie/SimplePie/Rating.php index b5fe80516..eaf57080c 100644 --- a/lib/SimplePie/SimplePie/Rating.php +++ b/lib/SimplePie/SimplePie/Rating.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Registry.php b/lib/SimplePie/SimplePie/Registry.php index dac55e34e..e0909bb74 100755 --- a/lib/SimplePie/SimplePie/Registry.php +++ b/lib/SimplePie/SimplePie/Registry.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Restriction.php b/lib/SimplePie/SimplePie/Restriction.php index a1d59916d..001a5cd28 100644 --- a/lib/SimplePie/SimplePie/Restriction.php +++ b/lib/SimplePie/SimplePie/Restriction.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/Sanitize.php b/lib/SimplePie/SimplePie/Sanitize.php index bdc601100..49fe5dbd5 100644 --- a/lib/SimplePie/SimplePie/Sanitize.php +++ b/lib/SimplePie/SimplePie/Sanitize.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -348,6 +347,7 @@ class SimplePie_Sanitize } $document = new DOMDocument(); $document->encoding = 'UTF-8'; + $data = $this->preprocess($data, $type); set_error_handler(array('SimplePie_Misc', 'silence_errors')); diff --git a/lib/SimplePie/SimplePie/Source.php b/lib/SimplePie/SimplePie/Source.php index 2613798fd..1a66a392d 100644 --- a/lib/SimplePie/SimplePie/Source.php +++ b/lib/SimplePie/SimplePie/Source.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/XML/Declaration/Parser.php b/lib/SimplePie/SimplePie/XML/Declaration/Parser.php index 589e452a2..99e751672 100644 --- a/lib/SimplePie/SimplePie/XML/Declaration/Parser.php +++ b/lib/SimplePie/SimplePie/XML/Declaration/Parser.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue diff --git a/lib/SimplePie/SimplePie/gzdecode.php b/lib/SimplePie/SimplePie/gzdecode.php index 6e65f0811..0e8bc8fc6 100644 --- a/lib/SimplePie/SimplePie/gzdecode.php +++ b/lib/SimplePie/SimplePie/gzdecode.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev - * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue -- cgit v1.2.3 From 07a9faf851e3b887899564f854c9933bb0b99140 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 8 Apr 2017 17:52:53 +0200 Subject: Check for fileinfo https://github.com/FreshRSS/FreshRSS/issues/1402 https://github.com/FreshRSS/FreshRSS/issues/1461 --- lib/Favicon/Favicon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/Favicon/Favicon.php b/lib/Favicon/Favicon.php index 8571a1b95..4ee42ebbc 100644 --- a/lib/Favicon/Favicon.php +++ b/lib/Favicon/Favicon.php @@ -179,7 +179,7 @@ class Favicon // Sometimes people lie, so check the status. // And sometimes, it's not even an image. Sneaky bastards! // If cacheDir isn't writable, that's not our problem - if ($favicon && is_writable($this->cacheDir) && !$this->checkImageMType($favicon)) { + if ($favicon && is_writable($this->cacheDir) && extension_loaded('fileinfo') && !$this->checkImageMType($favicon)) { $favicon = false; } -- cgit v1.2.3 From fe494e000b37bb45ec3eb73f6ddb880fe613f64d Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 8 Apr 2017 18:03:52 +0200 Subject: try/catch for finfo_open --- CHANGELOG.md | 1 + lib/Favicon/Favicon.php | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/CHANGELOG.md b/CHANGELOG.md index de9f2cc5d..e8a15ad1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * Bug fixing * Fix SQL uniqueness bug with PostgreSQL [#1476](https://github.com/FreshRSS/FreshRSS/pull/1476) * (Require manual update for existing installations) + * Do not require PHP extension `fileinfo` for favicons [#1461](https://github.com/FreshRSS/FreshRSS/issues/1461) * Fix UI lowest subscription popup hidden [#1479](https://github.com/FreshRSS/FreshRSS/issues/1479) * I18n * Improve English [#1465](https://github.com/FreshRSS/FreshRSS/pull/1465) diff --git a/lib/Favicon/Favicon.php b/lib/Favicon/Favicon.php index 4ee42ebbc..85d2ef19b 100644 --- a/lib/Favicon/Favicon.php +++ b/lib/Favicon/Favicon.php @@ -229,10 +229,14 @@ class Favicon $fileContent = $this->dataAccess->retrieveUrl($url); $this->dataAccess->saveCache($tmpFile, $fileContent); - $finfo = finfo_open(FILEINFO_MIME_TYPE); - $isImage = strpos(finfo_file($finfo, $tmpFile), 'image') !== false; - finfo_close($finfo); - + $isImage = true; + try { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $isImage = strpos(finfo_file($finfo, $tmpFile), 'image') !== false; + finfo_close($finfo); + } catch (Exception $e) { + } + unlink($tmpFile); return $isImage; -- cgit v1.2.3 From a542ab8fff7cd13ef54f5585f029b6c1d2244351 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 8 Apr 2017 18:12:12 +0200 Subject: Make fileinfo extension optional --- app/install.php | 2 +- lib/lib_install.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/app/install.php b/app/install.php index f598f6528..ebfffa47d 100644 --- a/app/install.php +++ b/app/install.php @@ -465,7 +465,7 @@ function printStep1() {

-

+

diff --git a/lib/lib_install.php b/lib/lib_install.php index 76871c98a..c625a670a 100644 --- a/lib/lib_install.php +++ b/lib/lib_install.php @@ -67,7 +67,7 @@ function checkRequirements($dbType = '') { 'favicons' => $favicons ? 'ok' : 'ko', 'http_referer' => $http_referer ? 'ok' : 'ko', 'message' => $message ?: 'ok', - 'all' => $php && $minz && $curl && $pdo && $pcre && $ctype && $fileinfo && $dom && $xml && + 'all' => $php && $minz && $curl && $pdo && $pcre && $ctype && $dom && $xml && $data && $cache && $users && $favicons && $http_referer && $message == '' ? 'ok' : 'ko' ); -- cgit v1.2.3 From 0ce43be9de5bf676ceffa2e419941863f98fa970 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 9 Apr 2017 00:25:04 +0200 Subject: Multi-user token https://github.com/FreshRSS/FreshRSS/issues/1390 https://github.com/FreshRSS/FreshRSS/issues/366 --- app/Controllers/authController.php | 9 ++------- app/Controllers/userController.php | 4 ++++ app/Models/Auth.php | 27 +++++++++++++++++++++++---- app/layout/nav_menu.phtml | 1 + app/views/auth/index.phtml | 13 ------------- app/views/user/profile.phtml | 13 +++++++++++++ lib/lib_rss.php | 3 +++ 7 files changed, 46 insertions(+), 24 deletions(-) (limited to 'lib') diff --git a/app/Controllers/authController.php b/app/Controllers/authController.php index 1398e4e49..5ad1a51d9 100644 --- a/app/Controllers/authController.php +++ b/app/Controllers/authController.php @@ -27,11 +27,6 @@ class FreshRSS_auth_Controller extends Minz_ActionController { if (Minz_Request::isPost()) { $ok = true; - $current_token = FreshRSS_Context::$user_conf->token; - $token = Minz_Request::param('token', $current_token); - FreshRSS_Context::$user_conf->token = $token; - $ok &= FreshRSS_Context::$user_conf->save(); - $anon = Minz_Request::param('anon_access', false); $anon = ((bool)$anon) && ($anon !== 'no'); $anon_refresh = Minz_Request::param('anon_refresh', false); @@ -123,7 +118,7 @@ class FreshRSS_auth_Controller extends Minz_ActionController { $challenge = Minz_Request::param('challenge', ''); $conf = get_user_configuration($username); - if (is_null($conf)) { + if ($conf == null) { Minz_Error::error(403, array(_t('feedback.auth.login.invalid')), false); return; } @@ -164,7 +159,7 @@ class FreshRSS_auth_Controller extends Minz_ActionController { } $conf = get_user_configuration($username); - if (is_null($conf)) { + if ($conf == null) { return; } diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php index f910cecd9..ee575fa09 100644 --- a/app/Controllers/userController.php +++ b/app/Controllers/userController.php @@ -74,6 +74,10 @@ class FreshRSS_user_Controller extends Minz_ActionController { FreshRSS_Context::$user_conf->apiPasswordHash = $passwordHash; } + $current_token = FreshRSS_Context::$user_conf->token; + $token = Minz_Request::param('token', $current_token); + FreshRSS_Context::$user_conf->token = $token; + $ok &= FreshRSS_Context::$user_conf->save(); if ($ok) { diff --git a/app/Models/Auth.php b/app/Models/Auth.php index 476627e10..4de058999 100644 --- a/app/Models/Auth.php +++ b/app/Models/Auth.php @@ -74,6 +74,10 @@ class FreshRSS_Auth { public static function giveAccess() { $current_user = Minz_Session::param('currentUser'); $user_conf = get_user_configuration($current_user); + if ($user_conf == null) { + self::$login_ok = false; + return; + } $system_conf = Minz_Configuration::get('system'); switch ($system_conf->auth_type) { @@ -120,13 +124,28 @@ class FreshRSS_Auth { * Removes all accesses for the current user. */ public static function removeAccess() { - Minz_Session::_param('loginOk'); self::$login_ok = false; - $conf = Minz_Configuration::get('system'); - Minz_Session::_param('currentUser', $conf->default_user); + Minz_Session::_param('loginOk'); Minz_Session::_param('csrf'); + $system_conf = Minz_Configuration::get('system'); - switch ($conf->auth_type) { + $username = ''; + $token_param = Minz_Request::param('token', ''); + if ($token_param != '') { + $username = trim(Minz_Request::param('user', '')); + if ($username != '') { + $conf = get_user_configuration($username); + if ($conf == null) { + $username = ''; + } + } + } + if ($username == '') { + $username = $system_conf->default_user; + } + Minz_Session::_param('currentUser', $username); + + switch ($system_conf->auth_type) { case 'form': Minz_Session::_param('passwordHash'); FreshRSS_FormAuth::deleteCookie(); diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index f6d824d55..04ee03cd6 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -149,6 +149,7 @@ token) { + $url_output['params']['user'] = Minz_Session::param('currentUser'); $url_output['params']['token'] = FreshRSS_Context::$user_conf->token; } if (FreshRSS_Context::$user_conf->since_hours_posts_per_rss) { diff --git a/app/views/auth/index.phtml b/app/views/auth/index.phtml index 010eae33f..20966f24e 100644 --- a/app/views/auth/index.phtml +++ b/app/views/auth/index.phtml @@ -52,19 +52,6 @@ - -
- - token; ?> -
- data-leave-validation=""/> - - 'rss', 'params' => array('token' => $token, 'hours' => FreshRSS_Context::$user_conf->since_hours_posts_per_rss)), 'html', true); ?> -
-
- -
+ +
+ + token; ?> +
+ data-leave-validation=""/> + + 'rss', 'params' => array('user' => Minz_Session::param('currentUser'), 'token' => $token, 'hours' => FreshRSS_Context::$user_conf->since_hours_posts_per_rss)), 'html', true); ?> +
+
+ +
diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 4298e90bf..247cc707b 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -334,6 +334,9 @@ function max_registrations_reached() { * @return a Minz_Configuration object, null if the configuration cannot be loaded. */ function get_user_configuration($username) { + if (!FreshRSS_user_Controller::checkUsername($username)) { + return null; + } $namespace = 'user_' . $username; try { Minz_Configuration::register($namespace, -- cgit v1.2.3 From ca4138d0217f699050f80aa6bfb37e121ebec9a6 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 22 Apr 2017 12:48:26 +0200 Subject: Update to Favicon 1.2.0 https://github.com/ArthurHoaro/favicon/releases/tag/v1.2.0 --- lib/Favicon/DataAccess.php | 53 +++++++------ lib/Favicon/Favicon.php | 172 ++++++++++++++++++++++++++++++------------ lib/Favicon/FaviconDLType.php | 23 ++++++ 3 files changed, 173 insertions(+), 75 deletions(-) create mode 100644 lib/Favicon/FaviconDLType.php (limited to 'lib') diff --git a/lib/Favicon/DataAccess.php b/lib/Favicon/DataAccess.php index 4c1a29541..2bfdf640e 100644 --- a/lib/Favicon/DataAccess.php +++ b/lib/Favicon/DataAccess.php @@ -9,33 +9,32 @@ namespace Favicon; **/ class DataAccess { public function retrieveUrl($url) { - $this->set_context(); - return @file_get_contents($url); + $this->set_context(); + return @file_get_contents($url); } - + public function retrieveHeader($url) { - $this->set_context(); - $headers = @get_headers($url, 1); - return is_array($headers) ? array_change_key_case($headers) : array(); - } - - public function saveCache($file, $data) { - file_put_contents($file, $data); - } - - public function readCache($file) { - return file_get_contents($file); - } - - private function set_context() { - stream_context_set_default( - array( - 'http' => array( - 'method' => 'GET', - 'timeout' => 10, - 'header' => "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:20.0; Favicon; +https://github.com/ArthurHoaro/favicon) Gecko/20100101 Firefox/32.0\r\n", - ) - ) - ); + $this->set_context(); + return @get_headers($url, TRUE); } -} + + public function saveCache($file, $data) { + file_put_contents($file, $data); + } + + public function readCache($file) { + return file_get_contents($file); + } + + private function set_context() { + stream_context_set_default( + array( + 'http' => array( + 'method' => 'GET', + 'timeout' => 10, + 'header' => "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:20.0; Favicon; +https://github.com/ArthurHoaro/favicon) Gecko/20100101 Firefox/32.0\r\n", + ) + ) + ); + } +} \ No newline at end of file diff --git a/lib/Favicon/Favicon.php b/lib/Favicon/Favicon.php index 85d2ef19b..f39adc7d7 100644 --- a/lib/Favicon/Favicon.php +++ b/lib/Favicon/Favicon.php @@ -4,6 +4,8 @@ namespace Favicon; class Favicon { + protected static $TYPE_CACHE_URL = 'url'; + protected static $TYPE_CACHE_IMG = 'img'; protected $url = ''; protected $cacheDir; protected $cacheTimeout; @@ -16,18 +18,24 @@ class Favicon } $this->cacheDir = __DIR__ . '/../../resources/cache'; + $this->cacheTimeout = 604800; $this->dataAccess = new DataAccess(); } + /** + * Set cache settings: + * - dir: cache directory + * - timeout: in seconds + * + * @param array $args + */ public function cache($args = array()) { if (isset($args['dir'])) { $this->cacheDir = $args['dir']; } if (!empty($args['timeout'])) { - $this->cacheTimeout = $args['timeout']; - } else { - $this->cacheTimeout = 0; + $this->cacheTimeout = $args['timeout']; } } @@ -89,9 +97,6 @@ class Favicon $loop = TRUE; while ($loop && $max_loop-- > 0) { $headers = $this->dataAccess->retrieveHeader($url); - if (empty($headers)) { - return false; - } $exploded = explode(' ', $headers[0]); if( !isset($exploded[1]) ) { @@ -102,7 +107,7 @@ class Favicon switch ($status) { case '301': case '302': - $url = isset($headers['location']) ? $headers['location'] : ''; + $url = $headers['Location']; break; default: $loop = FALSE; @@ -120,9 +125,16 @@ class Favicon /** * Find remote (or cached) favicon - * @return favicon URL, false if nothing was found - **/ - public function get($url = '') + * + * @param string $url to look for a favicon + * @param int $type type of retrieval (FaviconDLType): + * - HOTLINK_URL: returns remote URL + * - DL_FILE_PATH: returns file path of the favicon downloaded locally + * - RAW_IMAGE: returns the favicon image binary string + * + * @return string|bool favicon URL, false if nothing was found + */ + public function get($url = '', $type = FaviconDLType::HOTLINK_URL) { // URLs passed to this method take precedence. if (!empty($url)) { @@ -130,25 +142,30 @@ class Favicon } // Get the base URL without the path for clearer concatenations. - $original = rtrim($this->baseUrl($this->url, true), '/'); - $url = rtrim($this->endRedirect($this->baseUrl($this->url, false)), '/'); - - if(($favicon = $this->checkCache($url)) || ($favicon = $this->getFavicon($url))) { - $base = true; - } - elseif(($favicon = $this->checkCache($original)) || ($favicon = $this->getFavicon($original, false))) { - $base = false; + $url = rtrim($this->baseUrl($this->url, true), '/'); + $original = $url; + if (($favicon = $this->checkCache($original, self::$TYPE_CACHE_URL)) === false + && ! $favicon = $this->getFavicon($original, false) + ) { + $url = rtrim($this->endRedirect($this->baseUrl($this->url, false)), '/'); + if (($favicon = $this->checkCache($url, self::$TYPE_CACHE_URL)) === false + && ! $favicon = $this->getFavicon($url) + ) { + $url = $original; + } } - else - return false; - - // Save cache if necessary - $cache = $this->cacheDir . '/' . md5($base ? $url : $original); - if ($this->cacheTimeout && !file_exists($cache) || (is_writable($cache) && time() - filemtime($cache) > $this->cacheTimeout)) { - $this->dataAccess->saveCache($cache, $favicon); + + $this->saveCache($url, $favicon, self::$TYPE_CACHE_URL); + + switch ($type) { + case FaviconDLType::DL_FILE_PATH: + return $this->getImage($url, $favicon, false); + case FaviconDLType::RAW_IMAGE: + return $this->getImage($url, $favicon, true); + case FaviconDLType::HOTLINK_URL: + default: + return empty($favicon) ? false : $favicon; } - - return $favicon; } private function getFavicon($url, $checkDefault = true) { @@ -179,13 +196,54 @@ class Favicon // Sometimes people lie, so check the status. // And sometimes, it's not even an image. Sneaky bastards! // If cacheDir isn't writable, that's not our problem - if ($favicon && is_writable($this->cacheDir) && extension_loaded('fileinfo') && !$this->checkImageMType($favicon)) { + if ($favicon && is_writable($this->cacheDir) && !$this->checkImageMType($favicon)) { $favicon = false; } return $favicon; } - + + /** + * Find remote favicon and return it as an image + */ + private function getImage($url, $faviconUrl = '', $image = false) + { + if (empty($faviconUrl)) { + return false; + } + + $favicon = $this->checkCache($url, self::$TYPE_CACHE_IMG); + // Favicon not found in the cache + if( $favicon === false ) { + $favicon = $this->dataAccess->retrieveUrl($faviconUrl); + // Definitely not found + if (!$this->checkImageMTypeContent($favicon)) { + return false; + } else { + $this->saveCache($url, $favicon, self::$TYPE_CACHE_IMG); + } + } + + if( $image ) { + return $favicon; + } + else + return self::$TYPE_CACHE_IMG . md5($url); + } + + /** + * Display data as a PNG Favicon, then exit + * @param $data + */ + private function displayFavicon($data) { + header('Content-Type: image/png'); + header('Cache-Control: private, max-age=10800, pre-check=10800'); + header('Pragma: private'); + header('Expires: ' . date(DATE_RFC822,strtotime('7 day'))); + echo $data; + exit; + } + private function getInPage($url) { $html = $this->dataAccess->retrieveUrl("{$url}/"); preg_match('!.*!ims', $html, $match); @@ -197,7 +255,7 @@ class Favicon $head = $match[0]; $dom = new \DOMDocument(); - // Use error supression, because the HTML might be too malformed. + // Use error suppression, because the HTML might be too malformed. if (@$dom->loadHTML($head)) { $links = $dom->getElementsByTagName('link'); foreach ($links as $link) { @@ -212,33 +270,51 @@ class Favicon } return false; } - - private function checkCache($url) { + + private function checkCache($url, $type) { if ($this->cacheTimeout) { - $cache = $this->cacheDir . '/' . md5($url); - if (file_exists($cache) && is_readable($cache) && (time() - filemtime($cache) < $this->cacheTimeout)) { + $cache = $this->cacheDir . '/'. $type . md5($url); + if (file_exists($cache) && is_readable($cache) + && ($this->cacheTimeout === -1 || time() - filemtime($cache) < $this->cacheTimeout) + ) { return $this->dataAccess->readCache($cache); } - } + } return false; } - + + /** + * Will save data in cacheDir if the directory writable and any previous cache is expired (cacheTimeout) + * @param $url + * @param $data + * @param $type + * @return string cache file path + */ + private function saveCache($url, $data, $type) { + // Save cache if necessary + $cache = $this->cacheDir . '/'. $type . md5($url); + if ($this->cacheTimeout && !file_exists($cache) + || (is_writable($cache) && $this->cacheTimeout !== -1 && time() - filemtime($cache) > $this->cacheTimeout) + ) { + $this->dataAccess->saveCache($cache, $data); + } + return $cache; + } + private function checkImageMType($url) { - $tmpFile = $this->cacheDir . '/tmp.ico'; $fileContent = $this->dataAccess->retrieveUrl($url); - $this->dataAccess->saveCache($tmpFile, $fileContent); - $isImage = true; - try { - $finfo = finfo_open(FILEINFO_MIME_TYPE); - $isImage = strpos(finfo_file($finfo, $tmpFile), 'image') !== false; - finfo_close($finfo); - } catch (Exception $e) { - } + return $this->checkImageMTypeContent($fileContent); + } + + private function checkImageMTypeContent($content) { + if(empty($content)) return false; + + $fInfo = finfo_open(FILEINFO_MIME_TYPE); + $isImage = strpos(finfo_buffer($fInfo, $content), 'image') !== false; + finfo_close($fInfo); - unlink($tmpFile); - return $isImage; } @@ -291,7 +367,7 @@ class Favicon } /** - * @param DataAccess $dataAccess + * @param DataAccess|\PHPUnit_Framework_MockObject_MockObject $dataAccess */ public function setDataAccess($dataAccess) { diff --git a/lib/Favicon/FaviconDLType.php b/lib/Favicon/FaviconDLType.php new file mode 100644 index 000000000..6da525a7f --- /dev/null +++ b/lib/Favicon/FaviconDLType.php @@ -0,0 +1,23 @@ + Date: Sat, 22 Apr 2017 13:35:51 +0200 Subject: Re-apply Favicon FreshRSS patches Patches sent upstream https://github.com/ArthurHoaro/favicon/pull/5 --- lib/Favicon/DataAccess.php | 3 ++- lib/Favicon/Favicon.php | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/Favicon/DataAccess.php b/lib/Favicon/DataAccess.php index 2bfdf640e..838df66c3 100644 --- a/lib/Favicon/DataAccess.php +++ b/lib/Favicon/DataAccess.php @@ -15,7 +15,8 @@ class DataAccess { public function retrieveHeader($url) { $this->set_context(); - return @get_headers($url, TRUE); + $headers = @get_headers($url, 1); + return is_array($headers) ? array_change_key_case($headers) : array(); } public function saveCache($file, $data) { diff --git a/lib/Favicon/Favicon.php b/lib/Favicon/Favicon.php index f39adc7d7..7e6c42d6e 100644 --- a/lib/Favicon/Favicon.php +++ b/lib/Favicon/Favicon.php @@ -97,6 +97,9 @@ class Favicon $loop = TRUE; while ($loop && $max_loop-- > 0) { $headers = $this->dataAccess->retrieveHeader($url); + if (empty($headers)) { + return false; + } $exploded = explode(' ', $headers[0]); if( !isset($exploded[1]) ) { @@ -107,7 +110,7 @@ class Favicon switch ($status) { case '301': case '302': - $url = $headers['Location']; + $url = isset($headers['location']) ? $headers['location'] : ''; break; default: $loop = FALSE; @@ -196,7 +199,7 @@ class Favicon // Sometimes people lie, so check the status. // And sometimes, it's not even an image. Sneaky bastards! // If cacheDir isn't writable, that's not our problem - if ($favicon && is_writable($this->cacheDir) && !$this->checkImageMType($favicon)) { + if ($favicon && is_writable($this->cacheDir) && extension_loaded('fileinfo') && !$this->checkImageMType($favicon)) { $favicon = false; } @@ -311,9 +314,13 @@ class Favicon private function checkImageMTypeContent($content) { if(empty($content)) return false; - $fInfo = finfo_open(FILEINFO_MIME_TYPE); - $isImage = strpos(finfo_buffer($fInfo, $content), 'image') !== false; - finfo_close($fInfo); + $isImage = true; + try { + $fInfo = finfo_open(FILEINFO_MIME_TYPE); + $isImage = strpos(finfo_buffer($fInfo, $content), 'image') !== false; + finfo_close($fInfo); + } catch (Exception $e) { + } return $isImage; } -- cgit v1.2.3 From 1af1b3702e5336947d49f62b21c21b1ad9f9fba8 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 22 Apr 2017 18:56:00 +0200 Subject: Use new version 1.2 of Favicon library --- lib/favicons.php | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) (limited to 'lib') diff --git a/lib/favicons.php b/lib/favicons.php index d8c97964e..0e80aa145 100644 --- a/lib/favicons.php +++ b/lib/favicons.php @@ -1,43 +1,21 @@ setCacheDir($favicons_dir); - $favicon_url = $favicon_getter->get($website); - - if ($favicon_url === false) { - return @copy($default_favicon, $dest); - } - - syslog(LOG_INFO, 'FreshRSS Favicon GET ' . $favicon_url); - $c = curl_init($favicon_url); - curl_setopt($c, CURLOPT_HEADER, false); - curl_setopt($c, CURLOPT_RETURNTRANSFER, true); - curl_setopt($c, CURLOPT_BINARYTRANSFER, true); - curl_setopt($c, CURLOPT_USERAGENT, 'FreshRSS/' . FRESHRSS_VERSION . ' (' . PHP_OS . '; ' . FRESHRSS_WEBSITE . ')'); - $img_raw = curl_exec($c); - $status_code = curl_getinfo($c, CURLINFO_HTTP_CODE); - curl_close($c); - - if ($status_code === 200) { - $file = fopen($dest, 'w'); - if ($file !== false) { - fwrite($file, $img_raw); - fclose($file); - return true; - } - } else { - syslog(LOG_WARNING, 'FreshRSS Favicon GET ' . $favicon_url . ' error ' . $status_code); - } + $tmpPath = realpath(TMP_PATH) . '/'; + $favicon_getter->setCacheDir($tmpPath); + $favicon_path = $favicon_getter->get($website, \Favicon\FaviconDLType::DL_FILE_PATH); - return false; + return ($favicon_path != false && @rename($tmpPath . $favicon_path, $dest)) || + @copy($default_favicon, $dest); } -- cgit v1.2.3 From 57f1e9d6570e86f1bc679ed4897437ae4b14a2b5 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 22 Apr 2017 23:36:41 +0200 Subject: Fix some bugs of Favicon 1.2 https://github.com/ArthurHoaro/favicon/pull/6 https://github.com/ArthurHoaro/favicon/pull/7 --- lib/Favicon/Favicon.php | 18 ++++++++++++++---- lib/favicons.php | 4 ++-- 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/Favicon/Favicon.php b/lib/Favicon/Favicon.php index 7e6c42d6e..39f45f139 100644 --- a/lib/Favicon/Favicon.php +++ b/lib/Favicon/Favicon.php @@ -188,7 +188,10 @@ class Favicon // See if it's specified in a link tag in domain url. if (!$favicon) { - $favicon = $this->getInPage($url); + $favicon = trim($this->getInPage($url)); + } + if (substr($favicon, 0, 2) === '//') { + $favicon = 'https:' . $favicon; } // Make sure the favicon is an absolute URL. @@ -264,9 +267,15 @@ class Favicon foreach ($links as $link) { if ($link->hasAttribute('rel') && strtolower($link->getAttribute('rel')) == 'shortcut icon') { return $link->getAttribute('href'); - } elseif ($link->hasAttribute('rel') && strtolower($link->getAttribute('rel')) == 'icon') { + } + } + foreach ($links as $link) { + if ($link->hasAttribute('rel') && strtolower($link->getAttribute('rel')) == 'icon') { return $link->getAttribute('href'); - } elseif ($link->hasAttribute('href') && strpos($link->getAttribute('href'), 'favicon') !== FALSE) { + } + } + foreach ($links as $link) { + if ($link->hasAttribute('href') && strpos($link->getAttribute('href'), 'favicon') !== FALSE) { return $link->getAttribute('href'); } } @@ -319,7 +328,8 @@ class Favicon $fInfo = finfo_open(FILEINFO_MIME_TYPE); $isImage = strpos(finfo_buffer($fInfo, $content), 'image') !== false; finfo_close($fInfo); - } catch (Exception $e) { + } catch (\Exception $e) { + error_log('Favicon checkImageMTypeContent error: ' . $e->getMessage()); } return $isImage; diff --git a/lib/favicons.php b/lib/favicons.php index 0e80aa145..93e570d27 100644 --- a/lib/favicons.php +++ b/lib/favicons.php @@ -12,10 +12,10 @@ function download_favicon($website, $dest) { syslog(LOG_INFO, 'FreshRSS Favicon discovery GET ' . $website); $favicon_getter = new \Favicon\Favicon(); - $tmpPath = realpath(TMP_PATH) . '/'; + $tmpPath = realpath(TMP_PATH); $favicon_getter->setCacheDir($tmpPath); $favicon_path = $favicon_getter->get($website, \Favicon\FaviconDLType::DL_FILE_PATH); - return ($favicon_path != false && @rename($tmpPath . $favicon_path, $dest)) || + return ($favicon_path != false && @rename($tmpPath . '/' . $favicon_path, $dest)) || @copy($default_favicon, $dest); } -- cgit v1.2.3 From f483a5e95bc78cfb42e6fd90436c9f1c60e0242b Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 23 Apr 2017 01:59:09 +0200 Subject: Favicon fix redirects https://github.com/ArthurHoaro/favicon/pull/5/commits/92b42591591b4282261f21ed5ffa553f5e987a9d --- lib/Favicon/DataAccess.php | 2 ++ lib/Favicon/Favicon.php | 3 +++ lib/favicons.php | 1 + 3 files changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/Favicon/DataAccess.php b/lib/Favicon/DataAccess.php index 838df66c3..1445e9343 100644 --- a/lib/Favicon/DataAccess.php +++ b/lib/Favicon/DataAccess.php @@ -32,6 +32,8 @@ class DataAccess { array( 'http' => array( 'method' => 'GET', + 'follow_location' => 0, + 'max_redirects' => 1, 'timeout' => 10, 'header' => "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:20.0; Favicon; +https://github.com/ArthurHoaro/favicon) Gecko/20100101 Firefox/32.0\r\n", ) diff --git a/lib/Favicon/Favicon.php b/lib/Favicon/Favicon.php index 39f45f139..c026d8a95 100644 --- a/lib/Favicon/Favicon.php +++ b/lib/Favicon/Favicon.php @@ -111,6 +111,9 @@ class Favicon case '301': case '302': $url = isset($headers['location']) ? $headers['location'] : ''; + if (is_array($url)) { + $url = end($url); + } break; default: $loop = FALSE; diff --git a/lib/favicons.php b/lib/favicons.php index 93e570d27..d8baba342 100644 --- a/lib/favicons.php +++ b/lib/favicons.php @@ -14,6 +14,7 @@ function download_favicon($website, $dest) { $favicon_getter = new \Favicon\Favicon(); $tmpPath = realpath(TMP_PATH); $favicon_getter->setCacheDir($tmpPath); + $favicon_getter->setCacheTimeout(-1); $favicon_path = $favicon_getter->get($website, \Favicon\FaviconDLType::DL_FILE_PATH); return ($favicon_path != false && @rename($tmpPath . '/' . $favicon_path, $dest)) || -- cgit v1.2.3 From 44c9ae51c44478e56ee70ce692ade6a275981320 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 23 Apr 2017 14:06:37 +0200 Subject: Rewriten Favicon library using cURL Reduce the number of requests, more robust, many more cases working, reduced code --- CHANGELOG.md | 2 +- lib/Favicon/DataAccess.php | 43 ----- lib/Favicon/Favicon.php | 396 ------------------------------------------ lib/Favicon/FaviconDLType.php | 23 --- lib/favicons.php | 110 ++++++++++-- p/f.php | 3 +- 6 files changed, 98 insertions(+), 479 deletions(-) delete mode 100644 lib/Favicon/DataAccess.php delete mode 100644 lib/Favicon/Favicon.php delete mode 100644 lib/Favicon/FaviconDLType.php (limited to 'lib') diff --git a/CHANGELOG.md b/CHANGELOG.md index e680736db..08025bb3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ * Improve English [#1465](https://github.com/FreshRSS/FreshRSS/pull/1465) * Misc. * Fall back to article URL when the article GUID is empty [#1482](https://github.com/FreshRSS/FreshRSS/issues/1482) - * Update to version 1.2 of Favicon library [#1501](https://github.com/FreshRSS/FreshRSS/issues/1501) + * Rewriten Favicon library using cURL [#1503](https://github.com/FreshRSS/FreshRSS/pull/1503) ## 2017-03-11 FreshRSS 1.6.3 diff --git a/lib/Favicon/DataAccess.php b/lib/Favicon/DataAccess.php deleted file mode 100644 index 1445e9343..000000000 --- a/lib/Favicon/DataAccess.php +++ /dev/null @@ -1,43 +0,0 @@ -set_context(); - return @file_get_contents($url); - } - - public function retrieveHeader($url) { - $this->set_context(); - $headers = @get_headers($url, 1); - return is_array($headers) ? array_change_key_case($headers) : array(); - } - - public function saveCache($file, $data) { - file_put_contents($file, $data); - } - - public function readCache($file) { - return file_get_contents($file); - } - - private function set_context() { - stream_context_set_default( - array( - 'http' => array( - 'method' => 'GET', - 'follow_location' => 0, - 'max_redirects' => 1, - 'timeout' => 10, - 'header' => "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:20.0; Favicon; +https://github.com/ArthurHoaro/favicon) Gecko/20100101 Firefox/32.0\r\n", - ) - ) - ); - } -} \ No newline at end of file diff --git a/lib/Favicon/Favicon.php b/lib/Favicon/Favicon.php deleted file mode 100644 index c026d8a95..000000000 --- a/lib/Favicon/Favicon.php +++ /dev/null @@ -1,396 +0,0 @@ -url = $args['url']; - } - - $this->cacheDir = __DIR__ . '/../../resources/cache'; - $this->cacheTimeout = 604800; - $this->dataAccess = new DataAccess(); - } - - /** - * Set cache settings: - * - dir: cache directory - * - timeout: in seconds - * - * @param array $args - */ - public function cache($args = array()) { - if (isset($args['dir'])) { - $this->cacheDir = $args['dir']; - } - - if (!empty($args['timeout'])) { - $this->cacheTimeout = $args['timeout']; - } - } - - public static function baseUrl($url, $path = false) - { - $return = ''; - - if (!$url = parse_url($url)) { - return FALSE; - } - - // Scheme - $scheme = isset($url['scheme']) ? strtolower($url['scheme']) : null; - if ($scheme != 'http' && $scheme != 'https') { - - return FALSE; - } - $return .= "{$scheme}://"; - - // Username and password - if (isset($url['user'])) { - $return .= $url['user']; - if (isset($url['pass'])) { - $return .= ":{$url['pass']}"; - } - $return .= '@'; - } - - // Hostname - if( !isset($url['host']) ) { - return FALSE; - } - - $return .= $url['host']; - - // Port - if (isset($url['port'])) { - $return .= ":{$url['port']}"; - } - - // Path - if( $path && isset($url['path']) ) { - $return .= $url['path']; - } - $return .= '/'; - - return $return; - } - - public function info($url) - { - if(empty($url) || $url === false) { - return false; - } - - $max_loop = 5; - - // Discover real status by following redirects. - $loop = TRUE; - while ($loop && $max_loop-- > 0) { - $headers = $this->dataAccess->retrieveHeader($url); - if (empty($headers)) { - return false; - } - $exploded = explode(' ', $headers[0]); - - if( !isset($exploded[1]) ) { - return false; - } - list(,$status) = $exploded; - - switch ($status) { - case '301': - case '302': - $url = isset($headers['location']) ? $headers['location'] : ''; - if (is_array($url)) { - $url = end($url); - } - break; - default: - $loop = FALSE; - break; - } - } - - return array('status' => $status, 'url' => $url); - } - - public function endRedirect($url) { - $out = $this->info($url); - return !empty($out['url']) ? $out['url'] : false; - } - - /** - * Find remote (or cached) favicon - * - * @param string $url to look for a favicon - * @param int $type type of retrieval (FaviconDLType): - * - HOTLINK_URL: returns remote URL - * - DL_FILE_PATH: returns file path of the favicon downloaded locally - * - RAW_IMAGE: returns the favicon image binary string - * - * @return string|bool favicon URL, false if nothing was found - */ - public function get($url = '', $type = FaviconDLType::HOTLINK_URL) - { - // URLs passed to this method take precedence. - if (!empty($url)) { - $this->url = $url; - } - - // Get the base URL without the path for clearer concatenations. - $url = rtrim($this->baseUrl($this->url, true), '/'); - $original = $url; - if (($favicon = $this->checkCache($original, self::$TYPE_CACHE_URL)) === false - && ! $favicon = $this->getFavicon($original, false) - ) { - $url = rtrim($this->endRedirect($this->baseUrl($this->url, false)), '/'); - if (($favicon = $this->checkCache($url, self::$TYPE_CACHE_URL)) === false - && ! $favicon = $this->getFavicon($url) - ) { - $url = $original; - } - } - - $this->saveCache($url, $favicon, self::$TYPE_CACHE_URL); - - switch ($type) { - case FaviconDLType::DL_FILE_PATH: - return $this->getImage($url, $favicon, false); - case FaviconDLType::RAW_IMAGE: - return $this->getImage($url, $favicon, true); - case FaviconDLType::HOTLINK_URL: - default: - return empty($favicon) ? false : $favicon; - } - } - - private function getFavicon($url, $checkDefault = true) { - $favicon = false; - - if(empty($url)) { - return false; - } - - // Try /favicon.ico first. - if( $checkDefault ) { - $info = $this->info("{$url}/favicon.ico"); - if ($info['status'] == '200') { - $favicon = $info['url']; - } - } - - // See if it's specified in a link tag in domain url. - if (!$favicon) { - $favicon = trim($this->getInPage($url)); - } - if (substr($favicon, 0, 2) === '//') { - $favicon = 'https:' . $favicon; - } - - // Make sure the favicon is an absolute URL. - if( $favicon && filter_var($favicon, FILTER_VALIDATE_URL) === false ) { - $favicon = $url . '/' . $favicon; - } - - // Sometimes people lie, so check the status. - // And sometimes, it's not even an image. Sneaky bastards! - // If cacheDir isn't writable, that's not our problem - if ($favicon && is_writable($this->cacheDir) && extension_loaded('fileinfo') && !$this->checkImageMType($favicon)) { - $favicon = false; - } - - return $favicon; - } - - /** - * Find remote favicon and return it as an image - */ - private function getImage($url, $faviconUrl = '', $image = false) - { - if (empty($faviconUrl)) { - return false; - } - - $favicon = $this->checkCache($url, self::$TYPE_CACHE_IMG); - // Favicon not found in the cache - if( $favicon === false ) { - $favicon = $this->dataAccess->retrieveUrl($faviconUrl); - // Definitely not found - if (!$this->checkImageMTypeContent($favicon)) { - return false; - } else { - $this->saveCache($url, $favicon, self::$TYPE_CACHE_IMG); - } - } - - if( $image ) { - return $favicon; - } - else - return self::$TYPE_CACHE_IMG . md5($url); - } - - /** - * Display data as a PNG Favicon, then exit - * @param $data - */ - private function displayFavicon($data) { - header('Content-Type: image/png'); - header('Cache-Control: private, max-age=10800, pre-check=10800'); - header('Pragma: private'); - header('Expires: ' . date(DATE_RFC822,strtotime('7 day'))); - echo $data; - exit; - } - - private function getInPage($url) { - $html = $this->dataAccess->retrieveUrl("{$url}/"); - preg_match('!.*!ims', $html, $match); - - if(empty($match) || count($match) == 0) { - return false; - } - - $head = $match[0]; - - $dom = new \DOMDocument(); - // Use error suppression, because the HTML might be too malformed. - if (@$dom->loadHTML($head)) { - $links = $dom->getElementsByTagName('link'); - foreach ($links as $link) { - if ($link->hasAttribute('rel') && strtolower($link->getAttribute('rel')) == 'shortcut icon') { - return $link->getAttribute('href'); - } - } - foreach ($links as $link) { - if ($link->hasAttribute('rel') && strtolower($link->getAttribute('rel')) == 'icon') { - return $link->getAttribute('href'); - } - } - foreach ($links as $link) { - if ($link->hasAttribute('href') && strpos($link->getAttribute('href'), 'favicon') !== FALSE) { - return $link->getAttribute('href'); - } - } - } - return false; - } - - private function checkCache($url, $type) { - if ($this->cacheTimeout) { - $cache = $this->cacheDir . '/'. $type . md5($url); - if (file_exists($cache) && is_readable($cache) - && ($this->cacheTimeout === -1 || time() - filemtime($cache) < $this->cacheTimeout) - ) { - return $this->dataAccess->readCache($cache); - } - } - return false; - } - - /** - * Will save data in cacheDir if the directory writable and any previous cache is expired (cacheTimeout) - * @param $url - * @param $data - * @param $type - * @return string cache file path - */ - private function saveCache($url, $data, $type) { - // Save cache if necessary - $cache = $this->cacheDir . '/'. $type . md5($url); - if ($this->cacheTimeout && !file_exists($cache) - || (is_writable($cache) && $this->cacheTimeout !== -1 && time() - filemtime($cache) > $this->cacheTimeout) - ) { - $this->dataAccess->saveCache($cache, $data); - } - return $cache; - } - - private function checkImageMType($url) { - - $fileContent = $this->dataAccess->retrieveUrl($url); - - return $this->checkImageMTypeContent($fileContent); - } - - private function checkImageMTypeContent($content) { - if(empty($content)) return false; - - $isImage = true; - try { - $fInfo = finfo_open(FILEINFO_MIME_TYPE); - $isImage = strpos(finfo_buffer($fInfo, $content), 'image') !== false; - finfo_close($fInfo); - } catch (\Exception $e) { - error_log('Favicon checkImageMTypeContent error: ' . $e->getMessage()); - } - - return $isImage; - } - - /** - * @return mixed - */ - public function getCacheDir() - { - return $this->cacheDir; - } - - /** - * @param mixed $cacheDir - */ - public function setCacheDir($cacheDir) - { - $this->cacheDir = $cacheDir; - } - - /** - * @return mixed - */ - public function getCacheTimeout() - { - return $this->cacheTimeout; - } - - /** - * @param mixed $cacheTimeout - */ - public function setCacheTimeout($cacheTimeout) - { - $this->cacheTimeout = $cacheTimeout; - } - - /** - * @return string - */ - public function getUrl() - { - return $this->url; - } - - /** - * @param string $url - */ - public function setUrl($url) - { - $this->url = $url; - } - - /** - * @param DataAccess|\PHPUnit_Framework_MockObject_MockObject $dataAccess - */ - public function setDataAccess($dataAccess) - { - $this->dataAccess = $dataAccess; - } -} diff --git a/lib/Favicon/FaviconDLType.php b/lib/Favicon/FaviconDLType.php deleted file mode 100644 index 6da525a7f..000000000 --- a/lib/Favicon/FaviconDLType.php +++ /dev/null @@ -1,23 +0,0 @@ -setCacheDir($tmpPath); - $favicon_getter->setCacheTimeout(-1); - $favicon_path = $favicon_getter->get($website, \Favicon\FaviconDLType::DL_FILE_PATH); +function downloadHttp(&$url, $curlOptions = array()) { + syslog(LOG_INFO, 'FreshRSS Favicon GET ' . $url); + if (substr($url, 0, 2) === '//') { + $url = 'https:' . $favicon; + } + if ($url == '' || filter_var($url, FILTER_VALIDATE_URL) === false) { + return ''; + } + $ch = curl_init($url); + curl_setopt_array($ch, array( + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_MAXREDIRS => 10, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 15, + CURLOPT_USERAGENT => 'FreshRSS/' . FRESHRSS_VERSION . ' (' . PHP_OS . '; ' . FRESHRSS_WEBSITE . ')', + )); + if (defined('CURLOPT_ENCODING')) { + curl_setopt($ch, CURLOPT_ENCODING, ''); //Enable all encodings + } + curl_setopt_array($ch, $curlOptions); + $response = curl_exec($ch); + $info = curl_getinfo($ch); + curl_close($ch); + if (!empty($info['url']) && (filter_var($info['url'], FILTER_VALIDATE_URL) !== false)) { + $url = $info['url']; + } + return $info['http_code'] == 200 ? $response : ''; +} + +function searchFavicon(&$url) { + $dom = new DOMDocument(); + $html = downloadHttp($url); + if ($html != '' && @$dom->loadHTML($html, LIBXML_NONET | LIBXML_NOERROR | LIBXML_NOWARNING)) { + $rels = array('shortcut icon', 'icon'); + $links = $dom->getElementsByTagName('link'); + foreach ($rels as $rel) { + foreach ($links as $link) { + if ($link->hasAttribute('rel') && $link->hasAttribute('href') && + strtolower(trim($link->getAttribute('rel'))) === $rel) { + $href = trim($link->getAttribute('href')); + if (substr($href, 0, 2) === '//') { + $href = 'https:' . $href; + } + if (filter_var($href, FILTER_VALIDATE_URL) === false) { + $href = SimplePie_IRI::absolutize($url, $href); + } + $favicon = downloadHttp($href, array( + CURLOPT_REFERER => $url, + )); + if (isImgMime($favicon)) { + return $favicon; + } + } + } + } + } + return ''; +} - return ($favicon_path != false && @rename($tmpPath . '/' . $favicon_path, $dest)) || +function download_favicon($url, $dest) { + global $default_favicon; + $url = trim($url); + $favicon = searchFavicon($url); + if ($favicon == '') { + $rootUrl = preg_replace('%^(https?://[^/]+).*$%i', '$1/', $url); + if ($rootUrl != $url) { + $url = $rootUrl; + $favicon = searchFavicon($url); + } + if ($favicon == '') { + $link = $rootUrl . 'favicon.ico'; + $favicon = downloadHttp($link, array( + CURLOPT_REFERER => $url, + )); + if (!isImgMime($favicon)) { + $favicon = ''; + } + } + } + return ($favicon != '' && file_put_contents($dest, $favicon)) || @copy($default_favicon, $dest); } diff --git a/p/f.php b/p/f.php index e4c82bb16..c47fa747a 100644 --- a/p/f.php +++ b/p/f.php @@ -1,6 +1,6 @@ Date: Sun, 23 Apr 2017 14:24:12 +0200 Subject: Favicon minor --- CHANGELOG.md | 2 +- lib/favicons.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/CHANGELOG.md b/CHANGELOG.md index f8d10e6dd..0cb5155d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ * Improve English [#1465](https://github.com/FreshRSS/FreshRSS/pull/1465) * Misc. * Fall back to article URL when the article GUID is empty [#1482](https://github.com/FreshRSS/FreshRSS/issues/1482) - * Rewriten Favicon library using cURL [#1504](https://github.com/FreshRSS/FreshRSS/pull/1504) + * Rewritten Favicon library using cURL [#1504](https://github.com/FreshRSS/FreshRSS/pull/1504) ## 2017-03-11 FreshRSS 1.6.3 diff --git a/lib/favicons.php b/lib/favicons.php index cc6e54374..de993ec8a 100644 --- a/lib/favicons.php +++ b/lib/favicons.php @@ -44,7 +44,7 @@ function downloadHttp(&$url, $curlOptions = array()) { $info = curl_getinfo($ch); curl_close($ch); if (!empty($info['url']) && (filter_var($info['url'], FILTER_VALIDATE_URL) !== false)) { - $url = $info['url']; + $url = $info['url']; //Possible redirect } return $info['http_code'] == 200 ? $response : ''; } -- cgit v1.2.3 From 2ffb00c37fd0299ad7f13137115091fd62582ac6 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 23 Apr 2017 18:00:48 +0200 Subject: Better handling of protocol-relative favicons https://github.com/ArthurHoaro/favicon/pull/6/commits/cd5f98ecdd1d38e8bc5d87fd09c80079a74191ba https://github.com/FreshRSS/FreshRSS/pull/1504 --- lib/favicons.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/favicons.php b/lib/favicons.php index de993ec8a..62a21a246 100644 --- a/lib/favicons.php +++ b/lib/favicons.php @@ -61,7 +61,12 @@ function searchFavicon(&$url) { strtolower(trim($link->getAttribute('rel'))) === $rel) { $href = trim($link->getAttribute('href')); if (substr($href, 0, 2) === '//') { - $href = 'https:' . $href; + // Case of protocol-relative URLs + if (preg_match('%^(https?:)//%i', $url, $matches)) { + $href = $matches[1] . $href; + } else { + $href = 'https:' . $href; + } } if (filter_var($href, FILTER_VALIDATE_URL) === false) { $href = SimplePie_IRI::absolutize($url, $href); -- cgit v1.2.3 From ed99245810fce469b30c946e7fc405887c2a5b61 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 23 Apr 2017 18:23:37 +0200 Subject: Minor favicon text https://github.com/FreshRSS/FreshRSS/pull/1505 https://github.com/FreshRSS/FreshRSS/pull/1504 --- README.fr.md | 1 - README.md | 1 - lib/favicons.php | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/README.fr.md b/README.fr.md index de76919e6..25895d48c 100644 --- a/README.fr.md +++ b/README.fr.md @@ -159,7 +159,6 @@ Voir le [dépôt dédié à ces extensions](https://github.com/FreshRSS/Extensio * [MINZ](https://github.com/marienfressinaud/MINZ) * [php-http-304](http://alexandre.alapetite.fr/doc-alex/php-http-304/) * [jQuery](http://jquery.com/) -* [ArthurHoaro/favicon](https://github.com/ArthurHoaro/favicon) * [lib_opml](https://github.com/marienfressinaud/lib_opml) * [jQuery Plugin Sticky-Kit](http://leafo.net/sticky-kit/) * [keyboard_shortcuts](http://www.openjs.com/scripts/events/keyboard_shortcuts/) diff --git a/README.md b/README.md index 94b8ee045..ef04c8cc0 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,6 @@ See the [repository dedicated to those extensions](https://github.com/FreshRSS/E * [MINZ](https://github.com/marienfressinaud/MINZ) * [php-http-304](http://alexandre.alapetite.fr/doc-alex/php-http-304/) * [jQuery](http://jquery.com/) -* [ArthurHoaro/favicon](https://github.com/ArthurHoaro/favicon) * [lib_opml](https://github.com/marienfressinaud/lib_opml) * [jQuery Plugin Sticky-Kit](http://leafo.net/sticky-kit/) * [keyboard_shortcuts](http://www.openjs.com/scripts/events/keyboard_shortcuts/) diff --git a/lib/favicons.php b/lib/favicons.php index 62a21a246..48f7c9fda 100644 --- a/lib/favicons.php +++ b/lib/favicons.php @@ -4,7 +4,7 @@ $default_favicon = PUBLIC_PATH . '/themes/icons/default_favicon.ico'; function isImgMime($content) { //Based on https://github.com/ArthurHoaro/favicon/blob/3a4f93da9bb24915b21771eb7873a21bde26f5d1/src/Favicon/Favicon.php#L311-L319 - if($content == '') { + if ($content == '') { return false; } if (!extension_loaded('fileinfo')) { -- cgit v1.2.3 From d6bd90a8010a196b120f0a2a5639f64c8ebee568 Mon Sep 17 00:00:00 2001 From: Jonas Östanbäck Date: Tue, 9 May 2017 14:43:37 +0200 Subject: Add syslog_enabled when creating new simplepie_file --- lib/SimplePie/SimplePie.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/SimplePie/SimplePie.php b/lib/SimplePie/SimplePie.php index 7240fdf66..2796cf090 100644 --- a/lib/SimplePie/SimplePie.php +++ b/lib/SimplePie/SimplePie.php @@ -1579,7 +1579,7 @@ class SimplePie $headers['if-none-match'] = $this->data['headers']['etag']; } - $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options)); + $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options, $this->syslog_enabled)); if ($file->success) { -- cgit v1.2.3 From e825822ba0ba686fb3122026a4be8f1510cff8fa Mon Sep 17 00:00:00 2001 From: Jonas Östanbäck Date: Tue, 9 May 2017 19:16:57 +0200 Subject: Add syslog_enabled in one more file create call --- lib/SimplePie/SimplePie.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/SimplePie/SimplePie.php b/lib/SimplePie/SimplePie.php index 2796cf090..ec3ef1c77 100644 --- a/lib/SimplePie/SimplePie.php +++ b/lib/SimplePie/SimplePie.php @@ -1633,7 +1633,7 @@ class SimplePie $headers = array( 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', ); - $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options)); + $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options, $this->syslog_enabled)); } } // If the file connection has an error, set SimplePie::error to that and quit -- cgit v1.2.3 From af8960b8b3be3c78573d0319a8a537083fae2d4d Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Fri, 12 May 2017 23:33:58 +0200 Subject: Move default configuration files https://github.com/FreshRSS/FreshRSS/issues/1531 --- README.fr.md | 2 +- README.md | 2 +- app/FreshRSS.php | 2 +- app/install.php | 4 +- cli/_cli.php | 2 +- config-user.default.php | 75 ++++++++++++++++++++ config.default.php | 152 ++++++++++++++++++++++++++++++++++++++++ data/config.default.php | 152 ---------------------------------------- data/users/_/config.default.php | 75 -------------------- lib/Minz/FrontController.php | 2 +- lib/lib_install.php | 4 +- lib/lib_rss.php | 2 +- p/api/greader.php | 2 +- p/api/index.php | 2 +- p/api/pshb.php | 6 +- 15 files changed, 242 insertions(+), 242 deletions(-) create mode 100644 config-user.default.php create mode 100644 config.default.php delete mode 100644 data/config.default.php delete mode 100644 data/users/_/config.default.php (limited to 'lib') diff --git a/README.fr.md b/README.fr.md index 5e78ad803..b7a28fd91 100644 --- a/README.fr.md +++ b/README.fr.md @@ -52,7 +52,7 @@ Nous sommes une communauté amicale. 4. Accédez à FreshRSS à travers votre navigateur Web et suivez les instructions d’installation * ou utilisez [l’interface en ligne de commande](./cli/README.md) 5. Tout devrait fonctionner :) En cas de problème, n’hésitez pas à [nous contacter](https://github.com/FreshRSS/FreshRSS/issues). -6. Des paramètres de configuration avancée peuvent être accédés depuis [config.php](./data/config.default.php). +6. Des paramètres de configuration avancée peuvent être vues dans [config.default.php](./config.default.php) et modifiées dans `data/config.php`. ## Installation automatisée * [![DP deploy](https://raw.githubusercontent.com/DFabric/DPlatform-ShellCore/gh-pages/img/deploy.png)](https://dfabric.github.io/DPlatform-ShellCore) diff --git a/README.md b/README.md index 4c50acdd7..8e0d8bac9 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ We are a friendly community. 4. Access FreshRSS with your browser and follow the installation process * or use the [Command-Line Interface](./cli/README.md) 5. Everything should be working :) If you encounter any problem, feel free [contact us](https://github.com/FreshRSS/FreshRSS/issues). -6. Advanced configuration settings can be seen in [config.php](./data/config.default.php). +6. Advanced configuration settings can be seen in [config.default.php](./config.default.php) and modified in `data/config.php`. ## Automated install * [![Install on Cloudron](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=org.freshrss.cloudronapp) diff --git a/app/FreshRSS.php b/app/FreshRSS.php index e4caf23d1..563393c90 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -41,7 +41,7 @@ class FreshRSS extends Minz_FrontController { $current_user = Minz_Session::param('currentUser', '_'); Minz_Configuration::register('user', join_path(USERS_PATH, $current_user, 'config.php'), - join_path(USERS_PATH, '_', 'config.default.php'), + join_path(FRESHRSS_PATH, 'config-user.default.php'), $configuration_setter); // Finish to initialize the other FreshRSS / Minz components. diff --git a/app/install.php b/app/install.php index ebfffa47d..9e474ca73 100644 --- a/app/install.php +++ b/app/install.php @@ -88,13 +88,13 @@ function saveStep1() { // First, we try to get previous configurations Minz_Configuration::register('system', join_path(DATA_PATH, 'config.php'), - join_path(DATA_PATH, 'config.default.php')); + join_path(FRESHRSS_PATH, 'config.default.php')); $system_conf = Minz_Configuration::get('system'); $current_user = $system_conf->default_user; Minz_Configuration::register('user', join_path(USERS_PATH, $current_user, 'config.php'), - join_path(USERS_PATH, '_', 'config.default.php')); + join_path(FRESHRSS_PATH, 'config-user.default.php')); $user_conf = Minz_Configuration::get('user'); // Then, we set $_SESSION vars diff --git a/cli/_cli.php b/cli/_cli.php index f5e36eabc..1b26ea738 100644 --- a/cli/_cli.php +++ b/cli/_cli.php @@ -8,7 +8,7 @@ require(LIB_PATH . '/lib_rss.php'); Minz_Configuration::register('system', DATA_PATH . '/config.php', - DATA_PATH . '/config.default.php'); + FRESHRSS_PATH . '/config.default.php'); FreshRSS_Context::$system_conf = Minz_Configuration::get('system'); Minz_Translate::init('en'); diff --git a/config-user.default.php b/config-user.default.php new file mode 100644 index 000000000..f28ef9724 --- /dev/null +++ b/config-user.default.php @@ -0,0 +1,75 @@ + 'en', + 'old_entries' => 3, + 'keep_history_default' => 50, + 'ttl_default' => 3600, + 'mail_login' => '', + 'token' => '', + 'passwordHash' => '', + 'apiPasswordHash' => '', + 'posts_per_page' => 20, + 'since_hours_posts_per_rss' => 168, + 'min_posts_per_rss' => 2, + 'max_posts_per_rss' => 400, + 'view_mode' => 'normal', + 'default_view' => 'adaptive', + 'default_state' => FreshRSS_Entry::STATE_NOT_READ, + 'auto_load_more' => true, + 'display_posts' => false, + 'display_categories' => false, + 'hide_read_feeds' => true, + 'onread_jump_next' => true, + 'lazyload' => true, + 'sticky_post' => true, + 'reading_confirm' => false, + 'auto_remove_article' => false, + + # In the case an article has changed (e.g. updated content): + # Set to `true` to mark it unread, or `false` to leave it as-is. + 'mark_updated_article_unread' => false, //TODO: -1 => ignore, 0 => update, 1 => update and mark as unread + + 'sort_order' => 'DESC', + 'anon_access' => false, + 'mark_when' => array ( + 'article' => true, + 'site' => true, + 'scroll' => true, + 'reception' => false, + ), + 'theme' => 'Origine', + 'content_width' => 'thin', + 'shortcuts' => array ( + 'mark_read' => 'r', + 'mark_favorite' => 'f', + 'go_website' => 'space', + 'next_entry' => 'j', + 'prev_entry' => 'k', + 'first_entry' => 'home', + 'last_entry' => 'end', + 'collapse_entry' => 'c', + 'load_more' => 'm', + 'auto_share' => 's', + 'focus_search' => 'a', + 'user_filter' => 'u', + 'help' => 'f1', + 'close_dropdown' => 'escape', + ), + 'topline_read' => true, + 'topline_favorite' => true, + 'topline_date' => true, + 'topline_link' => true, + 'bottomline_read' => true, + 'bottomline_favorite' => true, + 'bottomline_sharing' => true, + 'bottomline_tags' => true, + 'bottomline_date' => true, + 'bottomline_link' => true, + 'sharing' => array ( + ), + 'queries' => array ( + ), + 'html5_notif_timeout' => 0, + 'extensions_enabled' => array(), +); diff --git a/config.default.php b/config.default.php new file mode 100644 index 000000000..748df1884 --- /dev/null +++ b/config.default.php @@ -0,0 +1,152 @@ + 'production', + + # Used to make crypto more unique. Generated during install. + 'salt' => '', + + # Specify address of the FreshRSS instance, + # used when building absolute URLs, e.g. for PubSubHubbub. + # Examples: + # https://example.net/FreshRSS/p/ + # https://freshrss.example.net/ + 'base_url' => '', + + # Specify address of the FreshRSS auto-update server. + 'auto_update_url' => 'https://update.freshrss.org', + + # Natural language of the user interface, e.g. `en`, `fr`. + 'language' => 'en', + + # Title of this FreshRSS instance in the Web user interface. + 'title' => 'FreshRSS', + + # Meta description used when `allow_robots` is true. + 'meta_description' => '', + + # Name of the user that has administration rights. + 'default_user' => '_', + + # Allow or not visitors without login to see the articles + # of the default user. + 'allow_anonymous' => false, + + # Allow or not anonymous users to start the refresh process. + 'allow_anonymous_refresh' => false, + + # Login method: + # `none` is without password and shows only the default user; + # `form` is a conventional Web login form; + # `http_auth` is an access controled by the HTTP Web server (e.g. `/FreshRSS/p/i/.htaccess` for Apache) + # if you use `http_auth`, remember to protect only `/FreshRSS/p/i/`, + # and in particular not protect `/FreshRSS/p/api/` if you would like to use the API (different login system). + 'auth_type' => 'form', + + # Allow or not the use of the API, used for mobile apps. + # End-point is http://example.net/FreshRSS/p/api/greader.php + # You need to set the user's API password. + 'api_enabled' => false, + + # Allow or not the use of an unsafe login, + # by providing username and password in the login URL: + # http://example.net/FreshRSS/p/i/?c=auth&a=login&u=alice&p=1234 + 'unsafe_autologin_enabled' => false, + + # Enable or not the use of syslog to log the activity of + # SimplePie, which is retrieving RSS feeds via HTTP requests. + 'simplepie_syslog_enabled' => true, + + # Enable or not support of PubSubHubbub. + # /!\ It should NOT be enabled if base_url is not reachable by an external server. + 'pubsubhubbub_enabled' => false, + + # Allow or not Web robots (e.g. search engines) in HTML headers. + 'allow_robots' => false, + + # If true does nothing, if false restricts HTTP Referer via: meta referrer origin + 'allow_referrer' => false, + + 'limits' => array( + + # Duration in seconds of the login cookie. + 'cookie_duration' => 2592000, + + # Duration in seconds of the SimplePie cache, + # during which a query to the RSS feed will return the local cached version. + # Especially important for multi-user setups. + 'cache_duration' => 800, + + # SimplePie HTTP request timeout in seconds. + 'timeout' => 15, + + # If a user has not used FreshRSS for more than x seconds, + # then its feeds are not refreshed anymore. + 'max_inactivity' => PHP_INT_MAX, + + # Max number of feeds for a user. + 'max_feeds' => 16384, + + # Max number of categories for a user. + 'max_categories' => 16384, + + # Max number of accounts that anonymous users can create + # 0 for an unlimited number of accounts + # 1 is to not allow user registrations (1 is corresponding to the admin account) + 'max_registrations' => 1, + ), + + # Options used by cURL when making HTTP requests, e.g. when the SimplePie library retrieves feeds. + # http://php.net/manual/function.curl-setopt + 'curl_options' => array( + # Options to disable SSL/TLS certificate check (e.g. for self-signed HTTPS) + //CURLOPT_SSL_VERIFYHOST => 0, + //CURLOPT_SSL_VERIFYPEER => false, + + # Options to use a proxy for retrieving feeds. + //CURLOPT_PROXYTYPE => CURLPROXY_HTTP, + //CURLOPT_PROXY => '127.0.0.1', + //CURLOPT_PROXYPORT => 8080, + //CURLOPT_PROXYAUTH => CURLAUTH_BASIC, + //CURLOPT_PROXYUSERPWD => 'user:password', + ), + + 'db' => array( + + # Type of database: `sqlite` or `mysql`. + 'type' => 'sqlite', + + # MySQL host. + 'host' => 'localhost', + + # MySQL user. + 'user' => '', + + # MySQL password. + 'password' => '', + + # MySQL database. + 'base' => '', + + # MySQL table prefix. + 'prefix' => 'freshrss_', + + 'pdo_options' => array( + //PDO::MYSQL_ATTR_SSL_KEY => '/path/to/client-key.pem', + //PDO::MYSQL_ATTR_SSL_CERT => '/path/to/client-cert.pem', + //PDO::MYSQL_ATTR_SSL_CA => '/path/to/ca-cert.pem', + ), + + ), + + # List of enabled FreshRSS extensions. + 'extensions_enabled' => array(), + + # Disable self-update, + 'disable_update' => false, +); diff --git a/data/config.default.php b/data/config.default.php deleted file mode 100644 index 748df1884..000000000 --- a/data/config.default.php +++ /dev/null @@ -1,152 +0,0 @@ - 'production', - - # Used to make crypto more unique. Generated during install. - 'salt' => '', - - # Specify address of the FreshRSS instance, - # used when building absolute URLs, e.g. for PubSubHubbub. - # Examples: - # https://example.net/FreshRSS/p/ - # https://freshrss.example.net/ - 'base_url' => '', - - # Specify address of the FreshRSS auto-update server. - 'auto_update_url' => 'https://update.freshrss.org', - - # Natural language of the user interface, e.g. `en`, `fr`. - 'language' => 'en', - - # Title of this FreshRSS instance in the Web user interface. - 'title' => 'FreshRSS', - - # Meta description used when `allow_robots` is true. - 'meta_description' => '', - - # Name of the user that has administration rights. - 'default_user' => '_', - - # Allow or not visitors without login to see the articles - # of the default user. - 'allow_anonymous' => false, - - # Allow or not anonymous users to start the refresh process. - 'allow_anonymous_refresh' => false, - - # Login method: - # `none` is without password and shows only the default user; - # `form` is a conventional Web login form; - # `http_auth` is an access controled by the HTTP Web server (e.g. `/FreshRSS/p/i/.htaccess` for Apache) - # if you use `http_auth`, remember to protect only `/FreshRSS/p/i/`, - # and in particular not protect `/FreshRSS/p/api/` if you would like to use the API (different login system). - 'auth_type' => 'form', - - # Allow or not the use of the API, used for mobile apps. - # End-point is http://example.net/FreshRSS/p/api/greader.php - # You need to set the user's API password. - 'api_enabled' => false, - - # Allow or not the use of an unsafe login, - # by providing username and password in the login URL: - # http://example.net/FreshRSS/p/i/?c=auth&a=login&u=alice&p=1234 - 'unsafe_autologin_enabled' => false, - - # Enable or not the use of syslog to log the activity of - # SimplePie, which is retrieving RSS feeds via HTTP requests. - 'simplepie_syslog_enabled' => true, - - # Enable or not support of PubSubHubbub. - # /!\ It should NOT be enabled if base_url is not reachable by an external server. - 'pubsubhubbub_enabled' => false, - - # Allow or not Web robots (e.g. search engines) in HTML headers. - 'allow_robots' => false, - - # If true does nothing, if false restricts HTTP Referer via: meta referrer origin - 'allow_referrer' => false, - - 'limits' => array( - - # Duration in seconds of the login cookie. - 'cookie_duration' => 2592000, - - # Duration in seconds of the SimplePie cache, - # during which a query to the RSS feed will return the local cached version. - # Especially important for multi-user setups. - 'cache_duration' => 800, - - # SimplePie HTTP request timeout in seconds. - 'timeout' => 15, - - # If a user has not used FreshRSS for more than x seconds, - # then its feeds are not refreshed anymore. - 'max_inactivity' => PHP_INT_MAX, - - # Max number of feeds for a user. - 'max_feeds' => 16384, - - # Max number of categories for a user. - 'max_categories' => 16384, - - # Max number of accounts that anonymous users can create - # 0 for an unlimited number of accounts - # 1 is to not allow user registrations (1 is corresponding to the admin account) - 'max_registrations' => 1, - ), - - # Options used by cURL when making HTTP requests, e.g. when the SimplePie library retrieves feeds. - # http://php.net/manual/function.curl-setopt - 'curl_options' => array( - # Options to disable SSL/TLS certificate check (e.g. for self-signed HTTPS) - //CURLOPT_SSL_VERIFYHOST => 0, - //CURLOPT_SSL_VERIFYPEER => false, - - # Options to use a proxy for retrieving feeds. - //CURLOPT_PROXYTYPE => CURLPROXY_HTTP, - //CURLOPT_PROXY => '127.0.0.1', - //CURLOPT_PROXYPORT => 8080, - //CURLOPT_PROXYAUTH => CURLAUTH_BASIC, - //CURLOPT_PROXYUSERPWD => 'user:password', - ), - - 'db' => array( - - # Type of database: `sqlite` or `mysql`. - 'type' => 'sqlite', - - # MySQL host. - 'host' => 'localhost', - - # MySQL user. - 'user' => '', - - # MySQL password. - 'password' => '', - - # MySQL database. - 'base' => '', - - # MySQL table prefix. - 'prefix' => 'freshrss_', - - 'pdo_options' => array( - //PDO::MYSQL_ATTR_SSL_KEY => '/path/to/client-key.pem', - //PDO::MYSQL_ATTR_SSL_CERT => '/path/to/client-cert.pem', - //PDO::MYSQL_ATTR_SSL_CA => '/path/to/ca-cert.pem', - ), - - ), - - # List of enabled FreshRSS extensions. - 'extensions_enabled' => array(), - - # Disable self-update, - 'disable_update' => false, -); diff --git a/data/users/_/config.default.php b/data/users/_/config.default.php deleted file mode 100644 index f28ef9724..000000000 --- a/data/users/_/config.default.php +++ /dev/null @@ -1,75 +0,0 @@ - 'en', - 'old_entries' => 3, - 'keep_history_default' => 50, - 'ttl_default' => 3600, - 'mail_login' => '', - 'token' => '', - 'passwordHash' => '', - 'apiPasswordHash' => '', - 'posts_per_page' => 20, - 'since_hours_posts_per_rss' => 168, - 'min_posts_per_rss' => 2, - 'max_posts_per_rss' => 400, - 'view_mode' => 'normal', - 'default_view' => 'adaptive', - 'default_state' => FreshRSS_Entry::STATE_NOT_READ, - 'auto_load_more' => true, - 'display_posts' => false, - 'display_categories' => false, - 'hide_read_feeds' => true, - 'onread_jump_next' => true, - 'lazyload' => true, - 'sticky_post' => true, - 'reading_confirm' => false, - 'auto_remove_article' => false, - - # In the case an article has changed (e.g. updated content): - # Set to `true` to mark it unread, or `false` to leave it as-is. - 'mark_updated_article_unread' => false, //TODO: -1 => ignore, 0 => update, 1 => update and mark as unread - - 'sort_order' => 'DESC', - 'anon_access' => false, - 'mark_when' => array ( - 'article' => true, - 'site' => true, - 'scroll' => true, - 'reception' => false, - ), - 'theme' => 'Origine', - 'content_width' => 'thin', - 'shortcuts' => array ( - 'mark_read' => 'r', - 'mark_favorite' => 'f', - 'go_website' => 'space', - 'next_entry' => 'j', - 'prev_entry' => 'k', - 'first_entry' => 'home', - 'last_entry' => 'end', - 'collapse_entry' => 'c', - 'load_more' => 'm', - 'auto_share' => 's', - 'focus_search' => 'a', - 'user_filter' => 'u', - 'help' => 'f1', - 'close_dropdown' => 'escape', - ), - 'topline_read' => true, - 'topline_favorite' => true, - 'topline_date' => true, - 'topline_link' => true, - 'bottomline_read' => true, - 'bottomline_favorite' => true, - 'bottomline_sharing' => true, - 'bottomline_tags' => true, - 'bottomline_date' => true, - 'bottomline_link' => true, - 'sharing' => array ( - ), - 'queries' => array ( - ), - 'html5_notif_timeout' => 0, - 'extensions_enabled' => array(), -); diff --git a/lib/Minz/FrontController.php b/lib/Minz/FrontController.php index f9eff3db6..952d983c9 100644 --- a/lib/Minz/FrontController.php +++ b/lib/Minz/FrontController.php @@ -33,7 +33,7 @@ class Minz_FrontController { try { Minz_Configuration::register('system', DATA_PATH . '/config.php', - DATA_PATH . '/config.default.php'); + FRESHRSS_PATH . '/config.default.php'); $this->setReporting(); Minz_Request::init(); diff --git a/lib/lib_install.php b/lib/lib_install.php index c625a670a..bf81c15b4 100644 --- a/lib/lib_install.php +++ b/lib/lib_install.php @@ -2,8 +2,8 @@ define('BCRYPT_COST', 9); -Minz_Configuration::register('default_system', join_path(DATA_PATH, 'config.default.php')); -Minz_Configuration::register('default_user', join_path(USERS_PATH, '_', 'config.default.php')); +Minz_Configuration::register('default_system', join_path(FRESHRSS_PATH, 'config.default.php')); +Minz_Configuration::register('default_user', join_path(FRESHRSS_PATH, 'config-user.default.php')); function checkRequirements($dbType = '') { $php = version_compare(PHP_VERSION, '5.3.3') >= 0; diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 247cc707b..1bf387712 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -341,7 +341,7 @@ function get_user_configuration($username) { try { Minz_Configuration::register($namespace, join_path(USERS_PATH, $username, 'config.php'), - join_path(USERS_PATH, '_', 'config.default.php')); + join_path(FRESHRSS_PATH, 'config-user.default.php')); } catch (Minz_ConfigurationNamespaceException $e) { // namespace already exists, do nothing. } catch (Minz_FileNotExistException $e) { diff --git a/p/api/greader.php b/p/api/greader.php index 01eca6d4f..e1f4202a7 100644 --- a/p/api/greader.php +++ b/p/api/greader.php @@ -695,7 +695,7 @@ $pathInfos = explode('/', $pathInfo); Minz_Configuration::register('system', DATA_PATH . '/config.php', - DATA_PATH . '/config.default.php'); + FRESHRSS_PATH . '/config.default.php'); FreshRSS_Context::$system_conf = Minz_Configuration::get('system'); if (!FreshRSS_Context::$system_conf->api_enabled) { serviceUnavailable(); diff --git a/p/api/index.php b/p/api/index.php index 3ab4e02b3..580c90255 100644 --- a/p/api/index.php +++ b/p/api/index.php @@ -16,7 +16,7 @@
diff --git a/p/api/pshb.php b/p/api/pshb.php index a0b64ede1..4b546908a 100644 --- a/p/api/pshb.php +++ b/p/api/pshb.php @@ -60,7 +60,7 @@ if (empty($users)) { unlink('../../keys/' . $key . '.txt'); Minz_Configuration::register('system', DATA_PATH . '/config.php', - DATA_PATH . '/config.default.php'); + FRESHRSS_PATH . '/config.default.php'); FreshRSS_Context::$system_conf = Minz_Configuration::get('system'); $feed = new FreshRSS_Feed($url); $feed->pubSubHubbubSubscribe(false); @@ -101,7 +101,7 @@ if ($ORIGINAL_INPUT == '') { die('Missing XML payload!'); } -Minz_Configuration::register('system', DATA_PATH . '/config.php', DATA_PATH . '/config.default.php'); +Minz_Configuration::register('system', DATA_PATH . '/config.php', FRESHRSS_PATH . '/config.default.php'); $system_conf = Minz_Configuration::get('system'); $system_conf->auth_type = 'none'; // avoid necessity to be logged in (not saved!) @@ -133,7 +133,7 @@ foreach ($users as $userFilename) { Minz_Session::_param('currentUser', $username); Minz_Configuration::register('user', join_path(USERS_PATH, $username, 'config.php'), - join_path(USERS_PATH, '_', 'config.default.php')); + join_path(FRESHRSS_PATH, 'config-user.default.php')); new Minz_ModelPdo($username); //TODO: FIXME: Quick-fix while waiting for a better FreshRSS() constructor/init FreshRSS_Context::init(); list($updated_feeds, $feed, $nb_new_articles) = FreshRSS_feed_Controller::actualizeFeed(0, $self, false, $simplePie); -- cgit v1.2.3 From e4ffbd3dade28f6263f143437b9865b1c640b269 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 13 May 2017 00:05:19 +0200 Subject: Move force-https.default.txt --- CHANGELOG.md | 2 +- data/force-https.default.txt | 7 ------- force-https.default.txt | 7 +++++++ lib/lib_rss.php | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 data/force-https.default.txt create mode 100644 force-https.default.txt (limited to 'lib') diff --git a/CHANGELOG.md b/CHANGELOG.md index de3c2cef9..16234e159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -200,7 +200,7 @@ * Cookie with `Secure` tag when used over HTTPS [#1117](https://github.com/FreshRSS/FreshRSS/pull/1117) * Limit API post input to 1MB [#1118](https://github.com/FreshRSS/FreshRSS/pull/1118) * Features - * New list of domains for which to force HTTPS (for images, videos, iframes…) defined in `./data/force-https.default.txt` and `./data/force-https.txt` [#1083](https://github.com/FreshRSS/FreshRSS/issues/1083) + * New list of domains for which to force HTTPS (for images, videos, iframes…) defined in `./force-https.default.txt` and `./data/force-https.txt` [#1083](https://github.com/FreshRSS/FreshRSS/issues/1083) * In particular useful for privacy and to avoid mixed content errors, e.g. to see YouTube videos when FreshRSS is in HTTPS * Add sharing with “Journal du Hacker” [#1056](https://github.com/FreshRSS/FreshRSS/pull/1056) * UI diff --git a/data/force-https.default.txt b/data/force-https.default.txt deleted file mode 100644 index 044620098..000000000 --- a/data/force-https.default.txt +++ /dev/null @@ -1,7 +0,0 @@ -dailymotion.com -feedburner.com -gravatar.com -gstatic.com -tumblr.com -wordpress.com -youtube.com diff --git a/force-https.default.txt b/force-https.default.txt new file mode 100644 index 000000000..044620098 --- /dev/null +++ b/force-https.default.txt @@ -0,0 +1,7 @@ +dailymotion.com +feedburner.com +gravatar.com +gstatic.com +tumblr.com +wordpress.com +youtube.com diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 1bf387712..7e14e638d 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -214,7 +214,7 @@ function customSimplePie() { ), )); $https_domains = array(); - $force = @file(DATA_PATH . '/force-https.default.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $force = @file(FRESHRSS_PATH . '/force-https.default.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); if (is_array($force)) { $https_domains = array_merge($https_domains, $force); } -- cgit v1.2.3 From dd65cb0f9c85b261af6db85d0ea7c06b9e0bc6ec Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 28 May 2017 02:02:21 +0200 Subject: Manual merge upstream SimplePie --- lib/SimplePie/SimplePie.php | 243 +++++++++++++++-------- lib/SimplePie/SimplePie/Category.php | 65 +++--- lib/SimplePie/SimplePie/Content/Type/Sniffer.php | 11 +- lib/SimplePie/SimplePie/File.php | 11 +- lib/SimplePie/SimplePie/HTTP/Parser.php | 18 ++ lib/SimplePie/SimplePie/Item.php | 130 +++++++----- lib/SimplePie/SimplePie/Locator.php | 27 ++- lib/SimplePie/SimplePie/Misc.php | 20 +- lib/SimplePie/SimplePie/Parser.php | 229 ++++++++++++++++++++- lib/SimplePie/SimplePie/Sanitize.php | 28 ++- lib/lib_rss.php | 2 +- 11 files changed, 581 insertions(+), 203 deletions(-) (limited to 'lib') diff --git a/lib/SimplePie/SimplePie.php b/lib/SimplePie/SimplePie.php index ec3ef1c77..5cd445b6d 100644 --- a/lib/SimplePie/SimplePie.php +++ b/lib/SimplePie/SimplePie.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2017, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -33,8 +33,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie - * @version 1.4-dev-FreshRSS - * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @version 1.5 + * @copyright 2004-2017 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -50,7 +50,7 @@ define('SIMPLEPIE_NAME', 'SimplePie'); /** * SimplePie Version */ -define('SIMPLEPIE_VERSION', '1.4-dev-FreshRSS'); +define('SIMPLEPIE_VERSION', '1.5'); /** * SimplePie Build @@ -509,6 +509,14 @@ class SimplePie */ public $cache = true; + /** + * @var bool Force SimplePie to fallback to expired cache, if enabled, + * when feed is unavailable. + * @see SimplePie::force_cache_fallback() + * @access private + */ + public $force_cache_fallback = false; + /** * @var int Cache duration (in seconds) * @see SimplePie::set_cache_duration() @@ -641,6 +649,12 @@ class SimplePie */ public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); + /** + * @var bool Should we throw exceptions, or use the old-style error property? + * @access private + */ + public $enable_exceptions = false; + /** * Use syslog to report HTTP requests done by SimplePie. * @see SimplePie::set_syslog() @@ -859,6 +873,21 @@ class SimplePie $this->cache = (bool) $enable; } + /** + * SimplePie to continue to fall back to expired cache, if enabled, when + * feed is unavailable. + * + * This tells SimplePie to ignore any file errors and fall back to cache + * instead. This only works if caching is enabled and cached content + * still exists. + + * @param bool $enable Force use of cache on fail. + */ + public function force_cache_fallback($enable = false) + { + $this->force_cache_fallback= (bool) $enable; + } + /** * Set the length of time (in seconds) that the contents of a feed will be * cached @@ -1387,7 +1416,6 @@ class SimplePie return $this->data['mtime']; } elseif ($fetched === false) { - $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__)); return false; } @@ -1398,6 +1426,13 @@ class SimplePie $md5 = $this->data['md5']; } } + + // Empty response check + if(empty($this->raw_data)){ + $this->error = "A feed could not be found at `$this->feed_url`. Empty body."; + $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__)); + return false; + } // Set up array of possible encodings $encodings = array(); @@ -1440,7 +1475,7 @@ class SimplePie // Text MIME-type default elseif (substr($sniffed, 0, 5) === 'text/') { - $encodings[] = 'US-ASCII'; + $encodings[] = 'UTF-8'; } } @@ -1500,12 +1535,20 @@ class SimplePie else { $this->error = 'The data could not be converted to UTF-8.'; - if (!extension_loaded('mbstring') && !extension_loaded('iconv')) { - $this->error .= ' You MUST have either the iconv or mbstring extension installed.'; - } elseif (!extension_loaded('mbstring')) { - $this->error .= ' Try installing the mbstring extension.'; - } elseif (!extension_loaded('iconv')) { - $this->error .= ' Try installing the iconv extension.'; + if (!extension_loaded('mbstring') && !extension_loaded('iconv') && !class_exists('\UConverter')) { + $this->error .= ' You MUST have either the iconv, mbstring or intl (PHP 5.5+) extension installed and enabled.'; + } else { + $missingExtensions = array(); + if (!extension_loaded('iconv')) { + $missingExtensions[] = 'iconv'; + } + if (!extension_loaded('mbstring')) { + $missingExtensions[] = 'mbstring'; + } + if (!class_exists('\UConverter')) { + $missingExtensions[] = 'intl (PHP 5.5+)'; + } + $this->error .= ' Try installing/enabling the ' . implode(' or ', $missingExtensions) . ' extension.'; } } @@ -1896,14 +1939,19 @@ class SimplePie { if ($this->permanent_url !== null) { - return $this->sanitize($this->permanent_url, SIMPLEPIE_CONSTRUCT_IRI); + // sanitize encodes ampersands which are required when used in a url. + return str_replace('&', '&', + $this->sanitize($this->permanent_url, + SIMPLEPIE_CONSTRUCT_IRI)); } } else { if ($this->feed_url !== null) { - return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI); + return str_replace('&', '&', + $this->sanitize($this->feed_url, + SIMPLEPIE_CONSTRUCT_IRI)); } } return null; @@ -2565,6 +2613,12 @@ class SimplePie { return $this->data['links'][$rel]; } + else if (isset($this->data['headers']['link']) && + preg_match('/<([^>]+)>; rel='.preg_quote($rel).'/', + $this->data['headers']['link'], $match)) + { + return array($match[1]); + } else { return null; @@ -3002,96 +3056,81 @@ class SimplePie if (!empty($this->multifeed_objects)) { $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit); + if (empty($this->data['items'])) + { + return array(); + } + return $this->data['items']; } - else + $this->data['items'] = array(); + if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry')) { - $this->data['items'] = array(); - if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry')) + $keys = array_keys($items); + foreach ($keys as $key) { - $keys = array_keys($items); - foreach ($keys as $key) - { - $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); - } + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); } - if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry')) + } + if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry')) + { + $keys = array_keys($items); + foreach ($keys as $key) { - $keys = array_keys($items); - foreach ($keys as $key) - { - $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); - } + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); } - if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item')) + } + if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item')) + { + $keys = array_keys($items); + foreach ($keys as $key) { - $keys = array_keys($items); - foreach ($keys as $key) - { - $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); - } + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); } - if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item')) + } + if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item')) + { + $keys = array_keys($items); + foreach ($keys as $key) { - $keys = array_keys($items); - foreach ($keys as $key) - { - $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); - } + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); } - if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item')) + } + if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item')) + { + $keys = array_keys($items); + foreach ($keys as $key) { - $keys = array_keys($items); - foreach ($keys as $key) - { - $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); - } + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); } } } - if (!empty($this->data['items'])) + if (empty($this->data['items'])) { - // If we want to order it by date, check if all items have a date, and then sort it - if ($this->order_by_date && empty($this->multifeed_objects)) - { - if (!isset($this->data['ordered_items'])) - { - $do_sort = true; - foreach ($this->data['items'] as $item) - { - if (!$item->get_date('U')) - { - $do_sort = false; - break; - } - } - $item = null; - $this->data['ordered_items'] = $this->data['items']; - if ($do_sort) - { - usort($this->data['ordered_items'], array(get_class($this), 'sort_items')); - } - } - $items = $this->data['ordered_items']; - } - else - { - $items = $this->data['items']; - } + return array(); + } - // Slice the data as desired - if ($end === 0) - { - return array_slice($items, $start); - } - else + if ($this->order_by_date) + { + if (!isset($this->data['ordered_items'])) { - return array_slice($items, $start, $end); - } + $this->data['ordered_items'] = $this->data['items']; + usort($this->data['ordered_items'], array(get_class($this), 'sort_items')); + } + $items = $this->data['ordered_items']; } else { - return array(); + $items = $this->data['items']; + } + // Slice the data as desired + if ($end === 0) + { + return array_slice($items, $start); + } + else + { + return array_slice($items, $start, $end); } } @@ -3226,4 +3265,42 @@ class SimplePie return array(); } } + + /** + * Store PubSubHubbub links as headers + * + * There is no way to find PuSH links in the body of a microformats feed, + * so they are added to the headers when found, to be used later by get_links. + * @param SimplePie_File $file + * @param string $hub + * @param string $self + */ + private function store_links(&$file, $hub, $self) { + if (isset($file->headers['link']['hub']) || + (isset($file->headers['link']) && + preg_match('/rel=hub/', $file->headers['link']))) + { + return; + } + + if ($hub) + { + if (isset($file->headers['link'])) + { + if ($file->headers['link'] !== '') + { + $file->headers['link'] = ', '; + } + } + else + { + $file->headers['link'] = ''; + } + $file->headers['link'] .= '<'.$hub.'>; rel=hub'; + if ($self) + { + $file->headers['link'] .= ', <'.$self.'>; rel=self'; + } + } + } } diff --git a/lib/SimplePie/SimplePie/Category.php b/lib/SimplePie/SimplePie/Category.php index 92d511e1a..df0f13f9a 100644 --- a/lib/SimplePie/SimplePie/Category.php +++ b/lib/SimplePie/SimplePie/Category.php @@ -56,7 +56,7 @@ class SimplePie_Category /** * Category identifier * - * @var string + * @var string|null * @see get_term */ var $term; @@ -64,7 +64,7 @@ class SimplePie_Category /** * Categorization scheme identifier * - * @var string + * @var string|null * @see get_scheme() */ var $scheme; @@ -72,23 +72,36 @@ class SimplePie_Category /** * Human readable label * - * @var string + * @var string|null * @see get_label() */ var $label; + /** + * Category type + * + * category for + * subject for + * + * @var string|null + * @see get_type() + */ + var $type; + /** * Constructor, used to input the data * - * @param string $term - * @param string $scheme - * @param string $label + * @param string|null $term + * @param string|null $scheme + * @param string|null $label + * @param string|null $type */ - public function __construct($term = null, $scheme = null, $label = null) + public function __construct($term = null, $scheme = null, $label = null, $type = null) { $this->term = $term; $this->scheme = $scheme; $this->label = $label; + $this->type = $type; } /** @@ -109,14 +122,7 @@ class SimplePie_Category */ public function get_term() { - if ($this->term !== null) - { - return $this->term; - } - else - { - return null; - } + return $this->term; } /** @@ -126,31 +132,32 @@ class SimplePie_Category */ public function get_scheme() { - if ($this->scheme !== null) - { - return $this->scheme; - } - else - { - return null; - } + return $this->scheme; } /** * Get the human readable label * + * @param bool $strict * @return string|null */ - public function get_label() + public function get_label($strict = false) { - if ($this->label !== null) - { - return $this->label; - } - else + if ($this->label === null && $strict !== true) { return $this->get_term(); } + return $this->label; + } + + /** + * Get the category type + * + * @return string|null + */ + public function get_type() + { + return $this->type; } } diff --git a/lib/SimplePie/SimplePie/Content/Type/Sniffer.php b/lib/SimplePie/SimplePie/Content/Type/Sniffer.php index b68b73134..6caf80f33 100644 --- a/lib/SimplePie/SimplePie/Content/Type/Sniffer.php +++ b/lib/SimplePie/SimplePie/Content/Type/Sniffer.php @@ -124,8 +124,8 @@ class SimplePie_Content_Type_Sniffer } } elseif ($official === 'text/html' - || $official === 'text/xml' - || $official === 'application/xml') + || $official === 'text/xml' //FreshRSS + || $official === 'application/xml') //FreshRSS { return $this->feed_or_html(); } @@ -255,12 +255,7 @@ class SimplePie_Content_Type_Sniffer public function feed_or_html() { $len = strlen($this->file->body); - $pos = 0; - if (isset($this->file->body[2]) && $this->file->body[0] === "\xEF" && - $this->file->body[1] === "\xBB" && $this->file->body[2] === "\xBF") { - $pos += 3; //UTF-8 BOM - } - $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos); + $pos = strspn($this->file->body, "\x09\x0A\x0D\x20\xEF\xBB\xBF"); while ($pos < $len) { diff --git a/lib/SimplePie/SimplePie/File.php b/lib/SimplePie/SimplePie/File.php index c1fab42dc..8be38f145 100644 --- a/lib/SimplePie/SimplePie/File.php +++ b/lib/SimplePie/SimplePie/File.php @@ -118,8 +118,7 @@ class SimplePie_File curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects); } - foreach ($curl_options as $curl_param => $curl_value) - { + foreach ($curl_options as $curl_param => $curl_value) { curl_setopt($fp, $curl_param, $curl_value); } @@ -136,10 +135,12 @@ class SimplePie_File } else { - $info = curl_getinfo($fp); + // Use the updated url provided by curl_getinfo after any redirects. + if ($info = curl_getinfo($fp)) { + $this->url = $info['url']; + } curl_close($fp); - $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1); - $this->headers = array_pop($this->headers); + $this->headers = SimplePie_HTTP_Parser::prepareHeaders($this->headers, $info['redirect_count'] + 1); $parser = new SimplePie_HTTP_Parser($this->headers); if ($parser->parse()) { diff --git a/lib/SimplePie/SimplePie/HTTP/Parser.php b/lib/SimplePie/SimplePie/HTTP/Parser.php index 63ae1e03d..3899c53fa 100644 --- a/lib/SimplePie/SimplePie/HTTP/Parser.php +++ b/lib/SimplePie/SimplePie/HTTP/Parser.php @@ -496,4 +496,22 @@ class SimplePie_HTTP_Parser } } } + + /** + * Prepare headers (take care of proxies headers) + * + * @param string $headers Raw headers + * @param integer $count Redirection count. Default to 1. + * + * @return string + */ + static public function prepareHeaders($headers, $count = 1) + { + $data = explode("\r\n\r\n", $headers, $count); + $data = array_pop($data); + if (false !== stripos($data, "HTTP/1.0 200 Connection established\r\n\r\n")) { + $data = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $data); + } + return $data; + } } diff --git a/lib/SimplePie/SimplePie/Item.php b/lib/SimplePie/SimplePie/Item.php index daecf0a15..425538606 100644 --- a/lib/SimplePie/SimplePie/Item.php +++ b/lib/SimplePie/SimplePie/Item.php @@ -206,9 +206,10 @@ class SimplePie_Item * * @since Beta 2 * @param boolean $hash Should we force using a hash instead of the supplied ID? - * @return string + * @param string|false $fn User-supplied function to generate an hash + * @return string|null */ - public function get_id($hash = false, $fn = '') + public function get_id($hash = false, $fn = 'md5') { if (!$hash) { @@ -237,7 +238,15 @@ class SimplePie_Item return $this->sanitize($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'], SIMPLEPIE_CONSTRUCT_TEXT); } } - if ($fn === '' || !is_callable($fn)) $fn = 'md5'; + if ($fn === false) + { + return null; + } + elseif (!is_callable($fn)) + { + trigger_error('User-supplied function $fn must be callable', E_USER_WARNING); + $fn = 'md5'; + } return call_user_func($fn, $this->get_permalink().$this->get_title().$this->get_content()); } @@ -307,41 +316,50 @@ class SimplePie_Item */ public function get_description($description_only = false) { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary')) + if (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary')) && + ($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0])))) { - return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary')) && + ($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0])))) { - return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) && + ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($tags[0])))) { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) && + ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($tags[0])))) { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) && + ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT))) { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) && + ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT))) { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) && + ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($tags[0])))) { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) && + ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT))) { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) && + ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML))) { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML); + return $return; } elseif (!$description_only) @@ -370,17 +388,20 @@ class SimplePie_Item */ public function get_content($content_only = false) { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content')) + if (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content')) && + ($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_10_content_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0])))) { - return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_content_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content')) && + ($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0])))) { - return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + return $return; } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) + elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) && + ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($tags[0])))) { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + return $return; } elseif (!$content_only) { @@ -448,47 +469,50 @@ class SimplePie_Item { $categories = array(); - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) + $type = 'category'; + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, $type) as $category) { $term = null; $scheme = null; $label = null; if (isset($category['attribs']['']['term'])) { - $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); + $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_HTML); } if (isset($category['attribs']['']['scheme'])) { - $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_HTML); } if (isset($category['attribs']['']['label'])) { - $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_HTML); } - $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + $categories[] = $this->registry->create('Category', array($term, $scheme, $label, $type)); } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, $type) as $category) { // This is really the label, but keep this as the term also for BC. // Label will also work on retrieving because that falls back to term. - $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_HTML); if (isset($category['attribs']['']['domain'])) { - $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); + $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_HTML); } else { $scheme = null; } - $categories[] = $this->registry->create('Category', array($term, $scheme, null)); + $categories[] = $this->registry->create('Category', array($term, $scheme, null, $type)); } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) + + $type = 'subject'; + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, $type) as $category) { - $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null, $type)); } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, $type) as $category) { - $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null, $type)); } if (!empty($categories)) @@ -625,7 +649,7 @@ class SimplePie_Item $email = null; if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) { - $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_HTML); } if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) { @@ -633,7 +657,7 @@ class SimplePie_Item } if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) { - $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_HTML); } if ($name !== null || $email !== null || $uri !== null) { @@ -647,7 +671,7 @@ class SimplePie_Item $email = null; if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) { - $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_HTML); } if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) { @@ -655,7 +679,7 @@ class SimplePie_Item } if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) { - $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_HTML); } if ($name !== null || $email !== null || $url !== null) { @@ -664,19 +688,19 @@ class SimplePie_Item } if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author')) { - $authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT))); + $authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_HTML))); } foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) { - $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null)); } foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) { - $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null)); } foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) { - $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null)); } if (!empty($authors)) @@ -2802,9 +2826,17 @@ class SimplePie_Item { $length = ceil($link['attribs']['']['length']); } + if (isset($link['attribs']['']['title'])) + { + $title = $this->sanitize($link['attribs']['']['title'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $title = $title_parent; + } // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor - $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width)); + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title, $width)); } } diff --git a/lib/SimplePie/SimplePie/Locator.php b/lib/SimplePie/SimplePie/Locator.php index 36bc02895..bc314c2cd 100644 --- a/lib/SimplePie/SimplePie/Locator.php +++ b/lib/SimplePie/SimplePie/Locator.php @@ -120,34 +120,41 @@ class SimplePie_Locator { if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local)) { - return $working; + return $working[0]; } if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local)) { - return $working; + return $working[0]; } if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere)) { - return $working; + return $working[0]; } if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere)) { - return $working; + return $working[0]; } } return null; } - public function is_feed($file) + public function is_feed($file, $check_html = false) { if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) { $sniffer = $this->registry->create('Content_Type_Sniffer', array($file)); $sniffed = $sniffer->get_type(); - if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml', 'application/x-rss+xml'))) + $mime_types = array('application/rss+xml', 'application/rdf+xml', + 'text/rdf', 'application/atom+xml', 'text/xml', + 'application/xml', 'application/x-rss+xml'); + if ($check_html) + { + $mime_types[] = 'text/html'; + } + if (in_array($sniffed, $mime_types)) { return true; } @@ -241,14 +248,14 @@ class SimplePie_Locator continue; } - if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href])) + if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('text/html', 'application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href])) { $this->checked_feeds++; $headers = array( 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', ); $feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent)); - if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) + if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed, true)) { $feeds[$href] = $feed; } @@ -380,7 +387,7 @@ class SimplePie_Locator $feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent)); if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) { - return $feed; + return array($feed); } else { @@ -408,7 +415,7 @@ class SimplePie_Locator $feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent)); if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) { - return $feed; + return array($feed); } else { diff --git a/lib/SimplePie/SimplePie/Misc.php b/lib/SimplePie/SimplePie/Misc.php index ca2810611..40477c01e 100644 --- a/lib/SimplePie/SimplePie/Misc.php +++ b/lib/SimplePie/SimplePie/Misc.php @@ -127,7 +127,7 @@ class SimplePie_Misc { $attribs[$j][2] = $attribs[$j][1]; } - $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8'); + $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j])); } } } @@ -337,11 +337,16 @@ class SimplePie_Misc { return $return; } - // This is last, as behaviour of this varies with OS userland and PHP version + // This is third, as behaviour of this varies with OS userland and PHP version elseif (function_exists('iconv') && ($return = SimplePie_Misc::change_encoding_iconv($data, $input, $output))) { return $return; } + // This is last, as behaviour of this varies with OS userland and PHP version + elseif (class_exists('\UConverter') && ($return = SimplePie_Misc::change_encoding_uconverter($data, $input, $output))) + { + return $return; + } // If we can't do anything, just fail else { @@ -392,6 +397,17 @@ class SimplePie_Misc return @iconv($input, $output, $data); } + /** + * @param string $data + * @param string $input + * @param string $output + * @return string|false + */ + protected static function change_encoding_uconverter($data, $input, $output) + { + return @\UConverter::transcode($data, $output, $input); + } + /** * Normalize an encoding name * diff --git a/lib/SimplePie/SimplePie/Parser.php b/lib/SimplePie/SimplePie/Parser.php index e3966218c..9348382ad 100644 --- a/lib/SimplePie/SimplePie/Parser.php +++ b/lib/SimplePie/SimplePie/Parser.php @@ -434,4 +434,231 @@ class SimplePie_Parser } return $cache[$string]; } -} + + private function parse_hcard($data, $category = false) { + $name = ''; + $link = ''; + // Check if h-card is set and pass that information on in the link. + if (isset($data['type']) && in_array('h-card', $data['type'])) { + if (isset($data['properties']['name'][0])) { + $name = $data['properties']['name'][0]; + } + if (isset($data['properties']['url'][0])) { + $link = $data['properties']['url'][0]; + if ($name === '') { + $name = $link; + } + else { + // can't have commas in categories. + $name = str_replace(',', '', $name); + } + $person_tag = $category ? '' : ''; + return ''.$person_tag.$name.''; + } + } + return isset($data['value']) ? $data['value'] : ''; + } + + private function parse_microformats(&$data, $url) { + $feed_title = ''; + $feed_author = NULL; + $author_cache = array(); + $items = array(); + $entries = array(); + $mf = Mf2\parse($data, $url); + // First look for an h-feed. + $h_feed = array(); + foreach ($mf['items'] as $mf_item) { + if (in_array('h-feed', $mf_item['type'])) { + $h_feed = $mf_item; + break; + } + // Also look for an h-feed in the children of each top level item. + if (!isset($mf_item['children'][0]['type'])) continue; + if (in_array('h-feed', $mf_item['children'][0]['type'])) { + $h_feed = $mf_item['children'][0]; + // In this case the parent of the h-feed may be an h-card, so use it as + // the feed_author. + if (in_array('h-card', $mf_item['type'])) $feed_author = $mf_item; + break; + } + } + if (isset($h_feed['children'])) { + $entries = $h_feed['children']; + // Also set the feed title and store author from the h-feed if available. + if (isset($mf['items'][0]['properties']['name'][0])) { + $feed_title = $mf['items'][0]['properties']['name'][0]; + } + if (isset($mf['items'][0]['properties']['author'][0])) { + $feed_author = $mf['items'][0]['properties']['author'][0]; + } + } + else { + $entries = $mf['items']; + } + for ($i = 0; $i < count($entries); $i++) { + $entry = $entries[$i]; + if (in_array('h-entry', $entry['type'])) { + $item = array(); + $title = ''; + $description = ''; + if (isset($entry['properties']['url'][0])) { + $link = $entry['properties']['url'][0]; + if (isset($link['value'])) $link = $link['value']; + $item['link'] = array(array('data' => $link)); + } + if (isset($entry['properties']['uid'][0])) { + $guid = $entry['properties']['uid'][0]; + if (isset($guid['value'])) $guid = $guid['value']; + $item['guid'] = array(array('data' => $guid)); + } + if (isset($entry['properties']['name'][0])) { + $title = $entry['properties']['name'][0]; + if (isset($title['value'])) $title = $title['value']; + $item['title'] = array(array('data' => $title)); + } + if (isset($entry['properties']['author'][0]) || isset($feed_author)) { + // author is a special case, it can be plain text or an h-card array. + // If it's plain text it can also be a url that should be followed to + // get the actual h-card. + $author = isset($entry['properties']['author'][0]) ? + $entry['properties']['author'][0] : $feed_author; + if (!is_string($author)) { + $author = $this->parse_hcard($author); + } + else if (strpos($author, 'http') === 0) { + if (isset($author_cache[$author])) { + $author = $author_cache[$author]; + } + else { + $mf = Mf2\fetch($author); + foreach ($mf['items'] as $hcard) { + // Only interested in an h-card by itself in this case. + if (!in_array('h-card', $hcard['type'])) { + continue; + } + // It must have a url property matching what we fetched. + if (!isset($hcard['properties']['url']) || + !(in_array($author, $hcard['properties']['url']))) { + continue; + } + // Save parse_hcard the trouble of finding the correct url. + $hcard['properties']['url'][0] = $author; + // Cache this h-card for the next h-entry to check. + $author_cache[$author] = $this->parse_hcard($hcard); + $author = $author_cache[$author]; + break; + } + } + } + $item['author'] = array(array('data' => $author)); + } + if (isset($entry['properties']['photo'][0])) { + // If a photo is also in content, don't need to add it again here. + $content = ''; + if (isset($entry['properties']['content'][0]['html'])) { + $content = $entry['properties']['content'][0]['html']; + } + $photo_list = array(); + for ($j = 0; $j < count($entry['properties']['photo']); $j++) { + $photo = $entry['properties']['photo'][$j]; + if (strpos($content, $photo) === false) { + $photo_list[] = $photo; + } + } + // When there's more than one photo show the first and use a lightbox. + $count = count($photo_list); + if ($count > 1) { + $description = '

'; + for ($j = 0; $j < $count; $j++) { + $hidden = $j === 0 ? '' : 'class="hidden" '; + $description .= ''. + ''; + } + $description .= '
'.$count.' photos

'; + } + else if ($count == 1) { + $description = '

'; + } + } + if (isset($entry['properties']['content'][0]['html'])) { + // e-content['value'] is the same as p-name when they are on the same + // element. Use this to replace title with a strip_tags version so + // that alt text from images is not included in the title. + if ($entry['properties']['content'][0]['value'] === $title) { + $title = strip_tags($entry['properties']['content'][0]['html']); + $item['title'] = array(array('data' => $title)); + } + $description .= $entry['properties']['content'][0]['html']; + if (isset($entry['properties']['in-reply-to'][0]['value'])) { + $in_reply_to = $entry['properties']['in-reply-to'][0]['value']; + $description .= '

'. + ''.$in_reply_to.'

'; + } + $item['description'] = array(array('data' => $description)); + } + if (isset($entry['properties']['category'])) { + $category_csv = ''; + // Categories can also contain h-cards. + foreach ($entry['properties']['category'] as $category) { + if ($category_csv !== '') $category_csv .= ', '; + if (is_string($category)) { + // Can't have commas in categories. + $category_csv .= str_replace(',', '', $category); + } + else { + $category_csv .= $this->parse_hcard($category, true); + } + } + $item['category'] = array(array('data' => $category_csv)); + } + if (isset($entry['properties']['published'][0])) { + $timestamp = strtotime($entry['properties']['published'][0]); + $pub_date = date('F j Y g:ia', $timestamp).' GMT'; + $item['pubDate'] = array(array('data' => $pub_date)); + } + // The title and description are set to the empty string to represent + // a deleted item (which also makes it an invalid rss item). + if (isset($entry['properties']['deleted'][0])) { + $item['title'] = array(array('data' => '')); + $item['description'] = array(array('data' => '')); + } + $items[] = array('child' => array('' => $item)); + } + } + // Mimic RSS data format when storing microformats. + $link = array(array('data' => $url)); + $image = ''; + if (!is_string($feed_author) && + isset($feed_author['properties']['photo'][0])) { + $image = array(array('child' => array('' => array('url' => + array(array('data' => $feed_author['properties']['photo'][0])))))); + } + // Use the a name given for the h-feed, or get the title from the html. + if ($feed_title !== '') { + $feed_title = array(array('data' => htmlspecialchars($feed_title))); + } + else if ($position = strpos($data, '')) { + $start = $position < 200 ? 0 : $position - 200; + $check = substr($data, $start, 400); + $matches = array(); + if (preg_match('/<title>(.+)<\/title>/', $check, $matches)) { + $feed_title = array(array('data' => htmlspecialchars($matches[1]))); + } + } + $channel = array('channel' => array(array('child' => array('' => + array('link' => $link, 'image' => $image, 'title' => $feed_title, + 'item' => $items))))); + $rss = array(array('attribs' => array('' => array('version' => '2.0')), + 'child' => array('' => $channel))); + $this->data = array('child' => array('' => array('rss' => $rss))); + return true; + } + + private function declare_html_entities() { + // This is required because the RSS specification says that entity-encoded + // html is allowed, but the xml specification says they must be declared. + return '<!DOCTYPE html [ <!ENTITY nbsp " "> <!ENTITY iexcl "¡"> <!ENTITY cent "¢"> <!ENTITY pound "£"> <!ENTITY curren "¤"> <!ENTITY yen "¥"> <!ENTITY brvbar "¦"> <!ENTITY sect "§"> <!ENTITY uml "¨"> <!ENTITY copy "©"> <!ENTITY ordf "ª"> <!ENTITY laquo "«"> <!ENTITY not "¬"> <!ENTITY shy "­"> <!ENTITY reg "®"> <!ENTITY macr "¯"> <!ENTITY deg "°"> <!ENTITY plusmn "±"> <!ENTITY sup2 "²"> <!ENTITY sup3 "³"> <!ENTITY acute "´"> <!ENTITY micro "µ"> <!ENTITY para "¶"> <!ENTITY middot "·"> <!ENTITY cedil "¸"> <!ENTITY sup1 "¹"> <!ENTITY ordm "º"> <!ENTITY raquo "»"> <!ENTITY frac14 "¼"> <!ENTITY frac12 "½"> <!ENTITY frac34 "¾"> <!ENTITY iquest "¿"> <!ENTITY Agrave "À"> <!ENTITY Aacute "Á"> <!ENTITY Acirc "Â"> <!ENTITY Atilde "Ã"> <!ENTITY Auml "Ä"> <!ENTITY Aring "Å"> <!ENTITY AElig "Æ"> <!ENTITY Ccedil "Ç"> <!ENTITY Egrave "È"> <!ENTITY Eacute "É"> <!ENTITY Ecirc "Ê"> <!ENTITY Euml "Ë"> <!ENTITY Igrave "Ì"> <!ENTITY Iacute "Í"> <!ENTITY Icirc "Î"> <!ENTITY Iuml "Ï"> <!ENTITY ETH "Ð"> <!ENTITY Ntilde "Ñ"> <!ENTITY Ograve "Ò"> <!ENTITY Oacute "Ó"> <!ENTITY Ocirc "Ô"> <!ENTITY Otilde "Õ"> <!ENTITY Ouml "Ö"> <!ENTITY times "×"> <!ENTITY Oslash "Ø"> <!ENTITY Ugrave "Ù"> <!ENTITY Uacute "Ú"> <!ENTITY Ucirc "Û"> <!ENTITY Uuml "Ü"> <!ENTITY Yacute "Ý"> <!ENTITY THORN "Þ"> <!ENTITY szlig "ß"> <!ENTITY agrave "à"> <!ENTITY aacute "á"> <!ENTITY acirc "â"> <!ENTITY atilde "ã"> <!ENTITY auml "ä"> <!ENTITY aring "å"> <!ENTITY aelig "æ"> <!ENTITY ccedil "ç"> <!ENTITY egrave "è"> <!ENTITY eacute "é"> <!ENTITY ecirc "ê"> <!ENTITY euml "ë"> <!ENTITY igrave "ì"> <!ENTITY iacute "í"> <!ENTITY icirc "î"> <!ENTITY iuml "ï"> <!ENTITY eth "ð"> <!ENTITY ntilde "ñ"> <!ENTITY ograve "ò"> <!ENTITY oacute "ó"> <!ENTITY ocirc "ô"> <!ENTITY otilde "õ"> <!ENTITY ouml "ö"> <!ENTITY divide "÷"> <!ENTITY oslash "ø"> <!ENTITY ugrave "ù"> <!ENTITY uacute "ú"> <!ENTITY ucirc "û"> <!ENTITY uuml "ü"> <!ENTITY yacute "ý"> <!ENTITY thorn "þ"> <!ENTITY yuml "ÿ"> <!ENTITY OElig "Œ"> <!ENTITY oelig "œ"> <!ENTITY Scaron "Š"> <!ENTITY scaron "š"> <!ENTITY Yuml "Ÿ"> <!ENTITY fnof "ƒ"> <!ENTITY circ "ˆ"> <!ENTITY tilde "˜"> <!ENTITY Alpha "Α"> <!ENTITY Beta "Β"> <!ENTITY Gamma "Γ"> <!ENTITY Epsilon "Ε"> <!ENTITY Zeta "Ζ"> <!ENTITY Eta "Η"> <!ENTITY Theta "Θ"> <!ENTITY Iota "Ι"> <!ENTITY Kappa "Κ"> <!ENTITY Lambda "Λ"> <!ENTITY Mu "Μ"> <!ENTITY Nu "Ν"> <!ENTITY Xi "Ξ"> <!ENTITY Omicron "Ο"> <!ENTITY Pi "Π"> <!ENTITY Rho "Ρ"> <!ENTITY Sigma "Σ"> <!ENTITY Tau "Τ"> <!ENTITY Upsilon "Υ"> <!ENTITY Phi "Φ"> <!ENTITY Chi "Χ"> <!ENTITY Psi "Ψ"> <!ENTITY Omega "Ω"> <!ENTITY alpha "α"> <!ENTITY beta "β"> <!ENTITY gamma "γ"> <!ENTITY delta "δ"> <!ENTITY epsilon "ε"> <!ENTITY zeta "ζ"> <!ENTITY eta "η"> <!ENTITY theta "θ"> <!ENTITY iota "ι"> <!ENTITY kappa "κ"> <!ENTITY lambda "λ"> <!ENTITY mu "μ"> <!ENTITY nu "ν"> <!ENTITY xi "ξ"> <!ENTITY omicron "ο"> <!ENTITY pi "π"> <!ENTITY rho "ρ"> <!ENTITY sigmaf "ς"> <!ENTITY sigma "σ"> <!ENTITY tau "τ"> <!ENTITY upsilon "υ"> <!ENTITY phi "φ"> <!ENTITY chi "χ"> <!ENTITY psi "ψ"> <!ENTITY omega "ω"> <!ENTITY thetasym "ϑ"> <!ENTITY upsih "ϒ"> <!ENTITY piv "ϖ"> <!ENTITY ensp " "> <!ENTITY emsp " "> <!ENTITY thinsp " "> <!ENTITY zwnj "‌"> <!ENTITY zwj "‍"> <!ENTITY lrm "‎"> <!ENTITY rlm "‏"> <!ENTITY ndash "–"> <!ENTITY mdash "—"> <!ENTITY lsquo "‘"> <!ENTITY rsquo "’"> <!ENTITY sbquo "‚"> <!ENTITY ldquo "“"> <!ENTITY rdquo "”"> <!ENTITY bdquo "„"> <!ENTITY dagger "†"> <!ENTITY Dagger "‡"> <!ENTITY bull "•"> <!ENTITY hellip "…"> <!ENTITY permil "‰"> <!ENTITY prime "′"> <!ENTITY Prime "″"> <!ENTITY lsaquo "‹"> <!ENTITY rsaquo "›"> <!ENTITY oline "‾"> <!ENTITY frasl "⁄"> <!ENTITY euro "€"> <!ENTITY image "ℑ"> <!ENTITY weierp "℘"> <!ENTITY real "ℜ"> <!ENTITY trade "™"> <!ENTITY alefsym "ℵ"> <!ENTITY larr "←"> <!ENTITY uarr "↑"> <!ENTITY rarr "→"> <!ENTITY darr "↓"> <!ENTITY harr "↔"> <!ENTITY crarr "↵"> <!ENTITY lArr "⇐"> <!ENTITY uArr "⇑"> <!ENTITY rArr "⇒"> <!ENTITY dArr "⇓"> <!ENTITY hArr "⇔"> <!ENTITY forall "∀"> <!ENTITY part "∂"> <!ENTITY exist "∃"> <!ENTITY empty "∅"> <!ENTITY nabla "∇"> <!ENTITY isin "∈"> <!ENTITY notin "∉"> <!ENTITY ni "∋"> <!ENTITY prod "∏"> <!ENTITY sum "∑"> <!ENTITY minus "−"> <!ENTITY lowast "∗"> <!ENTITY radic "√"> <!ENTITY prop "∝"> <!ENTITY infin "∞"> <!ENTITY ang "∠"> <!ENTITY and "∧"> <!ENTITY or "∨"> <!ENTITY cap "∩"> <!ENTITY cup "∪"> <!ENTITY int "∫"> <!ENTITY there4 "∴"> <!ENTITY sim "∼"> <!ENTITY cong "≅"> <!ENTITY asymp "≈"> <!ENTITY ne "≠"> <!ENTITY equiv "≡"> <!ENTITY le "≤"> <!ENTITY ge "≥"> <!ENTITY sub "⊂"> <!ENTITY sup "⊃"> <!ENTITY nsub "⊄"> <!ENTITY sube "⊆"> <!ENTITY supe "⊇"> <!ENTITY oplus "⊕"> <!ENTITY otimes "⊗"> <!ENTITY perp "⊥"> <!ENTITY sdot "⋅"> <!ENTITY lceil "⌈"> <!ENTITY rceil "⌉"> <!ENTITY lfloor "⌊"> <!ENTITY rfloor "⌋"> <!ENTITY lang "〈"> <!ENTITY rang "〉"> <!ENTITY loz "◊"> <!ENTITY spades "♠"> <!ENTITY clubs "♣"> <!ENTITY hearts "♥"> <!ENTITY diams "♦"> ]>'; + } +} \ No newline at end of file diff --git a/lib/SimplePie/SimplePie/Sanitize.php b/lib/SimplePie/SimplePie/Sanitize.php index 49fe5dbd5..c55ee50b7 100644 --- a/lib/SimplePie/SimplePie/Sanitize.php +++ b/lib/SimplePie/SimplePie/Sanitize.php @@ -60,8 +60,8 @@ class SimplePie_Sanitize var $image_handler = ''; var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); var $encode_instead_of_strip = false; - var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); - var $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')); //FreshRSS + var $strip_attributes = array('bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); + var $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')); var $strip_comments = false; var $output_encoding = 'UTF-8'; var $enable_cache = true; @@ -169,7 +169,7 @@ class SimplePie_Sanitize $this->encode_instead_of_strip = (bool) $encode; } - public function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc')) + public function strip_attributes($attribs = array('bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc')) { if ($attribs) { @@ -322,7 +322,7 @@ class SimplePie_Sanitize { if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML) { - $data = htmlspecialchars_decode($data, ENT_QUOTES); + $data = htmlspecialchars_decode($data, ENT_QUOTES); //FreshRSS if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data)) { $type |= SIMPLEPIE_CONSTRUCT_HTML; @@ -437,19 +437,17 @@ class SimplePie_Sanitize } } - // Remove the DOCTYPE - // Seems to cause segfaulting if we don't do this - if ($document->firstChild instanceof DOMDocumentType) + // Get content node + $div = $document->getElementsByTagName('body')->item(0)->firstChild; + // Finally, convert to a HTML string + if (version_compare(PHP_VERSION, '5.3.6', '>=')) { - $document->removeChild($document->firstChild); + $data = trim($document->saveHTML($div)); + } + else + { + $data = trim($document->saveXML($div)); } - - // Move everything from the body to the root - $real_body = $document->getElementsByTagName('body')->item(0)->childNodes->item(0); - $document->replaceChild($real_body, $document->firstChild); - - // Finally, convert to a HTML string - $data = trim($document->saveHTML()); if ($this->remove_div) { diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 7e14e638d..22136854e 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -183,7 +183,7 @@ function customSimplePie() { 'object', 'param', 'plaintext', 'script', 'style', )); $simplePie->strip_attributes(array_merge($simplePie->strip_attributes, array( - 'autoplay', 'onload', 'onunload', 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', + 'autoplay', 'class', 'onload', 'onunload', 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onfocus', 'onblur', 'onkeypress', 'onkeydown', 'onkeyup', 'onselect', 'onchange', 'seamless', 'sizes', 'srcset'))); $simplePie->add_attributes(array( -- cgit v1.2.3