External Libraries: Update the SimplePie library to version 1.5.7.

This version shows significant improvements in the compatibility of SimplePie with PHP 8.0, 8.1, and even contains an initial PHP 8.2 fix. The release also contains a number of other bug fixes.

Release notes: https://github.com/simplepie/simplepie/releases/tag/1.5.7

For a full list of changes in this update, see the SimplePie GitHub:
https://github.com/simplepie/simplepie/compare/1.5.6...1.5.7

Follow-up to [47733], [49176].

Props jrf, SergeyBiryukov.
Fixes #54659.
Built from https://develop.svn.wordpress.org/trunk@52393


git-svn-id: http://core.svn.wordpress.org/trunk@51985 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Sergey Biryukov 2021-12-20 19:33:00 +00:00
parent 9759353922
commit c3112cab39
12 changed files with 218 additions and 27 deletions

View File

@ -152,7 +152,7 @@ class SimplePie_Cache_Redis implements SimplePie_Cache_Base {
if ($data !== false) { if ($data !== false) {
$return = $this->cache->set($this->name, $data); $return = $this->cache->set($this->name, $data);
if ($this->options['expire']) { if ($this->options['expire']) {
return $this->cache->expire($this->name, $this->ttl); return $this->cache->expire($this->name, $this->options['expire']);
} }
return $return; return $return;
} }

View File

@ -1152,7 +1152,12 @@ class SimplePie_Enclosure
// If we encounter an unsupported mime-type, check the file extension and guess intelligently. // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3))) if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
{ {
switch (strtolower($this->get_extension())) $extension = $this->get_extension();
if ($extension === null) {
return null;
}
switch (strtolower($extension))
{ {
// Audio mime-types // Audio mime-types
case 'aac': case 'aac':

View File

@ -106,7 +106,7 @@ class SimplePie_File
curl_setopt($fp, CURLOPT_FAILONERROR, 1); curl_setopt($fp, CURLOPT_FAILONERROR, 1);
curl_setopt($fp, CURLOPT_TIMEOUT, $timeout); curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($fp, CURLOPT_REFERER, $url); curl_setopt($fp, CURLOPT_REFERER, SimplePie_Misc::url_remove_credentials($url));
curl_setopt($fp, CURLOPT_USERAGENT, $useragent); curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2); curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
foreach ($curl_options as $curl_param => $curl_value) { foreach ($curl_options as $curl_param => $curl_value) {
@ -119,6 +119,7 @@ class SimplePie_File
curl_setopt($fp, CURLOPT_ENCODING, 'none'); curl_setopt($fp, CURLOPT_ENCODING, 'none');
$this->headers = curl_exec($fp); $this->headers = curl_exec($fp);
} }
$this->status_code = curl_getinfo($fp, CURLINFO_HTTP_CODE);
if (curl_errno($fp)) if (curl_errno($fp))
{ {
$this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp); $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);

View File

@ -507,11 +507,13 @@ class SimplePie_HTTP_Parser
{ {
$data = explode("\r\n\r\n", $headers, $count); $data = explode("\r\n\r\n", $headers, $count);
$data = array_pop($data); $data = array_pop($data);
if (false !== stripos($data, "HTTP/1.0 200 Connection established\r\n\r\n")) { if (false !== stripos($data, "HTTP/1.0 200 Connection established\r\n")) {
$data = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $data); $exploded = explode("\r\n\r\n", $data, 2);
$data = end($exploded);
} }
if (false !== stripos($data, "HTTP/1.1 200 Connection established\r\n\r\n")) { if (false !== stripos($data, "HTTP/1.1 200 Connection established\r\n")) {
$data = str_ireplace("HTTP/1.1 200 Connection established\r\n\r\n", '', $data); $exploded = explode("\r\n\r\n", $data, 2);
$data = end($exploded);
} }
return $data; return $data;
} }

View File

@ -1803,7 +1803,7 @@ class SimplePie_Item
} }
if (isset($content['attribs']['']['fileSize'])) if (isset($content['attribs']['']['fileSize']))
{ {
$length = ceil($content['attribs']['']['fileSize']); $length = intval($content['attribs']['']['fileSize']);
} }
if (isset($content['attribs']['']['medium'])) if (isset($content['attribs']['']['medium']))
{ {
@ -2425,7 +2425,7 @@ class SimplePie_Item
} }
if (isset($content['attribs']['']['fileSize'])) if (isset($content['attribs']['']['fileSize']))
{ {
$length = ceil($content['attribs']['']['fileSize']); $length = intval($content['attribs']['']['fileSize']);
} }
if (isset($content['attribs']['']['medium'])) if (isset($content['attribs']['']['medium']))
{ {
@ -2790,7 +2790,7 @@ class SimplePie_Item
} }
if (isset($link['attribs']['']['length'])) if (isset($link['attribs']['']['length']))
{ {
$length = ceil($link['attribs']['']['length']); $length = intval($link['attribs']['']['length']);
} }
if (isset($link['attribs']['']['title'])) if (isset($link['attribs']['']['title']))
{ {
@ -2833,7 +2833,7 @@ class SimplePie_Item
} }
if (isset($link['attribs']['']['length'])) if (isset($link['attribs']['']['length']))
{ {
$length = ceil($link['attribs']['']['length']); $length = intval($link['attribs']['']['length']);
} }
// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
@ -2862,13 +2862,14 @@ class SimplePie_Item
$width = null; $width = null;
$url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0])); $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
$url = $this->feed->sanitize->https_url($url);
if (isset($enclosure[0]['attribs']['']['type'])) if (isset($enclosure[0]['attribs']['']['type']))
{ {
$type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
} }
if (isset($enclosure[0]['attribs']['']['length'])) if (isset($enclosure[0]['attribs']['']['length']))
{ {
$length = ceil($enclosure[0]['attribs']['']['length']); $length = intval($enclosure[0]['attribs']['']['length']);
} }
// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor

