aboutsummaryrefslogtreecommitdiff
path: root/lib/SimplePie
diff options
context:
space:
mode:
authorGravatar Clément <clement@selfhost.fr> 2017-02-15 14:14:03 +0100
committerGravatar Clément <clement@selfhost.fr> 2017-02-15 14:14:03 +0100
commit5a1bb1393b4496eb35a2ffb3cc63d41c9dc1e2e5 (patch)
tree67028e45792c575c25c92616633f64cc7a4a13eb /lib/SimplePie
parent7e949d50320317b5c3b5a2da2bdaf324e794b2f7 (diff)
parent5f637bd816b7323885bfe1751a1724ee59a822f6 (diff)
Merge remote-tracking branch 'FreshRSS/master'
Diffstat (limited to 'lib/SimplePie')
-rw-r--r--lib/SimplePie/SimplePie.php214
-rw-r--r--lib/SimplePie/SimplePie/Cache/File.php12
-rw-r--r--lib/SimplePie/SimplePie/Content/Type/Sniffer.php15
-rw-r--r--lib/SimplePie/SimplePie/Decode/HTML/Entities.php1
-rw-r--r--lib/SimplePie/SimplePie/File.php24
-rw-r--r--lib/SimplePie/SimplePie/Item.php43
-rw-r--r--lib/SimplePie/SimplePie/Locator.php2
-rw-r--r--lib/SimplePie/SimplePie/Misc.php20
-rw-r--r--lib/SimplePie/SimplePie/Parse/Date.php5
-rw-r--r--lib/SimplePie/SimplePie/Parser.php2
-rwxr-xr-xlib/SimplePie/SimplePie/Registry.php4
-rw-r--r--lib/SimplePie/SimplePie/Sanitize.php80
12 files changed, 314 insertions, 108 deletions
diff --git a/lib/SimplePie/SimplePie.php b/lib/SimplePie/SimplePie.php
index d7aaeb0c5..0f2fdbb87 100644
--- a/lib/SimplePie/SimplePie.php
+++ b/lib/SimplePie/SimplePie.php
@@ -75,6 +75,12 @@ define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed
define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
/**
+ * Use syslog to report HTTP requests done by SimplePie.
+ * @see SimplePie::set_syslog()
+ */
+define('SIMPLEPIE_SYSLOG', true); //FreshRSS
+
+/**
* No Autodiscovery
* @see SimplePie::set_autodiscovery_level()
*/
@@ -446,6 +452,13 @@ class SimplePie
public $feed_url;
/**
+ * @var string Original feed URL, or new feed URL iff HTTP 301 Moved Permanently
+ * @see SimplePie::subscribe_url()
+ * @access private
+ */
+ public $permanent_url = null;
+
+ /**
* @var object Instance of SimplePie_File to use as a feed
* @see SimplePie::set_file()
* @access private
@@ -467,6 +480,13 @@ class SimplePie
public $timeout = 10;
/**
+ * @var array Custom curl options
+ * @see SimplePie::set_curl_options()
+ * @access private
+ */
+ public $curl_options = array();
+
+ /**
* @var bool Forces fsockopen() to be used for remote files instead
* of cURL, even if a new enough version is installed
* @see SimplePie::force_fsockopen()
@@ -616,6 +636,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');
/**
+ * Use syslog to report HTTP requests done by SimplePie.
+ * @see SimplePie::set_syslog()
+ */
+ public $syslog_enabled = SIMPLEPIE_SYSLOG;
+
+ /**
* The SimplePie class contains feed level data and options
*
* To use SimplePie, create the SimplePie object with no parameters. You can
@@ -735,6 +761,7 @@ class SimplePie
else
{
$this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
+ $this->permanent_url = $this->feed_url;
}
}
@@ -749,6 +776,7 @@ class SimplePie
if ($file instanceof SimplePie_File)
{
$this->feed_url = $file->url;
+ $this->permanent_url = $this->feed_url;
$this->file =& $file;
return true;
}
@@ -786,6 +814,19 @@ class SimplePie
{
$this->timeout = (int) $timeout;
}
+
+ /**
+ * Set custom curl options
+ *
+ * This allows you to change default curl options
+ *
+ * @since 1.0 Beta 3
+ * @param array $curl_options Curl options to add to default settings
+ */
+ public function set_curl_options(array $curl_options = array())
+ {
+ $this->curl_options = $curl_options;
+ }
/**
* Force SimplePie to use fsockopen() instead of cURL
@@ -1082,6 +1123,7 @@ class SimplePie
$this->strip_attributes(false);
$this->add_attributes(false);
$this->set_image_handler(false);
+ $this->set_https_domains(array());
}
}
@@ -1127,7 +1169,7 @@ class SimplePie
$this->sanitize->strip_attributes($attribs);
}
- public function add_attributes($attribs = '')
+ public function add_attributes($attribs = '') //FreshRSS
{
if ($attribs === '')
{
@@ -1137,6 +1179,14 @@ class SimplePie
}
/**
+ * Use syslog to report HTTP requests done by SimplePie.
+ */
+ public function set_syslog($value = SIMPLEPIE_SYSLOG) //FreshRSS
+ {
+ $this->syslog_enabled = $value == true;
+ }
+
+ /**
* Set the output encoding
*
* Allows you to override SimplePie's output to match that of your webpage.
@@ -1185,6 +1235,19 @@ class SimplePie
}
/**
+ * Set the list of domains for which force HTTPS.
+ * @see SimplePie_Sanitize::set_https_domains()
+ * FreshRSS
+ */
+ public function set_https_domains($domains = array())
+ {
+ if (is_array($domains))
+ {
+ $this->sanitize->set_https_domains($domains);
+ }
+ }
+
+ /**
* Set the handler to enable the display of cached images.
*
* @param str $page Web-accessible path to the handler_image.php file.
@@ -1222,7 +1285,8 @@ class SimplePie
$this->enable_exceptions = $enable;
}
- function cleanMd5($rss) { //FreshRSS
+ function cleanMd5($rss)
+ {
return md5(preg_replace(array('#<(lastBuildDate|pubDate|updated|feedDate|dc:date|slash:comments)>[^<]+</\\1>#', '#<!--.+?-->#s'), '', $rss));
}
@@ -1240,6 +1304,7 @@ class SimplePie
// Check absolute bare minimum requirements.
if (!extension_loaded('xml') || !extension_loaded('pcre'))
{
+ $this->error = 'XML or PCRE extensions not loaded!';
return false;
}
// Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
@@ -1267,7 +1332,7 @@ class SimplePie
// Pass whatever was set with config options over to the sanitizer.
// Pass the classes in for legacy support; new classes should use the registry instead
$this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
- $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);
+ $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen, $this->curl_options);
if (!empty($this->multifeed_url))
{
@@ -1312,7 +1377,7 @@ class SimplePie
// Fetch the data via SimplePie_File into $this->raw_data
if (($fetched = $this->fetch_data($cache)) === true)
{
- return $this->data['mtime']; //FreshRSS
+ return $this->data['mtime'];
}
elseif ($fetched === false) {
return false;
@@ -1320,7 +1385,8 @@ class SimplePie
list($headers, $sniffed) = $fetched;
- if (isset($this->data['md5'])) { //FreshRSS
+ if (isset($this->data['md5']))
+ {
$md5 = $this->data['md5'];
}
}
@@ -1331,7 +1397,7 @@ class SimplePie
// First check to see if input has been overridden.
if ($this->input_encoding !== false)
{
- $encodings[] = strtoupper($this->input_encoding); //FreshRSS
+ $encodings[] = strtoupper($this->input_encoding);
}
$application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
@@ -1355,7 +1421,7 @@ class SimplePie
{
if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
{
- $encodings[] = strtoupper($charset[1]); //FreshRSS
+ $encodings[] = strtoupper($charset[1]);
}
else
{
@@ -1404,8 +1470,8 @@ class SimplePie
$this->data['headers'] = $headers;
}
$this->data['build'] = SIMPLEPIE_BUILD;
- $this->data['mtime'] = time(); //FreshRSS
- $this->data['md5'] = empty($md5) ? $this->cleanMd5($this->raw_data) : $md5; //FreshRSS
+ $this->data['mtime'] = time();
+ $this->data['md5'] = empty($md5) ? $this->cleanMd5($this->raw_data) : $md5;
// Cache the file if caching is enabled
if ($cache && !$cache->save($this))
@@ -1420,7 +1486,7 @@ 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', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
+ $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);
}
else
{
@@ -1446,7 +1512,12 @@ class SimplePie
{
// Load the Cache
$this->data = $cache->load();
- if (!empty($this->data))
+ if ($cache->mtime() + $this->cache_duration > time())
+ {
+ $this->raw_data = false;
+ return true; // If the cache is still valid, just return true
+ }
+ elseif (!empty($this->data))
{
// If the cache is for an outdated build of SimplePie
if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
@@ -1478,63 +1549,58 @@ class SimplePie
}
}
// Check if the cache has been updated
- elseif ($cache->mtime() + $this->cache_duration < time())
+ else
{
- // If we have last-modified and/or etag set
- //if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag'])) //FreshRSS removed
+ $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',
+ );
+ if (isset($this->data['headers']['last-modified']))
{
- $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',
- );
- if (isset($this->data['headers']['last-modified']))
- {
- $headers['if-modified-since'] = $this->data['headers']['last-modified'];
- }
- if (isset($this->data['headers']['etag']))
- {
- $headers['if-none-match'] = $this->data['headers']['etag'];
- }
+ $headers['if-modified-since'] = $this->data['headers']['last-modified'];
+ }
+ if (isset($this->data['headers']['etag']))
+ {
+ $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)); //FreshRSS
+ $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
- if ($file->success)
+ if ($file->success)
+ {
+ if ($file->status_code === 304)
{
- if ($file->status_code === 304)
- {
- $cache->touch();
- return true;
- }
+ $cache->touch();
+ return true;
}
- else
+ }
+ else
+ {
+ $cache->touch();
+ $this->error = $file->error;
+ return !empty($this->data);
+ }
+
+ $md5 = $this->cleanMd5($file->body);
+ if ($this->data['md5'] === $md5) {
+ if ($this->syslog_enabled)
{
- $this->error = $file->error; //FreshRSS
- return !empty($this->data); //FreshRSS
- //unset($file); //FreshRSS removed
+ syslog(LOG_DEBUG, 'SimplePie MD5 cache match for ' . SimplePie_Misc::url_remove_credentials($this->feed_url));
}
- }
- { //FreshRSS
- $md5 = $this->cleanMd5($file->body);
- if ($this->data['md5'] === $md5) {
- syslog(LOG_DEBUG, 'SimplePie MD5 cache match for ' . $this->feed_url);
- $cache->touch();
- return true; //Content unchanged even though server did not send a 304
- } else {
- syslog(LOG_DEBUG, 'SimplePie MD5 cache no match for ' . $this->feed_url);
- $this->data['md5'] = $md5;
+ $cache->touch();
+ return true; //Content unchanged even though server did not send a 304
+ } else {
+ if ($this->syslog_enabled)
+ {
+ syslog(LOG_DEBUG, 'SimplePie MD5 cache no match for ' . SimplePie_Misc::url_remove_credentials($this->feed_url));
}
+ $this->data['md5'] = $md5;
}
}
- // If the cache is still valid, just return true
- else
- {
- $this->raw_data = false;
- return true;
- }
}
- // If the cache is empty, delete it
+ // If the cache is empty
else
{
- $cache->unlink();
+ $cache->touch(); //To keep the date/time of the last tentative update
$this->data = array();
}
}
@@ -1550,7 +1616,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));
+ $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
}
}
// If the file connection has an error, set SimplePie::error to that and quit
@@ -1567,13 +1633,15 @@ class SimplePie
if (!$locate->is_feed($file))
{
+ $copyStatusCode = $file->status_code;
+ $copyContentType = $file->headers['content-type'];
// We need to unset this so that if SimplePie::set_file() has been called that object is untouched
unset($file);
try
{
if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))
{
- $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
+ $this->error = "A feed could not be found at `$this->feed_url`; the status code is `$copyStatusCode` and content-type is `$copyContentType`";
$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
return false;
}
@@ -1588,8 +1656,8 @@ class SimplePie
if ($cache)
{
$this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
- $this->data['mtime'] = time(); //FreshRSS
- $this->data['md5'] = empty($md5) ? $this->cleanMd5($file->body) : $md5; //FreshRSS
+ $this->data['mtime'] = time();
+ $this->data['md5'] = empty($md5) ? $this->cleanMd5($file->body) : $md5;
if (!$cache->save($this))
{
trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
@@ -1601,8 +1669,9 @@ class SimplePie
$locate = null;
}
+ $file->body = trim($file->body);
$this->raw_data = $file->body;
-
+ $this->permanent_url = $file->permanent_url;
$headers = $file->headers;
$sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
$sniffed = $sniffer->get_type();
@@ -1788,26 +1857,39 @@ class SimplePie
/**
* Get the URL for the feed
+ *
+ * When the 'permanent' mode is enabled, returns the original feed URL,
+ * except in the case of an `HTTP 301 Moved Permanently` status response,
+ * in which case the location of the first redirection is returned.
*
- * May or may not be different from the URL passed to {@see set_feed_url()},
+ * When the 'permanent' mode is disabled (default),
+ * may or may not be different from the URL passed to {@see set_feed_url()},
* depending on whether auto-discovery was used.
*
* @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
- * @todo If we have a perm redirect we should return the new URL
- * @todo When we make the above change, let's support <itunes:new-feed-url> as well
+ * @todo Support <itunes:new-feed-url>
* @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
* @return string|null
*/
- public function subscribe_url()
+ public function subscribe_url($permanent = false)
{
- if ($this->feed_url !== null)
+ if ($permanent)
{
- return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
+ if ($this->permanent_url !== null)
+ {
+ return $this->sanitize($this->permanent_url, SIMPLEPIE_CONSTRUCT_IRI);
+ }
}
else
{
- return null;
+ if ($this->feed_url !== null)
+ {
+ return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
+ }
}
+ return null;
}
/**
diff --git a/lib/SimplePie/SimplePie/Cache/File.php b/lib/SimplePie/SimplePie/Cache/File.php
index 3b163545b..72e75a4b6 100644
--- a/lib/SimplePie/SimplePie/Cache/File.php
+++ b/lib/SimplePie/SimplePie/Cache/File.php
@@ -136,11 +136,7 @@ class SimplePie_Cache_File implements SimplePie_Cache_Base
*/
public function mtime()
{
- if (file_exists($this->name))
- {
- return filemtime($this->name);
- }
- return false;
+ return @filemtime($this->name);
}
/**
@@ -150,11 +146,7 @@ class SimplePie_Cache_File implements SimplePie_Cache_Base
*/
public function touch()
{
- if (file_exists($this->name))
- {
- return touch($this->name);
- }
- return false;
+ return @touch($this->name);
}
/**
diff --git a/lib/SimplePie/SimplePie/Content/Type/Sniffer.php b/lib/SimplePie/SimplePie/Content/Type/Sniffer.php
index a32f47f59..ec0bf0952 100644
--- a/lib/SimplePie/SimplePie/Content/Type/Sniffer.php
+++ b/lib/SimplePie/SimplePie/Content/Type/Sniffer.php
@@ -109,9 +109,7 @@ class SimplePie_Content_Type_Sniffer
{
return $this->unknown();
}
- elseif (substr($official, -4) === '+xml'
- || $official === 'text/xml'
- || $official === 'application/xml')
+ elseif (substr($official, -4) === '+xml')
{
return $official;
}
@@ -126,7 +124,9 @@ class SimplePie_Content_Type_Sniffer
return $official;
}
}
- elseif ($official === 'text/html')
+ elseif ($official === 'text/html'
+ || $official === 'text/xml'
+ || $official === 'application/xml')
{
return $this->feed_or_html();
}
@@ -256,7 +256,12 @@ class SimplePie_Content_Type_Sniffer
public function feed_or_html()
{
$len = strlen($this->file->body);
- $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
+ $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);
while ($pos < $len)
{
diff --git a/lib/SimplePie/SimplePie/Decode/HTML/Entities.php b/lib/SimplePie/SimplePie/Decode/HTML/Entities.php
index cde06c884..46b3a1dff 100644
--- a/lib/SimplePie/SimplePie/Decode/HTML/Entities.php
+++ b/lib/SimplePie/SimplePie/Decode/HTML/Entities.php
@@ -169,7 +169,6 @@ class SimplePie_Decode_HTML_Entities
case "\x09":
case "\x0A":
case "\x0B":
- case "\x0B":
case "\x0C":
case "\x20":
case "\x3C":
diff --git a/lib/SimplePie/SimplePie/File.php b/lib/SimplePie/SimplePie/File.php
index faf5dd1f1..45994d102 100644
--- a/lib/SimplePie/SimplePie/File.php
+++ b/lib/SimplePie/SimplePie/File.php
@@ -64,8 +64,9 @@ class SimplePie_File
var $redirects = 0;
var $error;
var $method = SIMPLEPIE_FILE_SOURCE_NONE;
+ var $permanent_url; //FreshRSS
- public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
+ public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false, $curl_options = array(), $syslog_enabled = SIMPLEPIE_SYSLOG)
{
if (class_exists('idna_convert'))
{
@@ -74,10 +75,14 @@ class SimplePie_File
$url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
}
$this->url = $url;
+ $this->permanent_url = $url;
$this->useragent = $useragent;
if (preg_match('/^http(s)?:\/\//i', $url))
{
- syslog(LOG_INFO, 'SimplePie GET ' . $url); //FreshRSS
+ if ($syslog_enabled)
+ {
+ syslog(LOG_INFO, 'SimplePie GET ' . SimplePie_Misc::url_remove_credentials($url)); //FreshRSS
+ }
if ($useragent === null)
{
$useragent = ini_get('user_agent');
@@ -108,12 +113,15 @@ class SimplePie_File
curl_setopt($fp, CURLOPT_REFERER, $url);
curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
- curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, false); //FreshRSS
if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
{
curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
}
+ foreach ($curl_options as $curl_param => $curl_value)
+ {
+ curl_setopt($fp, $curl_param, $curl_value);
+ }
$this->headers = curl_exec($fp);
if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
@@ -142,7 +150,10 @@ class SimplePie_File
{
$this->redirects++;
$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
- return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
+ $previousStatusCode = $this->status_code;
+ $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
+ $this->permanent_url = ($previousStatusCode == 301) ? $location : $url;
+ return;
}
}
}
@@ -224,7 +235,10 @@ class SimplePie_File
{
$this->redirects++;
$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
- return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
+ $previousStatusCode = $this->status_code;
+ $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
+ $this->permanent_url = ($previousStatusCode == 301) ? $location : $url; //FreshRSS
+ return;
}
if (isset($this->headers['content-encoding']))
{
diff --git a/lib/SimplePie/SimplePie/Item.php b/lib/SimplePie/SimplePie/Item.php
index 7bd96c15f..19ba7c8f4 100644
--- a/lib/SimplePie/SimplePie/Item.php
+++ b/lib/SimplePie/SimplePie/Item.php
@@ -406,6 +406,30 @@ class SimplePie_Item
return null;
}
}
+
+ /**
+ * Get the media:thumbnail of the item
+ *
+ * Uses `<media:thumbnail>`
+ *
+ *
+ * @return array|null
+ */
+ public function get_thumbnail()
+ {
+ if (!isset($this->data['thumbnail']))
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
+ {
+ $this->data['thumbnail'] = $return[0]['attribs'][''];
+ }
+ else
+ {
+ $this->data['thumbnail'] = null;
+ }
+ }
+ return $this->data['thumbnail'];
+ }
/**
* Get a category for the item
@@ -738,31 +762,31 @@ class SimplePie_Item
{
$this->data['date']['raw'] = $return[0]['data'];
}
- elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
{
$this->data['date']['raw'] = $return[0]['data'];
}
- elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
{
$this->data['date']['raw'] = $return[0]['data'];
}
- elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
{
$this->data['date']['raw'] = $return[0]['data'];
}
- elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
{
$this->data['date']['raw'] = $return[0]['data'];
}
- elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
{
$this->data['date']['raw'] = $return[0]['data'];
}
- elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
{
$this->data['date']['raw'] = $return[0]['data'];
}
- elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
{
$this->data['date']['raw'] = $return[0]['data'];
}
@@ -2733,7 +2757,9 @@ class SimplePie_Item
{
foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
{
- $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ if (isset($thumbnail['attribs']['']['url'])) {
+ $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
}
if (is_array($thumbnails))
{
@@ -2851,6 +2877,7 @@ class SimplePie_Item
$width = null;
$url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
+ $url = $this->feed->sanitize->https_url($url); //FreshRSS
if (isset($enclosure[0]['attribs']['']['type']))
{
$type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
diff --git a/lib/SimplePie/SimplePie/Locator.php b/lib/SimplePie/SimplePie/Locator.php
index 90ee7a302..ba4a843b0 100644
--- a/lib/SimplePie/SimplePie/Locator.php
+++ b/lib/SimplePie/SimplePie/Locator.php
@@ -148,7 +148,7 @@ class SimplePie_Locator
{
$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')))
+ if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml', 'application/x-rss+xml')))
{
return true;
}
diff --git a/lib/SimplePie/SimplePie/Misc.php b/lib/SimplePie/SimplePie/Misc.php
index 5a263a2e5..2d154cbcb 100644
--- a/lib/SimplePie/SimplePie/Misc.php
+++ b/lib/SimplePie/SimplePie/Misc.php
@@ -79,9 +79,9 @@ class SimplePie_Misc
public static function absolutize_url($relative, $base)
{
- if (substr($relative, 0, 2) === '//') //FreshRSS: disable absolutize_url for "//www.example.net" which will pick HTTP or HTTPS automatically
- {
- return $relative;
+ if (substr($relative, 0, 2) === '//')
+ {//Protocol-relative URLs "//www.example.net"
+ return 'https:' . $relative;
}
$iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
if ($iri === false)
@@ -128,7 +128,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'); //FreshRSS
+ $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
}
}
}
@@ -142,7 +142,7 @@ class SimplePie_Misc
foreach ($element['attribs'] as $key => $value)
{
$key = strtolower($key);
- $full .= " $key=\"" . htmlspecialchars($value['data'], ENT_COMPAT, 'UTF-8') . '"'; //FreshRSS
+ $full .= " $key=\"" . htmlspecialchars($value['data'], ENT_COMPAT, 'UTF-8') . '"';
}
if ($element['self_closing'])
{
@@ -2240,5 +2240,15 @@ function embed_wmedia(width, height, link) {
{
// No-op
}
+
+ /**
+ * Sanitize a URL by removing HTTP credentials.
+ * @param $url the URL to sanitize.
+ * @return the same URL without HTTP credentials.
+ */
+ public static function url_remove_credentials($url) //FreshRSS
+ {
+ return preg_replace('#^(https?://)[^/:@]+:[^/:@]+@#i', '$1', $url);
+ }
}
diff --git a/lib/SimplePie/SimplePie/Parse/Date.php b/lib/SimplePie/SimplePie/Parse/Date.php
index ef800f125..50bb5cffa 100644
--- a/lib/SimplePie/SimplePie/Parse/Date.php
+++ b/lib/SimplePie/SimplePie/Parse/Date.php
@@ -173,7 +173,7 @@ class SimplePie_Parse_Date
'aug' => 8,
'august' => 8,
'sep' => 9,
- 'september' => 8,
+ 'september' => 9,
'oct' => 10,
'october' => 10,
'nov' => 11,
@@ -332,6 +332,7 @@ class SimplePie_Parse_Date
'CDT' => -18000,
'CEDT' => 7200,
'CET' => 3600,
+ 'CEST' => 7200,
'CGST' => -7200,
'CGT' => -10800,
'CHADT' => 49500,
@@ -720,7 +721,7 @@ class SimplePie_Parse_Date
{
$output .= substr($string, $position, $pos - $position);
$position = $pos + 1;
- if ($string[$pos - 1] !== '\\')
+ if ($pos === 0 || $string[$pos - 1] !== '\\')
{
$depth++;
while ($depth && $position < $length)
diff --git a/lib/SimplePie/SimplePie/Parser.php b/lib/SimplePie/SimplePie/Parser.php
index 9300b4ba9..7fb7bd9be 100644
--- a/lib/SimplePie/SimplePie/Parser.php
+++ b/lib/SimplePie/SimplePie/Parser.php
@@ -142,7 +142,7 @@ class SimplePie_Parser
$dom = new DOMDocument();
$dom->recover = true;
$dom->strictErrorChecking = false;
- $dom->loadXML($data);
+ @$dom->loadXML($data);
$this->encoding = $encoding = $dom->encoding = 'UTF-8';
$data2 = $dom->saveXML();
if (function_exists('mb_convert_encoding'))
diff --git a/lib/SimplePie/SimplePie/Registry.php b/lib/SimplePie/SimplePie/Registry.php
index bd9c1f535..dac55e34e 100755
--- a/lib/SimplePie/SimplePie/Registry.php
+++ b/lib/SimplePie/SimplePie/Registry.php
@@ -113,7 +113,7 @@ class SimplePie_Registry
*/
public function register($type, $class, $legacy = false)
{
- if (!is_subclass_of($class, $this->default[$type]))
+ if (!@is_subclass_of($class, $this->default[$type]))
{
return false;
}
@@ -222,4 +222,4 @@ class SimplePie_Registry
$result = call_user_func_array(array($class, $method), $parameters);
return $result;
}
-} \ No newline at end of file
+}
diff --git a/lib/SimplePie/SimplePie/Sanitize.php b/lib/SimplePie/SimplePie/Sanitize.php
index 168a5e2e8..bdc601100 100644
--- a/lib/SimplePie/SimplePie/Sanitize.php
+++ b/lib/SimplePie/SimplePie/Sanitize.php
@@ -73,6 +73,15 @@ class SimplePie_Sanitize
var $force_fsockopen = false;
var $replace_url_attributes = null;
+ /**
+ * List of domains for which force HTTPS.
+ * @see SimplePie_Sanitize::set_https_domains()
+ * Array is tree split at DNS levels. Example:
+ * array('biz' => true, 'com' => array('example' => true), 'net' => array('example') => array('www' => true))
+ * FreshRSS
+ */
+ var $https_domains = array('com' => array('dailymotion' => true, 'youtube' => true));
+
public function __construct()
{
// Set defaults
@@ -242,6 +251,71 @@ class SimplePie_Sanitize
$this->replace_url_attributes = (array) $element_attribute;
}
+ /**
+ * Set the list of domains for which force HTTPS.
+ * @see SimplePie_Misc::https_url()
+ * Example array('biz', 'example.com', 'example.org', 'www.example.net');
+ * FreshRSS
+ */
+ public function set_https_domains($domains)
+ {
+ $this->https_domains = array();
+ foreach ($domains as $domain)
+ {
+ $domain = trim($domain, ". \t\n\r\0\x0B");
+ $segments = array_reverse(explode('.', $domain));
+ $node =& $this->https_domains;
+ foreach ($segments as $segment)
+ {//Build a tree
+ if ($node === true)
+ {
+ break;
+ }
+ if (!isset($node[$segment]))
+ {
+ $node[$segment] = array();
+ }
+ $node =& $node[$segment];
+ }
+ $node = true;
+ }
+ }
+
+ /**
+ * Check if the domain is in the list of forced HTTPS
+ * FreshRSS
+ */
+ protected function is_https_domain($domain)
+ {
+ $domain = trim($domain, '. ');
+ $segments = array_reverse(explode('.', $domain));
+ $node =& $this->https_domains;
+ foreach ($segments as $segment)
+ {//Explore the tree
+ if (isset($node[$segment]))
+ {
+ $node =& $node[$segment];
+ }
+ else
+ {
+ break;
+ }
+ }
+ return $node === true;
+ }
+
+ /**
+ * Force HTTPS for selected Web sites
+ * FreshRSS
+ */
+ public function https_url($url)
+ {
+ return (strtolower(substr($url, 0, 7)) === 'http://') &&
+ $this->is_https_domain(parse_url($url, PHP_URL_HOST)) ?
+ substr_replace($url, 's', 4, 0) : //Add the 's' to HTTPS
+ $url;
+ }
+
public function sanitize($data, $type, $base = '')
{
$data = trim($data);
@@ -249,6 +323,7 @@ class SimplePie_Sanitize
{
if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
{
+ $data = htmlspecialchars_decode($data, ENT_QUOTES);
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;
@@ -279,7 +354,7 @@ class SimplePie_Sanitize
$document->loadHTML($data);
restore_error_handler();
- $xpath = new DOMXPath($document); //FreshRSS
+ $xpath = new DOMXPath($document);
// Strip comments
if ($this->strip_comments)
@@ -450,7 +525,8 @@ class SimplePie_Sanitize
if ($element->hasAttribute($attribute))
{
$value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base));
- if ($value !== false)
+ $value = $this->https_url($value); //FreshRSS
+ if ($value)
{
$element->setAttribute($attribute, $value);
}