Make WordPress Core


Ignore:
Timestamp:
09/30/2024 10:48:16 PM (8 months ago)
Author:
SergeyBiryukov
Message:

External Libraries: Update the SimplePie library to version 1.8.0.

The most notable change in this update is that all code is now namespaced and uses PSR-4 classes, though there is a compatibility layer available for extenders using the older class names, so plugin or theme authors directly using SimplePie can decide for themselves when they want to change to using the namespaced names for SimplePie classes.

Note: This commit includes additional fixes for PHP 8.4 compatibility (PR 875, PR 888) from the one-dot-eight branch of SimplePie, which is expected to be released as SimplePie 1.8.1 soon.

References:

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

Props jrf, peterwilsoncc, chaion07, cu121, markparnell, audrasjb, costdev, Presskopp, desrosj, faisal03, mukesh27, SergeyBiryukov.
See #55604.

Location:
trunk/src/wp-includes/SimplePie/src
Files:
1 added
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/SimplePie/src/File.php

    r59140 r59141  
    11<?php
     2
    23/**
    34 * SimplePie
     
    67 * Takes the hard work out of managing a complete RSS/Atom solution.
    78 *
    8  * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors
     9 * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors
    910 * All rights reserved.
    1011 *
     
    4243 */
    4344
     45namespace SimplePie;
     46
    4447/**
    4548 * Used for fetching remote files and reading local files
     
    4750 * Supports HTTP 1.0 via cURL or fsockopen, with spotty HTTP 1.1 support
    4851 *
    49  * This class can be overloaded with {@see SimplePie::set_file_class()}
     52 * This class can be overloaded with {@see \SimplePie\SimplePie::set_file_class()}
    5053 *
    5154 * @package SimplePie
     
    5356 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
    5457 */
    55 class SimplePie_File
     58class File
    5659{
    57     var $url;
    58     var $useragent;
    59     var $success = true;
    60     var $headers = array();
    61     var $body;
    62     var $status_code;
    63     var $redirects = 0;
    64     var $error;
    65     var $method = SIMPLEPIE_FILE_SOURCE_NONE;
    66     var $permanent_url;
    67 
    68     public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false, $curl_options = array())
    69     {
    70         if (class_exists('idna_convert'))
    71         {
    72             $idn = new idna_convert();
    73             $parsed = SimplePie_Misc::parse_url($url);
    74             $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], NULL);
    75         }
    76         $this->url = $url;
    77         $this->permanent_url = $url;
    78         $this->useragent = $useragent;
    79         if (preg_match('/^http(s)?:\/\//i', $url))
    80         {
    81             if ($useragent === null)
    82             {
    83                 $useragent = ini_get('user_agent');
    84                 $this->useragent = $useragent;
    85             }
    86             if (!is_array($headers))
    87             {
    88                 $headers = array();
    89             }
    90             if (!$force_fsockopen && function_exists('curl_exec'))
    91             {
    92                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
    93                 $fp = curl_init();
    94                 $headers2 = array();
    95                 foreach ($headers as $key => $value)
    96                 {
    97                     $headers2[] = "$key: $value";
    98                 }
    99                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
    100                 {
    101                     curl_setopt($fp, CURLOPT_ENCODING, '');
    102                 }
    103                 curl_setopt($fp, CURLOPT_URL, $url);
    104                 curl_setopt($fp, CURLOPT_HEADER, 1);
    105                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
    106                 curl_setopt($fp, CURLOPT_FAILONERROR, 1);
    107                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
    108                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
    109                 curl_setopt($fp, CURLOPT_REFERER, SimplePie_Misc::url_remove_credentials($url));
    110                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
    111                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
    112                 foreach ($curl_options as $curl_param => $curl_value) {
    113                     curl_setopt($fp, $curl_param, $curl_value);
    114                 }
    115 
    116                 $this->headers = curl_exec($fp);
    117                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
    118                 {
    119                     curl_setopt($fp, CURLOPT_ENCODING, 'none');
    120                     $this->headers = curl_exec($fp);
    121                 }
    122                 $this->status_code = curl_getinfo($fp, CURLINFO_HTTP_CODE);
    123                 if (curl_errno($fp))
    124                 {
    125                     $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
    126                     $this->success = false;
    127                 }
    128                 else
    129                 {
    130                     // Use the updated url provided by curl_getinfo after any redirects.
    131                     if ($info = curl_getinfo($fp)) {
    132                         $this->url = $info['url'];
    133                     }
    134                     curl_close($fp);
    135                     $this->headers = SimplePie_HTTP_Parser::prepareHeaders($this->headers, $info['redirect_count'] + 1);
    136                     $parser = new SimplePie_HTTP_Parser($this->headers);
    137                     if ($parser->parse())
    138                     {
    139                         $this->headers = $parser->headers;
    140                         $this->body = trim($parser->body);
    141                         $this->status_code = $parser->status_code;
    142                         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)
    143                         {
    144                             $this->redirects++;
    145                             $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
    146                             $previousStatusCode = $this->status_code;
    147                             $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen, $curl_options);
    148                             $this->permanent_url = ($previousStatusCode == 301) ? $location : $url;
    149                             return;
    150                         }
    151                     }
    152                 }
    153             }
    154             else
    155             {
    156                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
    157                 $url_parts = parse_url($url);
    158                 $socket_host = $url_parts['host'];
    159                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
    160                 {
    161                     $socket_host = "ssl://$url_parts[host]";
    162                     $url_parts['port'] = 443;
    163                 }
    164                 if (!isset($url_parts['port']))
    165                 {
    166                     $url_parts['port'] = 80;
    167                 }
    168                 $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
    169                 if (!$fp)
    170                 {
    171                     $this->error = 'fsockopen error: ' . $errstr;
    172                     $this->success = false;
    173                 }
    174                 else
    175                 {
    176                     stream_set_timeout($fp, $timeout);
    177                     if (isset($url_parts['path']))
    178                     {
    179                         if (isset($url_parts['query']))
    180                         {
    181                             $get = "$url_parts[path]?$url_parts[query]";
    182                         }
    183                         else
    184                         {
    185                             $get = $url_parts['path'];
    186                         }
    187                     }
    188                     else
    189                     {
    190                         $get = '/';
    191                     }
    192                     $out = "GET $get HTTP/1.1\r\n";
    193                     $out .= "Host: $url_parts[host]\r\n";
    194                     $out .= "User-Agent: $useragent\r\n";
    195                     if (extension_loaded('zlib'))
    196                     {
    197                         $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
    198                     }
    199 
    200                     if (isset($url_parts['user']) && isset($url_parts['pass']))
    201                     {
    202                         $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
    203                     }
    204                     foreach ($headers as $key => $value)
    205                     {
    206                         $out .= "$key: $value\r\n";
    207                     }
    208                     $out .= "Connection: Close\r\n\r\n";
    209                     fwrite($fp, $out);
    210 
    211                     $info = stream_get_meta_data($fp);
    212 
    213                     $this->headers = '';
    214                     while (!$info['eof'] && !$info['timed_out'])
    215                     {
    216                         $this->headers .= fread($fp, 1160);
    217                         $info = stream_get_meta_data($fp);
    218                     }
    219                     if (!$info['timed_out'])
    220                     {
    221                         $parser = new SimplePie_HTTP_Parser($this->headers);
    222                         if ($parser->parse())
    223                         {
    224                             $this->headers = $parser->headers;
    225                             $this->body = $parser->body;
    226                             $this->status_code = $parser->status_code;
    227                             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)
    228                             {
    229                                 $this->redirects++;
    230                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
    231                                 $previousStatusCode = $this->status_code;
    232                                 $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen, $curl_options);
    233                                 $this->permanent_url = ($previousStatusCode == 301) ? $location : $url;
    234                                 return;
    235                             }
    236                             if (isset($this->headers['content-encoding']))
    237                             {
    238                                 // Hey, we act dumb elsewhere, so let's do that here too
    239                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
    240                                 {
    241                                     case 'gzip':
    242                                     case 'x-gzip':
    243                                         $decoder = new SimplePie_gzdecode($this->body);
    244                                         if (!$decoder->parse())
    245                                         {
    246                                             $this->error = 'Unable to decode HTTP "gzip" stream';
    247                                             $this->success = false;
    248                                         }
    249                                         else
    250                                         {
    251                                             $this->body = trim($decoder->data);
    252                                         }
    253                                         break;
    254 
    255                                     case 'deflate':
    256                                         if (($decompressed = gzinflate($this->body)) !== false)
    257                                         {
    258                                             $this->body = $decompressed;
    259                                         }
    260                                         else if (($decompressed = gzuncompress($this->body)) !== false)
    261                                         {
    262                                             $this->body = $decompressed;
    263                                         }
    264                                         else if (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false)
    265                                         {
    266                                             $this->body = $decompressed;
    267                                         }
    268                                         else
    269                                         {
    270                                             $this->error = 'Unable to decode HTTP "deflate" stream';
    271                                             $this->success = false;
    272                                         }
    273                                         break;
    274 
    275                                     default:
    276                                         $this->error = 'Unknown content coding';
    277                                         $this->success = false;
    278                                 }
    279                             }
    280                         }
    281                     }
    282                     else
    283                     {
    284                         $this->error = 'fsocket timed out';
    285                         $this->success = false;
    286                     }
    287                     fclose($fp);
    288                 }
    289             }
    290         }
    291         else
    292         {
    293             $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
    294             if (empty($url) || !($this->body = trim(file_get_contents($url))))
    295             {
    296                 $this->error = 'file_get_contents could not read the file';
    297                 $this->success = false;
    298             }
    299         }
    300     }
     60    public $url;
     61    public $useragent;
     62    public $success = true;
     63    public $headers = [];
     64    public $body;
     65    public $status_code = 0;
     66    public $redirects = 0;
     67    public $error;
     68    public $method = \SimplePie\SimplePie::FILE_SOURCE_NONE;
     69    public $permanent_url;
     70
     71    public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false, $curl_options = [])
     72    {
     73        if (class_exists('idna_convert')) {
     74            $idn = new \idna_convert();
     75            $parsed = \SimplePie\Misc::parse_url($url);
     76            $url = \SimplePie\Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], null);
     77        }
     78        $this->url = $url;
     79        $this->permanent_url = $url;
     80        $this->useragent = $useragent;
     81        if (preg_match('/^http(s)?:\/\//i', $url)) {
     82            if ($useragent === null) {
     83                $useragent = ini_get('user_agent');
     84                $this->useragent = $useragent;
     85            }
     86            if (!is_array($headers)) {
     87                $headers = [];
     88            }
     89            if (!$force_fsockopen && function_exists('curl_exec')) {
     90                $this->method = \SimplePie\SimplePie::FILE_SOURCE_REMOTE | \SimplePie\SimplePie::FILE_SOURCE_CURL;
     91                $fp = curl_init();
     92                $headers2 = [];
     93                foreach ($headers as $key => $value) {
     94                    $headers2[] = "$key: $value";
     95                }
     96                if (version_compare(\SimplePie\Misc::get_curl_version(), '7.10.5', '>=')) {
     97                    curl_setopt($fp, CURLOPT_ENCODING, '');
     98                }
     99                curl_setopt($fp, CURLOPT_URL, $url);
     100                curl_setopt($fp, CURLOPT_HEADER, 1);
     101                curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
     102                curl_setopt($fp, CURLOPT_FAILONERROR, 1);
     103                curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
     104                curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
     105                curl_setopt($fp, CURLOPT_REFERER, \SimplePie\Misc::url_remove_credentials($url));
     106                curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
     107                curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
     108                foreach ($curl_options as $curl_param => $curl_value) {
     109                    curl_setopt($fp, $curl_param, $curl_value);
     110                }
     111
     112                $this->headers = curl_exec($fp);
     113                if (curl_errno($fp) === 23 || curl_errno($fp) === 61) {
     114                    curl_setopt($fp, CURLOPT_ENCODING, 'none');
     115                    $this->headers = curl_exec($fp);
     116                }
     117                $this->status_code = curl_getinfo($fp, CURLINFO_HTTP_CODE);
     118                if (curl_errno($fp)) {
     119                    $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
     120                    $this->success = false;
     121                } else {
     122                    // Use the updated url provided by curl_getinfo after any redirects.
     123                    if ($info = curl_getinfo($fp)) {
     124                        $this->url = $info['url'];
     125                    }
     126                    curl_close($fp);
     127                    $this->headers = \SimplePie\HTTP\Parser::prepareHeaders($this->headers, $info['redirect_count'] + 1);
     128                    $parser = new \SimplePie\HTTP\Parser($this->headers);
     129                    if ($parser->parse()) {
     130                        $this->headers = $parser->headers;
     131                        $this->body = trim($parser->body);
     132                        $this->status_code = $parser->status_code;
     133                        if ((in_array($this->status_code, [300, 301, 302, 303, 307]) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) {
     134                            $this->redirects++;
     135                            $location = \SimplePie\Misc::absolutize_url($this->headers['location'], $url);
     136                            $previousStatusCode = $this->status_code;
     137                            $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen, $curl_options);
     138                            $this->permanent_url = ($previousStatusCode == 301) ? $location : $url;
     139                            return;
     140                        }
     141                    }
     142                }
     143            } else {
     144                $this->method = \SimplePie\SimplePie::FILE_SOURCE_REMOTE | \SimplePie\SimplePie::FILE_SOURCE_FSOCKOPEN;
     145                $url_parts = parse_url($url);
     146                $socket_host = $url_parts['host'];
     147                if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') {
     148                    $socket_host = "ssl://$url_parts[host]";
     149                    $url_parts['port'] = 443;
     150                }
     151                if (!isset($url_parts['port'])) {
     152                    $url_parts['port'] = 80;
     153                }
     154                $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
     155                if (!$fp) {
     156                    $this->error = 'fsockopen error: ' . $errstr;
     157                    $this->success = false;
     158                } else {
     159                    stream_set_timeout($fp, $timeout);
     160                    if (isset($url_parts['path'])) {
     161                        if (isset($url_parts['query'])) {
     162                            $get = "$url_parts[path]?$url_parts[query]";
     163                        } else {
     164                            $get = $url_parts['path'];
     165                        }
     166                    } else {
     167                        $get = '/';
     168                    }
     169                    $out = "GET $get HTTP/1.1\r\n";
     170                    $out .= "Host: $url_parts[host]\r\n";
     171                    $out .= "User-Agent: $useragent\r\n";
     172                    if (extension_loaded('zlib')) {
     173                        $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
     174                    }
     175
     176                    if (isset($url_parts['user']) && isset($url_parts['pass'])) {
     177                        $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
     178                    }
     179                    foreach ($headers as $key => $value) {
     180                        $out .= "$key: $value\r\n";
     181                    }
     182                    $out .= "Connection: Close\r\n\r\n";
     183                    fwrite($fp, $out);
     184
     185                    $info = stream_get_meta_data($fp);
     186
     187                    $this->headers = '';
     188                    while (!$info['eof'] && !$info['timed_out']) {
     189                        $this->headers .= fread($fp, 1160);
     190                        $info = stream_get_meta_data($fp);
     191                    }
     192                    if (!$info['timed_out']) {
     193                        $parser = new \SimplePie\HTTP\Parser($this->headers);
     194                        if ($parser->parse()) {
     195                            $this->headers = $parser->headers;
     196                            $this->body = $parser->body;
     197                            $this->status_code = $parser->status_code;
     198                            if ((in_array($this->status_code, [300, 301, 302, 303, 307]) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) {
     199                                $this->redirects++;
     200                                $location = \SimplePie\Misc::absolutize_url($this->headers['location'], $url);
     201                                $previousStatusCode = $this->status_code;
     202                                $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen, $curl_options);
     203                                $this->permanent_url = ($previousStatusCode == 301) ? $location : $url;
     204                                return;
     205                            }
     206                            if (isset($this->headers['content-encoding'])) {
     207                                // Hey, we act dumb elsewhere, so let's do that here too
     208                                switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20"))) {
     209                                    case 'gzip':
     210                                    case 'x-gzip':
     211                                        $decoder = new \SimplePie\Gzdecode($this->body);
     212                                        if (!$decoder->parse()) {
     213                                            $this->error = 'Unable to decode HTTP "gzip" stream';
     214                                            $this->success = false;
     215                                        } else {
     216                                            $this->body = trim($decoder->data);
     217                                        }
     218                                        break;
     219
     220                                    case 'deflate':
     221                                        if (($decompressed = gzinflate($this->body)) !== false) {
     222                                            $this->body = $decompressed;
     223                                        } elseif (($decompressed = gzuncompress($this->body)) !== false) {
     224                                            $this->body = $decompressed;
     225                                        } elseif (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false) {
     226                                            $this->body = $decompressed;
     227                                        } else {
     228                                            $this->error = 'Unable to decode HTTP "deflate" stream';
     229                                            $this->success = false;
     230                                        }
     231                                        break;
     232
     233                                    default:
     234                                        $this->error = 'Unknown content coding';
     235                                        $this->success = false;
     236                                }
     237                            }
     238                        }
     239                    } else {
     240                        $this->error = 'fsocket timed out';
     241                        $this->success = false;
     242                    }
     243                    fclose($fp);
     244                }
     245            }
     246        } else {
     247            $this->method = \SimplePie\SimplePie::FILE_SOURCE_LOCAL | \SimplePie\SimplePie::FILE_SOURCE_FILE_GET_CONTENTS;
     248            if (empty($url) || !($this->body = trim(file_get_contents($url)))) {
     249                $this->error = 'file_get_contents could not read the file';
     250                $this->success = false;
     251            }
     252        }
     253    }
    301254}
     255
     256class_alias('SimplePie\File', 'SimplePie_File');
Note: See TracChangeset for help on using the changeset viewer.