View File

@ -64,6 +64,7 @@ class SimplePie_Locator
var $max_checked_feeds = 10; var $max_checked_feeds = 10;
var $force_fsockopen = false; var $force_fsockopen = false;
var $curl_options = array(); var $curl_options = array();
var $dom;
protected $registry; protected $registry;
public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10, $force_fsockopen = false, $curl_options = array()) public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10, $force_fsockopen = false, $curl_options = array())
@ -75,12 +76,19 @@ class SimplePie_Locator
$this->force_fsockopen = $force_fsockopen; $this->force_fsockopen = $force_fsockopen;
$this->curl_options = $curl_options; $this->curl_options = $curl_options;
if (class_exists('DOMDocument')) if (class_exists('DOMDocument') && $this->file->body != '')
{ {
$this->dom = new DOMDocument(); $this->dom = new DOMDocument();
set_error_handler(array('SimplePie_Misc', 'silence_errors')); set_error_handler(array('SimplePie_Misc', 'silence_errors'));
$this->dom->loadHTML($this->file->body); try
{
$this->dom->loadHTML($this->file->body);
}
catch (Throwable $ex)
{
$this->dom = null;
}
restore_error_handler(); restore_error_handler();
} }
else else

View File

@ -2260,4 +2260,14 @@ function embed_wmedia(width, height, link) {
{ {
// No-op // No-op
} }
/**
* Sanitize a URL by removing HTTP credentials.
* @param string $url the URL to sanitize.
* @return string the same URL without HTTP credentials.
*/
public static function url_remove_credentials($url)
{
return preg_replace('#^(https?://)[^/:@]+:[^/:@]+@#i', '$1', $url);
}
} }

View File

