Make WordPress Core


Ignore:
Timestamp:
11/25/2021 01:10:30 AM (5 years ago)
Author:
SergeyBiryukov
Message:

External Libraries: Update the Requests library to version 2.0.0.

This is a major release and contains breaking changes.

Most important changes to be aware of for this release:

  • All code is now namespaced. Though there is a full backward compatibility layer available and the old class names are still supported, using them will generate a deprecation notice (which can be silenced by plugins if they'd need to support multiple WP versions). See the ​upgrade guide for more details.
  • A lot of classes have been marked final. This should generally not affect userland code as care has been taken to not apply the final keyword to classes which are known to be extended in userland code.
  • Extensive input validation has been added to Requests. When Requests is used as documented though, this will be unnoticable.
  • A new WpOrg\Requests\Requests::has_capabilities() method has been introduced which can be used to address #37708.
  • A new WpOrg\Requests\Response::decode_body() method has been introduced which may be usable to simplify some of the WP native wrapper code.
  • Remaining PHP 8.0 compatibility fixed (support for named parameters).
  • PHP 8.1 compatibility.

Release notes: ​https://github.com/WordPress/Requests/releases/tag/v2.0.0

For a full list of changes in this update, see the Requests GitHub:
​https://github.com/WordPress/Requests/compare/v1.8.1...v2.0.0

Follow-up to [50842], [51078].

Props jrf, schlessera, datagutten, wojsmol, dd32, dustinrue, soulseekah, costdev, szepeviktor.
Fixes #54504.

File:
1 copied

Legend:

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

    r52243 r52244  
    1010 */
    1111
     12namespace WpOrg\Requests;
     13
     14use WpOrg\Requests\Auth\Basic;
     15use WpOrg\Requests\Capability;
     16use WpOrg\Requests\Cookie\Jar;
     17use WpOrg\Requests\Exception;
     18use WpOrg\Requests\Exception\InvalidArgument;
     19use WpOrg\Requests\Hooks;
     20use WpOrg\Requests\IdnaEncoder;
     21use WpOrg\Requests\Iri;
     22use WpOrg\Requests\Proxy\Http;
     23use WpOrg\Requests\Response;
     24use WpOrg\Requests\Transport\Curl;
     25use WpOrg\Requests\Transport\Fsockopen;
     26use WpOrg\Requests\Utility\InputValidator;
     27
    1228/**
    1329 * Requests for PHP
    … …  
    85101
    86102        /**
     103         * Option defaults.
     104         *
     105         * @see \WpOrg\Requests\Requests::get_default_options()
     106         * @see \WpOrg\Requests\Requests::request() for values returned by this method
     107         *
     108         * @since 2.0.0
     109         *
     110         * @var array
     111         */
     112        const OPTION_DEFAULTS = [
     113                'timeout'          => 10,
     114                'connect_timeout'  => 10,
     115                'useragent'        => 'php-requests/' . self::VERSION,
     116                'protocol_version' => 1.1,
     117                'redirected'       => 0,
     118                'redirects'        => 10,
     119                'follow_redirects' => true,
     120                'blocking'         => true,
     121                'type'             => self::GET,
     122                'filename'         => false,
     123                'auth'             => false,
     124                'proxy'            => false,
     125                'cookies'          => false,
     126                'max_bytes'        => false,
     127                'idn'              => true,
     128                'hooks'            => null,
     129                'transport'        => null,
     130                'verify'           => null,
     131                'verifyname'       => true,
     132        ];
     133
     134        /**
     135         * Default supported Transport classes.
     136         *
     137         * @since 2.0.0
     138         *
     139         * @var array
     140         */
     141        const DEFAULT_TRANSPORTS = [
     142                Curl::class      => Curl::class,
     143                Fsockopen::class => Fsockopen::class,
     144        ];
     145
     146        /**
    87147         * Current version of Requests
    88148         *
    89149         * @var string
    90150         */
    91         const VERSION = '1.8.1';
     151        const VERSION = '2.0.0';
     152
     153        /**
     154         * Selected transport name
     155         *
     156         * Use {@see \WpOrg\Requests\Requests::get_transport()} instead
     157         *
     158         * @var array
     159         */
     160        public static $transport = [];
    92161
    93162        /**
    … …  
    96165         * @var array
    97166         */
    98         protected static $transports = array();
    99 
    100         /**
    101          * Selected transport name
    102          *
    103          * Use {@see get_transport()} instead
     167        protected static $transports = [];
     168
     169        /**
     170         * Default certificate path.
     171         *
     172         * @see \WpOrg\Requests\Requests::get_certificate_path()
     173         * @see \WpOrg\Requests\Requests::set_certificate_path()
     174         *
     175         * @var string
     176         */
     177        protected static $certificate_path = __DIR__ . '/../certificates/cacert.pem';
     178
     179        /**
     180         * All (known) valid deflate, gzip header magic markers.
     181         *
     182         * These markers relate to different compression levels.
     183         *
     184         * @link https://stackoverflow.com/a/43170354/482864 Marker source.
     185         *
     186         * @since 2.0.0
    104187         *
    105188         * @var array
    106189         */
    107         public static $transport = array();
    108 
    109         /**
    110          * Default certificate path.
    111          *
    112          * @see Requests::get_certificate_path()
    113          * @see Requests::set_certificate_path()
    114          *
    115          * @var string
    116          */
    117         protected static $certificate_path;
     190        private static $magic_compression_headers = [
     191                "\x1f\x8b" => true, // Gzip marker.
     192                "\x78\x01" => true, // Zlib marker - level 1.
     193                "\x78\x5e" => true, // Zlib marker - level 2 to 5.
     194                "\x78\x9c" => true, // Zlib marker - level 6.
     195                "\x78\xda" => true, // Zlib marker - level 7 to 9.
     196        ];
    118197
    119198        /**
    … …  
    125204
    126205        /**
    127          * Autoloader for Requests
    128          *
    129          * Register this with {@see register_autoloader()} if you'd like to avoid
    130          * having to create your own.
    131          *
    132          * (You can also use `spl_autoload_register` directly if you'd prefer.)
    133          *
    134          * @codeCoverageIgnore
    135          *
    136          * @param string $class Class name to load
    137          */
    138         public static function autoloader($class) {
    139                 // Check that the class starts with "Requests"
    140                 if (strpos($class, 'Requests') !== 0) {
    141                         return;
    142                 }
    143 
    144                 $file = str_replace('_', '/', $class);
    145                 if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) {
    146                         require_once dirname(__FILE__) . '/' . $file . '.php';
    147                 }
    148         }
    149 
    150         /**
    151          * Register the built-in autoloader
    152          *
    153          * @codeCoverageIgnore
    154          */
    155         public static function register_autoloader() {
    156                 spl_autoload_register(array('Requests', 'autoloader'));
    157         }
    158 
    159         /**
    160206         * Register a transport
    161207         *
    162          * @param string $transport Transport class to add, must support the Requests_Transport interface
     208         * @param string $transport Transport class to add, must support the \WpOrg\Requests\Transport interface
    163209         */
    164210        public static function add_transport($transport) {
    165211                if (empty(self::$transports)) {
    166                         self::$transports = array(
    167                                 'Requests_Transport_cURL',
    168                                 'Requests_Transport_fsockopen',
    169                         );
    170                 }
    171 
    172                 self::$transports = array_merge(self::$transports, array($transport));
    173         }
    174 
    175         /**
    176          * Get a working transport
    177          *
    178          * @throws Requests_Exception If no valid transport is found (`notransport`)
    179          * @return Requests_Transport
    180          */
    181         protected static function get_transport($capabilities = array()) {
    182                 // Caching code, don't bother testing coverage
     212                        self::$transports = self::DEFAULT_TRANSPORTS;
     213                }
     214
     215                self::$transports[$transport] = $transport;
     216        }
     217
     218        /**
     219         * Get the fully qualified class name (FQCN) for a working transport.
     220         *
     221         * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`.
     222         * @return string FQCN of the transport to use, or an empty string if no transport was
     223         *                found which provided the requested capabilities.
     224         */
     225        protected static function get_transport_class(array $capabilities = []) {
     226                // Caching code, don't bother testing coverage.
    183227                // @codeCoverageIgnoreStart
    184                 // array of capabilities as a string to be used as an array key
     228                // Array of capabilities as a string to be used as an array key.
    185229                ksort($capabilities);
    186230                $cap_string = serialize($capabilities);
    187231
    188                 // Don't search for a transport if it's already been done for these $capabilities
    189                 if (isset(self::$transport[$cap_string]) && self::$transport[$cap_string] !== null) {
    190                         $class = self::$transport[$cap_string];
    191                         return new $class();
    192                 }
     232                // Don't search for a transport if it's already been done for these $capabilities.
     233                if (isset(self::$transport[$cap_string])) {
     234                        return self::$transport[$cap_string];
     235                }
     236
     237                // Ensure we will not run this same check again later on.
     238                self::$transport[$cap_string] = '';
    193239                // @codeCoverageIgnoreEnd
    194240
    195241                if (empty(self::$transports)) {
    196                         self::$transports = array(
    197                                 'Requests_Transport_cURL',
    198                                 'Requests_Transport_fsockopen',
    199                         );
    200                 }
    201 
    202                 // Find us a working transport
     242                        self::$transports = self::DEFAULT_TRANSPORTS;
     243                }
     244
     245                // Find us a working transport.
    203246                foreach (self::$transports as $class) {
    204247                        if (!class_exists($class)) {
    … …  
    206249                        }
    207250
    208                         $result = call_user_func(array($class, 'test'), $capabilities);
    209                         if ($result) {
     251                        $result = $class::test($capabilities);
     252                        if ($result === true) {
    210253                                self::$transport[$cap_string] = $class;
    211254                                break;
    212255                        }
    213256                }
    214                 if (self::$transport[$cap_string] === null) {
    215                         throw new Requests_Exception('No working transports found', 'notransport', self::$transports);
    216                 }
    217 
    218                 $class = self::$transport[$cap_string];
     257
     258                return self::$transport[$cap_string];
     259        }
     260
     261        /**
     262         * Get a working transport.
     263         *
     264         * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`.
     265         * @return \WpOrg\Requests\Transport
     266         * @throws \WpOrg\Requests\Exception If no valid transport is found (`notransport`).
     267         */
     268        protected static function get_transport(array $capabilities = []) {
     269                $class = self::get_transport_class($capabilities);
     270
     271                if ($class === '') {
     272                        throw new Exception('No working transports found', 'notransport', self::$transports);
     273                }
     274
    219275                return new $class();
    220276        }
    221277
     278        /**
     279         * Checks to see if we have a transport for the capabilities requested.
     280         *
     281         * Supported capabilities can be found in the {@see \WpOrg\Requests\Capability}
     282         * interface as constants.
     283         *
     284         * Example usage:
     285         * `Requests::has_capabilities([Capability::SSL => true])`.
     286         *
     287         * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`.
     288         * @return bool Whether the transport has the requested capabilities.
     289         */
     290        public static function has_capabilities(array $capabilities = []) {
     291                return self::get_transport_class($capabilities) !== '';
     292        }
     293
    222294        /**#@+
    223          * @see request()
     295         * @see \WpOrg\Requests\Requests::request()
    224296         * @param string $url
    225297         * @param array $headers
    226298         * @param array $options
    227          * @return Requests_Response
     299         * @return \WpOrg\Requests\Response
    228300         */
    229301        /**
    230302         * Send a GET request
    231303         */
    232         public static function get($url, $headers = array(), $options = array()) {
     304        public static function get($url, $headers = [], $options = []) {
    233305                return self::request($url, $headers, null, self::GET, $options);
    234306        }
    … …  
    237309         * Send a HEAD request
    238310         */
    239         public static function head($url, $headers = array(), $options = array()) {
     311        public static function head($url, $headers = [], $options = []) {
    240312                return self::request($url, $headers, null, self::HEAD, $options);
    241313        }
    … …  
    244316         * Send a DELETE request
    245317         */
    246         public static function delete($url, $headers = array(), $options = array()) {
     318        public static function delete($url, $headers = [], $options = []) {
    247319                return self::request($url, $headers, null, self::DELETE, $options);
    248320        }
    … …  
    251323         * Send a TRACE request
    252324         */
    253         public static function trace($url, $headers = array(), $options = array()) {
     325        public static function trace($url, $headers = [], $options = []) {
    254326                return self::request($url, $headers, null, self::TRACE, $options);
    255327        }
    … …  
    257329
    258330        /**#@+
    259          * @see request()
     331         * @see \WpOrg\Requests\Requests::request()
    260332         * @param string $url
    261333         * @param array $headers
    262334         * @param array $data
    263335         * @param array $options
    264          * @return Requests_Response
     336         * @return \WpOrg\Requests\Response
    265337         */
    266338        /**
    267339         * Send a POST request
    268340         */
    269         public static function post($url, $headers = array(), $data = array(), $options = array()) {
     341        public static function post($url, $headers = [], $data = [], $options = []) {
    270342                return self::request($url, $headers, $data, self::POST, $options);
    271343        }
    … …  
    273345         * Send a PUT request
    274346         */
    275         public static function put($url, $headers = array(), $data = array(), $options = array()) {
     347        public static function put($url, $headers = [], $data = [], $options = []) {
    276348                return self::request($url, $headers, $data, self::PUT, $options);
    277349        }
    … …  
    280352         * Send an OPTIONS request
    281353         */
    282         public static function options($url, $headers = array(), $data = array(), $options = array()) {
     354        public static function options($url, $headers = [], $data = [], $options = []) {
    283355                return self::request($url, $headers, $data, self::OPTIONS, $options);
    284356        }
    … …  
    287359         * Send a PATCH request
    288360         *
    289          * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the
    290          * specification recommends that should send an ETag
     361         * Note: Unlike {@see \WpOrg\Requests\Requests::post()} and {@see \WpOrg\Requests\Requests::put()},
     362         * `$headers` is required, as the specification recommends that should send an ETag
    291363         *
    292364         * @link https://tools.ietf.org/html/rfc5789
    293365         */
    294         public static function patch($url, $headers, $data = array(), $options = array()) {
     366        public static function patch($url, $headers, $data = [], $options = []) {
    295367                return self::request($url, $headers, $data, self::PATCH, $options);
    296368        }
    … …  
    324396         * - `auth`: Authentication handler or array of user/password details to use
    325397         *    for Basic authentication
    326          *    (Requests_Auth|array|boolean, default: false)
     398         *    (\WpOrg\Requests\Auth|array|boolean, default: false)
    327399         * - `proxy`: Proxy details to use for proxy by-passing and authentication
    328          *    (Requests_Proxy|array|string|boolean, default: false)
     400         *    (\WpOrg\Requests\Proxy|array|string|boolean, default: false)
    329401         * - `max_bytes`: Limit for the response body size.
    330402         *    (integer|boolean, default: false)
    … …  
    333405         * - `transport`: Custom transport. Either a class name, or a
    334406         *    transport object. Defaults to the first working transport from
    335          *    {@see getTransport()}
    336          *    (string|Requests_Transport, default: {@see getTransport()})
     407         *    {@see \WpOrg\Requests\Requests::getTransport()}
     408         *    (string|\WpOrg\Requests\Transport, default: {@see \WpOrg\Requests\Requests::getTransport()})
    337409         * - `hooks`: Hooks handler.
    338          *    (Requests_Hooker, default: new Requests_Hooks())
     410         *    (\WpOrg\Requests\HookManager, default: new WpOrg\Requests\Hooks())
    339411         * - `verify`: Should we verify SSL certificates? Allows passing in a custom
    340412         *    certificate file as a string. (Using true uses the system-wide root
    341413         *    certificate store instead, but this may have different behaviour
    342414         *    across transports.)
    343          *    (string|boolean, default: library/Requests/Transport/cacert.pem)
     415         *    (string|boolean, default: certificates/cacert.pem)
    344416         * - `verifyname`: Should we verify the common name in the SSL certificate?
    345417         *    (boolean, default: true)
    … …  
    348420         *    HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH)
    349421         *
    350          * @throws Requests_Exception On invalid URLs (`nonhttp`)
    351          *
    352          * @param string $url URL to request
     422         * @param string|Stringable $url URL to request
    353423         * @param array $headers Extra headers to send with the request
    354424         * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
    355425         * @param string $type HTTP request type (use Requests constants)
    356426         * @param array $options Options for the request (see description for more information)
    357          * @return Requests_Response
    358          */
    359         public static function request($url, $headers = array(), $data = array(), $type = self::GET, $options = array()) {
     427         * @return \WpOrg\Requests\Response
     428         *
     429         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable.
     430         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $type argument is not a string.
     431         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array.
     432         * @throws \WpOrg\Requests\Exception On invalid URLs (`nonhttp`)
     433         */
     434        public static function request($url, $headers = [], $data = [], $type = self::GET, $options = []) {
     435                if (InputValidator::is_string_or_stringable($url) === false) {
     436                        throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url));
     437                }
     438
     439                if (is_string($type) === false) {
     440                        throw InvalidArgument::create(4, '$type', 'string', gettype($type));
     441                }
     442
     443                if (is_array($options) === false) {
     444                        throw InvalidArgument::create(5, '$options', 'array', gettype($options));
     445                }
     446
    360447                if (empty($options['type'])) {
    361448                        $options['type'] = $type;
    … …  
    365452                self::set_defaults($url, $headers, $data, $type, $options);
    366453
    367                 $options['hooks']->dispatch('requests.before_request', array(&$url, &$headers, &$data, &$type, &$options));
     454                $options['hooks']->dispatch('requests.before_request', [&$url, &$headers, &$data, &$type, &$options]);
    368455
    369456                if (!empty($options['transport'])) {
    … …  
    376463                else {
    377464                        $need_ssl     = (stripos($url, 'https://') === 0);
    378                         $capabilities = array('ssl' => $need_ssl);
     465                        $capabilities = [Capability::SSL => $need_ssl];
    379466                        $transport    = self::get_transport($capabilities);
    380467                }
    381468                $response = $transport->request($url, $headers, $data, $options);
    382469
    383                 $options['hooks']->dispatch('requests.before_parse', array(&$response, $url, $headers, $data, $type, $options));
     470                $options['hooks']->dispatch('requests.before_parse', [&$response, $url, $headers, $data, $type, $options]);
    384471
    385472                return self::parse_response($response, $url, $headers, $data, $options);
    … …  
    397484         *
    398485         * - `url`: Request URL Same as the `$url` parameter to
    399          *    {@see Requests::request}
     486         *    {@see \WpOrg\Requests\Requests::request()}
    400487         *    (string, required)
    401488         * - `headers`: Associative array of header fields. Same as the `$headers`
    402          *    parameter to {@see Requests::request}
     489         *    parameter to {@see \WpOrg\Requests\Requests::request()}
    403490         *    (array, default: `array()`)
    404491         * - `data`: Associative array of data fields or a string. Same as the
    405          *    `$data` parameter to {@see Requests::request}
     492         *    `$data` parameter to {@see \WpOrg\Requests\Requests::request()}
    406493         *    (array|string, default: `array()`)
    407          * - `type`: HTTP request type (use Requests constants). Same as the `$type`
    408          *    parameter to {@see Requests::request}
    409          *    (string, default: `Requests::GET`)
     494         * - `type`: HTTP request type (use \WpOrg\Requests\Requests constants). Same as the `$type`
     495         *    parameter to {@see \WpOrg\Requests\Requests::request()}
     496         *    (string, default: `\WpOrg\Requests\Requests::GET`)
    410497         * - `cookies`: Associative array of cookie name to value, or cookie jar.
    411          *    (array|Requests_Cookie_Jar)
     498         *    (array|\WpOrg\Requests\Cookie\Jar)
    412499         *
    413500         * If the `$options` parameter is specified, individual requests will
    414501         * inherit options from it. This can be used to use a single hooking system,
    415          * or set all the types to `Requests::POST`, for example.
     502         * or set all the types to `\WpOrg\Requests\Requests::POST`, for example.
    416503         *
    417504         * In addition, the `$options` parameter takes the following global options:
    418505         *
    419506         * - `complete`: A callback for when a request is complete. Takes two
    420          *    parameters, a Requests_Response/Requests_Exception reference, and the
     507         *    parameters, a \WpOrg\Requests\Response/\WpOrg\Requests\Exception reference, and the
    421508         *    ID from the request array (Note: this can also be overridden on a
    422509         *    per-request basis, although that's a little silly)
    … …  
    424511         *
    425512         * @param array $requests Requests data (see description for more information)
    426          * @param array $options Global and default options (see {@see Requests::request})
    427          * @return array Responses (either Requests_Response or a Requests_Exception object)
    428          */
    429         public static function request_multiple($requests, $options = array()) {
     513         * @param array $options Global and default options (see {@see \WpOrg\Requests\Requests::request()})
     514         * @return array Responses (either \WpOrg\Requests\Response or a \WpOrg\Requests\Exception object)
     515         *
     516         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access.
     517         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array.
     518         */
     519        public static function request_multiple($requests, $options = []) {
     520                if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) {
     521                        throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests));
     522                }
     523
     524                if (is_array($options) === false) {
     525                        throw InvalidArgument::create(2, '$options', 'array', gettype($options));
     526                }
     527
    430528                $options = array_merge(self::get_default_options(true), $options);
    431529
    432530                if (!empty($options['hooks'])) {
    433                         $options['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple'));
     531                        $options['hooks']->register('transport.internal.parse_response', [static::class, 'parse_multiple']);
    434532                        if (!empty($options['complete'])) {
    435533                                $options['hooks']->register('multiple.request.complete', $options['complete']);
    … …  
    439537                foreach ($requests as $id => &$request) {
    440538                        if (!isset($request['headers'])) {
    441                                 $request['headers'] = array();
     539                                $request['headers'] = [];
    442540                        }
    443541                        if (!isset($request['data'])) {
    444                                 $request['data'] = array();
     542                                $request['data'] = [];
    445543                        }
    446544                        if (!isset($request['type'])) {
    … …  
    462560                        // Ensure we only hook in once
    463561                        if ($request['options']['hooks'] !== $options['hooks']) {
    464                                 $request['options']['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple'));
     562                                $request['options']['hooks']->register('transport.internal.parse_response', [static::class, 'parse_multiple']);
    465563                                if (!empty($request['options']['complete'])) {
    466564                                        $request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']);
    … …  
    488586                                $request = $requests[$id];
    489587                                self::parse_multiple($response, $request);
    490                                 $request['options']['hooks']->dispatch('multiple.request.complete', array(&$response, $id));
     588                                $request['options']['hooks']->dispatch('multiple.request.complete', [&$response, $id]);
    491589                        }
    492590                }
    … …  
    498596         * Get the default options
    499597         *
    500          * @see Requests::request() for values returned by this method
     598         * @see \WpOrg\Requests\Requests::request() for values returned by this method
    501599         * @param boolean $multirequest Is this a multirequest?
    502600         * @return array Default option values
    503601         */
    504602        protected static function get_default_options($multirequest = false) {
    505                 $defaults = array(
    506                         'timeout'          => 10,
    507                         'connect_timeout'  => 10,
    508                         'useragent'        => 'php-requests/' . self::VERSION,
    509                         'protocol_version' => 1.1,
    510                         'redirected'       => 0,
    511                         'redirects'        => 10,
    512                         'follow_redirects' => true,
    513                         'blocking'         => true,
    514                         'type'             => self::GET,
    515                         'filename'         => false,
    516                         'auth'             => false,
    517                         'proxy'            => false,
    518                         'cookies'          => false,
    519                         'max_bytes'        => false,
    520                         'idn'              => true,
    521                         'hooks'            => null,
    522                         'transport'        => null,
    523                         'verify'           => self::get_certificate_path(),
    524                         'verifyname'       => true,
    525                 );
     603                $defaults           = static::OPTION_DEFAULTS;
     604                $defaults['verify'] = self::$certificate_path;
     605
    526606                if ($multirequest !== false) {
    527607                        $defaults['complete'] = null;
    … …  
    536616         */
    537617        public static function get_certificate_path() {
    538                 if (!empty(self::$certificate_path)) {
    539                         return self::$certificate_path;
    540                 }
    541 
    542                 return dirname(__FILE__) . '/Requests/Transport/cacert.pem';
     618                return self::$certificate_path;
    543619        }
    544620
    … …  
    546622         * Set default certificate path.
    547623         *
    548          * @param string $path Certificate path, pointing to a PEM file.
     624         * @param string|Stringable|bool $path Certificate path, pointing to a PEM file.
     625         *
     626         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string, Stringable or boolean.
    549627         */
    550628        public static function set_certificate_path($path) {
     629                if (InputValidator::is_string_or_stringable($path) === false && is_bool($path) === false) {
     630                        throw InvalidArgument::create(1, '$path', 'string|Stringable|bool', gettype($path));
     631                }
     632
    551633                self::$certificate_path = $path;
    552634        }
    … …  
    560642         * @param string $type HTTP request type
    561643         * @param array $options Options for the request
    562          * @return array $options
     644         * @return void $options is updated with the results
     645         *
     646         * @throws \WpOrg\Requests\Exception When the $url is not an http(s) URL.
    563647         */
    564648        protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) {
    565649                if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) {
    566                         throw new Requests_Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url);
     650                        throw new Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url);
    567651                }
    568652
    569653                if (empty($options['hooks'])) {
    570                         $options['hooks'] = new Requests_Hooks();
     654                        $options['hooks'] = new Hooks();
    571655                }
    572656
    573657                if (is_array($options['auth'])) {
    574                         $options['auth'] = new Requests_Auth_Basic($options['auth']);
     658                        $options['auth'] = new Basic($options['auth']);
    575659                }
    576660                if ($options['auth'] !== false) {
    … …  
    579663
    580664                if (is_string($options['proxy']) || is_array($options['proxy'])) {
    581                         $options['proxy'] = new Requests_Proxy_HTTP($options['proxy']);
     665                        $options['proxy'] = new Http($options['proxy']);
    582666                }
    583667                if ($options['proxy'] !== false) {
    … …  
    586670
    587671                if (is_array($options['cookies'])) {
    588                         $options['cookies'] = new Requests_Cookie_Jar($options['cookies']);
     672                        $options['cookies'] = new Jar($options['cookies']);
    589673                }
    590674                elseif (empty($options['cookies'])) {
    591                         $options['cookies'] = new Requests_Cookie_Jar();
     675                        $options['cookies'] = new Jar();
    592676                }
    593677                if ($options['cookies'] !== false) {
    … …  
    596680
    597681                if ($options['idn'] !== false) {
    598                         $iri       = new Requests_IRI($url);
    599                         $iri->host = Requests_IDNAEncoder::encode($iri->ihost);
     682                        $iri       = new Iri($url);
     683                        $iri->host = IdnaEncoder::encode($iri->ihost);
    600684                        $url       = $iri->uri;
    601685                }
    … …  
    605689
    606690                if (!isset($options['data_format'])) {
    607                         if (in_array($type, array(self::HEAD, self::GET, self::DELETE), true)) {
     691                        if (in_array($type, [self::HEAD, self::GET, self::DELETE], true)) {
    608692                                $options['data_format'] = 'query';
    609693                        }
    … …  
    616700        /**
    617701         * HTTP response parser
    618          *
    619          * @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`)
    620          * @throws Requests_Exception On missing head/body separator (`noversion`)
    621          * @throws Requests_Exception On missing head/body separator (`toomanyredirects`)
    622702         *
    623703         * @param string $headers Full response text including headers and body
    … …  
    626706         * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects
    627707         * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects
    628          * @return Requests_Response
     708         * @return \WpOrg\Requests\Response
     709         *
     710         * @throws \WpOrg\Requests\Exception On missing head/body separator (`requests.no_crlf_separator`)
     711         * @throws \WpOrg\Requests\Exception On missing head/body separator (`noversion`)
     712         * @throws \WpOrg\Requests\Exception On missing head/body separator (`toomanyredirects`)
    629713         */
    630714        protected static function parse_response($headers, $url, $req_headers, $req_data, $options) {
    631                 $return = new Requests_Response();
     715                $return = new Response();
    632716                if (!$options['blocking']) {
    633717                        return $return;
    … …  
    642726                        if ($pos === false) {
    643727                                // Crap!
    644                                 throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator');
     728                                throw new Exception('Missing header/body separator', 'requests.no_crlf_separator');
    645729                        }
    646730
    … …  
    659743                preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches);
    660744                if (empty($matches)) {
    661                         throw new Requests_Exception('Response could not be parsed', 'noversion', $headers);
     745                        throw new Exception('Response could not be parsed', 'noversion', $headers);
    662746                }
    663747                $return->protocol_version = (float) $matches[1];
    … …  
    686770                }
    687771
    688                 $options['hooks']->dispatch('requests.before_redirect_check', array(&$return, $req_headers, $req_data, $options));
     772                $options['hooks']->dispatch('requests.before_redirect_check', [&$return, $req_headers, $req_data, $options]);
    689773
    690774                if ($return->is_redirect() && $options['follow_redirects'] === true) {
    … …  
    697781                                if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) {
    698782                                        // relative redirect, for compatibility make it absolute
    699                                         $location = Requests_IRI::absolutize($url, $location);
     783                                        $location = Iri::absolutize($url, $location);
    700784                                        $location = $location->uri;
    701785                                }
    702786
    703                                 $hook_args = array(
     787                                $hook_args = [
    704788                                        &$location,
    705789                                        &$req_headers,
    … …  
    707791                                        &$options,
    708792                                        $return,
    709                                 );
     793                                ];
    710794                                $options['hooks']->dispatch('requests.before_redirect', $hook_args);
    711795                                $redirected            = self::request($location, $req_headers, $req_data, $options['type'], $options);
    … …  
    714798                        }
    715799                        elseif ($options['redirected'] >= $options['redirects']) {
    716                                 throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return);
     800                                throw new Exception('Too many redirects', 'toomanyredirects', $return);
    717801                        }
    718802                }
    … …  
    720804                $return->redirects = $options['redirected'];
    721805
    722                 $options['hooks']->dispatch('requests.after_request', array(&$return, $req_headers, $req_data, $options));
     806                $options['hooks']->dispatch('requests.after_request', [&$return, $req_headers, $req_data, $options]);
    723807                return $return;
    724808        }
    … …  
    727811         * Callback for `transport.internal.parse_response`
    728812         *
    729          * Internal use only. Converts a raw HTTP response to a Requests_Response
     813         * Internal use only. Converts a raw HTTP response to a \WpOrg\Requests\Response
    730814         * while still executing a multiple request.
    731815         *
    732816         * @param string $response Full response text including headers and body (will be overwritten with Response instance)
    733          * @param array $request Request data as passed into {@see Requests::request_multiple()}
    734          * @return null `$response` is either set to a Requests_Response instance, or a Requests_Exception object
     817         * @param array $request Request data as passed into {@see \WpOrg\Requests\Requests::request_multiple()}
     818         * @return void `$response` is either set to a \WpOrg\Requests\Response instance, or a \WpOrg\Requests\Exception object
    735819         */
    736820        public static function parse_multiple(&$response, $request) {
    … …  
    742826                        $response = self::parse_response($response, $url, $headers, $data, $options);
    743827                }
    744                 catch (Requests_Exception $e) {
     828                catch (Exception $e) {
    745829                        $response = $e;
    746830                }
    … …  
    750834         * Decoded a chunked body as per RFC 2616
    751835         *
    752          * @see https://tools.ietf.org/html/rfc2616#section-3.6.1
     836         * @link https://tools.ietf.org/html/rfc2616#section-3.6.1
    753837         * @param string $data Chunked body
    754838         * @return string Decoded body
    … …  
    792876         * Convert a key => value array to a 'key: value' array for headers
    793877         *
    794          * @param array $array Dictionary of header values
     878         * @param iterable $dictionary Dictionary of header values
    795879         * @return array List of headers
    796          */
    797         public static function flatten($array) {
    798                 $return = array();
    799                 foreach ($array as $key => $value) {
     880         *
     881         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not iterable.
     882         */
     883        public static function flatten($dictionary) {
     884                if (InputValidator::is_iterable($dictionary) === false) {
     885                        throw InvalidArgument::create(1, '$dictionary', 'iterable', gettype($dictionary));
     886                }
     887
     888                $return = [];
     889                foreach ($dictionary as $key => $value) {
    800890                        $return[] = sprintf('%s: %s', $key, $value);
    801891                }
    802892                return $return;
    803         }
    804 
    805         /**
    806          * Convert a key => value array to a 'key: value' array for headers
    807          *
    808          * @codeCoverageIgnore
    809          * @deprecated Misspelling of {@see Requests::flatten}
    810          * @param array $array Dictionary of header values
    811          * @return array List of headers
    812          */
    813         public static function flattern($array) {
    814                 return self::flatten($array);
    815893        }
    816894
    … …  
    823901         * @param string $data Compressed data in one of the above formats
    824902         * @return string Decompressed string
     903         *
     904         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string.
    825905         */
    826906        public static function decompress($data) {
    827                 if (substr($data, 0, 2) !== "\x1f\x8b" && substr($data, 0, 2) !== "\x78\x9c") {
     907                if (is_string($data) === false) {
     908                        throw InvalidArgument::create(1, '$data', 'string', gettype($data));
     909                }
     910
     911                if (trim($data) === '') {
     912                        // Empty body does not need further processing.
     913                        return $data;
     914                }
     915
     916                $marker = substr($data, 0, 2);
     917                if (!isset(self::$magic_compression_headers[$marker])) {
    828918                        // Not actually compressed. Probably cURL ruining this for us.
    829919                        return $data;
    … …  
    831921
    832922                if (function_exists('gzdecode')) {
    833                         // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.gzdecodeFound -- Wrapped in function_exists() for PHP 5.2.
    834923                        $decoded = @gzdecode($data);
    835924                        if ($decoded !== false) {
    … …  
    872961         * https://core.trac.wordpress.org/ticket/18273
    873962         *
    874          * @since 2.8.1
     963         * @since 1.6.0
    875964         * @link https://core.trac.wordpress.org/ticket/18273
    876          * @link https://secure.php.net/manual/en/function.gzinflate.php#70875
    877          * @link https://secure.php.net/manual/en/function.gzinflate.php#77336
     965         * @link https://www.php.net/gzinflate#70875
     966         * @link https://www.php.net/gzinflate#77336
    878967         *
    879968         * @param string $gz_data String to decompress.
    880969         * @return string|bool False on failure.
     970         *
     971         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string.
    881972         */
    882973        public static function compatible_gzinflate($gz_data) {
     974                if (is_string($gz_data) === false) {
     975                        throw InvalidArgument::create(1, '$gz_data', 'string', gettype($gz_data));
     976                }
     977
     978                if (trim($gz_data) === '') {
     979                        return false;
     980                }
     981
    883982                // Compressed data might contain a full zlib header, if so strip it for
    884983                // gzinflate()
    … …  
    9101009                // byte Huffman marker for gzinflate()
    9111010                // The response is Huffman coded by many compressors such as
    912                 // java.util.zip.Deflater, Ruby’s Zlib::Deflate, and .NET's
     1011                // java.util.zip.Deflater, Ruby's Zlib::Deflate, and .NET's
    9131012                // System.IO.Compression.DeflateStream.
    9141013                //
    … …  
    9781077                return false;
    9791078        }
    980 
    981         public static function match_domain($host, $reference) {
    982                 // Check for a direct match
    983                 if ($host === $reference) {
    984                         return true;
    985                 }
    986 
    987                 // Calculate the valid wildcard match if the host is not an IP address
    988                 // Also validates that the host has 3 parts or more, as per Firefox's
    989                 // ruleset.
    990                 $parts = explode('.', $host);
    991                 if (ip2long($host) === false && count($parts) >= 3) {
    992                         $parts[0] = '*';
    993                         $wildcard = implode('.', $parts);
    994                         if ($wildcard === $reference) {
    995                                 return true;
    996                         }
    997                 }
    998 
    999                 return false;
    1000         }
    10011079}
Note: See TracChangeset for help on using the changeset viewer.