@ -164,12 +164,30 @@ class SimplePie_Parser
xml_set_element_handler($xml, 'tag_open', 'tag_close'); xml_set_element_handler($xml, 'tag_open', 'tag_close');
// Parse! // Parse!
if (!xml_parse($xml, $data, true)) $wrapper = @is_writable(sys_get_temp_dir()) ? 'php://temp' : 'php://memory';
if (($stream = fopen($wrapper, 'r+')) &&
fwrite($stream, $data) &&
rewind($stream))
{
//Parse by chunks not to use too much memory
do
{
$stream_data = fread($stream, 1048576);
if (!xml_parse($xml, $stream_data === false ? '' : $stream_data, feof($stream)))
{
$this->error_code = xml_get_error_code($xml);
$this->error_string = xml_error_string($this->error_code);
$return = false;
break;
}
} while (!feof($stream));
fclose($stream);
}
else
{ {
$this->error_code = xml_get_error_code($xml);
$this->error_string = xml_error_string($this->error_code);
$return = false; $return = false;
} }
$this->current_line = xml_get_current_line_number($xml); $this->current_line = xml_get_current_line_number($xml);
$this->current_column = xml_get_current_column_number($xml); $this->current_column = xml_get_current_column_number($xml);
$this->current_byte = xml_get_current_byte_index($xml); $this->current_byte = xml_get_current_byte_index($xml);

View File

@ -208,7 +208,8 @@ class SimplePie_Registry
{ {
case 'Cache': case 'Cache':
// For backwards compatibility with old non-static // For backwards compatibility with old non-static
// Cache::create() methods // Cache::create() methods in PHP < 8.0.
// No longer supported as of PHP 8.0.
if ($method === 'get_handler') if ($method === 'get_handler')
{ {
$result = @call_user_func_array(array($class, 'create'), $parameters); $result = @call_user_func_array(array($class, 'create'), $parameters);

View File

@ -71,6 +71,15 @@ class SimplePie_Sanitize
var $useragent = ''; var $useragent = '';
var $force_fsockopen = false; var $force_fsockopen = false;
var $replace_url_attributes = null; var $replace_url_attributes = null;
var $registry;
/**
* List of domains for which to force HTTPS.
* @see SimplePie_Sanitize::set_https_domains()
* Array is a tree split at DNS levels. Example:
* array('biz' => true, 'com' => array('example' => true), 'net' => array('example' => array('www' => true)))
*/
var $https_domains = array();
public function __construct() public function __construct()
{ {
@ -241,6 +250,68 @@ class SimplePie_Sanitize
$this->replace_url_attributes = (array) $element_attribute; $this->replace_url_attributes = (array) $element_attribute;
} }
/**
* Set the list of domains for which to force HTTPS.
* @see SimplePie_Misc::https_url()
* Example array('biz', 'example.com', 'example.org', 'www.example.net');
*/
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.
*/
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.
*/
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 = '') public function sanitize($data, $type, $base = '')
{ {
$data = trim($data); $data = trim($data);
@ -443,6 +514,7 @@ class SimplePie_Sanitize
$value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base)); $value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base));
if ($value !== false) if ($value !== false)
{ {
$value = $this->https_url($value);
$element->setAttribute($attribute, $value); $element->setAttribute($attribute, $value);
} }
} }

View File

@ -459,6 +459,13 @@ class SimplePie
*/ */
public $error; public $error;
/**
* @var int HTTP status code
* @see SimplePie::status_code()
* @access private
*/
public $status_code;
/** /**
* @var object Instance of SimplePie_Sanitize (or other class) * @var object Instance of SimplePie_Sanitize (or other class)
* @see SimplePie::set_sanitize_class() * @see SimplePie::set_sanitize_class()
@ -943,6 +950,39 @@ class SimplePie
$this->cache_location = (string) $location; $this->cache_location = (string) $location;
} }
/**
* Return the filename (i.e. hash, without path and without extension) of the file to cache a given URL.
* @param string $url The URL of the feed to be cached.
* @return string A filename (i.e. hash, without path and without extension).
*/
public function get_cache_filename($url)
{
// Append custom parameters to the URL to avoid cache pollution in case of multiple calls with different parameters.
$url .= $this->force_feed ? '#force_feed' : '';
$options = array();
if ($this->timeout != 10)
{
$options[CURLOPT_TIMEOUT] = $this->timeout;
}
if ($this->useragent !== SIMPLEPIE_USERAGENT)
{
$options[CURLOPT_USERAGENT] = $this->useragent;
}
if (!empty($this->curl_options))
{
foreach ($this->curl_options as $k => $v)
{
$options[$k] = $v;
}
}
if (!empty($options))
{
ksort($options);
$url .= '#' . urlencode(var_export($options, true));
}
return call_user_func($this->cache_name_function, $url);
}
/** /**
* Set whether feed items should be sorted into reverse chronological order * Set whether feed items should be sorted into reverse chronological order
* *
@ -1181,6 +1221,7 @@ class SimplePie
$this->strip_attributes(false); $this->strip_attributes(false);
$this->add_attributes(false); $this->add_attributes(false);
$this->set_image_handler(false); $this->set_image_handler(false);
$this->set_https_domains(array());
} }
} }
@ -1283,6 +1324,19 @@ class SimplePie
$this->sanitize->set_url_replacements($element_attribute); $this->sanitize->set_url_replacements($element_attribute);
} }
/**
* Set the list of domains for which to force HTTPS.
* @see SimplePie_Sanitize::set_https_domains()
* @param array List of HTTPS domains. Example array('biz', 'example.com', 'example.org', 'www.example.net').
*/
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. * Set the handler to enable the display of cached images.
* *
@ -1408,8 +1462,8 @@ class SimplePie
// Decide whether to enable caching // Decide whether to enable caching
if ($this->cache && $parsed_feed_url['scheme'] !== '') if ($this->cache && $parsed_feed_url['scheme'] !== '')
{ {
$url = $this->feed_url . ($this->force_feed ? '#force_feed' : ''); $filename = $this->get_cache_filename($this->feed_url);
$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $url), 'spc')); $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, $filename, 'spc'));
} }
// Fetch the data via SimplePie_File into $this->raw_data // Fetch the data via SimplePie_File into $this->raw_data
@ -1549,7 +1603,7 @@ class SimplePie
* Fetch the data via SimplePie_File * Fetch the data via SimplePie_File
* *
* If the data is already cached, attempt to fetch it from there instead * If the data is already cached, attempt to fetch it from there instead
* @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache * @param SimplePie_Cache_Base|false $cache Cache handler, or false to not load from the cache
* @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
*/ */
protected function fetch_data(&$cache) protected function fetch_data(&$cache)
@ -1612,6 +1666,7 @@ class SimplePie
} }
$file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options)); $file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
$this->status_code = $file->status_code;
if ($file->success) if ($file->success)
{ {
@ -1666,6 +1721,8 @@ class SimplePie
$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->status_code = $file->status_code;
// If the file connection has an error, set SimplePie::error to that and quit // If the file connection has an error, set SimplePie::error to that and quit
if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
{ {
@ -1772,6 +1829,16 @@ class SimplePie
return $this->error; return $this->error;
} }
/**
* Get the last HTTP status code
*
* @return int Status code
*/
public function status_code()
{
return $this->status_code;
}
/** /**
* Get the raw XML * Get the raw XML
* *
@ -2615,13 +2682,19 @@ class SimplePie
} }
} }
if (isset($this->data['headers']['link']) && if (isset($this->data['headers']['link']))
preg_match('/<([^>]+)>; rel='.preg_quote($rel).'/',
$this->data['headers']['link'], $match))
{ {
return array($match[1]); $link_headers = $this->data['headers']['link'];
if (is_string($link_headers)) {
$link_headers = array($link_headers);
}
$matches = preg_filter('/<([^>]+)>; rel='.preg_quote($rel).'/', '$1', $link_headers);
if (!empty($matches)) {
return $matches;
}
} }
else if (isset($this->data['links'][$rel]))
if (isset($this->data['links'][$rel]))
{ {
return $this->data['links'][$rel]; return $this->data['links'][$rel];
} }

View File

@ -16,7 +16,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '5.9-beta3-52392'; $wp_version = '5.9-beta3-52393';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.